Repository: kestra-io/kestra (java)

Issue:
Flows not specific when navigating from Namespaces
### Describe the issue

When navigating as follows: Namespaces (in menubar) -> mynamespace (from the available list) -> Flow (at the top) I would expect to only get a list of Flows for this particular namespace.

Instead I get an unfiltered list of all Flows. This seems like a bug with the Flow filtering in this particular instance.

![image](https://github.com/user-attachments/assets/ab41eeef-6f26-438b-b6c4-6819cebddee0)



### Environment

- Kestra Version: 0.19.9


Pull request:
fix(ui): filter flows in namespace tab by namespace
<!-- Thanks for submitting a Pull Request to Kestra. To help us review your contribution, please follow the guidelines below:

- Make sure that your commits follow the [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) specification e.g. `feat(ui): add a new navigation menu item` or `fix(core): fix a bug in the core model` or `docs: update the README.md`. This will help us automatically generate the changelog.
- The title should briefly summarize the proposed changes.
- Provide a short overview of the change and the value it adds.
- Share a flow example to help the reviewer understand and QA the change.
- Use "closes" to automatically close an issue. For example, `closes #1234` will close issue #1234. -->

### What changes are being made and why?

Update the flow query filter inside namespace tab to get flows for the selected namespace only.
closes #5965 

<!-- Please include a brief summary of the changes included in this PR e.g. closes #1234. -->

---

### How the changes have been QAed?

Below we can see that only flows for selected namespace org.timon is visible.

<img width="1424" alt="Screenshot 2024-11-22 at 12 59 39 PM" src="https://github.com/user-attachments/assets/4280e88e-977b-4834-a602-2b9fd4fb66e5">

The list of all flows is shown in below image.

<img width="1440" alt="Screenshot 2024-11-22 at 1 00 18 PM" src="https://github.com/user-attachments/assets/cb7f5ab1-8eb3-48f9-8c50-9b8c88ec040b">

<!-- Include example code that shows how this PR has been QAed. The code should present a complete yet easily reproducible flow.

```yaml
# Your example flow code here
```

Note that this is not a replacement for unit tests but rather a way to demonstrate how the changes work in a real-life scenario, as the end-user would experience them.

Remove this section if this change applies to all flows or to the documentation only. -->

---



Patch:
diff --git a/core/src/main/java/io/kestra/core/runners/pebble/Extension.java b/core/src/main/java/io/kestra/core/runners/pebble/Extension.java
index 6dea6f573..455b79f86 100644
--- a/core/src/main/java/io/kestra/core/runners/pebble/Extension.java
+++ b/core/src/main/java/io/kestra/core/runners/pebble/Extension.java
@@ -147,6 +147,7 @@ public class Extension extends AbstractExtension {
         if (this.errorLogsFunction != null) {
             functions.put("errorLogs", errorLogsFunction);
         }
+        functions.put("randomInt", new RandomIntFunction());
         return functions;
     }
 
diff --git a/core/src/main/java/io/kestra/core/runners/pebble/functions/RandomIntFunction.java b/core/src/main/java/io/kestra/core/runners/pebble/functions/RandomIntFunction.java
new file mode 100644
index 000000000..22ab5642c
--- /dev/null
+++ b/core/src/main/java/io/kestra/core/runners/pebble/functions/RandomIntFunction.java
@@ -0,0 +1,52 @@
+package io.kestra.core.runners.pebble.functions;
+
+import io.pebbletemplates.pebble.error.PebbleException;
+import io.pebbletemplates.pebble.extension.Function;
+import io.pebbletemplates.pebble.template.EvaluationContext;
+import io.pebbletemplates.pebble.template.PebbleTemplate;
+
+import java.util.List;
+import java.util.Map;
+
+public class RandomIntFunction implements Function {
+
+  @Override
+  public Object execute(
+      Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
+    Integer lower = getArgument(args, "lower", self, lineNumber);
+    Integer upper = getArgument(args, "upper", self, lineNumber);
+    if (upper < lower) {
+        throw new PebbleException(
+            null,
+            "In 'GenerateRandomNumber' upper is less than lower",
+            lineNumber,
+            self.getName());
+    }
+    return (int) (Math.floor(Math.random() * (upper - lower)) + lower);
+  }
+
+  @Override
+  public List<String> getArgumentNames() {
+    return List.of("lower", "upper");
+  }
+
+  private Integer getArgument(
+      Map<String, Object> args, String arg, PebbleTemplate self, int lineNumber) {
+    if (!args.containsKey(arg)) {
+      throw new PebbleException(
+          null,
+          "The 'GenerateRandomNumber' function expects an argument " + arg,
+          lineNumber,
+          self.getName());
+    }
+
+    if (!(args.get(arg) instanceof Integer)) {
+      throw new PebbleException(
+          null,
+          "The 'GenerateRandomNumber' function expects an argument " + arg + "with type Integer.",
+          lineNumber,
+          self.getName());
+    }
+    return (Integer) args.get(arg);
+  }
+}
diff --git a/ui/src/components/flows/Flows.vue b/ui/src/components/flows/Flows.vue
index 5d6bcf1d9..efa7ab420 100644
--- a/ui/src/components/flows/Flows.vue
+++ b/ui/src/components/flows/Flows.vue
@@ -497,6 +497,8 @@
             loadQuery(base) {
                 let queryFilter = this.queryWithFilter();
 
+                this.namespace && (queryFilter.namespace = this.namespace);
+                
                 return _merge(base, queryFilter)
             },
             loadStats() {


Test patch:
diff --git a/core/src/test/java/io/kestra/core/runners/pebble/functions/RandomIntFunctionTest.java b/core/src/test/java/io/kestra/core/runners/pebble/functions/RandomIntFunctionTest.java
new file mode 100644
index 000000000..fdf9a948a
--- /dev/null
+++ b/core/src/test/java/io/kestra/core/runners/pebble/functions/RandomIntFunctionTest.java
@@ -0,0 +1,71 @@
+package io.kestra.core.runners.pebble.functions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import io.kestra.core.exceptions.IllegalVariableEvaluationException;
+import io.kestra.core.junit.annotations.KestraTest;
+import io.kestra.core.runners.VariableRenderer;
+import jakarta.inject.Inject;
+import java.util.Collections;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+
+@KestraTest
+class RandomIntFunctionTest {
+  @Inject VariableRenderer variableRenderer;
+
+  @Test
+  void missingParameter() {
+    assertThrows(
+        IllegalVariableEvaluationException.class,
+        () -> variableRenderer.render("{{randomInt(lower)}}", Map.of("lower", 10)));
+
+    assertThrows(
+        IllegalVariableEvaluationException.class,
+        () -> variableRenderer.render("{{randomInt(upper)}}", Map.of("upper", 1)));
+    assertThrows(
+        IllegalVariableEvaluationException.class,
+        () -> variableRenderer.render("{{randomInt()}}", Collections.emptyMap()));
+  }
+
+  @Test
+  void testGenerateNumberPositive() throws IllegalVariableEvaluationException {
+    String rendered =
+        variableRenderer.render(
+            "{{ randomInt(lower, upper) }}", Map.of("lower", 1, "upper", 10));
+    assertThat(rendered, Integer.parseInt(rendered) >= 1 && Integer.parseInt(rendered) <= 10);
+  }
+
+    @Test
+    void testGenerateNumberPositiveString() {
+        assertThrows(
+            IllegalVariableEvaluationException.class,
+            () -> variableRenderer.render("{{ randomInt(lower, upper) }}", Map.of("lower", "1", "upper", "10")));
+    }
+
+    @Test
+  void testGenerateNumberUpperLessThanLower() {
+    assertThrows(
+        IllegalVariableEvaluationException.class,
+        () ->
+            variableRenderer.render(
+                "{{ randomInt(lower, upper) }}", Map.of("lower", 10, "upper", 1)));
+  }
+
+  @Test
+  void testGenerateNumberNegative() throws IllegalVariableEvaluationException {
+    String rendered =
+        variableRenderer.render(
+            "{{ randomInt(lower, upper) }}", Map.of("lower", -10, "upper", -1));
+    assertThat(rendered, Integer.parseInt(rendered) >= -10 && Integer.parseInt(rendered) <= -1);
+  }
+
+    @Test
+    void testGenerateNumberSame() throws IllegalVariableEvaluationException {
+        String rendered =
+            variableRenderer.render(
+                "{{ randomInt(lower, upper) }}", Map.of("lower", 10, "upper", 10));
+        assertThat(rendered, Integer.parseInt(rendered) == 10);
+    }
+}