Compare commits

..

6 Commits

Author SHA1 Message Date
Miloš Paunović
cb31e48f4f chore(core): improve file organization in .github folder (#13836) 2025-12-25 16:00:11 +01:00
Miloš Paunović
a3f96a2741 chore(core): make left menu appear as overlay on small screens (#13834)
Closes https://github.com/kestra-io/kestra/issues/1425.
Closes https://github.com/kestra-io/kestra/issues/13502.
Closes https://github.com/kestra-io/kestra/issues/13503.
Closes https://github.com/kestra-io/kestra/issues/13504.
Closes https://github.com/kestra-io/kestra/issues/13505.
Closes https://github.com/kestra-io/kestra/issues/13506.
Closes https://github.com/kestra-io/kestra/issues/13507.
Closes https://github.com/kestra-io/kestra/issues/13508.
Closes https://github.com/kestra-io/kestra/issues/13510.
Closes https://github.com/kestra-io/kestra/issues/13511.
Closes https://github.com/kestra-io/kestra/issues/13512.
Closes https://github.com/kestra-io/kestra/issues/13513.
Closes https://github.com/kestra-io/kestra/issues/13514.
Closes https://github.com/kestra-io/kestra/issues/13516.
2025-12-25 14:29:56 +01:00
Miloš Paunović
5ca6fa8d77 fix(secrets): mark secret field required during creation (#13833)
Closes https://github.com/kestra-io/kestra-ee/issues/6209.
2025-12-25 10:54:55 +01:00
Miloš Paunović
a3a206f3c4 chore(core): polishing of templated blueprints ui (#13806)
Related to https://github.com/kestra-io/kestra-ee/pull/6201.

Closes https://github.com/kestra-io/kestra-ee/issues/6179.
2025-12-25 09:06:49 +01:00
aflahaa
31f1e505e3 refactor(core): remove usage of unnecessary i18n composable (#13826)
Closes https://github.com/kestra-io/kestra/issues/13350.

Co-authored-by: MilosPaunovic <paun992@hotmail.com>
2025-12-24 12:56:51 +01:00
YannC
75e0c1d11f fix: updated the package-lock.json after dependencies upgrade (#13825) 2025-12-24 10:43:09 +01:00
13 changed files with 1466 additions and 1254 deletions

View File

@@ -63,9 +63,9 @@ You can also build it from a terminal using `./gradlew build`, the Gradle wrappe
- 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`.
- `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: ![Intellij IDEA Configuration ](run-app.png)
- See the screenshot below for an example: ![Intellij IDEA Configuration ](./assets/run-app.png)
- 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` ![Intellij IDEA Configuration ](node_option_env_var.png)
- Example `NODE_OPTIONS: --max-old-space-size=4096` or `NODE_OPTIONS: --max-old-space-size=8192` ![Intellij IDEA Configuration ](./assets/node_option_env_var.png)
- 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:

View File

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

View File

Before

Width:  |  Height:  |  Size: 210 KiB

After

Width:  |  Height:  |  Size: 210 KiB

2633
ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
<Keyboard />
</el-icon>
<span class="fs-6">
{{ t("editor_shortcuts.label") }}
{{ $t("editor_shortcuts.label") }}
</span>
</div>
</template>
@@ -27,7 +27,7 @@
</template>
</div>
<div class="text-break">
{{ t(command.description) }}
{{ $t(command.description) }}
</div>
</div>
</div>
@@ -35,11 +35,9 @@
</template>
<script setup lang="ts">
import {useI18n} from "vue-i18n";
import Keyboard from "vue-material-design-icons/Keyboard.vue";
import {useKeyShortcuts} from "../../utils/useKeyShortcuts";
const {t} = useI18n();
const {isKeyShortcutsDialogShown} = useKeyShortcuts();
const commands = [

View File

@@ -1,11 +1,11 @@
<template>
<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 align-items-end gap-2">
<SidebarToggleButton
v-if="layoutStore.sideMenuCollapsed"
@toggle="layoutStore.setSideMenuCollapsed(false)"
/>
<div class="d-flex flex-column gap-2">
<el-breadcrumb v-if="breadcrumb">
<el-breadcrumb-item v-for="(item, x) in breadcrumb" :key="x" :class="{'pe-none': item.disabled}">

View File

@@ -28,15 +28,7 @@
</Wrapper>
</template>
</el-collapse-item>
<el-collapse-item name="general" v-if="generalProperties?.length" :title="$t('no_code.sections.general')">
<template v-for="[fieldKey, fieldSchema] in generalProperties" :key="fieldKey">
<Wrapper>
<template #tasks>
<TaskObjectField v-bind="fieldProps(fieldKey, fieldSchema)" />
</template>
</Wrapper>
</template>
</el-collapse-item>
<el-collapse-item name="deprecated" v-if="deprecatedProperties?.length" :title="$t('no_code.sections.deprecated')">
<template v-for="[fieldKey, fieldSchema] in deprecatedProperties" :key="fieldKey">
<Wrapper>
@@ -133,16 +125,6 @@
return value?.$deprecated;
}
function isPartOfGroup(value: any, groups: string[]) {
if (value?.allOf) {
return value.allOf.some((item: any) => isPartOfGroup(item, groups));
}
if (value?.anyOf) {
return value.anyOf.some((item: any) => isPartOfGroup(item, groups));
}
return value?.$group && groups.includes(value.$group);
}
const filteredProperties = computed<Entry[]>(() => {
const propertiesProc = (props.properties ?? props.schema?.properties);
const isOutputsContext = props.root?.startsWith("outputs[") || false;
@@ -177,17 +159,9 @@
const protectedRequiredProperties = computed<Entry[]>(() => {
return requiredProperties.value.length ? requiredProperties.value : sortedProperties.value;
});
const connectionProperties = computed<Entry[]>(() => {
return props.merge ? [] : sortedProperties.value.filter(([p, v]) => v && !isRequired(p) && isPartOfGroup(v, ["connection"]));
});
const optionalProperties = computed<Entry[]>(() => {
return props.merge ? [] : sortedProperties.value.filter(([p, v]) => v && !isRequired(p) && !isDeprecated(v) && !isPartOfGroup(v, ["core","connection"]));
});
const generalProperties = computed<Entry[]>(() => {
return props.merge ? [] : sortedProperties.value.filter(([p, v]) => v && !isRequired(p) && !isDeprecated(v) && isPartOfGroup(v, ["core"]));
return props.merge ? [] : sortedProperties.value.filter(([p, v]) => v && !isRequired(p) && !isDeprecated(v) && v.$group !== "connection");
});
const deprecatedProperties = computed<Entry[]>(() => {
@@ -195,6 +169,9 @@
return props.merge ? [] : sortedProperties.value.filter(([k, v]) => v && isDeprecated(v) && obj[k] !== undefined);
});
const connectionProperties = computed<Entry[]>(() => {
return props.merge ? [] : sortedProperties.value.filter(([p, v]) => v && v.$group === "connection" && !isRequired(p));
});
function onInput(value: any) {
emit("update:modelValue", collapseEmptyValues(value));

View File

@@ -156,7 +156,7 @@
<el-form-item :label="$t('secret.key')" prop="key">
<el-input v-model="secret.key" :disabled="secret.update" required />
</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" />
</el-form-item>
<el-form-item v-if="secret.update" :label="$t('secret.name')" prop="value">

View File

@@ -1,3 +1,4 @@
import {computed, watch} from "vue";
import {useI18n} from "vue-i18n";
import {configureMonacoYaml} from "monaco-yaml";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
@@ -21,6 +22,7 @@ import {
registerPebbleAutocompletion
} from "./pebbleLanguageConfigurator";
import {usePluginsStore} from "../../../stores/plugins";
import {useBlueprintsStore} from "../../../stores/blueprints";
import {languages} from "monaco-editor/esm/vs/editor/editor.api";
import CompletionItem = languages.CompletionItem;
@@ -34,11 +36,14 @@ export class YamlLanguageConfigurator extends AbstractLanguageConfigurator {
}
async configureLanguage(pluginsStore: ReturnType<typeof usePluginsStore>) {
const validateYAML = computed(() => useBlueprintsStore().validateYAML);
watch(validateYAML, (shouldValidate) => configureMonacoYaml(monaco, {validate: shouldValidate}));
configureMonacoYaml(monaco, {
enableSchemaRequest: true,
hover: localStorage.getItem("hoverTextEditor") === "true",
completion: true,
validate: true,
validate: validateYAML.value ?? true,
format: true,
schemas: yamlSchemas()
});

View File

@@ -1,5 +1,11 @@
<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>
<Auth />
</template>
@@ -11,6 +17,9 @@
import SideBar from "../../components/layout/SideBar.vue";
import Auth from "../../override/components/auth/Auth.vue";
import {useBreakpoints, breakpointsElement} from "@vueuse/core";
const verticalLayout = useBreakpoints(breakpointsElement).smallerOrEqual("sm");
withDefaults(defineProps<{
showLink?: boolean
}>(), {

View File

@@ -56,7 +56,10 @@
<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>
</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">
{{ blueprint.title ?? blueprint.id }}
</h3>
@@ -151,6 +154,7 @@
id: string;
tags: string[];
title?: string;
template?: Record<string, any>;
}[] | undefined>(undefined);
const error = ref(false);
const icon = {ContentCopy};

View File

@@ -25,6 +25,8 @@ interface Blueprint {
[key: string]: any;
}
export type TemplateArgument = Record<string, Input>;
export interface BlueprintTemplate {
source: string;
templateArguments: Record<string, Input>;
@@ -55,6 +57,8 @@ export const useBlueprintsStore = defineStore("blueprints", () => {
const source = ref<string | 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 PARAMS = {params: options.params, ...VALIDATE};
@@ -166,6 +170,8 @@ export const useBlueprintsStore = defineStore("blueprints", () => {
source,
graph,
validateYAML,
getBlueprints,
getBlueprint,
getBlueprintSource,

View File

@@ -1,6 +1,10 @@
@import "@kestra-io/ui-libs/src/scss/variables.scss";
#app {
.v-sidebar-menu.vsm_expanded.overlay {
position: absolute;
}
.vsm--item {
padding: 0 30px;
transition: padding 0.2s ease;