mirror of
https://github.com/kestra-io/kestra.git
synced 2025-12-25 11:12:12 -05:00
Compare commits
26 Commits
fix/remove
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb31e48f4f | ||
|
|
a3f96a2741 | ||
|
|
5ca6fa8d77 | ||
|
|
a3a206f3c4 | ||
|
|
31f1e505e3 | ||
|
|
75e0c1d11f | ||
|
|
4cf883877d | ||
|
|
87b1e8fb01 | ||
|
|
b5c6101090 | ||
|
|
e4323728d6 | ||
|
|
5495971ecf | ||
|
|
dec1ee4272 | ||
|
|
69cc6b2715 | ||
|
|
431b4ccdb9 | ||
|
|
e9207a6f53 | ||
|
|
419c1041d5 | ||
|
|
02cd5efb05 | ||
|
|
2d549940c4 | ||
|
|
97e138fbae | ||
|
|
d48f3b9bd9 | ||
|
|
291fba3281 | ||
|
|
db3b3236ac | ||
|
|
5a8a631b47 | ||
|
|
2da191896f | ||
|
|
111026369b | ||
|
|
e3a0e59e9c |
4
.github/CONTRIBUTING.md
vendored
4
.github/CONTRIBUTING.md
vendored
@@ -63,9 +63,9 @@ You can also build it from a terminal using `./gradlew build`, the Gradle wrappe
|
|||||||
- Configure the following environment variables:
|
- Configure the following environment variables:
|
||||||
- `MICRONAUT_ENVIRONMENTS`: can be set to any string and will load a custom configuration file in `cli/src/main/resources/application-{env}.yml`.
|
- `MICRONAUT_ENVIRONMENTS`: can be set to any string and will load a custom configuration file in `cli/src/main/resources/application-{env}.yml`.
|
||||||
- `KESTRA_PLUGINS_PATH`: is the path where you will save plugins as Jar and will be load on startup.
|
- `KESTRA_PLUGINS_PATH`: is the path where you will save plugins as Jar and will be load on startup.
|
||||||
- See the screenshot below for an example: 
|
- See the screenshot below for an example: 
|
||||||
- If you encounter **JavaScript memory heap out** error during startup, configure `NODE_OPTIONS` environment variable with some large value.
|
- If you encounter **JavaScript memory heap out** error during startup, configure `NODE_OPTIONS` environment variable with some large value.
|
||||||
- Example `NODE_OPTIONS: --max-old-space-size=4096` or `NODE_OPTIONS: --max-old-space-size=8192` 
|
- Example `NODE_OPTIONS: --max-old-space-size=4096` or `NODE_OPTIONS: --max-old-space-size=8192` 
|
||||||
- The server starts by default on port 8080 and is reachable on `http://localhost:8080`
|
- The server starts by default on port 8080 and is reachable on `http://localhost:8080`
|
||||||
|
|
||||||
If you want to launch all tests, you need Python and some packages installed on your machine, on Ubuntu you can install them with:
|
If you want to launch all tests, you need Python and some packages installed on your machine, on Ubuntu you can install them with:
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 210 KiB |
171
build.gradle
171
build.gradle
@@ -171,13 +171,22 @@ allprojects {
|
|||||||
subprojects {subProj ->
|
subprojects {subProj ->
|
||||||
|
|
||||||
if (subProj.name != 'platform' && subProj.name != 'jmh-benchmarks') {
|
if (subProj.name != 'platform' && subProj.name != 'jmh-benchmarks') {
|
||||||
|
|
||||||
apply plugin: "com.adarshr.test-logger"
|
apply plugin: "com.adarshr.test-logger"
|
||||||
|
apply plugin: 'jacoco'
|
||||||
|
|
||||||
java {
|
java {
|
||||||
sourceCompatibility = targetJavaVersion
|
sourceCompatibility = targetJavaVersion
|
||||||
targetCompatibility = targetJavaVersion
|
targetCompatibility = targetJavaVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
agent {
|
||||||
|
canBeResolved = true
|
||||||
|
canBeConsumed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Platform
|
// Platform
|
||||||
testAnnotationProcessor enforcedPlatform(project(":platform"))
|
testAnnotationProcessor enforcedPlatform(project(":platform"))
|
||||||
@@ -204,9 +213,17 @@ subprojects {subProj ->
|
|||||||
|
|
||||||
//assertj
|
//assertj
|
||||||
testImplementation 'org.assertj:assertj-core'
|
testImplementation 'org.assertj:assertj-core'
|
||||||
|
|
||||||
|
agent "org.aspectj:aspectjweaver:1.9.25.1"
|
||||||
|
|
||||||
|
testImplementation platform("io.qameta.allure:allure-bom")
|
||||||
|
testImplementation "io.qameta.allure:allure-junit5"
|
||||||
}
|
}
|
||||||
|
|
||||||
def commonTestConfig = { Test t ->
|
def commonTestConfig = { Test t ->
|
||||||
|
t.ignoreFailures = true
|
||||||
|
t.finalizedBy jacocoTestReport
|
||||||
|
|
||||||
// set Xmx for test workers
|
// set Xmx for test workers
|
||||||
t.maxHeapSize = '4g'
|
t.maxHeapSize = '4g'
|
||||||
|
|
||||||
@@ -232,6 +249,52 @@ subprojects {subProj ->
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.register('integrationTest', Test) { Test t ->
|
||||||
|
description = 'Runs integration tests'
|
||||||
|
group = 'verification'
|
||||||
|
|
||||||
|
useJUnitPlatform {
|
||||||
|
includeTags 'integration'
|
||||||
|
}
|
||||||
|
|
||||||
|
testClassesDirs = sourceSets.test.output.classesDirs
|
||||||
|
classpath = sourceSets.test.runtimeClasspath
|
||||||
|
|
||||||
|
reports {
|
||||||
|
junitXml.required = true
|
||||||
|
junitXml.outputPerTestCase = true
|
||||||
|
junitXml.mergeReruns = true
|
||||||
|
junitXml.includeSystemErrLog = true
|
||||||
|
junitXml.outputLocation = layout.buildDirectory.dir("test-results/test")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Integration tests typically not parallel (but you can enable)
|
||||||
|
maxParallelForks = 1
|
||||||
|
commonTestConfig(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register('unitTest', Test) { Test t ->
|
||||||
|
description = 'Runs unit tests'
|
||||||
|
group = 'verification'
|
||||||
|
|
||||||
|
useJUnitPlatform {
|
||||||
|
excludeTags 'flaky', 'integration'
|
||||||
|
}
|
||||||
|
|
||||||
|
testClassesDirs = sourceSets.test.output.classesDirs
|
||||||
|
classpath = sourceSets.test.runtimeClasspath
|
||||||
|
|
||||||
|
reports {
|
||||||
|
junitXml.required = true
|
||||||
|
junitXml.outputPerTestCase = true
|
||||||
|
junitXml.mergeReruns = true
|
||||||
|
junitXml.includeSystemErrLog = true
|
||||||
|
junitXml.outputLocation = layout.buildDirectory.dir("test-results/test")
|
||||||
|
}
|
||||||
|
|
||||||
|
commonTestConfig(t)
|
||||||
|
}
|
||||||
|
|
||||||
tasks.register('flakyTest', Test) { Test t ->
|
tasks.register('flakyTest', Test) { Test t ->
|
||||||
group = 'verification'
|
group = 'verification'
|
||||||
description = 'Runs tests tagged @Flaky but does not fail the build.'
|
description = 'Runs tests tagged @Flaky but does not fail the build.'
|
||||||
@@ -239,7 +302,6 @@ subprojects {subProj ->
|
|||||||
useJUnitPlatform {
|
useJUnitPlatform {
|
||||||
includeTags 'flaky'
|
includeTags 'flaky'
|
||||||
}
|
}
|
||||||
ignoreFailures = true
|
|
||||||
|
|
||||||
reports {
|
reports {
|
||||||
junitXml.required = true
|
junitXml.required = true
|
||||||
@@ -249,10 +311,13 @@ subprojects {subProj ->
|
|||||||
junitXml.outputLocation = layout.buildDirectory.dir("test-results/flakyTest")
|
junitXml.outputLocation = layout.buildDirectory.dir("test-results/flakyTest")
|
||||||
}
|
}
|
||||||
commonTestConfig(t)
|
commonTestConfig(t)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
// test task (default)
|
||||||
|
tasks.named('test', Test) { Test t ->
|
||||||
|
group = 'verification'
|
||||||
|
description = 'Runs all non-flaky tests.'
|
||||||
|
|
||||||
useJUnitPlatform {
|
useJUnitPlatform {
|
||||||
excludeTags 'flaky'
|
excludeTags 'flaky'
|
||||||
}
|
}
|
||||||
@@ -263,10 +328,12 @@ subprojects {subProj ->
|
|||||||
junitXml.includeSystemErrLog = true
|
junitXml.includeSystemErrLog = true
|
||||||
junitXml.outputLocation = layout.buildDirectory.dir("test-results/test")
|
junitXml.outputLocation = layout.buildDirectory.dir("test-results/test")
|
||||||
}
|
}
|
||||||
commonTestConfig(it)
|
commonTestConfig(t)
|
||||||
|
jvmArgs = ["-javaagent:${configurations.agent.singleFile}"]
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named('check') {
|
||||||
finalizedBy(tasks.named('flakyTest'))
|
dependsOn(tasks.named('test'))// default behaviour
|
||||||
}
|
}
|
||||||
|
|
||||||
testlogger {
|
testlogger {
|
||||||
@@ -282,83 +349,25 @@ subprojects {subProj ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************************\
|
|
||||||
* End-to-End Tests
|
|
||||||
**********************************************************************************************************************/
|
|
||||||
def e2eTestsCheck = tasks.register('e2eTestsCheck') {
|
|
||||||
group = 'verification'
|
|
||||||
description = "Runs the 'check' task for all e2e-tests modules"
|
|
||||||
doFirst {
|
|
||||||
project.ext.set("e2e-tests", true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subprojects {
|
|
||||||
// Add e2e-tests modules check tasks to e2eTestsCheck
|
|
||||||
if (project.name.startsWith("e2e-tests")) {
|
|
||||||
test {
|
|
||||||
onlyIf {
|
|
||||||
project.hasProperty("e2e-tests")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEvaluate {
|
|
||||||
// Add e2e-tests modules check tasks to e2eTestsCheck
|
|
||||||
if (project.name.startsWith("e2e-tests")) {
|
|
||||||
e2eTestsCheck.configure {
|
|
||||||
finalizedBy(check)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************************************************************\
|
|
||||||
* Allure Reports
|
|
||||||
**********************************************************************************************************************/
|
|
||||||
subprojects {
|
|
||||||
if (it.name != 'platform' && it.name != 'jmh-benchmarks') {
|
|
||||||
dependencies {
|
|
||||||
testImplementation platform("io.qameta.allure:allure-bom")
|
|
||||||
testImplementation "io.qameta.allure:allure-junit5"
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
agent {
|
|
||||||
canBeResolved = true
|
|
||||||
canBeConsumed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
agent "org.aspectj:aspectjweaver:1.9.25.1"
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
jvmArgs = ["-javaagent:${configurations.agent.singleFile}"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************************************************************\
|
|
||||||
* Jacoco
|
|
||||||
**********************************************************************************************************************/
|
|
||||||
subprojects {
|
|
||||||
if (it.name != 'platform' && it.name != 'jmh-benchmarks') {
|
|
||||||
apply plugin: 'jacoco'
|
|
||||||
|
|
||||||
test {
|
|
||||||
finalizedBy jacocoTestReport
|
|
||||||
}
|
|
||||||
|
|
||||||
jacocoTestReport {
|
|
||||||
dependsOn test
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named('check') {
|
tasks.named('check') {
|
||||||
dependsOn tasks.named('testCodeCoverageReport', JacocoReport)
|
dependsOn tasks.named('testCodeCoverageReport', JacocoReport)
|
||||||
|
finalizedBy jacocoTestReport
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register('unitTest') {
|
||||||
|
// No jacocoTestReport here, because it depends by default on :test,
|
||||||
|
// and that would make :test being run twice in our CI.
|
||||||
|
// In practice the report will be generated later in the CI by :check.
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register('integrationTest') {
|
||||||
|
dependsOn tasks.named('testCodeCoverageReport', JacocoReport)
|
||||||
|
finalizedBy jacocoTestReport
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register('flakyTest') {
|
||||||
|
dependsOn tasks.named('testCodeCoverageReport', JacocoReport)
|
||||||
|
finalizedBy jacocoTestReport
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('testCodeCoverageReport') {
|
tasks.named('testCodeCoverageReport') {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import io.micronaut.configuration.picocli.PicocliRunner;
|
|||||||
import io.micronaut.context.ApplicationContext;
|
import io.micronaut.context.ApplicationContext;
|
||||||
import io.micronaut.context.env.Environment;
|
import io.micronaut.context.env.Environment;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -15,7 +14,6 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@@ -25,7 +23,8 @@ class PluginDocCommandTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void run() throws IOException, URISyntaxException {
|
void run() throws IOException, URISyntaxException {
|
||||||
Path pluginsPath = Files.createTempDirectory(PluginListCommandTest.class.getSimpleName());
|
var testDirectoryName = PluginListCommandTest.class.getSimpleName();
|
||||||
|
Path pluginsPath = Files.createTempDirectory(testDirectoryName + "_pluginsPath_");
|
||||||
pluginsPath.toFile().deleteOnExit();
|
pluginsPath.toFile().deleteOnExit();
|
||||||
|
|
||||||
FileUtils.copyFile(
|
FileUtils.copyFile(
|
||||||
@@ -34,7 +33,7 @@ class PluginDocCommandTest {
|
|||||||
new File(URI.create("file://" + pluginsPath.toAbsolutePath() + "/" + PLUGIN_TEMPLATE_TEST))
|
new File(URI.create("file://" + pluginsPath.toAbsolutePath() + "/" + PLUGIN_TEMPLATE_TEST))
|
||||||
);
|
);
|
||||||
|
|
||||||
Path docPath = Files.createTempDirectory(PluginInstallCommandTest.class.getSimpleName());
|
Path docPath = Files.createTempDirectory(testDirectoryName + "_docPath_");
|
||||||
docPath.toFile().deleteOnExit();
|
docPath.toFile().deleteOnExit();
|
||||||
|
|
||||||
try (ApplicationContext ctx = ApplicationContext.run(Environment.CLI, Environment.TEST)) {
|
try (ApplicationContext ctx = ApplicationContext.run(Environment.CLI, Environment.TEST)) {
|
||||||
@@ -43,9 +42,9 @@ class PluginDocCommandTest {
|
|||||||
|
|
||||||
List<Path> files = Files.list(docPath).toList();
|
List<Path> files = Files.list(docPath).toList();
|
||||||
|
|
||||||
assertThat(files.size()).isEqualTo(1);
|
assertThat(files.stream().map(path -> path.getFileName().toString())).contains("plugin-template-test");
|
||||||
assertThat(files.getFirst().getFileName().toString()).isEqualTo("plugin-template-test");
|
// don't know why, but sometimes there is an addition "plugin-notifications" directory present
|
||||||
var directory = files.getFirst().toFile();
|
var directory = files.stream().filter(path -> "plugin-template-test".equals(path.getFileName().toString())).findFirst().get().toFile();
|
||||||
assertThat(directory.isDirectory()).isTrue();
|
assertThat(directory.isDirectory()).isTrue();
|
||||||
assertThat(directory.listFiles().length).isEqualTo(3);
|
assertThat(directory.listFiles().length).isEqualTo(3);
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,12 @@ public record QueryFilter(
|
|||||||
return List.of(Op.EQUALS, Op.NOT_EQUALS, Op.CONTAINS, Op.STARTS_WITH, Op.ENDS_WITH, Op.IN, Op.NOT_IN);
|
return List.of(Op.EQUALS, Op.NOT_EQUALS, Op.CONTAINS, Op.STARTS_WITH, Op.ENDS_WITH, Op.IN, Op.NOT_IN);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
TRIGGER_STATE("triggerState"){
|
||||||
|
@Override
|
||||||
|
public List<Op> supportedOp() {
|
||||||
|
return List.of(Op.EQUALS, Op.NOT_EQUALS);
|
||||||
|
}
|
||||||
|
},
|
||||||
EXECUTION_ID("executionId") {
|
EXECUTION_ID("executionId") {
|
||||||
@Override
|
@Override
|
||||||
public List<Op> supportedOp() {
|
public List<Op> supportedOp() {
|
||||||
@@ -271,7 +277,7 @@ public record QueryFilter(
|
|||||||
@Override
|
@Override
|
||||||
public List<Field> supportedField() {
|
public List<Field> supportedField() {
|
||||||
return List.of(Field.QUERY, Field.SCOPE, Field.NAMESPACE, Field.WORKER_ID, Field.FLOW_ID,
|
return List.of(Field.QUERY, Field.SCOPE, Field.NAMESPACE, Field.WORKER_ID, Field.FLOW_ID,
|
||||||
Field.START_DATE, Field.END_DATE, Field.TRIGGER_ID
|
Field.START_DATE, Field.END_DATE, Field.TRIGGER_ID, Field.TRIGGER_STATE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package io.kestra.core.plugins.notifications;
|
||||||
|
|
||||||
|
import io.kestra.core.models.property.Property;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface ExecutionInterface {
|
||||||
|
@Schema(
|
||||||
|
title = "The execution id to use",
|
||||||
|
description = "Default is the current execution, " +
|
||||||
|
"change it to {{ trigger.executionId }} if you use this task with a Flow trigger to use the original execution."
|
||||||
|
)
|
||||||
|
Property<String> getExecutionId();
|
||||||
|
|
||||||
|
@Schema(
|
||||||
|
title = "Custom fields to be added on notification"
|
||||||
|
)
|
||||||
|
Property<Map<String, Object>> getCustomFields();
|
||||||
|
|
||||||
|
@Schema(
|
||||||
|
title = "Custom message to be added on notification"
|
||||||
|
)
|
||||||
|
Property<String> getCustomMessage();
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
package io.kestra.core.plugins.notifications;
|
||||||
|
|
||||||
|
import io.kestra.core.exceptions.IllegalVariableEvaluationException;
|
||||||
|
import io.kestra.core.models.executions.Execution;
|
||||||
|
import io.kestra.core.models.executions.TaskRun;
|
||||||
|
import io.kestra.core.models.flows.State;
|
||||||
|
import io.kestra.core.models.property.Property;
|
||||||
|
import io.kestra.core.models.tasks.retrys.Exponential;
|
||||||
|
import io.kestra.core.repositories.ExecutionRepositoryInterface;
|
||||||
|
import io.kestra.core.runners.DefaultRunContext;
|
||||||
|
import io.kestra.core.runners.RunContext;
|
||||||
|
import io.kestra.core.serializers.JacksonMapper;
|
||||||
|
import io.kestra.core.utils.ListUtils;
|
||||||
|
import io.kestra.core.utils.RetryUtils;
|
||||||
|
import io.kestra.core.utils.UriProvider;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public final class ExecutionService {
|
||||||
|
private ExecutionService() {}
|
||||||
|
|
||||||
|
public static Execution findExecution(RunContext runContext, Property<String> executionId) throws IllegalVariableEvaluationException, NoSuchElementException {
|
||||||
|
ExecutionRepositoryInterface executionRepository = ((DefaultRunContext) runContext).getApplicationContext().getBean(ExecutionRepositoryInterface.class);
|
||||||
|
|
||||||
|
RetryUtils.Instance<Execution, NoSuchElementException> retryInstance = RetryUtils
|
||||||
|
.of(Exponential.builder()
|
||||||
|
.delayFactor(2.0)
|
||||||
|
.interval(Duration.ofSeconds(1))
|
||||||
|
.maxInterval(Duration.ofSeconds(15))
|
||||||
|
.maxAttempts(-1)
|
||||||
|
.maxDuration(Duration.ofMinutes(10))
|
||||||
|
.build(),
|
||||||
|
runContext.logger()
|
||||||
|
);
|
||||||
|
|
||||||
|
var executionRendererId = runContext.render(executionId).as(String.class).orElse(null);
|
||||||
|
var flowTriggerExecutionState = getOptionalFlowTriggerExecutionState(runContext);
|
||||||
|
|
||||||
|
var flowVars = (Map<String, String>) runContext.getVariables().get("flow");
|
||||||
|
var isCurrentExecution = isCurrentExecution(runContext, executionRendererId);
|
||||||
|
if (isCurrentExecution) {
|
||||||
|
runContext.logger().info("Loading execution data for the current execution.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return retryInstance.run(
|
||||||
|
NoSuchElementException.class,
|
||||||
|
() -> executionRepository.findById(flowVars.get("tenantId"), executionRendererId)
|
||||||
|
.filter(foundExecution -> isExecutionInTheWantedState(foundExecution, isCurrentExecution, flowTriggerExecutionState))
|
||||||
|
.orElseThrow(() -> new NoSuchElementException("Unable to find execution '" + executionRendererId + "'"))
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ExecutionRepository can be out of sync in ElasticSearch stack, with this filter we try to mitigate that
|
||||||
|
*
|
||||||
|
* @param execution the Execution we fetched from ExecutionRepository
|
||||||
|
* @param isCurrentExecution true if this *Execution Task is configured to send a notification for the current Execution
|
||||||
|
* @param flowTriggerExecutionState the Execution State that triggered the Flow trigger, if any
|
||||||
|
* @return true if we think we fetched the right Execution data for our usecase
|
||||||
|
*/
|
||||||
|
public static boolean isExecutionInTheWantedState(Execution execution, boolean isCurrentExecution, Optional<String> flowTriggerExecutionState) {
|
||||||
|
if (isCurrentExecution) {
|
||||||
|
// we don't wait for current execution to be terminated as it could not be possible as long as this task is running
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flowTriggerExecutionState.isPresent()) {
|
||||||
|
// we were triggered by a Flow trigger that can be, for example: PAUSED
|
||||||
|
if (flowTriggerExecutionState.get().equals(State.Type.RUNNING.toString())) {
|
||||||
|
// RUNNING special case: we take the first state we got
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// to handle the case where the ExecutionRepository is out of sync in ElasticSearch stack,
|
||||||
|
// we try to match an Execution with the same state
|
||||||
|
return execution.getState().getCurrent().name().equals(flowTriggerExecutionState.get());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return execution.getState().getCurrent().isTerminated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Object> executionMap(RunContext runContext, ExecutionInterface executionInterface) throws IllegalVariableEvaluationException {
|
||||||
|
Execution execution = findExecution(runContext, executionInterface.getExecutionId());
|
||||||
|
UriProvider uriProvider = ((DefaultRunContext) runContext).getApplicationContext().getBean(UriProvider.class);
|
||||||
|
|
||||||
|
Map<String, Object> templateRenderMap = new HashMap<>();
|
||||||
|
templateRenderMap.put("duration", execution.getState().humanDuration());
|
||||||
|
templateRenderMap.put("startDate", execution.getState().getStartDate());
|
||||||
|
templateRenderMap.put("link", uriProvider.executionUrl(execution));
|
||||||
|
templateRenderMap.put("execution", JacksonMapper.toMap(execution));
|
||||||
|
|
||||||
|
runContext.render(executionInterface.getCustomMessage())
|
||||||
|
.as(String.class)
|
||||||
|
.ifPresent(s -> templateRenderMap.put("customMessage", s));
|
||||||
|
|
||||||
|
final Map<String, Object> renderedCustomFields = runContext.render(executionInterface.getCustomFields()).asMap(String.class, Object.class);
|
||||||
|
if (!renderedCustomFields.isEmpty()) {
|
||||||
|
templateRenderMap.put("customFields", renderedCustomFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
var isCurrentExecution = isCurrentExecution(runContext, execution.getId());
|
||||||
|
|
||||||
|
List<TaskRun> taskRuns;
|
||||||
|
|
||||||
|
if (isCurrentExecution) {
|
||||||
|
taskRuns = execution.getTaskRunList();
|
||||||
|
} else {
|
||||||
|
taskRuns = execution.getTaskRunList().stream()
|
||||||
|
.filter(t -> (execution.hasFailed() ? State.Type.FAILED : State.Type.SUCCESS).equals(t.getState().getCurrent()))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ListUtils.isEmpty(taskRuns)) {
|
||||||
|
TaskRun lastTaskRun = taskRuns.getLast();
|
||||||
|
templateRenderMap.put("firstFailed", State.Type.FAILED.equals(lastTaskRun.getState().getCurrent()) ? lastTaskRun : false);
|
||||||
|
templateRenderMap.put("lastTask", lastTaskRun);
|
||||||
|
}
|
||||||
|
|
||||||
|
return templateRenderMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if there is a state, we assume this is a Flow trigger with type: {@link io.kestra.plugin.core.trigger.Flow.Output}
|
||||||
|
*
|
||||||
|
* @return the state of the execution that triggered the Flow trigger, or empty if another usecase/trigger
|
||||||
|
*/
|
||||||
|
private static Optional<String> getOptionalFlowTriggerExecutionState(RunContext runContext) {
|
||||||
|
var triggerVar = Optional.ofNullable(
|
||||||
|
runContext.getVariables().get("trigger")
|
||||||
|
);
|
||||||
|
return triggerVar.map(trigger -> ((Map<String, String>) trigger).get("state"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isCurrentExecution(RunContext runContext, String executionId) {
|
||||||
|
var executionVars = (Map<String, String>) runContext.getVariables().get("execution");
|
||||||
|
return executionId.equals(executionVars.get("id"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import io.kestra.core.models.dashboards.charts.DataChart;
|
|||||||
import io.kestra.core.plugins.DefaultPluginRegistry;
|
import io.kestra.core.plugins.DefaultPluginRegistry;
|
||||||
import io.kestra.core.plugins.PluginRegistry;
|
import io.kestra.core.plugins.PluginRegistry;
|
||||||
import io.kestra.core.serializers.JacksonMapper;
|
import io.kestra.core.serializers.JacksonMapper;
|
||||||
|
import io.micronaut.context.exceptions.NoSuchBeanException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ public final class PluginDeserializer<T extends Plugin> extends JsonDeserializer
|
|||||||
// By default, if no plugin-registry is configured retrieve
|
// By default, if no plugin-registry is configured retrieve
|
||||||
// the one configured from the static Kestra's context.
|
// the one configured from the static Kestra's context.
|
||||||
pluginRegistry = KestraContext.getContext().getPluginRegistry();
|
pluginRegistry = KestraContext.getContext().getPluginRegistry();
|
||||||
} catch (IllegalStateException ignore) {
|
} catch (IllegalStateException | NoSuchBeanException ignore) {
|
||||||
// This error can only happen if the KestraContext is not initialized (i.e. in unit tests).
|
// This error can only happen if the KestraContext is not initialized (i.e. in unit tests).
|
||||||
log.error("No plugin registry was initialized. Use default implementation.");
|
log.error("No plugin registry was initialized. Use default implementation.");
|
||||||
pluginRegistry = DefaultPluginRegistry.getOrCreate();
|
pluginRegistry = DefaultPluginRegistry.getOrCreate();
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE triggers
|
||||||
|
ADD COLUMN "disabled" BOOL
|
||||||
|
GENERATED ALWAYS AS (JQ_BOOLEAN("value", '.disabled')) NOT NULL;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE triggers
|
||||||
|
ADD COLUMN `disabled` BOOL
|
||||||
|
GENERATED ALWAYS AS (value ->> '$.disabled' = 'true') STORED NOT NULL
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE triggers
|
||||||
|
ADD COLUMN "disabled" BOOL
|
||||||
|
GENERATED ALWAYS AS (CAST(value ->> 'disabled' AS BOOL)) STORED NOT NULL;
|
||||||
|
|
||||||
@@ -324,6 +324,10 @@ public abstract class AbstractJdbcRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(field == QueryFilter.Field.TRIGGER_STATE){
|
||||||
|
return applyTriggerStateCondition(value, operation);
|
||||||
|
}
|
||||||
|
|
||||||
// Convert the field name to lowercase and quote it
|
// Convert the field name to lowercase and quote it
|
||||||
Name columnName = getColumnName(field);
|
Name columnName = getColumnName(field);
|
||||||
|
|
||||||
@@ -341,7 +345,7 @@ public abstract class AbstractJdbcRepository {
|
|||||||
case CONTAINS -> DSL.field(columnName).like("%" + value + "%");
|
case CONTAINS -> DSL.field(columnName).like("%" + value + "%");
|
||||||
case REGEX -> DSL.field(columnName).likeRegex((String) value);
|
case REGEX -> DSL.field(columnName).likeRegex((String) value);
|
||||||
case PREFIX -> DSL.field(columnName).like(value + "%")
|
case PREFIX -> DSL.field(columnName).like(value + "%")
|
||||||
.or(DSL.field(columnName).eq(value));
|
.or(DSL.field(columnName).eq(value));
|
||||||
default -> throw new InvalidQueryFiltersException("Unsupported operation: " + operation);
|
default -> throw new InvalidQueryFiltersException("Unsupported operation: " + operation);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -469,6 +473,23 @@ public abstract class AbstractJdbcRepository {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Condition applyTriggerStateCondition(Object value, QueryFilter.Op operation) {
|
||||||
|
String triggerState = value.toString();
|
||||||
|
Boolean isDisabled = switch (triggerState) {
|
||||||
|
case "disabled" -> true;
|
||||||
|
case "enabled" -> false;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
if (isDisabled == null) {
|
||||||
|
return DSL.noCondition();
|
||||||
|
}
|
||||||
|
return switch (operation) {
|
||||||
|
case EQUALS -> field("disabled").eq(isDisabled);
|
||||||
|
case NOT_EQUALS -> field("disabled").ne(isDisabled);
|
||||||
|
default -> throw new InvalidQueryFiltersException("Unsupported operation for Trigger State: " + operation);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected Field<Date> formatDateField(String dateField, DateUtils.GroupType groupType) {
|
protected Field<Date> formatDateField(String dateField, DateUtils.GroupType groupType) {
|
||||||
throw new UnsupportedOperationException("formatDateField() not implemented");
|
throw new UnsupportedOperationException("formatDateField() not implemented");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ import io.micronaut.context.annotation.Factory;
|
|||||||
import io.micronaut.context.annotation.Requires;
|
import io.micronaut.context.annotation.Requires;
|
||||||
import io.micronaut.test.annotation.TransactionMode;
|
import io.micronaut.test.annotation.TransactionMode;
|
||||||
import io.micronaut.test.condition.TestActiveCondition;
|
import io.micronaut.test.condition.TestActiveCondition;
|
||||||
|
import org.junit.jupiter.api.Tag;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Tag("integration")
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
|
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
|
||||||
@ExtendWith(KestraTestExtension.class)
|
@ExtendWith(KestraTestExtension.class)
|
||||||
|
|||||||
@@ -8,25 +8,31 @@ import io.micronaut.test.extensions.junit5.MicronautJunit5Extension;
|
|||||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||||
import org.junit.platform.commons.support.AnnotationSupport;
|
import org.junit.platform.commons.support.AnnotationSupport;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class KestraTestExtension extends MicronautJunit5Extension {
|
public class KestraTestExtension extends MicronautJunit5Extension {
|
||||||
@Override
|
@Override
|
||||||
protected MicronautTestValue buildMicronautTestValue(Class<?> testClass) {
|
protected MicronautTestValue buildMicronautTestValue(Class<?> testClass) {
|
||||||
testProperties.put("kestra.jdbc.executor.thread-count", Runtime.getRuntime().availableProcessors() * 4);
|
testProperties.put("kestra.jdbc.executor.thread-count", Runtime.getRuntime().availableProcessors() * 4);
|
||||||
return AnnotationSupport
|
return AnnotationSupport
|
||||||
.findAnnotation(testClass, KestraTest.class)
|
.findAnnotation(testClass, KestraTest.class)
|
||||||
.map(kestraTestAnnotation -> new MicronautTestValue(
|
.map(kestraTestAnnotation -> {
|
||||||
kestraTestAnnotation.application(),
|
var envsSet = new java.util.HashSet<>(Set.of(kestraTestAnnotation.environments()));
|
||||||
kestraTestAnnotation.environments(),
|
envsSet.add("test");// add test env if not already present
|
||||||
kestraTestAnnotation.packages(),
|
return new MicronautTestValue(
|
||||||
kestraTestAnnotation.propertySources(),
|
kestraTestAnnotation.application(),
|
||||||
kestraTestAnnotation.rollback(),
|
envsSet.toArray(new String[0]),
|
||||||
kestraTestAnnotation.transactional(),
|
kestraTestAnnotation.packages(),
|
||||||
kestraTestAnnotation.rebuildContext(),
|
kestraTestAnnotation.propertySources(),
|
||||||
kestraTestAnnotation.contextBuilder(),
|
kestraTestAnnotation.rollback(),
|
||||||
kestraTestAnnotation.transactionMode(),
|
kestraTestAnnotation.transactional(),
|
||||||
kestraTestAnnotation.startApplication(),
|
kestraTestAnnotation.rebuildContext(),
|
||||||
kestraTestAnnotation.resolveParameters()
|
kestraTestAnnotation.contextBuilder(),
|
||||||
))
|
kestraTestAnnotation.transactionMode(),
|
||||||
|
kestraTestAnnotation.startApplication(),
|
||||||
|
kestraTestAnnotation.resolveParameters()
|
||||||
|
);
|
||||||
|
})
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3108
ui/package-lock.json
generated
3108
ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@
|
|||||||
"@kestra-io/ui-libs": "^0.0.268",
|
"@kestra-io/ui-libs": "^0.0.268",
|
||||||
"@vue-flow/background": "^1.3.2",
|
"@vue-flow/background": "^1.3.2",
|
||||||
"@vue-flow/controls": "^1.1.2",
|
"@vue-flow/controls": "^1.1.2",
|
||||||
"@vue-flow/core": "^1.48.0",
|
"@vue-flow/core": "^1.48.1",
|
||||||
"@vueuse/core": "^14.1.0",
|
"@vueuse/core": "^14.1.0",
|
||||||
"ansi-to-html": "^0.7.2",
|
"ansi-to-html": "^0.7.2",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
"cytoscape": "^3.33.0",
|
"cytoscape": "^3.33.0",
|
||||||
"dagre": "^0.8.5",
|
"dagre": "^0.8.5",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"element-plus": "2.12.0",
|
"element-plus": "2.13.0",
|
||||||
"humanize-duration": "^3.33.2",
|
"humanize-duration": "^3.33.2",
|
||||||
"js-yaml": "^4.1.1",
|
"js-yaml": "^4.1.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -59,15 +59,15 @@
|
|||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"pdfjs-dist": "^5.4.449",
|
"pdfjs-dist": "^5.4.449",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
"posthog-js": "^1.308.0",
|
"posthog-js": "^1.310.1",
|
||||||
"rapidoc": "^9.3.8",
|
"rapidoc": "^9.3.8",
|
||||||
"semver": "^7.7.3",
|
"semver": "^7.7.3",
|
||||||
"shiki": "^3.20.0",
|
"shiki": "^3.20.0",
|
||||||
"vue": "^3.5.25",
|
"vue": "^3.5.26",
|
||||||
"vue-axios": "^3.5.2",
|
"vue-axios": "^3.5.2",
|
||||||
"vue-chartjs": "^5.3.3",
|
"vue-chartjs": "^5.3.3",
|
||||||
"vue-gtag": "^3.6.3",
|
"vue-gtag": "^3.6.3",
|
||||||
"vue-i18n": "^11.2.2",
|
"vue-i18n": "^11.2.7",
|
||||||
"vue-material-design-icons": "^5.3.1",
|
"vue-material-design-icons": "^5.3.1",
|
||||||
"vue-router": "^4.6.4",
|
"vue-router": "^4.6.4",
|
||||||
"vue-sidebar-menu": "^5.9.1",
|
"vue-sidebar-menu": "^5.9.1",
|
||||||
@@ -97,9 +97,9 @@
|
|||||||
"@types/semver": "^7.7.1",
|
"@types/semver": "^7.7.1",
|
||||||
"@types/testing-library__jest-dom": "^6.0.0",
|
"@types/testing-library__jest-dom": "^6.0.0",
|
||||||
"@types/testing-library__user-event": "^4.2.0",
|
"@types/testing-library__user-event": "^4.2.0",
|
||||||
"@typescript-eslint/parser": "^8.50.0",
|
"@typescript-eslint/parser": "^8.50.1",
|
||||||
"@vitejs/plugin-vue": "^6.0.3",
|
"@vitejs/plugin-vue": "^6.0.3",
|
||||||
"@vitejs/plugin-vue-jsx": "^5.1.2",
|
"@vitejs/plugin-vue-jsx": "^5.1.3",
|
||||||
"@vitest/browser": "^3.2.4",
|
"@vitest/browser": "^3.2.4",
|
||||||
"@vitest/coverage-v8": "^3.2.4",
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"@vue/eslint-config-prettier": "^10.2.0",
|
"@vue/eslint-config-prettier": "^10.2.0",
|
||||||
@@ -120,29 +120,29 @@
|
|||||||
"playwright": "^1.55.0",
|
"playwright": "^1.55.0",
|
||||||
"prettier": "^3.7.4",
|
"prettier": "^3.7.4",
|
||||||
"rimraf": "^6.1.2",
|
"rimraf": "^6.1.2",
|
||||||
"rolldown-vite": "^7.2.11",
|
"rolldown-vite": "^7.3.0",
|
||||||
"rollup-plugin-copy": "^3.5.0",
|
"rollup-plugin-copy": "^3.5.0",
|
||||||
"sass": "^1.97.0",
|
"sass": "^1.97.1",
|
||||||
"storybook": "^9.1.16",
|
"storybook": "^9.1.17",
|
||||||
"storybook-vue3-router": "^6.0.2",
|
"storybook-vue3-router": "^6.0.2",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"typescript-eslint": "^8.50.0",
|
"typescript-eslint": "^8.50.1",
|
||||||
"uuid": "^13.0.0",
|
"uuid": "^13.0.0",
|
||||||
"vite": "npm:rolldown-vite@latest",
|
"vite": "npm:rolldown-vite@latest",
|
||||||
"vitest": "^3.2.4",
|
"vitest": "^3.2.4",
|
||||||
"vue-tsc": "^3.1.8"
|
"vue-tsc": "^3.2.1"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@esbuild/darwin-arm64": "^0.27.2",
|
"@esbuild/darwin-arm64": "^0.27.2",
|
||||||
"@esbuild/darwin-x64": "^0.27.2",
|
"@esbuild/darwin-x64": "^0.27.2",
|
||||||
"@esbuild/linux-x64": "^0.27.2",
|
"@esbuild/linux-x64": "^0.27.2",
|
||||||
"@rollup/rollup-darwin-arm64": "^4.53.5",
|
"@rollup/rollup-darwin-arm64": "^4.54.0",
|
||||||
"@rollup/rollup-darwin-x64": "^4.53.5",
|
"@rollup/rollup-darwin-x64": "^4.54.0",
|
||||||
"@rollup/rollup-linux-x64-gnu": "^4.53.5",
|
"@rollup/rollup-linux-x64-gnu": "^4.54.0",
|
||||||
"@swc/core-darwin-arm64": "^1.15.5",
|
"@swc/core-darwin-arm64": "^1.15.7",
|
||||||
"@swc/core-darwin-x64": "^1.15.5",
|
"@swc/core-darwin-x64": "^1.15.7",
|
||||||
"@swc/core-linux-x64-gnu": "^1.15.5"
|
"@swc/core-linux-x64-gnu": "^1.15.7"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"bootstrap": {
|
"bootstrap": {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
REF_PATH_INJECTION_KEY,
|
REF_PATH_INJECTION_KEY,
|
||||||
ROOT_SCHEMA_INJECTION_KEY,
|
ROOT_SCHEMA_INJECTION_KEY,
|
||||||
SCHEMA_DEFINITIONS_INJECTION_KEY,
|
SCHEMA_DEFINITIONS_INJECTION_KEY,
|
||||||
UPDATE_TASK_FUNCTION_INJECTION_KEY
|
UPDATE_YAML_FUNCTION_INJECTION_KEY
|
||||||
} from "../../no-code/injectionKeys";
|
} from "../../no-code/injectionKeys";
|
||||||
import {NoCodeProps} from "../../flows/noCodeTypes";
|
import {NoCodeProps} from "../../flows/noCodeTypes";
|
||||||
import {deepEqual} from "../../../utils/utils";
|
import {deepEqual} from "../../../utils/utils";
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
dashboardStore.sourceCode = YAML_UTILS.stringify(app);
|
dashboardStore.sourceCode = YAML_UTILS.stringify(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
provide(UPDATE_TASK_FUNCTION_INJECTION_KEY, (yaml) => {
|
provide(UPDATE_YAML_FUNCTION_INJECTION_KEY, (yaml) => {
|
||||||
editorUpdate(yaml)
|
editorUpdate(yaml)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -103,6 +103,10 @@ export function useValues(label: string | undefined, t?: ReturnType<typeof useI1
|
|||||||
STATUSES: buildFromArray(["PENDING", "ACCEPTED", "EXPIRED"]),
|
STATUSES: buildFromArray(["PENDING", "ACCEPTED", "EXPIRED"]),
|
||||||
AGGREGATIONS: buildFromArray(["SUM", "AVG", "MIN", "MAX"]),
|
AGGREGATIONS: buildFromArray(["SUM", "AVG", "MIN", "MAX"]),
|
||||||
RELATIVE_DATE,
|
RELATIVE_DATE,
|
||||||
|
TRIGGER_STATES:[
|
||||||
|
{label: t("filter.triggerState.enabled"), value: "enabled"},
|
||||||
|
{label: t("filter.triggerState.disabled"), value: "disabled"}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
return {VALUES, getRelativeDateLabel};
|
return {VALUES, getRelativeDateLabel};
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ export const useTriggerFilter = (): ComputedRef<FilterConfiguration> => {
|
|||||||
return [...current, `${(previousCombination ? previousCombination + "." : "")}${part}`];
|
return [...current, `${(previousCombination ? previousCombination + "." : "")}${part}`];
|
||||||
}, []);
|
}, []);
|
||||||
}))].map(namespace => ({
|
}))].map(namespace => ({
|
||||||
label: namespace,
|
label: namespace,
|
||||||
value: namespace
|
value: namespace
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
@@ -116,8 +116,22 @@ export const useTriggerFilter = (): ComputedRef<FilterConfiguration> => {
|
|||||||
],
|
],
|
||||||
valueType: "text",
|
valueType: "text",
|
||||||
searchable: true,
|
searchable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "triggerState",
|
||||||
|
label: t("filter.triggerState.label"),
|
||||||
|
description: t("filter.triggerState.description"),
|
||||||
|
comparators: [
|
||||||
|
Comparators.EQUALS,
|
||||||
|
Comparators.NOT_EQUALS
|
||||||
|
],
|
||||||
|
valueType: "select",
|
||||||
|
valueProvider: async () => {
|
||||||
|
const {VALUES} = useValues("triggers");
|
||||||
|
return VALUES.TRIGGER_STATES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-tooltip placement="bottom" :content="t('playground.tooltip_persistence')">
|
<el-tooltip placement="bottom" :content="$t('playground.tooltip_persistence')">
|
||||||
<el-switch v-model="playgroundStore.enabled" :activeText="t('playground.toggle')" class="toggle" :class="{'is-active': playgroundStore.enabled}" />
|
<el-switch v-model="playgroundStore.enabled" :activeText="$t('playground.toggle')" class="toggle" :class="{'is-active': playgroundStore.enabled}" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {useI18n} from "vue-i18n";
|
|
||||||
import {usePlaygroundStore} from "../../stores/playground";
|
import {usePlaygroundStore} from "../../stores/playground";
|
||||||
|
|
||||||
const {t} = useI18n();
|
|
||||||
const playgroundStore = usePlaygroundStore();
|
const playgroundStore = usePlaygroundStore();
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<Keyboard />
|
<Keyboard />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<span class="fs-6">
|
<span class="fs-6">
|
||||||
{{ t("editor_shortcuts.label") }}
|
{{ $t("editor_shortcuts.label") }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-break">
|
<div class="text-break">
|
||||||
{{ t(command.description) }}
|
{{ $t(command.description) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -35,11 +35,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {useI18n} from "vue-i18n";
|
|
||||||
import Keyboard from "vue-material-design-icons/Keyboard.vue";
|
import Keyboard from "vue-material-design-icons/Keyboard.vue";
|
||||||
import {useKeyShortcuts} from "../../utils/useKeyShortcuts";
|
import {useKeyShortcuts} from "../../utils/useKeyShortcuts";
|
||||||
|
|
||||||
const {t} = useI18n();
|
|
||||||
const {isKeyShortcutsDialogShown} = useKeyShortcuts();
|
const {isKeyShortcutsDialogShown} = useKeyShortcuts();
|
||||||
|
|
||||||
const commands = [
|
const commands = [
|
||||||
|
|||||||
@@ -97,7 +97,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
computed,
|
computed,
|
||||||
getCurrentInstance,
|
|
||||||
h,
|
h,
|
||||||
inject,
|
inject,
|
||||||
onBeforeUnmount,
|
onBeforeUnmount,
|
||||||
@@ -126,7 +125,7 @@
|
|||||||
import uniqBy from "lodash/uniqBy";
|
import uniqBy from "lodash/uniqBy";
|
||||||
import {useI18n} from "vue-i18n";
|
import {useI18n} from "vue-i18n";
|
||||||
import {ElDatePicker} from "element-plus";
|
import {ElDatePicker} from "element-plus";
|
||||||
import {Moment} from "moment";
|
import moment, {Moment} from "moment";
|
||||||
import PlaceholderContentWidget from "../../composables/monaco/PlaceholderContentWidget";
|
import PlaceholderContentWidget from "../../composables/monaco/PlaceholderContentWidget";
|
||||||
import Utils from "../../utils/utils";
|
import Utils from "../../utils/utils";
|
||||||
import {hashCode} from "../../utils/global";
|
import {hashCode} from "../../utils/global";
|
||||||
@@ -137,7 +136,6 @@
|
|||||||
import EditorType = editor.EditorType;
|
import EditorType = editor.EditorType;
|
||||||
import {useRoute} from "vue-router";
|
import {useRoute} from "vue-router";
|
||||||
|
|
||||||
const currentInstance = getCurrentInstance()!;
|
|
||||||
const {t} = useI18n();
|
const {t} = useI18n();
|
||||||
|
|
||||||
const textAreaValue = computed({
|
const textAreaValue = computed({
|
||||||
@@ -371,8 +369,7 @@
|
|||||||
}
|
}
|
||||||
}, {deep: true});
|
}, {deep: true});
|
||||||
|
|
||||||
const nowMoment: Moment = currentInstance.appContext.config.globalProperties.$moment().startOf("day");
|
const nowMoment: Moment = moment().startOf("day");
|
||||||
|
|
||||||
function addedSuggestRows(mutations: MutationRecord[]) {
|
function addedSuggestRows(mutations: MutationRecord[]) {
|
||||||
return mutations.flatMap(({addedNodes}) => {
|
return mutations.flatMap(({addedNodes}) => {
|
||||||
const nodes = [...addedNodes];
|
const nodes = [...addedNodes];
|
||||||
@@ -461,7 +458,7 @@
|
|||||||
endColumn: wordAtPosition?.endColumn ?? position?.column
|
endColumn: wordAtPosition?.endColumn ?? position?.column
|
||||||
},
|
},
|
||||||
// We don't use the selectedDate directly because if user modifies the input value directly it doesn't work otherwise
|
// We don't use the selectedDate directly because if user modifies the input value directly it doesn't work otherwise
|
||||||
text: `${currentInstance.appContext.config.globalProperties.$moment(
|
text: `${moment(
|
||||||
datePicker.value!.$el.nextElementSibling.querySelector("input").value
|
datePicker.value!.$el.nextElementSibling.querySelector("input").value
|
||||||
).toISOString(true)} `,
|
).toISOString(true)} `,
|
||||||
forceMoveMarkers: true
|
forceMoveMarkers: true
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
id="side-menu"
|
id="side-menu"
|
||||||
:menu
|
:menu
|
||||||
@update:collapsed="onToggleCollapse"
|
@update:collapsed="onToggleCollapse"
|
||||||
width="268px"
|
width="280px"
|
||||||
:collapsed="collapsed"
|
:collapsed="collapsed"
|
||||||
linkComponentName="LeftMenuLink"
|
linkComponentName="LeftMenuLink"
|
||||||
hideToggle
|
hideToggle
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav class="d-flex align-items-center w-100 gap-3 top-bar">
|
<nav class="d-flex align-items-center w-100 gap-3 top-bar">
|
||||||
|
<SidebarToggleButton
|
||||||
|
v-if="layoutStore.sideMenuCollapsed"
|
||||||
|
@toggle="layoutStore.setSideMenuCollapsed(false)"
|
||||||
|
/>
|
||||||
<div class="d-flex flex-column flex-grow-1 flex-shrink-1 overflow-hidden top-title">
|
<div class="d-flex flex-column flex-grow-1 flex-shrink-1 overflow-hidden top-title">
|
||||||
<div class="d-flex align-items-end gap-2">
|
<div class="d-flex align-items-end gap-2">
|
||||||
<SidebarToggleButton
|
|
||||||
v-if="layoutStore.sideMenuCollapsed"
|
|
||||||
@toggle="layoutStore.setSideMenuCollapsed(false)"
|
|
||||||
/>
|
|
||||||
<div class="d-flex flex-column gap-2">
|
<div class="d-flex flex-column gap-2">
|
||||||
<el-breadcrumb v-if="breadcrumb">
|
<el-breadcrumb v-if="breadcrumb">
|
||||||
<el-breadcrumb-item v-for="(item, x) in breadcrumb" :key="x" :class="{'pe-none': item.disabled}">
|
<el-breadcrumb-item v-for="(item, x) in breadcrumb" :key="x" :class="{'pe-none': item.disabled}">
|
||||||
|
|||||||
@@ -43,7 +43,9 @@
|
|||||||
BLOCK_SCHEMA_PATH_INJECTION_KEY,
|
BLOCK_SCHEMA_PATH_INJECTION_KEY,
|
||||||
CLOSE_TASK_FUNCTION_INJECTION_KEY,
|
CLOSE_TASK_FUNCTION_INJECTION_KEY,
|
||||||
CREATE_TASK_FUNCTION_INJECTION_KEY,
|
CREATE_TASK_FUNCTION_INJECTION_KEY,
|
||||||
|
CREATING_FLOW_INJECTION_KEY,
|
||||||
CREATING_TASK_INJECTION_KEY,
|
CREATING_TASK_INJECTION_KEY,
|
||||||
|
DEFAULT_NAMESPACE_INJECTION_KEY,
|
||||||
EDIT_TASK_FUNCTION_INJECTION_KEY,
|
EDIT_TASK_FUNCTION_INJECTION_KEY,
|
||||||
EDITING_TASK_INJECTION_KEY,
|
EDITING_TASK_INJECTION_KEY,
|
||||||
FIELDNAME_INJECTION_KEY,
|
FIELDNAME_INJECTION_KEY,
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
REF_PATH_INJECTION_KEY,
|
REF_PATH_INJECTION_KEY,
|
||||||
ROOT_SCHEMA_INJECTION_KEY,
|
ROOT_SCHEMA_INJECTION_KEY,
|
||||||
SCHEMA_DEFINITIONS_INJECTION_KEY,
|
SCHEMA_DEFINITIONS_INJECTION_KEY,
|
||||||
UPDATE_TASK_FUNCTION_INJECTION_KEY,
|
UPDATE_YAML_FUNCTION_INJECTION_KEY,
|
||||||
} from "./injectionKeys";
|
} from "./injectionKeys";
|
||||||
import {useFlowFields, SECTIONS_IDS} from "./utils/useFlowFields";
|
import {useFlowFields, SECTIONS_IDS} from "./utils/useFlowFields";
|
||||||
import debounce from "lodash/debounce";
|
import debounce from "lodash/debounce";
|
||||||
@@ -65,6 +67,7 @@
|
|||||||
import {useKeyboardSave} from "./utils/useKeyboardSave";
|
import {useKeyboardSave} from "./utils/useKeyboardSave";
|
||||||
import {deepEqual} from "../../utils/utils";
|
import {deepEqual} from "../../utils/utils";
|
||||||
import {useScrollMemory} from "../../composables/useScrollMemory";
|
import {useScrollMemory} from "../../composables/useScrollMemory";
|
||||||
|
import {defaultNamespace} from "../../composables/useNamespaces";
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps<NoCodeProps>();
|
const props = defineProps<NoCodeProps>();
|
||||||
@@ -166,6 +169,8 @@
|
|||||||
provide(REF_PATH_INJECTION_KEY, props.refPath);
|
provide(REF_PATH_INJECTION_KEY, props.refPath);
|
||||||
provide(PANEL_INJECTION_KEY, panel)
|
provide(PANEL_INJECTION_KEY, panel)
|
||||||
provide(POSITION_INJECTION_KEY, props.position ?? "after");
|
provide(POSITION_INJECTION_KEY, props.position ?? "after");
|
||||||
|
provide(CREATING_FLOW_INJECTION_KEY, flowStore.isCreating ?? false);
|
||||||
|
provide(DEFAULT_NAMESPACE_INJECTION_KEY, computed(() => flowStore.flow?.namespace ?? defaultNamespace() ?? "company.team"));
|
||||||
provide(CREATING_TASK_INJECTION_KEY, props.creatingTask);
|
provide(CREATING_TASK_INJECTION_KEY, props.creatingTask);
|
||||||
provide(EDITING_TASK_INJECTION_KEY, props.editingTask);
|
provide(EDITING_TASK_INJECTION_KEY, props.editingTask);
|
||||||
provide(FIELDNAME_INJECTION_KEY, props.fieldName);
|
provide(FIELDNAME_INJECTION_KEY, props.fieldName);
|
||||||
@@ -184,7 +189,7 @@
|
|||||||
emit("closeTask")
|
emit("closeTask")
|
||||||
})
|
})
|
||||||
|
|
||||||
provide(UPDATE_TASK_FUNCTION_INJECTION_KEY, (yaml) => {
|
provide(UPDATE_YAML_FUNCTION_INJECTION_KEY, (yaml) => {
|
||||||
editorUpdate(yaml)
|
editorUpdate(yaml)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, inject, ref} from "vue";
|
import {computed, inject, ref} from "vue";
|
||||||
import {BLOCK_SCHEMA_PATH_INJECTION_KEY} from "../../injectionKeys";
|
import {BLOCK_SCHEMA_PATH_INJECTION_KEY} from "../../injectionKeys";
|
||||||
import {useFlowStore} from "../../../../stores/flow";
|
|
||||||
import Creation from "./taskList/buttons/Creation.vue";
|
import Creation from "./taskList/buttons/Creation.vue";
|
||||||
import Element from "./taskList/Element.vue";
|
import Element from "./taskList/Element.vue";
|
||||||
import * as YAML_UTILS from "@kestra-io/ui-libs/flow-yaml-utils";
|
import * as YAML_UTILS from "@kestra-io/ui-libs/flow-yaml-utils";
|
||||||
@@ -53,7 +52,7 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
CREATING_TASK_INJECTION_KEY, FULL_SCHEMA_INJECTION_KEY, FULL_SOURCE_INJECTION_KEY,
|
CREATING_TASK_INJECTION_KEY, FULL_SCHEMA_INJECTION_KEY, FULL_SOURCE_INJECTION_KEY,
|
||||||
PARENT_PATH_INJECTION_KEY, REF_PATH_INJECTION_KEY,
|
PARENT_PATH_INJECTION_KEY, REF_PATH_INJECTION_KEY, UPDATE_YAML_FUNCTION_INJECTION_KEY,
|
||||||
} from "../../injectionKeys";
|
} from "../../injectionKeys";
|
||||||
import {SECTIONS_MAP} from "../../../../utils/constants";
|
import {SECTIONS_MAP} from "../../../../utils/constants";
|
||||||
import {getValueAtJsonPath} from "../../../../utils/utils";
|
import {getValueAtJsonPath} from "../../../../utils/utils";
|
||||||
@@ -83,8 +82,6 @@
|
|||||||
inheritAttrs: false
|
inheritAttrs: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const flowStore = useFlowStore();
|
|
||||||
|
|
||||||
interface Task {
|
interface Task {
|
||||||
id:string,
|
id:string,
|
||||||
type:string
|
type:string
|
||||||
@@ -150,6 +147,8 @@
|
|||||||
|
|
||||||
const movedIndex = ref(-1);
|
const movedIndex = ref(-1);
|
||||||
|
|
||||||
|
const updateYaml = inject(UPDATE_YAML_FUNCTION_INJECTION_KEY, () => {});
|
||||||
|
|
||||||
const moveElement = (
|
const moveElement = (
|
||||||
items: Record<string, any>[] | undefined,
|
items: Record<string, any>[] | undefined,
|
||||||
elementID: string,
|
elementID: string,
|
||||||
@@ -171,7 +170,7 @@
|
|||||||
movedIndex.value = -1;
|
movedIndex.value = -1;
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
flowStore.flowYaml =
|
updateYaml(
|
||||||
YAML_UTILS.swapBlocks({
|
YAML_UTILS.swapBlocks({
|
||||||
source:flow.value,
|
source:flow.value,
|
||||||
section: SECTIONS_MAP[section.value.toLowerCase() as keyof typeof SECTIONS_MAP],
|
section: SECTIONS_MAP[section.value.toLowerCase() as keyof typeof SECTIONS_MAP],
|
||||||
@@ -179,6 +178,7 @@
|
|||||||
key2:items[newIndex][keyName],
|
key2:items[newIndex][keyName],
|
||||||
keyName,
|
keyName,
|
||||||
})
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fullSchema = inject(FULL_SCHEMA_INJECTION_KEY, ref<Record<string, any>>({}));
|
const fullSchema = inject(FULL_SCHEMA_INJECTION_KEY, ref<Record<string, any>>({}));
|
||||||
|
|||||||
@@ -8,18 +8,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {computed, onMounted} from "vue";
|
import {onMounted, inject, computed, provide} from "vue";
|
||||||
import {useFlowStore} from "../../../../stores/flow";
|
|
||||||
import NamespaceSelect from "../../../namespaces/components/NamespaceSelect.vue";
|
import NamespaceSelect from "../../../namespaces/components/NamespaceSelect.vue";
|
||||||
|
import {CREATING_FLOW_INJECTION_KEY, DEFAULT_NAMESPACE_INJECTION_KEY} from "../../injectionKeys";
|
||||||
|
|
||||||
const modelValue = defineModel<string>();
|
const modelValue = defineModel<string>();
|
||||||
|
const isCreating = inject(CREATING_FLOW_INJECTION_KEY, false);
|
||||||
const flowStore = useFlowStore();
|
const defaultNamespace = inject(DEFAULT_NAMESPACE_INJECTION_KEY, computed(() => ""));
|
||||||
|
provide(DEFAULT_NAMESPACE_INJECTION_KEY, computed(() => modelValue.value || defaultNamespace.value));
|
||||||
const isCreating = computed(() => flowStore.isCreating);
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const flowNamespace = flowStore.flow?.namespace;
|
const flowNamespace = defaultNamespace.value;
|
||||||
if (!modelValue.value && flowNamespace) {
|
if (!modelValue.value && flowNamespace) {
|
||||||
modelValue.value = flowNamespace;
|
modelValue.value = flowNamespace;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export const POSITION_INJECTION_KEY = Symbol("position-injection-key") as Inject
|
|||||||
* NOTE: different from the `isCreating` flag coming from the store. `isCreating` refers to the Complete flow being in creation
|
* NOTE: different from the `isCreating` flag coming from the store. `isCreating` refers to the Complete flow being in creation
|
||||||
*/
|
*/
|
||||||
export const CREATING_TASK_INJECTION_KEY = Symbol("creating-injection-key") as InjectionKey<boolean>
|
export const CREATING_TASK_INJECTION_KEY = Symbol("creating-injection-key") as InjectionKey<boolean>
|
||||||
|
export const CREATING_FLOW_INJECTION_KEY = Symbol("creating-flow-injection-key") as InjectionKey<boolean>
|
||||||
/**
|
/**
|
||||||
* When creating anew task, allows to specify a field where the new task should be injected.
|
* When creating anew task, allows to specify a field where the new task should be injected.
|
||||||
* @example
|
* @example
|
||||||
@@ -51,9 +52,9 @@ export const EDIT_TASK_FUNCTION_INJECTION_KEY = Symbol("edit-function-injection-
|
|||||||
*/
|
*/
|
||||||
export const CLOSE_TASK_FUNCTION_INJECTION_KEY = Symbol("close-function-injection-key") as InjectionKey<() => void>
|
export const CLOSE_TASK_FUNCTION_INJECTION_KEY = Symbol("close-function-injection-key") as InjectionKey<() => void>
|
||||||
/**
|
/**
|
||||||
* We call this function when a task is changed, as soon as the first click or type is done
|
* Call this function to update the full Yaml content
|
||||||
*/
|
*/
|
||||||
export const UPDATE_TASK_FUNCTION_INJECTION_KEY = Symbol("update-function-injection-key") as InjectionKey<(yaml: string) => void>
|
export const UPDATE_YAML_FUNCTION_INJECTION_KEY = Symbol("update-function-injection-key") as InjectionKey<(yaml: string) => void>
|
||||||
/**
|
/**
|
||||||
* Set this to override the contents of the no-code editor with a component of your choice
|
* Set this to override the contents of the no-code editor with a component of your choice
|
||||||
* This is used to display the metadata edition inputs
|
* This is used to display the metadata edition inputs
|
||||||
@@ -92,4 +93,6 @@ export const SCHEMA_DEFINITIONS_INJECTION_KEY = Symbol("schema-definitions-injec
|
|||||||
|
|
||||||
export const DATA_TYPES_MAP_INJECTION_KEY = Symbol("data-types-injection-key") as InjectionKey<ComputedRef<Record<string, string[] | undefined>>>
|
export const DATA_TYPES_MAP_INJECTION_KEY = Symbol("data-types-injection-key") as InjectionKey<ComputedRef<Record<string, string[] | undefined>>>
|
||||||
|
|
||||||
export const ON_TASK_EDITOR_CLICK_INJECTION_KEY = Symbol("on-task-editor-click-injection-key") as InjectionKey<(elt?: Partial<NoCodeElement>) => void>;
|
export const ON_TASK_EDITOR_CLICK_INJECTION_KEY = Symbol("on-task-editor-click-injection-key") as InjectionKey<(elt?: Partial<NoCodeElement>) => void>;
|
||||||
|
|
||||||
|
export const DEFAULT_NAMESPACE_INJECTION_KEY = Symbol("default-namespace-injection-key") as InjectionKey<ComputedRef<string>>;
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
import {PLUGIN_DEFAULTS_SECTION, SECTIONS_MAP} from "../../../utils/constants";
|
import {PLUGIN_DEFAULTS_SECTION, SECTIONS_MAP} from "../../../utils/constants";
|
||||||
import {
|
import {
|
||||||
CLOSE_TASK_FUNCTION_INJECTION_KEY,
|
CLOSE_TASK_FUNCTION_INJECTION_KEY,
|
||||||
UPDATE_TASK_FUNCTION_INJECTION_KEY,
|
UPDATE_YAML_FUNCTION_INJECTION_KEY,
|
||||||
FULL_SOURCE_INJECTION_KEY, CREATING_TASK_INJECTION_KEY,
|
FULL_SOURCE_INJECTION_KEY, CREATING_TASK_INJECTION_KEY,
|
||||||
PARENT_PATH_INJECTION_KEY, POSITION_INJECTION_KEY,
|
PARENT_PATH_INJECTION_KEY, POSITION_INJECTION_KEY,
|
||||||
REF_PATH_INJECTION_KEY, EDIT_TASK_FUNCTION_INJECTION_KEY,
|
REF_PATH_INJECTION_KEY, EDIT_TASK_FUNCTION_INJECTION_KEY,
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
const fieldName = inject(FIELDNAME_INJECTION_KEY, undefined);
|
const fieldName = inject(FIELDNAME_INJECTION_KEY, undefined);
|
||||||
const blockSchemaPath = inject(BLOCK_SCHEMA_PATH_INJECTION_KEY, ref(""));
|
const blockSchemaPath = inject(BLOCK_SCHEMA_PATH_INJECTION_KEY, ref(""));
|
||||||
const updateTask = inject(UPDATE_TASK_FUNCTION_INJECTION_KEY, () => {})
|
const updateTask = inject(UPDATE_YAML_FUNCTION_INJECTION_KEY, () => {})
|
||||||
|
|
||||||
const closeTaskAddition = inject(
|
const closeTaskAddition = inject(
|
||||||
CLOSE_TASK_FUNCTION_INJECTION_KEY,
|
CLOSE_TASK_FUNCTION_INJECTION_KEY,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<template #additional-right>
|
<template #additional-right>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<el-button v-if="canCreate" tag="router-link" :to="{name: 'flows/create', query: {namespace: $route.query.namespace}}" :icon="Plus" type="primary">
|
<el-button v-if="canCreate" tag="router-link" :to="{name: 'flows/create', query: {namespace: $route.query.namespace}}" :icon="Plus" type="secondary">
|
||||||
{{ $t('create_flow') }}
|
{{ $t('create_flow') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</li>
|
</li>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<el-button
|
<el-button
|
||||||
v-if="isOSS"
|
v-if="isOSS"
|
||||||
@click="startTour"
|
@click="startTour"
|
||||||
:icon="Plus"
|
:icon="Compass"
|
||||||
size="large"
|
size="large"
|
||||||
type="primary"
|
type="primary"
|
||||||
class="px-3 p-4 section-1-link product-link"
|
class="px-3 p-4 section-1-link product-link"
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-else
|
v-else
|
||||||
:icon="Plus"
|
:icon="Compass"
|
||||||
tag="router-link"
|
tag="router-link"
|
||||||
:to="{name: 'flows/create'}"
|
:to="{name: 'flows/create'}"
|
||||||
size="large"
|
size="large"
|
||||||
@@ -74,6 +74,7 @@
|
|||||||
import {useCoreStore} from "../../stores/core";
|
import {useCoreStore} from "../../stores/core";
|
||||||
import {useI18n} from "vue-i18n";
|
import {useI18n} from "vue-i18n";
|
||||||
import Plus from "vue-material-design-icons/Plus.vue";
|
import Plus from "vue-material-design-icons/Plus.vue";
|
||||||
|
import Compass from "vue-material-design-icons/Compass.vue";
|
||||||
import Play from "vue-material-design-icons/Play.vue";
|
import Play from "vue-material-design-icons/Play.vue";
|
||||||
import OnboardingBottom from "override/components/OnboardingBottom.vue";
|
import OnboardingBottom from "override/components/OnboardingBottom.vue";
|
||||||
import kestraWelcome from "../../assets/onboarding/kestra_welcome.svg";
|
import kestraWelcome from "../../assets/onboarding/kestra_welcome.svg";
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
<el-form-item :label="$t('secret.key')" prop="key">
|
<el-form-item :label="$t('secret.key')" prop="key">
|
||||||
<el-input v-model="secret.key" :disabled="secret.update" required />
|
<el-input v-model="secret.key" :disabled="secret.update" required />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="!secret.update" :label="$t('secret.name')" prop="value">
|
<el-form-item v-if="!secret.update" :label="$t('secret.name')" prop="value" required>
|
||||||
<MultilineSecret v-model="secret.value" :placeholder="secretModalTitle" />
|
<MultilineSecret v-model="secret.value" :placeholder="secretModalTitle" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="secret.update" :label="$t('secret.name')" prop="value">
|
<el-form-item v-if="secret.update" :label="$t('secret.name')" prop="value">
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import {computed, watch} from "vue";
|
||||||
import {useI18n} from "vue-i18n";
|
import {useI18n} from "vue-i18n";
|
||||||
import {configureMonacoYaml} from "monaco-yaml";
|
import {configureMonacoYaml} from "monaco-yaml";
|
||||||
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
|
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
|
||||||
@@ -21,6 +22,7 @@ import {
|
|||||||
registerPebbleAutocompletion
|
registerPebbleAutocompletion
|
||||||
} from "./pebbleLanguageConfigurator";
|
} from "./pebbleLanguageConfigurator";
|
||||||
import {usePluginsStore} from "../../../stores/plugins";
|
import {usePluginsStore} from "../../../stores/plugins";
|
||||||
|
import {useBlueprintsStore} from "../../../stores/blueprints";
|
||||||
import {languages} from "monaco-editor/esm/vs/editor/editor.api";
|
import {languages} from "monaco-editor/esm/vs/editor/editor.api";
|
||||||
import CompletionItem = languages.CompletionItem;
|
import CompletionItem = languages.CompletionItem;
|
||||||
|
|
||||||
@@ -34,11 +36,14 @@ export class YamlLanguageConfigurator extends AbstractLanguageConfigurator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async configureLanguage(pluginsStore: ReturnType<typeof usePluginsStore>) {
|
async configureLanguage(pluginsStore: ReturnType<typeof usePluginsStore>) {
|
||||||
|
const validateYAML = computed(() => useBlueprintsStore().validateYAML);
|
||||||
|
watch(validateYAML, (shouldValidate) => configureMonacoYaml(monaco, {validate: shouldValidate}));
|
||||||
|
|
||||||
configureMonacoYaml(monaco, {
|
configureMonacoYaml(monaco, {
|
||||||
enableSchemaRequest: true,
|
enableSchemaRequest: true,
|
||||||
hover: localStorage.getItem("hoverTextEditor") === "true",
|
hover: localStorage.getItem("hoverTextEditor") === "true",
|
||||||
completion: true,
|
completion: true,
|
||||||
validate: true,
|
validate: validateYAML.value ?? true,
|
||||||
format: true,
|
format: true,
|
||||||
schemas: yamlSchemas()
|
schemas: yamlSchemas()
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<SideBar v-if="menu" :menu :showLink="showLink" @menu-collapse="onCollapse">
|
<SideBar
|
||||||
|
v-if="menu"
|
||||||
|
:menu
|
||||||
|
:showLink
|
||||||
|
@menu-collapse="onCollapse"
|
||||||
|
:class="{overlay: verticalLayout}"
|
||||||
|
>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<Auth />
|
<Auth />
|
||||||
</template>
|
</template>
|
||||||
@@ -11,6 +17,9 @@
|
|||||||
import SideBar from "../../components/layout/SideBar.vue";
|
import SideBar from "../../components/layout/SideBar.vue";
|
||||||
import Auth from "../../override/components/auth/Auth.vue";
|
import Auth from "../../override/components/auth/Auth.vue";
|
||||||
|
|
||||||
|
import {useBreakpoints, breakpointsElement} from "@vueuse/core";
|
||||||
|
const verticalLayout = useBreakpoints(breakpointsElement).smallerOrEqual("sm");
|
||||||
|
|
||||||
withDefaults(defineProps<{
|
withDefaults(defineProps<{
|
||||||
showLink?: boolean
|
showLink?: boolean
|
||||||
}>(), {
|
}>(), {
|
||||||
|
|||||||
@@ -56,7 +56,10 @@
|
|||||||
<div v-if="!system && blueprint.tags?.length > 0" class="tags-section">
|
<div v-if="!system && blueprint.tags?.length > 0" class="tags-section">
|
||||||
<span v-for="tag in processedTags(blueprint.tags)" :key="tag.original" class="tag-item">{{ tag.display }}</span>
|
<span v-for="tag in processedTags(blueprint.tags)" :key="tag.original" class="tag-item">{{ tag.display }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-section">
|
<div v-if="blueprint.template" class="tags-section">
|
||||||
|
<span class="tag-item">{{ $t('template') }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-section">
|
||||||
<h3 class="title">
|
<h3 class="title">
|
||||||
{{ blueprint.title ?? blueprint.id }}
|
{{ blueprint.title ?? blueprint.id }}
|
||||||
</h3>
|
</h3>
|
||||||
@@ -151,6 +154,7 @@
|
|||||||
id: string;
|
id: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
title?: string;
|
title?: string;
|
||||||
|
template?: Record<string, any>;
|
||||||
}[] | undefined>(undefined);
|
}[] | undefined>(undefined);
|
||||||
const error = ref(false);
|
const error = ref(false);
|
||||||
const icon = {ContentCopy};
|
const icon = {ContentCopy};
|
||||||
|
|||||||
@@ -1,45 +1,70 @@
|
|||||||
import {computed} from "vue";
|
import {computed} from "vue";
|
||||||
import {useRoute, useRouter} from "vue-router";
|
|
||||||
|
import {useRoute, useRouter, type RouteRecordNameGeneric} from "vue-router";
|
||||||
import {useI18n} from "vue-i18n";
|
import {useI18n} from "vue-i18n";
|
||||||
|
|
||||||
import {useMiscStore} from "override/stores/misc";
|
import {useMiscStore} from "override/stores/misc";
|
||||||
|
|
||||||
import {getDashboard} from "../../components/dashboard/composables/useDashboards";
|
import {getDashboard} from "../../components/dashboard/composables/useDashboards";
|
||||||
|
|
||||||
|
// Main icons
|
||||||
|
import ChartLineVariant from "vue-material-design-icons/ChartLineVariant.vue";
|
||||||
import FileTreeOutline from "vue-material-design-icons/FileTreeOutline.vue";
|
import FileTreeOutline from "vue-material-design-icons/FileTreeOutline.vue";
|
||||||
|
import LayersTripleOutline from "vue-material-design-icons/LayersTripleOutline.vue";
|
||||||
import ContentCopy from "vue-material-design-icons/ContentCopy.vue";
|
import ContentCopy from "vue-material-design-icons/ContentCopy.vue";
|
||||||
import TimelineClockOutline from "vue-material-design-icons/TimelineClockOutline.vue";
|
import PlayOutline from "vue-material-design-icons/PlayOutline.vue";
|
||||||
import TimelineTextOutline from "vue-material-design-icons/TimelineTextOutline.vue";
|
import FileDocumentOutline from "vue-material-design-icons/FileDocumentOutline.vue";
|
||||||
import BallotOutline from "vue-material-design-icons/BallotOutline.vue";
|
|
||||||
import ShieldAccountVariantOutline from "vue-material-design-icons/ShieldAccountVariantOutline.vue";
|
|
||||||
import ViewDashboardVariantOutline from "vue-material-design-icons/ViewDashboardVariantOutline.vue";
|
|
||||||
import Connection from "vue-material-design-icons/Connection.vue";
|
|
||||||
import DotsSquare from "vue-material-design-icons/DotsSquare.vue";
|
|
||||||
import FormatListGroupPlus from "vue-material-design-icons/FormatListGroupPlus.vue";
|
|
||||||
import DatabaseOutline from "vue-material-design-icons/DatabaseOutline.vue";
|
|
||||||
import ShieldKeyOutline from "vue-material-design-icons/ShieldKeyOutline.vue";
|
|
||||||
import FlaskOutline from "vue-material-design-icons/FlaskOutline.vue";
|
import FlaskOutline from "vue-material-design-icons/FlaskOutline.vue";
|
||||||
|
// import PackageVariantClosed from "vue-material-design-icons/PackageVariantClosed.vue";
|
||||||
|
import FolderOpenOutline from "vue-material-design-icons/FolderOpenOutline.vue";
|
||||||
|
import PuzzleOutline from "vue-material-design-icons/PuzzleOutline.vue";
|
||||||
|
import ShapePlusOutline from "vue-material-design-icons/ShapePlusOutline.vue";
|
||||||
|
import OfficeBuildingOutline from "vue-material-design-icons/OfficeBuildingOutline.vue";
|
||||||
|
import ServerNetworkOutline from "vue-material-design-icons/ServerNetworkOutline.vue";
|
||||||
|
|
||||||
|
// Blueprints icons
|
||||||
|
import Wrench from "vue-material-design-icons/Wrench.vue";
|
||||||
|
|
||||||
|
// Tenant Administration icons
|
||||||
|
import Monitor from "vue-material-design-icons/Monitor.vue";
|
||||||
|
import DatabaseOutline from "vue-material-design-icons/DatabaseOutline.vue";
|
||||||
|
import LockOutline from "vue-material-design-icons/LockOutline.vue";
|
||||||
|
import LightningBolt from "vue-material-design-icons/LightningBolt.vue";
|
||||||
|
import Battery40 from "vue-material-design-icons/Battery40.vue";
|
||||||
|
import ShieldAccount from "vue-material-design-icons/ShieldAccount.vue";
|
||||||
|
|
||||||
export type MenuItem = {
|
export type MenuItem = {
|
||||||
|
title: string;
|
||||||
|
routes?: RouteRecordNameGeneric[];
|
||||||
href?: {
|
href?: {
|
||||||
path?: string,
|
name: string;
|
||||||
name: string,
|
params?: Record<string, any>;
|
||||||
params?: Record<string, any>,
|
query?: Record<string, any>;
|
||||||
query?: Record<string, any>
|
};
|
||||||
},
|
icon?: {
|
||||||
child?: MenuItem[],
|
element?: any;
|
||||||
disabled?: boolean,
|
class?: any;
|
||||||
|
};
|
||||||
|
child?: MenuItem[];
|
||||||
|
attributes?: {
|
||||||
|
locked?: boolean;
|
||||||
|
};
|
||||||
|
hidden?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useLeftMenu() {
|
export function useLeftMenu() {
|
||||||
const {t} = useI18n({useScope: "global"});
|
|
||||||
const $route = useRoute();
|
const $route = useRoute();
|
||||||
const $router = useRouter();
|
const $router = useRouter();
|
||||||
const miscStore = useMiscStore();
|
|
||||||
|
const {t} = useI18n({useScope: "global"});
|
||||||
|
|
||||||
|
const configs = useMiscStore().configs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all route names that start with the given route
|
* Returns the names of all registered routes whose name starts with the given prefix.
|
||||||
* @param route
|
*
|
||||||
* @returns
|
* @param route - The route name prefix to match against.
|
||||||
|
* @returns An array of route names starting with the provided prefix.
|
||||||
*/
|
*/
|
||||||
function routeStartWith(route: string) {
|
function routeStartWith(route: string) {
|
||||||
return $router
|
return $router
|
||||||
@@ -50,140 +75,145 @@ export function useLeftMenu() {
|
|||||||
.map((r) => r.name);
|
.map((r) => r.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
const flatMenuItems = (items: MenuItem[]): MenuItem[] => {
|
const menu = computed<MenuItem[]>(() => {
|
||||||
return items.flatMap(item => item.child ? [item, ...flatMenuItems(item.child)] : [item])
|
return [
|
||||||
}
|
|
||||||
|
|
||||||
const menu = computed(() => {
|
|
||||||
const generatedMenu = [
|
|
||||||
{
|
{
|
||||||
|
title: t("dashboards.labels.plural"),
|
||||||
href: {
|
href: {
|
||||||
name: "home",
|
name: "home",
|
||||||
params: {dashboard: getDashboard($route, "id")},
|
params: {
|
||||||
|
dashboard: getDashboard($route, "id"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
title: t("dashboards.labels.plural"),
|
|
||||||
icon: {
|
icon: {
|
||||||
element: ViewDashboardVariantOutline,
|
element: ChartLineVariant,
|
||||||
class: "menu-icon",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: {name: "flows/list"},
|
|
||||||
routes: routeStartWith("flows"),
|
|
||||||
title: t("flows"),
|
title: t("flows"),
|
||||||
|
routes: routeStartWith("flows"),
|
||||||
|
href: {
|
||||||
|
name: "flows/list",
|
||||||
|
},
|
||||||
icon: {
|
icon: {
|
||||||
element: FileTreeOutline,
|
element: FileTreeOutline,
|
||||||
class: "menu-icon",
|
|
||||||
},
|
},
|
||||||
exact: false,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: {name: "apps/list"},
|
|
||||||
routes: routeStartWith("apps"),
|
|
||||||
title: t("apps"),
|
title: t("apps"),
|
||||||
|
routes: routeStartWith("apps"),
|
||||||
|
href: {
|
||||||
|
name: "apps/list",
|
||||||
|
},
|
||||||
icon: {
|
icon: {
|
||||||
element: FormatListGroupPlus,
|
element: LayersTripleOutline,
|
||||||
class: "menu-icon",
|
|
||||||
},
|
},
|
||||||
attributes: {
|
attributes: {
|
||||||
locked: true,
|
locked: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: {name: "templates/list"},
|
|
||||||
routes: routeStartWith("templates"),
|
|
||||||
title: t("templates"),
|
|
||||||
icon: {
|
|
||||||
element: ContentCopy,
|
|
||||||
class: "menu-icon",
|
|
||||||
},
|
|
||||||
hidden: !miscStore.configs?.isTemplateEnabled,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: {name: "executions/list"},
|
|
||||||
routes: routeStartWith("executions"),
|
|
||||||
title: t("executions"),
|
title: t("executions"),
|
||||||
|
routes: routeStartWith("executions"),
|
||||||
|
href: {
|
||||||
|
name: "executions/list",
|
||||||
|
},
|
||||||
icon: {
|
icon: {
|
||||||
element: TimelineClockOutline,
|
element: PlayOutline,
|
||||||
class: "menu-icon",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: {name: "logs/list"},
|
|
||||||
routes: routeStartWith("logs"),
|
|
||||||
title: t("logs"),
|
title: t("logs"),
|
||||||
|
routes: routeStartWith("logs"),
|
||||||
|
href: {
|
||||||
|
name: "logs/list",
|
||||||
|
},
|
||||||
icon: {
|
icon: {
|
||||||
element: TimelineTextOutline,
|
element: FileDocumentOutline,
|
||||||
class: "menu-icon",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: {name: "tests/list"},
|
|
||||||
routes: routeStartWith("tests"),
|
|
||||||
title: t("demos.tests.label"),
|
title: t("demos.tests.label"),
|
||||||
|
routes: routeStartWith("tests"),
|
||||||
|
href: {
|
||||||
|
name: "tests/list",
|
||||||
|
},
|
||||||
icon: {
|
icon: {
|
||||||
element: FlaskOutline,
|
element: FlaskOutline,
|
||||||
class: "menu-icon"
|
|
||||||
},
|
},
|
||||||
attributes: {
|
attributes: {
|
||||||
locked: true,
|
locked: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// TODO: To add Assets entry here in future release
|
||||||
|
// Uncomment PackageVariantClosed on line 25 and use as the icon
|
||||||
{
|
{
|
||||||
href: {name: "namespaces/list"},
|
|
||||||
routes: routeStartWith("namespaces"),
|
|
||||||
title: t("namespaces"),
|
title: t("namespaces"),
|
||||||
|
routes: routeStartWith("namespaces"),
|
||||||
|
href: {
|
||||||
|
name: "namespaces/list",
|
||||||
|
},
|
||||||
icon: {
|
icon: {
|
||||||
element: DotsSquare,
|
element: FolderOpenOutline,
|
||||||
class: "menu-icon",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: {name: "kv/list"},
|
title: t("templates"),
|
||||||
routes: routeStartWith("kv"),
|
routes: routeStartWith("templates"),
|
||||||
title: t("kv.name"),
|
href: {
|
||||||
|
name: "templates/list",
|
||||||
|
},
|
||||||
icon: {
|
icon: {
|
||||||
element: DatabaseOutline,
|
element: ContentCopy,
|
||||||
class: "menu-icon",
|
},
|
||||||
|
hidden: !configs?.isTemplateEnabled,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("plugins.names"),
|
||||||
|
routes: routeStartWith("plugins"),
|
||||||
|
href: {
|
||||||
|
name: "plugins/list",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: PuzzleOutline,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: {name: "secrets/list"},
|
|
||||||
routes: routeStartWith("secrets"),
|
|
||||||
title: t("secret.names"),
|
|
||||||
icon: {
|
|
||||||
element: ShieldKeyOutline,
|
|
||||||
class: "menu-icon",
|
|
||||||
},
|
|
||||||
attributes: {
|
|
||||||
locked: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
routes: routeStartWith("blueprints"),
|
|
||||||
title: t("blueprints.title"),
|
title: t("blueprints.title"),
|
||||||
|
routes: routeStartWith("blueprints"),
|
||||||
icon: {
|
icon: {
|
||||||
element: BallotOutline,
|
element: ShapePlusOutline,
|
||||||
class: "menu-icon",
|
|
||||||
},
|
},
|
||||||
child: [
|
child: [
|
||||||
{
|
{
|
||||||
title: t("blueprints.custom"),
|
title: t("blueprints.custom"),
|
||||||
routes: routeStartWith("blueprints/flow"),
|
routes: routeStartWith("blueprints/flow/custom"),
|
||||||
attributes: {
|
|
||||||
locked: true,
|
|
||||||
},
|
|
||||||
href: {
|
href: {
|
||||||
name: "blueprints",
|
name: "blueprints",
|
||||||
params: {kind: "flow", tab: "custom"},
|
params: {
|
||||||
|
kind: "flow",
|
||||||
|
tab: "custom",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: Wrench,
|
||||||
|
},
|
||||||
|
attributes: {
|
||||||
|
locked: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("blueprints.flows"),
|
title: t("blueprints.flows"),
|
||||||
routes: routeStartWith("blueprints/flow"),
|
routes: routeStartWith("blueprints/flow/community"),
|
||||||
href: {
|
href: {
|
||||||
name: "blueprints",
|
name: "blueprints",
|
||||||
params: {kind: "flow", tab: "community"},
|
params: {
|
||||||
|
kind: "flow",
|
||||||
|
tab: "community",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: FileTreeOutline,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -191,91 +221,144 @@ export function useLeftMenu() {
|
|||||||
routes: routeStartWith("blueprints/dashboard"),
|
routes: routeStartWith("blueprints/dashboard"),
|
||||||
href: {
|
href: {
|
||||||
name: "blueprints",
|
name: "blueprints",
|
||||||
params: {kind: "dashboard", tab: "community"},
|
params: {
|
||||||
|
kind: "dashboard",
|
||||||
|
tab: "community",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: ChartLineVariant,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: {name: "plugins/list"},
|
title: t("tenant_administration"),
|
||||||
routes: routeStartWith("plugins"),
|
routes: [
|
||||||
title: t("plugins.names"),
|
"admin/stats",
|
||||||
|
"kv",
|
||||||
|
"secrets",
|
||||||
|
"admin/triggers",
|
||||||
|
"admin/auditlogs",
|
||||||
|
"admin/iam",
|
||||||
|
"admin/concurrency-limits",
|
||||||
|
]
|
||||||
|
.map(routeStartWith)
|
||||||
|
.find((routes) => routes.length > 0),
|
||||||
icon: {
|
icon: {
|
||||||
element: Connection,
|
element: OfficeBuildingOutline,
|
||||||
class: "menu-icon",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("administration"),
|
|
||||||
routes: routeStartWith("admin"),
|
|
||||||
icon: {
|
|
||||||
element: ShieldAccountVariantOutline,
|
|
||||||
class: "menu-icon",
|
|
||||||
},
|
},
|
||||||
child: [
|
child: [
|
||||||
{
|
{
|
||||||
href: {name: "admin/iam"},
|
|
||||||
routes: routeStartWith("admin/iam"),
|
|
||||||
title: t("iam"),
|
|
||||||
attributes: {
|
|
||||||
locked: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: {name: "admin/auditlogs/list"},
|
|
||||||
routes: routeStartWith("admin/auditlogs"),
|
|
||||||
title: t("auditlogs"),
|
|
||||||
attributes: {
|
|
||||||
locked: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: {name: "admin/triggers"},
|
|
||||||
routes: routeStartWith("admin/triggers"),
|
|
||||||
title: t("triggers"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: {name: "admin/instance"},
|
|
||||||
routes: routeStartWith("admin/instance"),
|
|
||||||
title: t("instance"),
|
|
||||||
attributes: {
|
|
||||||
locked: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: {name: "admin/tenants/list"},
|
|
||||||
routes: routeStartWith("admin/tenants"),
|
|
||||||
title: t("tenant.names"),
|
|
||||||
attributes: {
|
|
||||||
locked: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: {name: "admin/concurrency-limits"},
|
|
||||||
routes: routeStartWith("admin/concurrency-limits"),
|
|
||||||
title: t("concurrency limits"),
|
|
||||||
hidden: !miscStore.configs?.isConcurrencyViewEnabled,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: {name: "admin/stats"},
|
|
||||||
routes: routeStartWith("admin/stats"),
|
|
||||||
title: t("system overview"),
|
title: t("system overview"),
|
||||||
|
routes: routeStartWith("admin/stats"),
|
||||||
|
href: {
|
||||||
|
name: "admin/stats",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: Monitor,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("kv.name"),
|
||||||
|
routes: routeStartWith("kv"),
|
||||||
|
href: {
|
||||||
|
name: "kv/list",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: DatabaseOutline,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("secret.names"),
|
||||||
|
routes: routeStartWith("secrets"),
|
||||||
|
href: {
|
||||||
|
name: "secrets/list",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: LockOutline,
|
||||||
|
},
|
||||||
|
attributes: {
|
||||||
|
locked: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("triggers"),
|
||||||
|
routes: routeStartWith("admin/triggers"),
|
||||||
|
href: {
|
||||||
|
name: "admin/triggers",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: LightningBolt,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("auditlogs"),
|
||||||
|
routes: routeStartWith("admin/auditlogs"),
|
||||||
|
href: {
|
||||||
|
name: "admin/auditlogs/list",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: FileDocumentOutline,
|
||||||
|
},
|
||||||
|
attributes: {
|
||||||
|
locked: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("concurrency limits"),
|
||||||
|
routes: routeStartWith("admin/concurrency-limits"),
|
||||||
|
href: {
|
||||||
|
name: "admin/concurrency-limits",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: Battery40,
|
||||||
|
},
|
||||||
|
hidden: !configs?.isConcurrencyViewEnabled,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("iam"),
|
||||||
|
routes: routeStartWith("admin/iam"),
|
||||||
|
href: {
|
||||||
|
name: "admin/iam",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: ShieldAccount,
|
||||||
|
},
|
||||||
|
attributes: {
|
||||||
|
locked: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("instance_administration"),
|
||||||
|
routes: routeStartWith("admin/instance"),
|
||||||
|
href: {
|
||||||
|
name: "admin/instance",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
element: ServerNetworkOutline,
|
||||||
|
},
|
||||||
|
attributes: {
|
||||||
|
locked: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
].map((item: MenuItem) => {
|
||||||
|
if (item.icon?.element) {
|
||||||
|
item.icon.class = "menu-icon"; // Add default class to all menu icons
|
||||||
}
|
}
|
||||||
];
|
|
||||||
|
|
||||||
flatMenuItems(generatedMenu).forEach(menuItem => {
|
if (item.href && item.href?.name === $route.name) {
|
||||||
if (menuItem.href !== undefined && menuItem.href?.name === $route.name) {
|
item.href.query = {
|
||||||
menuItem.href.query = {...$route.query, ...menuItem.href?.query};
|
...$route.query,
|
||||||
|
...item.href?.query,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
});
|
});
|
||||||
|
|
||||||
return generatedMenu;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {menu};
|
||||||
routeStartWith,
|
|
||||||
menu
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export default [
|
|||||||
|
|
||||||
//Admin
|
//Admin
|
||||||
{name: "admin/triggers", path: "/:tenant?/admin/triggers", component: () => import("../components/admin/Triggers.vue")},
|
{name: "admin/triggers", path: "/:tenant?/admin/triggers", component: () => import("../components/admin/Triggers.vue")},
|
||||||
{name: "admin/stats", path: "/:tenant?/admin/stats", component: () => import("override/components/admin/stats/Stats.vue")},
|
{name: "admin/stats", path: "/:tenant?/admin/stats/:type?", component: () => import("override/components/admin/stats/Stats.vue")},
|
||||||
{name: "admin/concurrency-limits", path: "/:tenant?/admin/concurrency-limits", component: () => import("../components/admin/ConcurrencyLimits.vue")},
|
{name: "admin/concurrency-limits", path: "/:tenant?/admin/concurrency-limits", component: () => import("../components/admin/ConcurrencyLimits.vue")},
|
||||||
|
|
||||||
//Setup
|
//Setup
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ interface Blueprint {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type TemplateArgument = Record<string, Input>;
|
||||||
|
|
||||||
export interface BlueprintTemplate {
|
export interface BlueprintTemplate {
|
||||||
source: string;
|
source: string;
|
||||||
templateArguments: Record<string, Input>;
|
templateArguments: Record<string, Input>;
|
||||||
@@ -55,6 +57,8 @@ export const useBlueprintsStore = defineStore("blueprints", () => {
|
|||||||
const source = ref<string | undefined>(undefined);
|
const source = ref<string | undefined>(undefined);
|
||||||
const graph = ref<any | undefined>(undefined);
|
const graph = ref<any | undefined>(undefined);
|
||||||
|
|
||||||
|
const validateYAML = ref<boolean>(true); // Used to enable/disable YAML validation in Monaco editor, for the purpose of Templated Blueprints
|
||||||
|
|
||||||
const getBlueprints = async (options: Options) => {
|
const getBlueprints = async (options: Options) => {
|
||||||
const PARAMS = {params: options.params, ...VALIDATE};
|
const PARAMS = {params: options.params, ...VALIDATE};
|
||||||
|
|
||||||
@@ -166,6 +170,8 @@ export const useBlueprintsStore = defineStore("blueprints", () => {
|
|||||||
source,
|
source,
|
||||||
graph,
|
graph,
|
||||||
|
|
||||||
|
validateYAML,
|
||||||
|
|
||||||
getBlueprints,
|
getBlueprints,
|
||||||
getBlueprint,
|
getBlueprint,
|
||||||
getBlueprintSource,
|
getBlueprintSource,
|
||||||
|
|||||||
@@ -1,208 +1,237 @@
|
|||||||
|
@import "@kestra-io/ui-libs/src/scss/variables.scss";
|
||||||
|
|
||||||
|
#app {
|
||||||
|
.v-sidebar-menu.vsm_expanded.overlay {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
#app {
|
.vsm--item {
|
||||||
.vsm--icon {
|
padding: 0 30px;
|
||||||
transition: left 0.2s ease;
|
transition: padding 0.2s ease;
|
||||||
font-size: 1.5em;
|
}
|
||||||
background-color: transparent !important;
|
|
||||||
padding-bottom: 15px;
|
|
||||||
width: 30px !important;
|
|
||||||
z-index: 20; // in collapsed menu, keep the icon above the opening menu
|
|
||||||
|
|
||||||
svg {
|
.vsm--icon {
|
||||||
position: relative;
|
width: 20px;
|
||||||
margin-top: 13px;
|
margin-right: calc($spacer / 2);
|
||||||
|
transition: left 0.2s ease;
|
||||||
|
background-color: transparent !important;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
height: 20px !important;
|
||||||
|
width: 20px !important;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--title {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
|
&>span {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--child {
|
||||||
|
.vsm--item {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.vsm--title {
|
||||||
|
font-size: $font-size-xs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make Plugins icon appear as outline
|
.vsm--icon {
|
||||||
.vsm--link[href*="plugins"] .vsm--icon svg {
|
width: 1rem;
|
||||||
fill: none !important;
|
|
||||||
stroke: currentColor !important;
|
svg {
|
||||||
stroke-width: 1.5 !important;
|
height: 1rem !important;
|
||||||
|
width: 1rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--link {
|
||||||
|
height: 30px;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
border-radius: .25rem;
|
||||||
|
transition: padding 0.2s ease;
|
||||||
|
color: var(--ks-content-primary);
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
&_active,
|
||||||
|
body &_active:hover {
|
||||||
|
background-color: var(--ks-button-background-primary) !important;
|
||||||
|
color: var(--ks-button-content-primary);
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vsm--item {
|
&.vsm--link_open,
|
||||||
padding: 0 30px;
|
&.vsm--link_open:hover {
|
||||||
transition: padding 0.2s ease;
|
background-color: var(--ks-background-left-menu);
|
||||||
|
color: var(--ks-content-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.vsm--child {
|
&_disabled {
|
||||||
.vsm--item {
|
pointer-events: auto;
|
||||||
padding: 0;
|
opacity: 1;
|
||||||
.vsm--title {
|
}
|
||||||
padding-left: 10px;
|
|
||||||
|
&:hover,
|
||||||
|
body &_hover {
|
||||||
|
background-color: var(--ks-button-background-secondary-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tooltip__trigger {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
&>span {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--link_open {
|
||||||
|
position: relative !important;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm_collapsed .vsm--link_open {
|
||||||
|
position: static !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--child .vsm--link {
|
||||||
|
padding: 0 0.2rem;
|
||||||
|
position: relative !important;
|
||||||
|
margin-left: 1.8rem;
|
||||||
|
|
||||||
|
&.vsm--link_level-3 {
|
||||||
|
margin-left: 3.6rem;
|
||||||
|
|
||||||
|
& span {
|
||||||
|
margin-left: calc($spacer / 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--icon {
|
||||||
|
margin-left: calc($spacer / 2);
|
||||||
|
color: var(--ks-content-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.vsm--link_active .vsm--icon {
|
||||||
|
color: var(--ks-button-content-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: -.8rem;
|
||||||
|
height: 150%;
|
||||||
|
border: 2px solid var(--ks-border-primary);
|
||||||
|
border-top: 0;
|
||||||
|
border-right: 0;
|
||||||
|
z-index: 2;
|
||||||
|
// mask the right half of the object and the top border
|
||||||
|
clip-path: polygon(50% 8px, 50% 100%, 0 100%, 0 8px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--title span:first-child {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--link_open.vsm--link_active {
|
||||||
|
|
||||||
|
.vsm--title,
|
||||||
|
.vsm--icon {
|
||||||
|
color: var(--ks-button-content-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--arrow_default {
|
||||||
|
width: 8px;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
border-left-width: 1px;
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
height: 4px;
|
||||||
|
width: 4px;
|
||||||
|
top: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.vsm--link_active[href="#"] {
|
||||||
|
cursor: initial !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--dropdown {
|
||||||
|
background-color: var(--ks-background-left-menu);
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
|
||||||
|
.vsm--title {
|
||||||
|
top: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--scroll-thumb {
|
||||||
|
background: var(--ks-border-primary) !important;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--mobile-bg {
|
||||||
|
border-radius: 0 var(--bs-border-radius) var(--bs-border-radius) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm_collapsed {
|
||||||
|
.logo {
|
||||||
|
>* {
|
||||||
|
left: 10px;
|
||||||
|
|
||||||
|
span.img {
|
||||||
|
background-size: 207px 55px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vsm--link {
|
.vsm--link {
|
||||||
padding: 0.3rem 0.5rem;
|
padding-left: 13px;
|
||||||
margin-bottom: 0.3rem;
|
|
||||||
border-radius: .25rem;
|
|
||||||
transition: padding 0.2s ease;
|
|
||||||
color: var(--ks-content-primary);
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
&_active, body &_active:hover {
|
&.vsm--link_hover {
|
||||||
background-color: var(--ks-button-background-primary) !important;
|
background-color: var(--ks-button-background-primary);
|
||||||
color: var(--ks-button-content-primary);
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.vsm--link_open, &.vsm--link_open:hover {
|
|
||||||
background-color: var(--ks-background-left-menu);
|
|
||||||
color: var(--ks-content-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
&_disabled {
|
|
||||||
pointer-events: auto;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover, body &_hover {
|
|
||||||
background-color: var(--ks-button-background-secondary-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tooltip__trigger {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > span{
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm--link_open{
|
|
||||||
position: relative !important;
|
|
||||||
z-index: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm_collapsed .vsm--link_open{
|
|
||||||
position: static !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm--child .vsm--link{
|
|
||||||
padding: 0 0.2rem;
|
|
||||||
position: relative!important;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-left: 1.8rem;
|
|
||||||
.vsm--icon {
|
|
||||||
margin-right:4px;
|
|
||||||
color: var(--ks-content-secondary);
|
|
||||||
}
|
|
||||||
&.vsm--link_active .vsm--icon{
|
|
||||||
color: var(--ks-button-content-primary);
|
color: var(--ks-button-content-primary);
|
||||||
}
|
}
|
||||||
&:before{
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
left: -.8rem;
|
|
||||||
top: -2.5rem;
|
|
||||||
border-radius: 8px;
|
|
||||||
width: 1.6rem;
|
|
||||||
height: 170%;
|
|
||||||
border: 2px solid var(--ks-border-primary);
|
|
||||||
border-top:0;
|
|
||||||
border-right:0;
|
|
||||||
z-index: 2;
|
|
||||||
// mask the right half of the object and the top border
|
|
||||||
clip-path: polygon(50% 8px, 50% 100%, 0 100%, 0 8px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm--title span:first-child{
|
|
||||||
flex-grow: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm--link_open.vsm--link_active {
|
|
||||||
.vsm--title, .vsm--icon {
|
|
||||||
color: var(--ks-button-content-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm--arrow_default{
|
|
||||||
width: 8px;
|
|
||||||
&:before{
|
|
||||||
border-left-width: 1px;
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
height: 4px;
|
|
||||||
width: 4px;
|
|
||||||
top: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
a.vsm--link_active[href="#"] {
|
|
||||||
cursor: initial !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm--dropdown {
|
|
||||||
background-color: var(--ks-background-left-menu);
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-bottom: .5rem;
|
|
||||||
|
|
||||||
.vsm--title {
|
|
||||||
top: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm--scroll-thumb {
|
|
||||||
background: var(--ks-border-primary) !important;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm--mobile-bg {
|
|
||||||
border-radius: 0 var(--bs-border-radius) var(--bs-border-radius) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm_collapsed {
|
|
||||||
.logo {
|
|
||||||
> * {
|
|
||||||
left: 10px;
|
|
||||||
|
|
||||||
span.img {
|
|
||||||
background-size: 207px 55px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm--link {
|
|
||||||
padding-left: 13px;
|
|
||||||
&.vsm--link_hover {
|
|
||||||
background-color: var(--ks-button-background-primary);
|
|
||||||
color: var(--ks-button-content-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vsm--item {
|
|
||||||
padding: 0 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-button {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tooltip__trigger .lock-icon.material-design-icon > .material-design-icon__svg {
|
|
||||||
bottom: 0 !important;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.vsm--item {
|
.vsm--item {
|
||||||
position: relative;
|
padding: 0 5px;
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 10px;
|
|
||||||
height: 1.25rem;
|
|
||||||
z-index: 5;
|
|
||||||
background: linear-gradient(to top, var(--ks-background-left-menu), transparent);
|
|
||||||
opacity: 0.18;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
.el-button {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tooltip__trigger .lock-icon.material-design-icon>.material-design-icon__svg {
|
||||||
|
bottom: 0 !important;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vsm--item {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 10px;
|
||||||
|
height: 1.25rem;
|
||||||
|
z-index: 5;
|
||||||
|
background: linear-gradient(to top, var(--ks-background-left-menu), transparent);
|
||||||
|
opacity: 0.18;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "Nach Trigger-ID filtern",
|
"description": "Nach Trigger-ID filtern",
|
||||||
"label": "Trigger-ID"
|
"label": "Trigger-ID"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "Nach Trigger-Zustand filtern",
|
||||||
|
"disabled": "Deaktiviert",
|
||||||
|
"enabled": "Aktiviert",
|
||||||
|
"label": "Trigger-Zustand"
|
||||||
|
},
|
||||||
"update": "Aktualisieren",
|
"update": "Aktualisieren",
|
||||||
"value": "Wert",
|
"value": "Wert",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "oder benutzerdefinierte Dauer eingeben:",
|
"input_custom_duration": "oder benutzerdefinierte Dauer eingeben:",
|
||||||
"inputs": "Inputs",
|
"inputs": "Inputs",
|
||||||
"instance": "Instanz",
|
"instance": "Instanz",
|
||||||
|
"instance_administration": "Instanzverwaltung",
|
||||||
"invalid bulk delete": "Ausführungen konnten nicht gelöscht werden",
|
"invalid bulk delete": "Ausführungen konnten nicht gelöscht werden",
|
||||||
"invalid bulk force run": "Konnte Ausführungen nicht erzwingen",
|
"invalid bulk force run": "Konnte Ausführungen nicht erzwingen",
|
||||||
"invalid bulk kill": "Ausführungen konnten nicht beendet werden",
|
"invalid bulk kill": "Ausführungen konnten nicht beendet werden",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "Weiter",
|
"next": "Weiter",
|
||||||
"no_flows": "Keine Flows unter der tutorial Namespace verfügbar.",
|
"no_flows": "Keine Flows unter der tutorial Namespace verfügbar.",
|
||||||
"previous": "Zurück",
|
"previous": "Zurück",
|
||||||
"skip": "Tutorial überspringen",
|
"skip": "Produkt-Tour überspringen",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "Wir freuen uns, dass Sie hier sind.<br />Lassen Sie uns Ihren ersten Flow erstellen.",
|
"content": "Wir freuen uns, dass Sie hier sind.<br />Lassen Sie uns Ihren ersten Flow erstellen.",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "Mandanten"
|
"names": "Mandanten"
|
||||||
},
|
},
|
||||||
"tenantId": "Mandanten-ID",
|
"tenantId": "Mandanten-ID",
|
||||||
|
"tenant_administration": "Mandantenverwaltung",
|
||||||
"test-badge-text": "Test",
|
"test-badge-text": "Test",
|
||||||
"test-badge-tooltip": "Diese Ausführung wurde durch einen Test erstellt",
|
"test-badge-tooltip": "Diese Ausführung wurde durch einen Test erstellt",
|
||||||
"theme": "Modus",
|
"theme": "Modus",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 Willkommen bei Kestra!",
|
"welcome aboard": "🚀 Willkommen bei Kestra!",
|
||||||
"welcome aboard content": "Nutzen Sie unsere geführte Tour, um Ihren ersten Flow zu erstellen, und schauen Sie sich Blueprints an, um weitere Beispiele zu finden.",
|
"welcome aboard content": "Nutzen Sie unsere geführte Tour, um Ihren ersten Flow zu erstellen, und schauen Sie sich Blueprints an, um weitere Beispiele zu finden.",
|
||||||
"welcome button create": "Meinen ersten Flow erstellen",
|
"welcome button create": "Produkt-Tour starten",
|
||||||
"welcome display require": "Führen Sie Ihren <strong>ersten Flow</strong> aus, um loszulegen",
|
"welcome display require": "Führen Sie Ihren <strong>ersten Flow</strong> aus, um loszulegen",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "Benötigen Sie Unterstützung, um Ihren ersten flow auszuführen?",
|
"guide": "Benötigen Sie Unterstützung, um Ihren ersten flow auszuführen?",
|
||||||
|
|||||||
@@ -391,6 +391,8 @@
|
|||||||
"conditions": "Conditions",
|
"conditions": "Conditions",
|
||||||
"triggerId": "Trigger ID",
|
"triggerId": "Trigger ID",
|
||||||
"tenantId": "Tenant ID",
|
"tenantId": "Tenant ID",
|
||||||
|
"tenant_administration": "Tenant Administration",
|
||||||
|
"instance_administration": "Instance Administration",
|
||||||
"codeDisabled": "Disabled in Flow",
|
"codeDisabled": "Disabled in Flow",
|
||||||
"paused": "Paused",
|
"paused": "Paused",
|
||||||
"Fold auto": "Editor: automatic fold of multi-lines",
|
"Fold auto": "Editor: automatic fold of multi-lines",
|
||||||
@@ -538,7 +540,7 @@
|
|||||||
"welcome aboard": "\uD83D\uDE80 Welcome to Kestra!",
|
"welcome aboard": "\uD83D\uDE80 Welcome to Kestra!",
|
||||||
"welcome aboard content": "Use our Guided Tour to create your first flow and check Blueprints to find more examples.",
|
"welcome aboard content": "Use our Guided Tour to create your first flow and check Blueprints to find more examples.",
|
||||||
"welcome display require": "Run your <strong>first flow</strong> to get started",
|
"welcome display require": "Run your <strong>first flow</strong> to get started",
|
||||||
"welcome button create": "Create my first flow",
|
"welcome button create": "Start Product Tour",
|
||||||
"live help": "Live help",
|
"live help": "Live help",
|
||||||
"show task documentation": "Show task documentation",
|
"show task documentation": "Show task documentation",
|
||||||
"hide task documentation": "Hide task documentation",
|
"hide task documentation": "Hide task documentation",
|
||||||
@@ -945,7 +947,7 @@
|
|||||||
"next": "Next",
|
"next": "Next",
|
||||||
"previous": "Previous",
|
"previous": "Previous",
|
||||||
"finish": "Finish",
|
"finish": "Finish",
|
||||||
"skip": "Skip Tutorial",
|
"skip": "Skip Product Tour",
|
||||||
"no_flows": "No flows available under tutorial namespace.",
|
"no_flows": "No flows available under tutorial namespace.",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
@@ -1727,6 +1729,12 @@
|
|||||||
"label": "Trigger Execution ID",
|
"label": "Trigger Execution ID",
|
||||||
"description": "Filter by trigger execution ID"
|
"description": "Filter by trigger execution ID"
|
||||||
},
|
},
|
||||||
|
"triggerState":{
|
||||||
|
"label": " Trigger State",
|
||||||
|
"description": "Filter by trigger state",
|
||||||
|
"enabled": "Enabled",
|
||||||
|
"disabled": "Disabled"
|
||||||
|
},
|
||||||
"scope_flow": {
|
"scope_flow": {
|
||||||
"label": "Scope",
|
"label": "Scope",
|
||||||
"description": "Filter by flow scope"
|
"description": "Filter by flow scope"
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "Filtrar por trigger ID",
|
"description": "Filtrar por trigger ID",
|
||||||
"label": "ID de Trigger"
|
"label": "ID de Trigger"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "Filtrar por estado del trigger",
|
||||||
|
"disabled": "Desactivado",
|
||||||
|
"enabled": "Habilitado",
|
||||||
|
"label": "Estado del Trigger"
|
||||||
|
},
|
||||||
"update": "Actualizar",
|
"update": "Actualizar",
|
||||||
"value": "Valor",
|
"value": "Valor",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "o ingrese duración personalizada:",
|
"input_custom_duration": "o ingrese duración personalizada:",
|
||||||
"inputs": "Entradas",
|
"inputs": "Entradas",
|
||||||
"instance": "Instancia",
|
"instance": "Instancia",
|
||||||
|
"instance_administration": "Administración de Instancia",
|
||||||
"invalid bulk delete": "No se pudieron eliminar las ejecuciones",
|
"invalid bulk delete": "No se pudieron eliminar las ejecuciones",
|
||||||
"invalid bulk force run": "No se pudo forzar la ejecución de ejecuciones",
|
"invalid bulk force run": "No se pudo forzar la ejecución de ejecuciones",
|
||||||
"invalid bulk kill": "No se pudieron matar las ejecuciones",
|
"invalid bulk kill": "No se pudieron matar las ejecuciones",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "Siguiente",
|
"next": "Siguiente",
|
||||||
"no_flows": "No hay flows disponibles bajo el namespace del tutorial.",
|
"no_flows": "No hay flows disponibles bajo el namespace del tutorial.",
|
||||||
"previous": "Anterior",
|
"previous": "Anterior",
|
||||||
"skip": "Saltar Tutorial",
|
"skip": "Omitir recorrido del producto",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "Estamos encantados de tenerte aquí.<br />Vamos a crear tu primer flow.",
|
"content": "Estamos encantados de tenerte aquí.<br />Vamos a crear tu primer flow.",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "Arrendatarios"
|
"names": "Arrendatarios"
|
||||||
},
|
},
|
||||||
"tenantId": "ID de Mandante",
|
"tenantId": "ID de Mandante",
|
||||||
|
"tenant_administration": "Administración de Mandantes",
|
||||||
"test-badge-text": "Prueba",
|
"test-badge-text": "Prueba",
|
||||||
"test-badge-tooltip": "Esta ejecución fue creada por una prueba",
|
"test-badge-tooltip": "Esta ejecución fue creada por una prueba",
|
||||||
"theme": "Tema",
|
"theme": "Tema",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 ¡Bienvenido a Kestra!",
|
"welcome aboard": "🚀 ¡Bienvenido a Kestra!",
|
||||||
"welcome aboard content": "Usa nuestro Tour Guiado para crear tu primer flow y revisa los Blueprints para encontrar más ejemplos.",
|
"welcome aboard content": "Usa nuestro Tour Guiado para crear tu primer flow y revisa los Blueprints para encontrar más ejemplos.",
|
||||||
"welcome button create": "Crear mi primer flow",
|
"welcome button create": "Iniciar Tour del Producto",
|
||||||
"welcome display require": "Ejecuta tu <strong>primer flow</strong> para comenzar",
|
"welcome display require": "Ejecuta tu <strong>primer flow</strong> para comenzar",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "¿Necesitas orientación para ejecutar tu primer flow?",
|
"guide": "¿Necesitas orientación para ejecutar tu primer flow?",
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "Filtrer par trigger ID",
|
"description": "Filtrer par trigger ID",
|
||||||
"label": "ID du trigger"
|
"label": "ID du trigger"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "Filtrer par état du trigger",
|
||||||
|
"disabled": "Désactivé",
|
||||||
|
"enabled": "Activé",
|
||||||
|
"label": "État du Trigger"
|
||||||
|
},
|
||||||
"update": "Mettre à jour",
|
"update": "Mettre à jour",
|
||||||
"value": "Valeur",
|
"value": "Valeur",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "ou saisir une durée personnalisée :",
|
"input_custom_duration": "ou saisir une durée personnalisée :",
|
||||||
"inputs": "Entrées",
|
"inputs": "Entrées",
|
||||||
"instance": "Instance",
|
"instance": "Instance",
|
||||||
|
"instance_administration": "Administration de l'Instance",
|
||||||
"invalid bulk delete": "Impossible de supprimer les exécutions",
|
"invalid bulk delete": "Impossible de supprimer les exécutions",
|
||||||
"invalid bulk force run": "Impossible de forcer l'exécution des exécutions",
|
"invalid bulk force run": "Impossible de forcer l'exécution des exécutions",
|
||||||
"invalid bulk kill": "Impossible d'arrêter les exécutions",
|
"invalid bulk kill": "Impossible d'arrêter les exécutions",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "Suivant",
|
"next": "Suivant",
|
||||||
"no_flows": "Aucun flux disponible dans l'espace de noms du tutoriel.",
|
"no_flows": "Aucun flux disponible dans l'espace de noms du tutoriel.",
|
||||||
"previous": "Précédent",
|
"previous": "Précédent",
|
||||||
"skip": "Passer le tutoriel",
|
"skip": "Passer la visite guidée du produit",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "Nous sommes ravis de vous avoir ici.<br />Créons votre premier flux.",
|
"content": "Nous sommes ravis de vous avoir ici.<br />Créons votre premier flux.",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "Mandants"
|
"names": "Mandants"
|
||||||
},
|
},
|
||||||
"tenantId": "ID du mandant",
|
"tenantId": "ID du mandant",
|
||||||
|
"tenant_administration": "Administration des Mandants",
|
||||||
"test-badge-text": "Test",
|
"test-badge-text": "Test",
|
||||||
"test-badge-tooltip": "Cette exécution a été créée par un Test",
|
"test-badge-tooltip": "Cette exécution a été créée par un Test",
|
||||||
"theme": "Thème",
|
"theme": "Thème",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 Bienvenue à bord !",
|
"welcome aboard": "🚀 Bienvenue à bord !",
|
||||||
"welcome aboard content": "Tout est prêt pour Kestra, commencez la création de votre flow et admirez la magie !",
|
"welcome aboard content": "Tout est prêt pour Kestra, commencez la création de votre flow et admirez la magie !",
|
||||||
"welcome button create": "Créer mon premier flow",
|
"welcome button create": "Démarrer la visite guidée du produit",
|
||||||
"welcome display require": "Prêt à commencer à utiliser Kestra ? Créons ensemble <strong>votre premier flow</strong> !",
|
"welcome display require": "Prêt à commencer à utiliser Kestra ? Créons ensemble <strong>votre premier flow</strong> !",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "Besoin d'aide pour exécuter votre premier flow ?",
|
"guide": "Besoin d'aide pour exécuter votre premier flow ?",
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "ट्रिगर ID द्वारा फ़िल्टर करें",
|
"description": "ट्रिगर ID द्वारा फ़िल्टर करें",
|
||||||
"label": "ट्रिगर ID"
|
"label": "ट्रिगर ID"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "ट्रिगर स्थिति द्वारा फ़िल्टर करें",
|
||||||
|
"disabled": "अक्षम",
|
||||||
|
"enabled": "सक्रिय",
|
||||||
|
"label": "ट्रिगर स्थिति"
|
||||||
|
},
|
||||||
"update": "अपडेट",
|
"update": "अपडेट",
|
||||||
"value": "मान",
|
"value": "मान",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "या कस्टम अवधि दर्ज करें:",
|
"input_custom_duration": "या कस्टम अवधि दर्ज करें:",
|
||||||
"inputs": "इनपुट्स",
|
"inputs": "इनपुट्स",
|
||||||
"instance": "इंस्टेंस",
|
"instance": "इंस्टेंस",
|
||||||
|
"instance_administration": "इंस्टेंस प्रशासन",
|
||||||
"invalid bulk delete": "निष्पादन हटाने में असमर्थ",
|
"invalid bulk delete": "निष्पादन हटाने में असमर्थ",
|
||||||
"invalid bulk force run": "निष्पादन को जबरन चलाने में असमर्थ",
|
"invalid bulk force run": "निष्पादन को जबरन चलाने में असमर्थ",
|
||||||
"invalid bulk kill": "निष्पादन kill करने में असमर्थ",
|
"invalid bulk kill": "निष्पादन kill करने में असमर्थ",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "अगला",
|
"next": "अगला",
|
||||||
"no_flows": "ट्यूटोरियल namespace के अंतर्गत कोई flows उपलब्ध नहीं हैं।",
|
"no_flows": "ट्यूटोरियल namespace के अंतर्गत कोई flows उपलब्ध नहीं हैं।",
|
||||||
"previous": "पिछला",
|
"previous": "पिछला",
|
||||||
"skip": "ट्यूटोरियल छोड़ें",
|
"skip": "उत्पाद टूर छोड़ें",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "हमें खुशी है कि आप यहाँ हैं।<br />आइए अपना पहला flow बनाएं।",
|
"content": "हमें खुशी है कि आप यहाँ हैं।<br />आइए अपना पहला flow बनाएं।",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "मंडल"
|
"names": "मंडल"
|
||||||
},
|
},
|
||||||
"tenantId": "टेनेंट ID",
|
"tenantId": "टेनेंट ID",
|
||||||
|
"tenant_administration": "किरायेदार प्रशासन",
|
||||||
"test-badge-text": "परीक्षण",
|
"test-badge-text": "परीक्षण",
|
||||||
"test-badge-tooltip": "यह execution एक Test द्वारा बनाया गया था",
|
"test-badge-tooltip": "यह execution एक Test द्वारा बनाया गया था",
|
||||||
"theme": "थीम",
|
"theme": "थीम",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 केस्ट्रा में आपका स्वागत है!",
|
"welcome aboard": "🚀 केस्ट्रा में आपका स्वागत है!",
|
||||||
"welcome aboard content": "अपना पहला flow बनाने के लिए हमारे Guided Tour का उपयोग करें और अधिक उदाहरण खोजने के लिए Blueprints देखें।",
|
"welcome aboard content": "अपना पहला flow बनाने के लिए हमारे Guided Tour का उपयोग करें और अधिक उदाहरण खोजने के लिए Blueprints देखें।",
|
||||||
"welcome button create": "मेरा पहला flow बनाएं",
|
"welcome button create": "उत्पाद यात्रा शुरू करें",
|
||||||
"welcome display require": "शुरू करने के लिए अपना <strong>पहला flow</strong> चलाएँ",
|
"welcome display require": "शुरू करने के लिए अपना <strong>पहला flow</strong> चलाएँ",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "क्या आपको अपना पहला flow निष्पादित करने के लिए मार्गदर्शन चाहिए?",
|
"guide": "क्या आपको अपना पहला flow निष्पादित करने के लिए मार्गदर्शन चाहिए?",
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "Filtra per trigger ID",
|
"description": "Filtra per trigger ID",
|
||||||
"label": "ID del trigger"
|
"label": "ID del trigger"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "Filtra per stato del trigger",
|
||||||
|
"disabled": "Disabilitato",
|
||||||
|
"enabled": "Abilitato",
|
||||||
|
"label": "Stato del Trigger"
|
||||||
|
},
|
||||||
"update": "Aggiorna",
|
"update": "Aggiorna",
|
||||||
"value": "Valore",
|
"value": "Valore",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "oppure inserisci durata personalizzata:",
|
"input_custom_duration": "oppure inserisci durata personalizzata:",
|
||||||
"inputs": "Inputs",
|
"inputs": "Inputs",
|
||||||
"instance": "Istanza",
|
"instance": "Istanza",
|
||||||
|
"instance_administration": "Amministrazione dell'istanza",
|
||||||
"invalid bulk delete": "Impossibile eliminare le esecuzioni",
|
"invalid bulk delete": "Impossibile eliminare le esecuzioni",
|
||||||
"invalid bulk force run": "Impossibile forzare l'esecuzione delle esecuzioni",
|
"invalid bulk force run": "Impossibile forzare l'esecuzione delle esecuzioni",
|
||||||
"invalid bulk kill": "Impossibile kill le esecuzioni",
|
"invalid bulk kill": "Impossibile kill le esecuzioni",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "Successivo",
|
"next": "Successivo",
|
||||||
"no_flows": "Nessun flow disponibile sotto il namespace del tutorial.",
|
"no_flows": "Nessun flow disponibile sotto il namespace del tutorial.",
|
||||||
"previous": "Precedente",
|
"previous": "Precedente",
|
||||||
"skip": "Salta Tutorial",
|
"skip": "Salta il Tour del Prodotto",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "Siamo entusiasti di averti qui.<br />Creiamo il tuo primo flow.",
|
"content": "Siamo entusiasti di averti qui.<br />Creiamo il tuo primo flow.",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "Mandanti"
|
"names": "Mandanti"
|
||||||
},
|
},
|
||||||
"tenantId": "ID del Mandante",
|
"tenantId": "ID del Mandante",
|
||||||
|
"tenant_administration": "Amministrazione del Mandante",
|
||||||
"test-badge-text": "Test",
|
"test-badge-text": "Test",
|
||||||
"test-badge-tooltip": "Questa esecuzione è stata creata da un Test",
|
"test-badge-tooltip": "Questa esecuzione è stata creata da un Test",
|
||||||
"theme": "Tema",
|
"theme": "Tema",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 Benvenuto su Kestra!",
|
"welcome aboard": "🚀 Benvenuto su Kestra!",
|
||||||
"welcome aboard content": "Usa il nostro Tour Guidato per creare il tuo primo flow e controlla i Blueprints per trovare altri esempi.",
|
"welcome aboard content": "Usa il nostro Tour Guidato per creare il tuo primo flow e controlla i Blueprints per trovare altri esempi.",
|
||||||
"welcome button create": "Crea il mio primo flow",
|
"welcome button create": "Inizia il Tour del Prodotto",
|
||||||
"welcome display require": "Esegui il tuo <strong>primo flow</strong> per iniziare",
|
"welcome display require": "Esegui il tuo <strong>primo flow</strong> per iniziare",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "Hai bisogno di assistenza per eseguire il tuo primo flow?",
|
"guide": "Hai bisogno di assistenza per eseguire il tuo primo flow?",
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "トリガーIDでフィルター",
|
"description": "トリガーIDでフィルター",
|
||||||
"label": "トリガーID"
|
"label": "トリガーID"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "トリガー状態でフィルター",
|
||||||
|
"disabled": "無効",
|
||||||
|
"enabled": "有効",
|
||||||
|
"label": "トリガー状態"
|
||||||
|
},
|
||||||
"update": "更新",
|
"update": "更新",
|
||||||
"value": "値",
|
"value": "値",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "またはカスタム期間を入力してください:",
|
"input_custom_duration": "またはカスタム期間を入力してください:",
|
||||||
"inputs": "Inputs",
|
"inputs": "Inputs",
|
||||||
"instance": "インスタンス",
|
"instance": "インスタンス",
|
||||||
|
"instance_administration": "インスタンス管理",
|
||||||
"invalid bulk delete": "実行を削除できませんでした",
|
"invalid bulk delete": "実行を削除できませんでした",
|
||||||
"invalid bulk force run": "実行を強制的に開始できませんでした",
|
"invalid bulk force run": "実行を強制的に開始できませんでした",
|
||||||
"invalid bulk kill": "実行をkillできませんでした",
|
"invalid bulk kill": "実行をkillできませんでした",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "次へ",
|
"next": "次へ",
|
||||||
"no_flows": "チュートリアルnamespaceに利用可能なflowはありません。",
|
"no_flows": "チュートリアルnamespaceに利用可能なflowはありません。",
|
||||||
"previous": "前へ",
|
"previous": "前へ",
|
||||||
"skip": "チュートリアルをスキップ",
|
"skip": "プロダクトツアーをスキップ",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "ここに来てくれてとても嬉しいです。<br />最初のflowを作成しましょう。",
|
"content": "ここに来てくれてとても嬉しいです。<br />最初のflowを作成しましょう。",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "テナント"
|
"names": "テナント"
|
||||||
},
|
},
|
||||||
"tenantId": "テナントID",
|
"tenantId": "テナントID",
|
||||||
|
"tenant_administration": "テナント管理",
|
||||||
"test-badge-text": "テスト",
|
"test-badge-text": "テスト",
|
||||||
"test-badge-tooltip": "この実行はテストによって作成されました",
|
"test-badge-tooltip": "この実行はテストによって作成されました",
|
||||||
"theme": "テーマ",
|
"theme": "テーマ",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 Kestraへようこそ!",
|
"welcome aboard": "🚀 Kestraへようこそ!",
|
||||||
"welcome aboard content": "ガイド付きツアーを利用して最初のflowを作成し、Blueprintsでさらに多くの例を見つけてください。",
|
"welcome aboard content": "ガイド付きツアーを利用して最初のflowを作成し、Blueprintsでさらに多くの例を見つけてください。",
|
||||||
"welcome button create": "最初のflowを作成",
|
"welcome button create": "プロダクトツアーを開始",
|
||||||
"welcome display require": "<strong>最初のflow</strong>を実行して始めましょう",
|
"welcome display require": "<strong>最初のflow</strong>を実行して始めましょう",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "最初のflowを実行するためのガイダンスが必要ですか?",
|
"guide": "最初のflowを実行するためのガイダンスが必要ですか?",
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "트리거 ID로 필터링",
|
"description": "트리거 ID로 필터링",
|
||||||
"label": "트리거 ID"
|
"label": "트리거 ID"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "트리거 상태별 필터링",
|
||||||
|
"disabled": "비활성화됨",
|
||||||
|
"enabled": "사용 가능",
|
||||||
|
"label": "트리거 상태"
|
||||||
|
},
|
||||||
"update": "업데이트",
|
"update": "업데이트",
|
||||||
"value": "값",
|
"value": "값",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "또는 사용자 지정 기간 입력:",
|
"input_custom_duration": "또는 사용자 지정 기간 입력:",
|
||||||
"inputs": "Inputs",
|
"inputs": "Inputs",
|
||||||
"instance": "인스턴스",
|
"instance": "인스턴스",
|
||||||
|
"instance_administration": "인스턴스 관리",
|
||||||
"invalid bulk delete": "실행을 삭제할 수 없습니다",
|
"invalid bulk delete": "실행을 삭제할 수 없습니다",
|
||||||
"invalid bulk force run": "실행을 강제로 실행할 수 없습니다.",
|
"invalid bulk force run": "실행을 강제로 실행할 수 없습니다.",
|
||||||
"invalid bulk kill": "실행을 강제 종료할 수 없습니다",
|
"invalid bulk kill": "실행을 강제 종료할 수 없습니다",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "다음",
|
"next": "다음",
|
||||||
"no_flows": "튜토리얼 namespace에 사용할 수 있는 flow가 없습니다.",
|
"no_flows": "튜토리얼 namespace에 사용할 수 있는 flow가 없습니다.",
|
||||||
"previous": "이전",
|
"previous": "이전",
|
||||||
"skip": "튜토리얼 건너뛰기",
|
"skip": "제품 투어 건너뛰기",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "여기 오신 것을 환영합니다.<br />첫 번째 flow를 만들어 봅시다.",
|
"content": "여기 오신 것을 환영합니다.<br />첫 번째 flow를 만들어 봅시다.",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "테넌트"
|
"names": "테넌트"
|
||||||
},
|
},
|
||||||
"tenantId": "테넌트 ID",
|
"tenantId": "테넌트 ID",
|
||||||
|
"tenant_administration": "테넌트 관리",
|
||||||
"test-badge-text": "테스트",
|
"test-badge-text": "테스트",
|
||||||
"test-badge-tooltip": "이 실행은 테스트에 의해 생성되었습니다.",
|
"test-badge-tooltip": "이 실행은 테스트에 의해 생성되었습니다.",
|
||||||
"theme": "테마",
|
"theme": "테마",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 Kestra에 오신 것을 환영합니다!",
|
"welcome aboard": "🚀 Kestra에 오신 것을 환영합니다!",
|
||||||
"welcome aboard content": "가이드 투어를 사용하여 첫 번째 flow를 만들고 Blueprints에서 더 많은 예제를 확인하세요.",
|
"welcome aboard content": "가이드 투어를 사용하여 첫 번째 flow를 만들고 Blueprints에서 더 많은 예제를 확인하세요.",
|
||||||
"welcome button create": "첫 번째 flow 만들기",
|
"welcome button create": "제품 투어 시작",
|
||||||
"welcome display require": "<strong>첫 번째 flow</strong>를 실행하여 시작하세요",
|
"welcome display require": "<strong>첫 번째 flow</strong>를 실행하여 시작하세요",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "첫 번째 flow를 실행하는 데 도움이 필요하신가요?",
|
"guide": "첫 번째 flow를 실행하는 데 도움이 필요하신가요?",
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "Filtruj według trigger ID",
|
"description": "Filtruj według trigger ID",
|
||||||
"label": "Identyfikator Trigger"
|
"label": "Identyfikator Trigger"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "Filtruj według stanu triggera",
|
||||||
|
"disabled": "Wyłączone",
|
||||||
|
"enabled": "Włączone",
|
||||||
|
"label": "Stan Trigger"
|
||||||
|
},
|
||||||
"update": "Aktualizuj",
|
"update": "Aktualizuj",
|
||||||
"value": "Wartość",
|
"value": "Wartość",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "lub wprowadź niestandardowy czas trwania:",
|
"input_custom_duration": "lub wprowadź niestandardowy czas trwania:",
|
||||||
"inputs": "Inputs",
|
"inputs": "Inputs",
|
||||||
"instance": "Instancja",
|
"instance": "Instancja",
|
||||||
|
"instance_administration": "Administracja Instancji",
|
||||||
"invalid bulk delete": "Nie można usunąć wykonań",
|
"invalid bulk delete": "Nie można usunąć wykonań",
|
||||||
"invalid bulk force run": "Nie można wymusić uruchomienia wykonania",
|
"invalid bulk force run": "Nie można wymusić uruchomienia wykonania",
|
||||||
"invalid bulk kill": "Nie można zabić wykonań",
|
"invalid bulk kill": "Nie można zabić wykonań",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "Następny",
|
"next": "Następny",
|
||||||
"no_flows": "Brak flowów w namespace o nazwie tutorial.",
|
"no_flows": "Brak flowów w namespace o nazwie tutorial.",
|
||||||
"previous": "Poprzedni",
|
"previous": "Poprzedni",
|
||||||
"skip": "Pomiń samouczek",
|
"skip": "Pomiń Przewodnik po Produkcie",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "Jesteśmy zachwyceni, że jesteś tutaj.<br />Stwórzmy twój pierwszy flow.",
|
"content": "Jesteśmy zachwyceni, że jesteś tutaj.<br />Stwórzmy twój pierwszy flow.",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "Najemcy"
|
"names": "Najemcy"
|
||||||
},
|
},
|
||||||
"tenantId": "Identyfikator Mandanta",
|
"tenantId": "Identyfikator Mandanta",
|
||||||
|
"tenant_administration": "Administracja Mandanta",
|
||||||
"test-badge-text": "Test",
|
"test-badge-text": "Test",
|
||||||
"test-badge-tooltip": "To wykonanie zostało utworzone przez Test.",
|
"test-badge-tooltip": "To wykonanie zostało utworzone przez Test.",
|
||||||
"theme": "Motyw",
|
"theme": "Motyw",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 Witamy w Kestra!",
|
"welcome aboard": "🚀 Witamy w Kestra!",
|
||||||
"welcome aboard content": "Skorzystaj z naszego Przewodnika, aby stworzyć swój pierwszy flow i sprawdź Blueprints, aby znaleźć więcej przykładów.",
|
"welcome aboard content": "Skorzystaj z naszego Przewodnika, aby stworzyć swój pierwszy flow i sprawdź Blueprints, aby znaleźć więcej przykładów.",
|
||||||
"welcome button create": "Stwórz mój pierwszy flow",
|
"welcome button create": "Rozpocznij Przewodnik po Produkcie",
|
||||||
"welcome display require": "Uruchom swój <strong>pierwszy flow</strong>, aby rozpocząć",
|
"welcome display require": "Uruchom swój <strong>pierwszy flow</strong>, aby rozpocząć",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "Potrzebujesz wskazówek, jak uruchomić swój pierwszy flow?",
|
"guide": "Potrzebujesz wskazówek, jak uruchomić swój pierwszy flow?",
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "Filtrar por trigger ID",
|
"description": "Filtrar por trigger ID",
|
||||||
"label": "ID do Trigger"
|
"label": "ID do Trigger"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "Filtrar por estado do trigger",
|
||||||
|
"disabled": "Desativado",
|
||||||
|
"enabled": "Habilitado",
|
||||||
|
"label": "Estado do Trigger"
|
||||||
|
},
|
||||||
"update": "Atualizar",
|
"update": "Atualizar",
|
||||||
"value": "Valor",
|
"value": "Valor",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "ou insira uma duração personalizada:",
|
"input_custom_duration": "ou insira uma duração personalizada:",
|
||||||
"inputs": "Inputs",
|
"inputs": "Inputs",
|
||||||
"instance": "Instância",
|
"instance": "Instância",
|
||||||
|
"instance_administration": "Administração da Instância",
|
||||||
"invalid bulk delete": "Não foi possível deletar execuções",
|
"invalid bulk delete": "Não foi possível deletar execuções",
|
||||||
"invalid bulk force run": "Não foi possível forçar a execução das execuções",
|
"invalid bulk force run": "Não foi possível forçar a execução das execuções",
|
||||||
"invalid bulk kill": "Não foi possível matar execuções",
|
"invalid bulk kill": "Não foi possível matar execuções",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "Próximo",
|
"next": "Próximo",
|
||||||
"no_flows": "Não há flows disponíveis no namespace do tutorial.",
|
"no_flows": "Não há flows disponíveis no namespace do tutorial.",
|
||||||
"previous": "Anterior",
|
"previous": "Anterior",
|
||||||
"skip": "Pular Tutorial",
|
"skip": "Pular Tour do Produto",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "Estamos entusiasmados em tê-lo aqui.<br />Vamos criar seu primeiro flow.",
|
"content": "Estamos entusiasmados em tê-lo aqui.<br />Vamos criar seu primeiro flow.",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "Mandantes"
|
"names": "Mandantes"
|
||||||
},
|
},
|
||||||
"tenantId": "ID do Mandante",
|
"tenantId": "ID do Mandante",
|
||||||
|
"tenant_administration": "Administração do Mandante",
|
||||||
"test-badge-text": "Teste",
|
"test-badge-text": "Teste",
|
||||||
"test-badge-tooltip": "Esta execução foi criada por um Teste",
|
"test-badge-tooltip": "Esta execução foi criada por um Teste",
|
||||||
"theme": "Tema",
|
"theme": "Tema",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 Bem-vindo ao Kestra!",
|
"welcome aboard": "🚀 Bem-vindo ao Kestra!",
|
||||||
"welcome aboard content": "Use nosso Tour Guiado para criar seu primeiro flow e confira os Blueprints para encontrar mais exemplos.",
|
"welcome aboard content": "Use nosso Tour Guiado para criar seu primeiro flow e confira os Blueprints para encontrar mais exemplos.",
|
||||||
"welcome button create": "Criar meu primeiro flow",
|
"welcome button create": "Iniciar Tour do Produto",
|
||||||
"welcome display require": "Execute seu <strong>primeiro flow</strong> para começar",
|
"welcome display require": "Execute seu <strong>primeiro flow</strong> para começar",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "Precisa de orientação para executar seu primeiro flow?",
|
"guide": "Precisa de orientação para executar seu primeiro flow?",
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "Filtrar por trigger ID",
|
"description": "Filtrar por trigger ID",
|
||||||
"label": "ID do Trigger"
|
"label": "ID do Trigger"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "Filtrar por estado do trigger",
|
||||||
|
"disabled": "Desativado",
|
||||||
|
"enabled": "Habilitado",
|
||||||
|
"label": "Estado do Trigger"
|
||||||
|
},
|
||||||
"update": "Atualizar",
|
"update": "Atualizar",
|
||||||
"value": "Valor",
|
"value": "Valor",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "ou insira uma duração personalizada:",
|
"input_custom_duration": "ou insira uma duração personalizada:",
|
||||||
"inputs": "Inputs",
|
"inputs": "Inputs",
|
||||||
"instance": "Instância",
|
"instance": "Instância",
|
||||||
|
"instance_administration": "Administração da Instância",
|
||||||
"invalid bulk delete": "Não foi possível excluir execuções",
|
"invalid bulk delete": "Não foi possível excluir execuções",
|
||||||
"invalid bulk force run": "Não foi possível forçar a execução das execuções",
|
"invalid bulk force run": "Não foi possível forçar a execução das execuções",
|
||||||
"invalid bulk kill": "Não foi possível matar execuções",
|
"invalid bulk kill": "Não foi possível matar execuções",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "Próximo",
|
"next": "Próximo",
|
||||||
"no_flows": "Não há flows disponíveis no namespace do tutorial.",
|
"no_flows": "Não há flows disponíveis no namespace do tutorial.",
|
||||||
"previous": "Anterior",
|
"previous": "Anterior",
|
||||||
"skip": "Pular Tutorial",
|
"skip": "Pular Tour do Produto",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "Estamos entusiasmados em tê-lo aqui.<br />Vamos criar seu primeiro flow.",
|
"content": "Estamos entusiasmados em tê-lo aqui.<br />Vamos criar seu primeiro flow.",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "Clientes"
|
"names": "Clientes"
|
||||||
},
|
},
|
||||||
"tenantId": "ID do Cliente",
|
"tenantId": "ID do Cliente",
|
||||||
|
"tenant_administration": "Administração de Tenant",
|
||||||
"test-badge-text": "Teste",
|
"test-badge-text": "Teste",
|
||||||
"test-badge-tooltip": "Esta execução foi criada por um Teste",
|
"test-badge-tooltip": "Esta execução foi criada por um Teste",
|
||||||
"theme": "Tema",
|
"theme": "Tema",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 Bem-vindo ao Kestra!",
|
"welcome aboard": "🚀 Bem-vindo ao Kestra!",
|
||||||
"welcome aboard content": "Use nosso Tour Guiado para criar seu primeiro flow e confira os Blueprints para encontrar mais exemplos.",
|
"welcome aboard content": "Use nosso Tour Guiado para criar seu primeiro flow e confira os Blueprints para encontrar mais exemplos.",
|
||||||
"welcome button create": "Criar meu primeiro flow",
|
"welcome button create": "Iniciar Tour do Produto",
|
||||||
"welcome display require": "Execute seu <strong>primeiro flow</strong> para começar",
|
"welcome display require": "Execute seu <strong>primeiro flow</strong> para começar",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "Precisa de orientação para executar seu primeiro flow?",
|
"guide": "Precisa de orientação para executar seu primeiro flow?",
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "Фильтр по trigger ID",
|
"description": "Фильтр по trigger ID",
|
||||||
"label": "ID триггера"
|
"label": "ID триггера"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "Фильтр по состоянию trigger",
|
||||||
|
"disabled": "Отключено",
|
||||||
|
"enabled": "Включено",
|
||||||
|
"label": "Состояние Trigger"
|
||||||
|
},
|
||||||
"update": "Обновить",
|
"update": "Обновить",
|
||||||
"value": "Значение",
|
"value": "Значение",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "или введите пользовательскую продолжительность:",
|
"input_custom_duration": "или введите пользовательскую продолжительность:",
|
||||||
"inputs": "Входные данные",
|
"inputs": "Входные данные",
|
||||||
"instance": "Экземпляр",
|
"instance": "Экземпляр",
|
||||||
|
"instance_administration": "Администрирование экземпляра",
|
||||||
"invalid bulk delete": "Не удалось удалить выполнения",
|
"invalid bulk delete": "Не удалось удалить выполнения",
|
||||||
"invalid bulk force run": "Не удалось принудительно запустить executions",
|
"invalid bulk force run": "Не удалось принудительно запустить executions",
|
||||||
"invalid bulk kill": "Не удалось убить выполнения",
|
"invalid bulk kill": "Не удалось убить выполнения",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "Далее",
|
"next": "Далее",
|
||||||
"no_flows": "Нет доступных flows в namespace учебника.",
|
"no_flows": "Нет доступных flows в namespace учебника.",
|
||||||
"previous": "Назад",
|
"previous": "Назад",
|
||||||
"skip": "Пропустить учебник",
|
"skip": "Пропустить ознакомительный тур с продуктом",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "Мы рады видеть вас здесь.<br />Давайте создадим ваш первый flow.",
|
"content": "Мы рады видеть вас здесь.<br />Давайте создадим ваш первый flow.",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "Арендаторы"
|
"names": "Арендаторы"
|
||||||
},
|
},
|
||||||
"tenantId": "ID арендатора",
|
"tenantId": "ID арендатора",
|
||||||
|
"tenant_administration": "Администрирование Манданта",
|
||||||
"test-badge-text": "Тест",
|
"test-badge-text": "Тест",
|
||||||
"test-badge-tooltip": "Это выполнение было создано тестом",
|
"test-badge-tooltip": "Это выполнение было создано тестом",
|
||||||
"theme": "Тема",
|
"theme": "Тема",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 Добро пожаловать в Kestra!",
|
"welcome aboard": "🚀 Добро пожаловать в Kestra!",
|
||||||
"welcome aboard content": "Используйте наше Руководство, чтобы создать ваш первый flow и ознакомьтесь с Blueprints для поиска дополнительных примеров.",
|
"welcome aboard content": "Используйте наше Руководство, чтобы создать ваш первый flow и ознакомьтесь с Blueprints для поиска дополнительных примеров.",
|
||||||
"welcome button create": "Создать мой первый flow",
|
"welcome button create": "Начать ознакомительный тур с продуктом",
|
||||||
"welcome display require": "Запустите ваш <strong>первый flow</strong>, чтобы начать",
|
"welcome display require": "Запустите ваш <strong>первый flow</strong>, чтобы начать",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "Нужна помощь в выполнении вашего первого flow?",
|
"guide": "Нужна помощь в выполнении вашего первого flow?",
|
||||||
|
|||||||
@@ -883,6 +883,12 @@
|
|||||||
"description": "按 trigger ID 筛选",
|
"description": "按 trigger ID 筛选",
|
||||||
"label": "触发器 ID"
|
"label": "触发器 ID"
|
||||||
},
|
},
|
||||||
|
"triggerState": {
|
||||||
|
"description": "按触发器状态筛选",
|
||||||
|
"disabled": "禁用",
|
||||||
|
"enabled": "启用",
|
||||||
|
"label": "触发状态"
|
||||||
|
},
|
||||||
"update": "更新",
|
"update": "更新",
|
||||||
"value": "值",
|
"value": "值",
|
||||||
"workerId": {
|
"workerId": {
|
||||||
@@ -1005,6 +1011,7 @@
|
|||||||
"input_custom_duration": "或输入自定义持续时间:",
|
"input_custom_duration": "或输入自定义持续时间:",
|
||||||
"inputs": "输入",
|
"inputs": "输入",
|
||||||
"instance": "实例",
|
"instance": "实例",
|
||||||
|
"instance_administration": "实例管理",
|
||||||
"invalid bulk delete": "无法删除执行",
|
"invalid bulk delete": "无法删除执行",
|
||||||
"invalid bulk force run": "无法强制运行执行",
|
"invalid bulk force run": "无法强制运行执行",
|
||||||
"invalid bulk kill": "无法终止执行",
|
"invalid bulk kill": "无法终止执行",
|
||||||
@@ -1307,7 +1314,7 @@
|
|||||||
"next": "下一步",
|
"next": "下一步",
|
||||||
"no_flows": "教程命名空间下没有可用的流程。",
|
"no_flows": "教程命名空间下没有可用的流程。",
|
||||||
"previous": "上一步",
|
"previous": "上一步",
|
||||||
"skip": "跳过教程",
|
"skip": "跳过产品指南",
|
||||||
"steps": {
|
"steps": {
|
||||||
"0": {
|
"0": {
|
||||||
"content": "我们很高兴你在这里。<br />让我们创建你的第一个流程。",
|
"content": "我们很高兴你在这里。<br />让我们创建你的第一个流程。",
|
||||||
@@ -1737,6 +1744,7 @@
|
|||||||
"names": "租户"
|
"names": "租户"
|
||||||
},
|
},
|
||||||
"tenantId": "租户 ID",
|
"tenantId": "租户 ID",
|
||||||
|
"tenant_administration": "租户管理",
|
||||||
"test-badge-text": "测试",
|
"test-badge-text": "测试",
|
||||||
"test-badge-tooltip": "此执行由测试创建",
|
"test-badge-tooltip": "此执行由测试创建",
|
||||||
"theme": "主题",
|
"theme": "主题",
|
||||||
@@ -1855,7 +1863,7 @@
|
|||||||
},
|
},
|
||||||
"welcome aboard": "🚀 欢迎使用 Kestra!",
|
"welcome aboard": "🚀 欢迎使用 Kestra!",
|
||||||
"welcome aboard content": "使用我们的引导游览来创建你的第一个流程,并查看蓝图以找到更多示例。",
|
"welcome aboard content": "使用我们的引导游览来创建你的第一个流程,并查看蓝图以找到更多示例。",
|
||||||
"welcome button create": "创建我的第一个流程",
|
"welcome button create": "开始产品导览",
|
||||||
"welcome display require": "运行你的 <strong>第一个流程</strong> 以开始",
|
"welcome display require": "运行你的 <strong>第一个流程</strong> 以开始",
|
||||||
"welcome_page": {
|
"welcome_page": {
|
||||||
"guide": "需要指导来执行您的第一个flow吗?",
|
"guide": "需要指导来执行您的第一个flow吗?",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class ConcurrencyLimitController {
|
|||||||
|
|
||||||
@ExecuteOn(TaskExecutors.IO)
|
@ExecuteOn(TaskExecutors.IO)
|
||||||
@Get(uri = "/search")
|
@Get(uri = "/search")
|
||||||
@Operation(tags = {"Flows", "Executions"}, summary = "Search for flow concurrency limits")
|
@Operation(tags = {"Flows"}, summary = "Search for flow concurrency limits")
|
||||||
public PagedResults<ConcurrencyLimit> searchConcurrencyLimits() {
|
public PagedResults<ConcurrencyLimit> searchConcurrencyLimits() {
|
||||||
var results = concurrencyLimitService.find(tenantService.resolveTenant());
|
var results = concurrencyLimitService.find(tenantService.resolveTenant());
|
||||||
return PagedResults.of(new ArrayListTotal<>(results, results.size()));
|
return PagedResults.of(new ArrayListTotal<>(results, results.size()));
|
||||||
@@ -33,7 +33,7 @@ public class ConcurrencyLimitController {
|
|||||||
|
|
||||||
@ExecuteOn(TaskExecutors.IO)
|
@ExecuteOn(TaskExecutors.IO)
|
||||||
@Put("/{namespace}/{flowId}")
|
@Put("/{namespace}/{flowId}")
|
||||||
@Operation(tags = {"Flows", "Executions"}, summary = "Update a flow concurrency limit")
|
@Operation(tags = {"Flows"}, summary = "Update a flow concurrency limit")
|
||||||
public HttpResponse<ConcurrencyLimit> updateConcurrencyLimit(@Body ConcurrencyLimit concurrencyLimit) {
|
public HttpResponse<ConcurrencyLimit> updateConcurrencyLimit(@Body ConcurrencyLimit concurrencyLimit) {
|
||||||
var existing = concurrencyLimitService.findById(concurrencyLimit.getTenantId(), concurrencyLimit.getNamespace(), concurrencyLimit.getFlowId());
|
var existing = concurrencyLimitService.findById(concurrencyLimit.getTenantId(), concurrencyLimit.getNamespace(), concurrencyLimit.getFlowId());
|
||||||
if (existing.isEmpty()) {
|
if (existing.isEmpty()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user