refactor: add async loading for better performance (#6643)

Co-authored-by: YannC <37600690+Skraye@users.noreply.github.com>
This commit is contained in:
Barthélémy Ledoux
2025-01-10 17:26:29 +01:00
committed by GitHub
parent f8a7299daf
commit 8d57f8f0b2
84 changed files with 1437 additions and 4044 deletions

View File

@@ -2,7 +2,7 @@ import type {StorybookConfig} from "@storybook/vue3-vite";
const config: StorybookConfig = {
stories: [
"../@(tests|theme)/**/*.stories.@(js|jsx|mjs|ts|tsx)"
"../tests/**/*.stories.@(js|jsx|mjs|ts|tsx)"
],
addons: [
"@storybook/addon-essentials",

898
ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@
},
"dependencies": {
"@js-joda/core": "^5.6.3",
"@kestra-io/ui-libs": "^0.0.83",
"@kestra-io/ui-libs": "^0.0.100",
"@vue-flow/background": "^1.3.2",
"@vue-flow/controls": "^1.1.2",
"@vue-flow/core": "^1.41.6",

View File

@@ -1,84 +0,0 @@
// @ts-check
import fs from "fs"
import path from "path"
import figma from "../theme/figma.json" with {type: "json"}
const __dirname = path.dirname(new URL(import.meta.url).pathname)
const [{
color:paletteLight
}, {
color:paletteDark
}] = figma[0].values
makePalettes(paletteLight, "light", ":root")
makePalettes(paletteDark, "dark", "html.dark")
function getValue(color, colorIndex) {
if (color.var.startsWith("base-color-palette/")) {
return `$base-${color.var.split("/").pop()}`
}
// if the value of the color has 8 hexadecimal it has an alpha channel
// we therefore extract the color and compare it with the values in the base palette
if (color.value.length === 9) {
const alpha = Math.round(parseInt(color.value.slice(7), 16) / 2.55) / 100
const baseColor = color.value.slice(0, 7)
const baseColorName = colorIndex[baseColor]
if(baseColorName){
return `rgba($base-${baseColorName}, ${alpha})`
}
}
return color.value
}
/**
*
* @param {Array<{name:string, value:string, var:string }>} themeColors
* @returns
*/
function getVariableScss(themeColors, colorIndex) {
let prevCategory = null
const cssVariableNames = {}
const content = themeColors.map(c => {
const currentCategory = c.name.replace(/^ks\//, "").split("-")[0]
const val = getValue(c, colorIndex)
const categoryTitle = currentCategory !== prevCategory ? `\n\t/* ${currentCategory} */\n` : ""
cssVariableNames[currentCategory] = cssVariableNames[currentCategory] || []
const varName = c.name.replace(/\//g, "-")
cssVariableNames[currentCategory].push(varName)
prevCategory = currentCategory
return `${categoryTitle}\t#{--${varName}}: ${val};`
})
return {tokenScss: content.join("\n").trim(), cssVariableNames}
}
/**
*
* @param {Array<{name:string, value:string, var:string}>} palette
* @param {string} paletteName
* @param {string} selector
*/
function makePalettes(palette, paletteName, selector) {
const baseColorNames = palette.filter(c => c.name.startsWith("base-color-palette/"))
const colorIndex = baseColorNames.reduce((acc, color) => {
acc[color.value] = color.name.split("/").pop()
return acc
}, {})
const scss = baseColorNames.map(color => `$base-${color.name.split("/").pop()}: ${color.value};`).join("\n")
// write the scss file containing colors in the base palette
fs.writeFileSync(path.resolve(__dirname, "../src/styles/color-palette.scss"), scss, {encoding: "utf-8"})
const {tokenScss, cssVariableNames} = getVariableScss(palette.filter(c => !c.name.startsWith("base-color-palette/")), colorIndex)
// write the scss file containing colors in the token palette
fs.writeFileSync(path.resolve(__dirname, `../src/styles/layout/theme-${paletteName}.scss`), `@import "../color-palette.scss";\n\n${selector}{\n\t${tokenScss}\n}`, {encoding: "utf-8"})
// write the css variables into an index for theme documentation
// NOTE: we assume that all themes will have the same variables and write the same file over and over
fs.writeFileSync(path.resolve(__dirname, "../theme/css-variables.json"), JSON.stringify(cssVariableNames, null, 2), {encoding: "utf-8"})
}

View File

@@ -20,7 +20,7 @@
<script>
import Slack from "vue-material-design-icons/Slack.vue";
import Markdown from "../utils/markdown";
import * as Markdown from "../utils/markdown";
export default {
props: {

View File

@@ -7,7 +7,7 @@
</template>
<script>
import State from "../utils/state";
import {State} from "@kestra-io/ui-libs"
const StatusRemap = {
"failed": "error",

View File

@@ -1,6 +1,7 @@
<template>
<rapi-doc
:spec-url="$store.getters['doc/resourceUrl']('kestra.yml')"
v-if="ready"
:spec-url="store.getters['doc/resourceUrl']('kestra.yml')"
:theme="theme"
render-style="view"
show-header="false"
@@ -14,17 +15,18 @@
</template>
<script setup lang="ts">
import "rapidoc";
</script>
import {ref} from "vue";
import {useStore} from "vuex";
const store = useStore();
const ready = ref(false)
// @ts-expect-error rapidoc is not typed
import("rapidoc").then(() => {
ready.value = true
});
<script lang="ts">
export default {
data() {
return {
theme: localStorage.getItem("theme") === "dark" ? "dark" : "light"
}
}
}
const theme = ref(localStorage.getItem("theme") === "dark" ? "dark" : "light")
</script>
<style lang="scss" scoped>
@@ -32,5 +34,4 @@
background: transparent;
width: 100%;
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<rapi-doc
:spec-url="$store.getters['doc/resourceUrl']('kestra-ee.yml')"
:spec-url="store.getters['doc/resourceUrl']('kestra-ee.yml')"
:theme="theme"
render-style="view"
show-header="false"
@@ -14,17 +14,18 @@
</template>
<script setup lang="ts">
import "rapidoc";
</script>
import {ref} from "vue";
import {useStore} from "vuex";
const store = useStore();
const ready = ref(false)
// @ts-expect-error rapidoc is not typed
import("rapidoc").then(() => {
ready.value = true
});
<script lang="ts">
export default {
data() {
return {
theme: localStorage.getItem("theme") === "dark" ? "dark" : "light"
}
}
}
const theme = ref(localStorage.getItem("theme") === "dark" ? "dark" : "light")
</script>
<style lang="scss" scoped>

View File

@@ -236,7 +236,7 @@
import moment from "moment";
import {apiUrl} from "override/utils/route";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import Header from "./components/Header.vue";
import Card from "./components/Card.vue";

View File

@@ -24,7 +24,7 @@
import moment from "moment";
import {useRoute} from "vue-router";
import Utils from "@kestra-io/ui-libs/src/utils/Utils";
import {Utils} from "@kestra-io/ui-libs";
const store = useStore();

View File

@@ -25,7 +25,7 @@
import moment from "moment";
import {useRoute} from "vue-router";
import Utils from "@kestra-io/ui-libs/src/utils/Utils";
import {Utils} from "@kestra-io/ui-libs";
const store = useStore();

View File

@@ -1,5 +1,5 @@
import Utils from "../../../../utils/utils.js";
import {cssVariable} from "@kestra-io/ui-libs/src/utils/global";
import {cssVariable} from "@kestra-io/ui-libs";
import {getConsistentHEXColor} from "../../../../utils/charts.js";
const getOrCreateLegendList = (chart, id, direction = "row") => {

View File

@@ -40,7 +40,7 @@
import moment from "moment";
import {useRoute} from "vue-router";
import Utils from "@kestra-io/ui-libs/src/utils/Utils";
import {Utils} from "@kestra-io/ui-libs";
const {t} = useI18n({useScope: "global"});

View File

@@ -130,7 +130,7 @@
import moment from "moment";
import State from "../../../../../utils/state.js"
import {State} from "@kestra-io/ui-libs";
import Status from "../../../../Status.vue";
import NoData from "../../../../layout/NoData.vue";

View File

@@ -31,8 +31,7 @@
import OpenInNew from "vue-material-design-icons/OpenInNew.vue";
import useMarkdownParser from "@kestra-io/ui-libs/src/composables/useMarkdownParser";
import MDCRenderer from "@kestra-io/ui-libs/src/components/content/MDCRenderer.vue";
import {MDCRenderer, getMDCParser} from "@kestra-io/ui-libs";
import DocsLayout from "./DocsLayout.vue";
import ContextDocsLink from "./ContextDocsLink.vue";
import ContextChildCard from "./ContextChildCard.vue";
@@ -40,7 +39,6 @@
import ContextInfoContent from "../ContextInfoContent.vue";
import ContextChildTableOfContents from "./ContextChildTableOfContents.vue";
const parse = useMarkdownParser();
const store = useStore();
const {t} = useI18n({useScope: "global"});
@@ -102,6 +100,7 @@
if (!("canShare" in navigator)) {
content = content.replaceAll(/\s*web-share\s*/g, "");
}
const parse = await getMDCParser()
ast.value = await parse(content);
}
</script>

View File

@@ -14,15 +14,13 @@
</template>
<script>
import useMarkdownParser from "@kestra-io/ui-libs/src/composables/useMarkdownParser";
import MDCRenderer from "@kestra-io/ui-libs/src/components/content/MDCRenderer.vue";
import {MDCRenderer, getMDCParser} from "@kestra-io/ui-libs";
import TopNavBar from "../layout/TopNavBar.vue";
import {mapGetters} from "vuex";
import DocsLayout from "./DocsLayout.vue";
import Toc from "./Toc.vue";
import {getCurrentInstance} from "vue";
const parse = useMarkdownParser();
export default {
computed: {
@@ -79,6 +77,7 @@
if (!("canShare" in navigator)) {
content = content.replaceAll(/\s*web-share\s*/g, "");
}
const parse = await getMDCParser();
this.ast = await parse(content);
},
immediate: true

View File

@@ -73,7 +73,7 @@
import {mapState} from "vuex";
import permission from "../../models/permission";
import action from "../../models/action";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import Status from "../../components/Status.vue";
import ExecutionUtils from "../../utils/executionUtils";

View File

@@ -67,7 +67,7 @@
import {mapState} from "vuex";
import permission from "../../models/permission";
import action from "../../models/action";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import Status from "../../components/Status.vue";
import ExecutionUtils from "../../utils/executionUtils";
import {shallowRef} from "vue";

View File

@@ -41,7 +41,7 @@
import TopNavBar from "../layout/TopNavBar.vue";
import permission from "../../models/permission";
import action from "../../models/action";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import {apiUrl} from "override/utils/route";
import {mapState} from "vuex";

View File

@@ -379,7 +379,7 @@
import Kicon from "../Kicon.vue"
import Labels from "../layout/Labels.vue"
import RestoreUrl from "../../mixins/restoreUrl";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import Id from "../Id.vue";
import _merge from "lodash/merge";
import permission from "../../models/permission";

View File

@@ -28,9 +28,9 @@
</div>
</template>
<script>
import {cssVariable} from "@kestra-io/ui-libs/src/utils/global";
import {cssVariable} from "@kestra-io/ui-libs";
import {stateDisplayValues} from "../../utils/constants";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import throttle from "lodash/throttle"
export default {

View File

@@ -36,9 +36,9 @@
<script>
import {mapState} from "vuex";
import {State} from "@kestra-io/ui-libs";
import permission from "../../models/permission";
import action from "../../models/action";
import State from "../../utils/state.js";
export default {
props: {

View File

@@ -84,7 +84,7 @@
<script>
import TaskRunDetails from "../logs/TaskRunDetails.vue";
import {mapState} from "vuex";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import Duration from "../layout/Duration.vue";
import Utils from "../../utils/utils";
import FlowUtils from "../../utils/flowUtils";

View File

@@ -33,7 +33,7 @@
import {mapState} from "vuex";
import permission from "../../models/permission";
import action from "../../models/action";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
export default {
props: {

View File

@@ -117,7 +117,7 @@
import {DynamicScroller, DynamicScrollerItem} from "vue-virtual-scroller";
import "vue-virtual-scroller/dist/vue-virtual-scroller.css"
import Collapse from "../layout/Collapse.vue";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import Utils from "../../utils/utils";
import LogLine from "../logs/LogLine.vue";
import Restart from "./Restart.vue";

View File

@@ -156,7 +156,7 @@
import Unqueue from "./Unqueue.vue";
import ForceRun from "./ForceRun.vue";
import Kill from "./Kill.vue";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import DateAgo from "../layout/DateAgo.vue";
import Crud from "override/components/auth/Crud.vue";
import Duration from "../layout/Duration.vue";

View File

@@ -29,7 +29,7 @@
import {mapState} from "vuex";
import permission from "../../models/permission";
import action from "../../models/action";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
export default {
props: {

View File

@@ -79,7 +79,7 @@
import {mapState} from "vuex";
import permission from "../../models/permission";
import action from "../../models/action";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import ExecutionUtils from "../../utils/executionUtils";
export default {

View File

@@ -35,7 +35,7 @@
import {mapState} from "vuex";
import permission from "../../models/permission";
import action from "../../models/action";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import FlowUtils from "../../utils/flowUtils";
import ExecutionUtils from "../../utils/executionUtils";
import InputsForm from "../../components/inputs/InputsForm.vue";

View File

@@ -51,7 +51,7 @@
<script>
import {mapState} from "vuex";
import LabelInput from "../../components/labels/LabelInput.vue";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import {filterLabels} from "./utils"
import permission from "../../models/permission.js";

View File

@@ -150,13 +150,13 @@
import ChevronDown from "vue-material-design-icons/ChevronDown.vue";
import Clock from "vue-material-design-icons/Clock.vue";
import Outputs from "./Outputs.vue";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import FlowUtils from "../../utils/flowUtils";
import {mapState} from "vuex";
import {SECTIONS} from "../../utils/constants";
import Download from "vue-material-design-icons/Download.vue";
import _groupBy from "lodash/groupBy";
import TaskIcon from "@kestra-io/ui-libs/src/components/misc/TaskIcon.vue";
import {TaskIcon} from "@kestra-io/ui-libs";
import Duration from "../layout/Duration.vue";
import Utils from "../../utils/utils";
import Delete from "vue-material-design-icons/Delete.vue";

View File

@@ -25,9 +25,8 @@
<script>
import LowCodeEditor from "../inputs/LowCodeEditor.vue";
import {mapGetters, mapState} from "vuex";
import {CLUSTER_PREFIX} from "@kestra-io/ui-libs/src/utils/constants";
import Utils from "@kestra-io/ui-libs/src/utils/Utils";
import STATE from "../../utils/state";
import {CLUSTER_PREFIX} from "@kestra-io/ui-libs/src/utils/constants.ts";
import {Utils, State} from "@kestra-io/ui-libs";
import throttle from "lodash/throttle";
export default {
components: {
@@ -215,7 +214,7 @@
const executionId = taskIdMatchingTaskrun?.outputs?.executionId;
if(!executionId) {
if(taskIdMatchingTaskrun?.state?.current === STATE.SUCCESS) {
if(taskIdMatchingTaskrun?.state?.current === State.SUCCESS) {
// Generating more than 1 subflow execution, we're not showing anything
this.loadGraph(true);
return;

View File

@@ -29,7 +29,7 @@
import {mapState} from "vuex";
import permission from "../../models/permission";
import action from "../../models/action";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
export default {
props: {

View File

@@ -248,7 +248,7 @@
import VarValue from "../VarValue.vue";
import SubFlowLink from "../../flows/SubFlowLink.vue";
import TaskIcon from "@kestra-io/ui-libs/src/components/misc/TaskIcon.vue";
import {TaskIcon} from "@kestra-io/ui-libs";
import TimelineTextOutline from "vue-material-design-icons/TimelineTextOutline.vue";
import TextBoxSearchOutline from "vue-material-design-icons/TextBoxSearchOutline.vue";

View File

@@ -2,7 +2,7 @@ import {useI18n} from "vue-i18n";
import {Value} from "../utils/types";
import State from "../../../utils/state.js";
import {State} from "@kestra-io/ui-libs";
import {auditLogTypes} from "../../../models/auditLogTypes";
import permission from "../../../models/permission.js";
import action from "../../../models/action.js";

View File

@@ -38,7 +38,7 @@
import Executions from "../executions/Executions.vue";
import EmptyState from "../layout/EmptyState.vue";
import {mapState} from "vuex";
import State from "../../utils/state.js";
import {State} from "@kestra-io/ui-libs";
import Status from "../Status.vue";
import noConcurrencyImage from "../../assets/no_concurrency.svg";

View File

@@ -17,12 +17,12 @@
</template>
<script>
import {YamlUtils} from "@kestra-io/ui-libs";
import EditorView from "../inputs/EditorView.vue";
import {mapGetters, mapMutations, mapState} from "vuex";
import RouteContext from "../../mixins/routeContext";
import TopNavBar from "../../components/layout/TopNavBar.vue";
import {apiUrl} from "override/utils/route";
import {YamlUtils} from "@kestra-io/ui-libs";
export default {
mixins: [RouteContext],

View File

@@ -38,7 +38,7 @@
import dagre from "dagre"
import ArrowExpandAll from "vue-material-design-icons/ArrowExpandAll.vue";
import {cssVariable} from "@kestra-io/ui-libs/src/utils/global";
import {cssVariable} from "@kestra-io/ui-libs";
import {DependenciesNode} from "@kestra-io/ui-libs"
import {linkedElements} from "../../utils/vueFlow"

View File

@@ -61,7 +61,7 @@
import {mapState} from "vuex";
import moment from "moment";
import {defaultConfig, getFormat, tooltip} from "../../utils/charts";
import {cssVariable} from "@kestra-io/ui-libs/src/utils/global";
import {cssVariable} from "@kestra-io/ui-libs";
import KestraFilter from "../filter/KestraFilter.vue";
export default {

View File

@@ -26,7 +26,7 @@
<script>
import TriggerVars from "./TriggerVars.vue";
import {mapState} from "vuex";
import TaskIcon from "@kestra-io/ui-libs/src/components/misc/TaskIcon.vue";
import {TaskIcon} from "@kestra-io/ui-libs";
export default {
props: {

View File

@@ -11,7 +11,11 @@
transition=""
:hide-after="0"
>
<el-button :icon="icon.UnfoldLessHorizontal" @click="autoFold(true)" size="small" />
<el-button
:icon="icon.UnfoldLessHorizontal"
@click="autoFold(true)"
size="small"
/>
</el-tooltip>
<el-tooltip
effect="light"
@@ -20,7 +24,11 @@
transition=""
:hide-after="0"
>
<el-button :icon="icon.UnfoldMoreHorizontal" @click="unfoldAll" size="small" />
<el-button
:icon="icon.UnfoldMoreHorizontal"
@click="unfoldAll"
size="small"
/>
</el-tooltip>
</el-button-group>
<slot name="extends-navbar" />
@@ -61,7 +69,7 @@
</template>
<script>
import {defineAsyncComponent, shallowRef} from "vue"
import {defineAsyncComponent, shallowRef} from "vue";
import UnfoldLessHorizontal from "vue-material-design-icons/UnfoldLessHorizontal.vue";
import UnfoldMoreHorizontal from "vue-material-design-icons/UnfoldMoreHorizontal.vue";
import Help from "vue-material-design-icons/Help.vue";
@@ -70,9 +78,7 @@
import Close from "vue-material-design-icons/Close.vue";
import {TabFocus} from "monaco-editor/esm/vs/editor/browser/config/tabFocus.js";
const MonacoEditor = defineAsyncComponent(() =>
import("./MonacoEditor.vue")
)
const MonacoEditor = defineAsyncComponent(() => import("./MonacoEditor.vue"));
export default {
props: {
@@ -91,12 +97,20 @@
readOnly: {type: Boolean, default: false},
lineNumbers: {type: Boolean, default: undefined},
minimap: {type: Boolean, default: false},
creating: {type: Boolean, default: false}
creating: {type: Boolean, default: false},
},
components: {
MonacoEditor,
},
emits: ["save", "execute", "focusout", "tab", "update:modelValue", "cursor", "confirm"],
emits: [
"save",
"execute",
"focusout",
"tab",
"update:modelValue",
"cursor",
"confirm",
],
editor: undefined,
data() {
return {
@@ -106,7 +120,7 @@
UnfoldMoreHorizontal: shallowRef(UnfoldMoreHorizontal),
Help: shallowRef(Help),
BookMultipleOutline: shallowRef(BookMultipleOutline),
Close: shallowRef(Close)
Close: shallowRef(Close),
},
editorDocumentation: undefined,
plugin: undefined,
@@ -122,37 +136,49 @@
themeComputed() {
const savedEditorTheme = localStorage.getItem("editorTheme");
return savedEditorTheme === "syncWithSystem"
? (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light")
: (savedEditorTheme === "light" ? "light" : "dark");
? window.matchMedia("(prefers-color-scheme: dark)").matches
? "dark"
: "light"
: savedEditorTheme === "light"
? "light"
: "dark";
},
containerClass() {
return [
!this.input ? "" : "single-line",
"theme-" + this.themeComputed,
this.themeComputed === "dark" ? "custom-dark-vs-theme" : ""
]
this.themeComputed === "dark" ? "custom-dark-vs-theme" : "",
];
},
showPlaceholder() {
return this.input === true && !this.focus &&
(!Object.hasOwn(this, "editor") || this.editor === undefined || !(this.editor.getValue() !== undefined && this.editor.getValue() !== ""));
return (
this.input === true &&
!this.focus &&
(!Object.hasOwn(this, "editor") ||
this.editor === undefined ||
!(
this.editor.getValue() !== undefined &&
this.editor.getValue() !== ""
))
);
},
options() {
const options = {}
const options = {};
if (this.input) {
options.lineNumbers = "off"
options.lineNumbers = "off";
options.folding = false;
options.renderLineHighlight = "none"
options.renderLineHighlight = "none";
options.wordBasedSuggestions = false;
options.occurrencesHighlight = false
options.hideCursorInOverviewRuler = true
options.overviewRulerBorder = false
options.overviewRulerLanes = 0
options.occurrencesHighlight = false;
options.hideCursorInOverviewRuler = true;
options.overviewRulerBorder = false;
options.overviewRulerLanes = 0;
options.lineNumbersMinChars = 0;
options.fontSize = 13;
options.minimap = {
enabled: false
}
enabled: false,
};
options.scrollBeyondLastColumn = 0;
options.overviewRulerLanes = 0;
options.scrollbar = {
@@ -165,13 +191,13 @@
useShadows: false,
};
options.stickyScroll = {
enabled: false
enabled: false,
};
options.find = {
addExtraSpaceOnTop: false,
autoFindInSelection: "never",
seedSearchStringFromSelection: false,
}
};
options.contextmenu = false;
options.lineDecorationsWidth = 0;
} else {
@@ -180,38 +206,43 @@
verticalScrollbarSize: this.original !== undefined ? 0 : 10,
alwaysConsumeMouseWheel: false,
};
options.renderSideBySide = this.diffSideBySide
options.renderSideBySide = this.diffSideBySide;
}
if (this.minimap === false) {
options.minimap = {
enabled: false
}
enabled: false,
};
}
if (this.readOnly) {
options.readOnly = true
options.readOnly = true;
}
options.wordWrap = true
options.wordWrap = true;
options.automaticLayout = true;
return {
...{
tabSize: 2,
fontFamily: localStorage.getItem("editorFontFamily") ? localStorage.getItem("editorFontFamily") : "'Source Code Pro', monospace",
fontSize: localStorage.getItem("editorFontSize") ? parseInt(localStorage.getItem("editorFontSize")) : 12,
fontFamily: localStorage.getItem("editorFontFamily")
? localStorage.getItem("editorFontFamily")
: "'Source Code Pro', monospace",
fontSize: localStorage.getItem("editorFontSize")
? parseInt(localStorage.getItem("editorFontSize"))
: 12,
showFoldingControls: "always",
scrollBeyondLastLine: false,
roundedSelection: false,
},
...options
...options,
};
}
},
},
created() {
this.editorDocumentation = localStorage.getItem("editorDocumentation") !== "false" && this.navbar;
this.editorDocumentation =
localStorage.getItem("editorDocumentation") !== "false" &&
this.navbar;
},
methods: {
editorDidMount(editor) {
@@ -227,11 +258,11 @@
this.editor.onDidBlurEditorWidget?.(() => {
this.$emit("focusout", editor.getValue());
this.focus = false;
})
});
this.editor.onDidFocusEditorText?.(() => {
this.focus = true;
})
});
this.$refs.monacoEditor.focus();
}
@@ -240,59 +271,55 @@
this.editor.addAction({
id: "kestra-save",
label: "Save",
keybindings: [
KeyMod.CtrlCmd | KeyCode.KeyS,
],
keybindings: [KeyMod.CtrlCmd | KeyCode.KeyS],
contextMenuGroupId: "navigation",
contextMenuOrder: 1.5,
run: (ed) => {
this.$emit("save", ed.getValue())
}
this.$emit("save", ed.getValue());
},
});
}
else {
} else {
if (this.lang === "json") {
editor.getAction("editor.action.formatDocument").run()
editor.getAction("editor.action.formatDocument").run();
}
}
this.editor.addAction({
id: "kestra-execute",
label: "Execute the flow",
keybindings: [
KeyMod.CtrlCmd | KeyCode.KeyE,
],
keybindings: [KeyMod.CtrlCmd | KeyCode.KeyE],
contextMenuGroupId: "navigation",
contextMenuOrder: 1.5,
run: (ed) => {
this.$emit("execute", ed.getValue())
}
this.$emit("execute", ed.getValue());
},
});
this.editor.addAction({
id: "confirm",
label: "Confirm",
keybindings: [
KeyMod.CtrlCmd | KeyCode.Enter,
],
keybindings: [KeyMod.CtrlCmd | KeyCode.Enter],
contextMenuGroupId: "navigation",
contextMenuOrder: 1.5,
run: (ed) => {
this.$emit("confirm", ed.getValue())
}
this.$emit("confirm", ed.getValue());
},
});
// TabFocus is global to all editor so revert the behavior on non inputs
this.editor.onDidFocusEditorText?.(() => {
TabFocus.setTabFocusMode(this.input);
})
});
if (this.input) {
this.editor.addCommand(KeyMod.CtrlCmd | KeyCode.KeyH, () => {});
this.editor.addCommand(KeyCode.F1, () => {});
if (!this.readOnly) {
this.editor.addCommand(KeyMod.CtrlCmd | KeyCode.KeyF, () => { });
this.editor.addCommand(
KeyMod.CtrlCmd | KeyCode.KeyF,
() => {},
);
}
}
@@ -300,32 +327,39 @@
this.editor.addAction({
id: "fold-multiline",
label: "Fold All Multi Lines",
keybindings: [
KeyCode.F10,
],
keybindings: [KeyCode.F10],
contextMenuGroupId: "fold",
contextMenuOrder: 1.5,
run: (ed) => {
const foldingContrib = ed.getContribution("editor.contrib.folding");
foldingContrib.getFoldingModel().then(foldingModel => {
const foldingContrib = ed.getContribution(
"editor.contrib.folding",
);
foldingContrib
.getFoldingModel()
.then((foldingModel) => {
let editorModel = foldingModel.textModel;
let regions = foldingModel.regions;
let toToggle = [];
for (let i = regions.length - 1; i >= 0; i--) {
if (regions.isCollapsed(i) === false) {
let startLineNumber =
regions.getStartLineNumber(i);
let editorModel = foldingModel.textModel;
let regions = foldingModel.regions;
let toToggle = [];
for (let i = regions.length - 1; i >= 0; i--) {
if (regions.isCollapsed(i) === false) {
let startLineNumber = regions.getStartLineNumber(i);
if (editorModel.getLineContent(startLineNumber).trim().endsWith("|")) {
toToggle.push(regions.toRegion(i));
if (
editorModel
.getLineContent(startLineNumber)
.trim()
.endsWith("|")
) {
toToggle.push(regions.toRegion(i));
}
}
}
}
foldingModel.toggleCollapseState(toToggle);
});
foldingModel.toggleCollapseState(toToggle);
});
return null;
}
},
});
if (localStorage.getItem("autofoldTextEditor") === "1") {
@@ -334,26 +368,29 @@
}
if (this.original !== undefined) {
this.editor.updateOptions({readOnly: true})
this.editor.updateOptions({readOnly: true});
}
if (!this.fullHeight) {
editor.onDidContentSizeChange(e => {
if(!this.$refs.container) return;
this.$refs.container.style.height = (e.contentHeight + this.customHeight) + "px";
editor.onDidContentSizeChange((e) => {
if (!this.$refs.container) return;
this.$refs.container.style.height =
e.contentHeight + this.customHeight + "px";
});
}
if (!this.original) {
this.editor.onDidContentSizeChange(_ => {
this.editor.onDidContentSizeChange((_) => {
if (this.guidedProperties.monacoRange) {
editor.revealLine(this.guidedProperties.monacoRange.endLineNumber);
editor.revealLine(
this.guidedProperties.monacoRange.endLineNumber,
);
const decorationsToAdd = [];
decorationsToAdd.push({
range: this.guidedProperties.monacoRange,
options: {
isWholeLine: true,
inlineClassName: "highlight-text"
inlineClassName: "highlight-text",
},
className: "highlight-text",
});
@@ -362,7 +399,7 @@
range: this.guidedProperties.monacoDisableRange,
options: {
isWholeLine: true,
inlineClassName: "disable-text"
inlineClassName: "disable-text",
},
className: "disable-text",
});
@@ -379,7 +416,10 @@
let model = this.editor.getModel();
clearTimeout(this.lastTimeout);
this.lastTimeout = setTimeout(() => {
this.$emit("cursor", {position: position, model: model})
this.$emit("cursor", {
position: position,
model: model,
});
}, 100);
this.highlightPebble();
});
@@ -389,7 +429,7 @@
// the value of the editor without dealing with how Monaco handles the exact keystrokes
this.$refs.monacoEditor.$el.__setValueInTests = (value) => {
this.editor.setValue(value);
}
};
},
autoFold(autoFold) {
if (autoFold) {
@@ -403,8 +443,8 @@
this.$emit("update:modelValue", value);
},
onPlaceholderClick() {
this.editor.layout()
this.editor.focus()
this.editor.layout();
this.editor.focus();
},
highlightPebble() {
// Highlight code that match pebble content
@@ -421,11 +461,11 @@
startLineNumber: startPos.lineNumber,
startColumn: startPos.column,
endLineNumber: endPos.lineNumber,
endColumn: endPos.column
endColumn: endPos.column,
},
options: {
inlineClassName: "highlight-pebble"
}
inlineClassName: "highlight-pebble",
},
});
}
this.decorations.set(decorationsToAdd);
@@ -435,154 +475,162 @@
</script>
<style lang="scss">
@import "../../styles/layout/root-dark";
@import "../../styles/color-palette";
@import "@kestra-io/ui-libs/src/scss/color-palette.scss";
@import "../../styles/layout/root-dark.scss";
:not(.namespace-form, .el-drawer__body) > .ks-editor{
flex-direction: column;
height: 100%;
}
:not(.namespace-form, .el-drawer__body) > .ks-editor {
flex-direction: column;
height: 100%;
}
.el-form .ks-editor {
display: flex;
width: 100%;
}
.el-form .ks-editor {
display: flex;
width: 100%;
}
.ks-editor {
display: flex;
.ks-editor {
display: flex;
.top-nav {
background-color: var(--ks-background-card);
padding: .5rem;
border-radius: var(--bs-border-radius-lg);
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
html.dark & {
background-color: var(--bs-gray-100);
}
}
.editor-container {
display: flex;
flex-grow: 1;
&.single-line {
min-height: var(--el-component-size);
padding: 1px 11px;
background-color: var(--el-input-bg-color, var(--el-fill-color-blank));
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
transition: var(--el-transition-box-shadow);
box-shadow: 0 0 0 1px var(--ks-border-primary) inset;
padding-top: 7px;
&.custom-dark-vs-theme {
background-color: $input-bg;
}
&.theme-light{
background-color: $base-white;
}
}
.placeholder {
position: absolute;
top: -3px;
overflow: hidden;
padding-left: inherit;
padding-right: inherit;
cursor: text;
user-select: none;
color: var(--ks-content-inactive);
}
.editor-wrapper {
min-width: 75%;
width: 100%;
.monaco-hover-content {
h4 {
font-size: var(--font-size-base);
font-weight: bold;
line-height: var(--bs-body-line-height);
}
p {
margin-bottom: .5rem;
&:last-child {
display: none;
}
}
*:nth-last-child(2n) {
margin-bottom: 0;
}
}
}
.bottom-right {
bottom: 0px;
right: 0px;
ul {
display: flex;
list-style: none;
padding: 0;
margin: 0;
//gap: .5rem;
}
}
}
}
.custom-dark-vs-theme {
.monaco-editor, .monaco-editor-background {
outline: none;
background-color: $input-bg;
--vscode-editor-background: $input-bg;
--vscode-breadcrumb-background: $input-bg;
--vscode-editorGutter-background: $input-bg;
}
.monaco-editor .margin {
background-color: $input-bg;
}
}
.highlight-text {
cursor: pointer;
font-weight: 700;
box-shadow: 0 19px 44px rgba(157, 29, 236, 0.31);
.top-nav {
background-color: var(--ks-background-card);
padding: 0.5rem;
border-radius: var(--bs-border-radius-lg);
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
html.dark & {
background-color: rgba(255, 255, 255, 0.2);
background-color: var(--bs-gray-100);
}
}
.highlight-pebble {
color: #977100 !important;
.editor-container {
display: flex;
flex-grow: 1;
html.dark & {
color: #ffca16 !important;
&.single-line {
min-height: var(--el-component-size);
padding: 1px 11px;
background-color: var(
--el-input-bg-color,
var(--el-fill-color-blank)
);
border-radius: var(
--el-input-border-radius,
var(--el-border-radius-base)
);
transition: var(--el-transition-box-shadow);
box-shadow: 0 0 0 1px var(--ks-border-primary) inset;
padding-top: 7px;
&.custom-dark-vs-theme {
background-color: $input-bg;
}
&.theme-light {
background-color: $base-white;
}
}
}
.disable-text {
color: grey !important;
}
.placeholder {
position: absolute;
top: -3px;
overflow: hidden;
padding-left: inherit;
padding-right: inherit;
cursor: text;
user-select: none;
color: var(--ks-content-inactive);
}
div.img {
min-height: 130px;
height: 100%;
.editor-wrapper {
min-width: 75%;
width: 100%;
&.get-started {
background: url("../../assets/onboarding/onboarding-doc-light.svg") no-repeat center;
.monaco-hover-content {
h4 {
font-size: var(--font-size-base);
font-weight: bold;
line-height: var(--bs-body-line-height);
}
html.dark & {
background: url("../../assets/onboarding/onboarding-doc-dark.svg") no-repeat center;
p {
margin-bottom: 0.5rem;
&:last-child {
display: none;
}
}
*:nth-last-child(2n) {
margin-bottom: 0;
}
}
}
.bottom-right {
bottom: 0px;
right: 0px;
ul {
display: flex;
list-style: none;
padding: 0;
margin: 0;
//gap: .5rem;
}
}
}
}
.custom-dark-vs-theme {
.monaco-editor,
.monaco-editor-background {
outline: none;
background-color: $input-bg;
--vscode-editor-background: $input-bg;
--vscode-breadcrumb-background: $input-bg;
--vscode-editorGutter-background: $input-bg;
}
.monaco-editor .margin {
background-color: $input-bg;
}
}
.highlight-text {
cursor: pointer;
font-weight: 700;
box-shadow: 0 19px 44px rgba(157, 29, 236, 0.31);
html.dark & {
background-color: rgba(255, 255, 255, 0.2);
}
}
.highlight-pebble {
color: #977100 !important;
html.dark & {
color: #ffca16 !important;
}
}
.disable-text {
color: grey !important;
}
div.img {
min-height: 130px;
height: 100%;
&.get-started {
background: url("../../assets/onboarding/onboarding-doc-light.svg")
no-repeat center;
html.dark & {
background: url("../../assets/onboarding/onboarding-doc-dark.svg")
no-repeat center;
}
}
}
</style>

View File

@@ -320,7 +320,7 @@
import {SECTIONS} from "../../utils/constants.js";
import LowCodeEditor from "../inputs/LowCodeEditor.vue";
import {editorViewTypes} from "../../utils/constants";
import Utils from "@kestra-io/ui-libs/src/utils/Utils";
import {Utils} from "@kestra-io/ui-libs";
import {apiUrl} from "override/utils/route";
import EditorButtons from "./EditorButtons.vue";
import Drawer from "../Drawer.vue";

View File

@@ -14,7 +14,7 @@
</template>
<script>
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import Utils from "../../utils/utils";
const ts = date => new Date(date).getTime();

View File

@@ -6,7 +6,7 @@
<script>
import {mapGetters} from "vuex";
import {cssVariable} from "@kestra-io/ui-libs/src/utils/global";
import {cssVariable} from "@kestra-io/ui-libs";
export default {
computed: {

View File

@@ -5,7 +5,7 @@
</template>
<script>
import Markdown from "../../utils/markdown";
import * as Markdown from "../../utils/markdown";
export default {
props: {

View File

@@ -21,7 +21,7 @@
</el-select>
</template>
<script>
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import Status from "../Status.vue";
export default {

View File

@@ -37,7 +37,7 @@
<script>
import Convert from "ansi-to-html";
import xss from "xss";
import Markdown from "../../utils/markdown";
import * as Markdown from "../../utils/markdown";
import VRuntimeTemplate from "vue3-runtime-template";
import MenuRight from "vue-material-design-icons/MenuRight.vue";

View File

@@ -104,7 +104,7 @@
<script>
import LogLine from "./LogLine.vue";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import _xor from "lodash/xor";
import _groupBy from "lodash/groupBy";
import moment from "moment";

View File

@@ -43,7 +43,7 @@
import dagre from "dagre"
import ArrowExpandAll from "vue-material-design-icons/ArrowExpandAll.vue";
import {cssVariable} from "@kestra-io/ui-libs/src/utils/global";
import {cssVariable} from "@kestra-io/ui-libs";
import {DependenciesNode} from "@kestra-io/ui-libs"
import {linkedElements} from "../../utils/vueFlow"

View File

@@ -139,7 +139,7 @@
</script>
<style lang="scss" scoped>
@import "../../styles/color-palette";
@import "@kestra-io/ui-libs/src/scss/color-palette.scss";
.filter {
min-width: 200px;

View File

@@ -146,7 +146,7 @@
import {pageFromRoute} from "../../utils/eventsRouter";
import TaskIcon from "@kestra-io/ui-libs/src/components/misc/TaskIcon.vue";
import {TaskIcon} from "@kestra-io/ui-libs";
import Animation from "../../assets/onboarding/animation.gif";
import LightningBolt from "../../assets/onboarding/icons/lightning-bolt.svg";

View File

@@ -75,7 +75,7 @@
</template>
<script>
import TaskIcon from "@kestra-io/ui-libs/src/components/misc/TaskIcon.vue";
import {TaskIcon} from "@kestra-io/ui-libs";
import DottedLayout from "../layout/DottedLayout.vue";
import headerImage from "../../assets/icons/plugin.svg";
import headerImageDark from "../../assets/icons/plugin-dark.svg";

View File

@@ -28,7 +28,7 @@
<script>
import {mapState} from "vuex";
import TaskIcon from "@kestra-io/ui-libs/src/components/misc/TaskIcon.vue";
import {TaskIcon} from "@kestra-io/ui-libs";
export default {
components: {

View File

@@ -52,7 +52,7 @@
</template>
<script>
import TaskIcon from "@kestra-io/ui-libs/src/components/misc/TaskIcon.vue";
import {TaskIcon} from "@kestra-io/ui-libs";
import {mapState} from "vuex";
export default {

View File

@@ -175,7 +175,7 @@
import DateAgo from "../layout/DateAgo.vue";
import Kicon from "../Kicon.vue"
import RestoreUrl from "../../mixins/restoreUrl";
import State from "../../utils/state";
import {State} from "@kestra-io/ui-libs"
import Id from "../Id.vue";
import _merge from "lodash/merge";
import {stateGlobalChartTypes} from "../../utils/constants";

View File

@@ -5,36 +5,25 @@ import App from "./App.vue"
import initApp from "./utils/init"
import configureAxios from "./utils/axios"
import routes from "./routes/routes";
import de from "./translations/de.json";
import en from "./translations/en.json";
import es from "./translations/es.json";
import fr from "./translations/fr.json";
import hi from "./translations/hi.json";
import it from "./translations/it.json";
import ja from "./translations/ja.json";
import ko from "./translations/ko.json";
import pl from "./translations/pl.json";
import pt from "./translations/pt.json";
import ru from "./translations/ru.json";
import zh_CN from "./translations/zh_CN.json"
import stores from "./stores/store";
const app = createApp(App)
const translations = {...de,...en,...es,...fr,...hi,...it,...ja,...ko,...pl,...pt,...ru,...zh_CN}
const {store, router} = initApp(app, routes, stores, translations);
initApp(app, routes, stores, en).then(({store, router}) => {
// Passing toast to VUEX store to be used in modules
store.$toast = app.config.globalProperties.$toast();
// Passing toast to VUEX store to be used in modules
store.$toast = app.config.globalProperties.$toast();
// axios
configureAxios((instance) => {
app.use(VueAxios, instance);
app.provide("axios", instance);
// axios
configureAxios((instance) => {
app.use(VueAxios, instance);
app.provide("axios", instance);
store.$http = app.$http;
store.axios = app.axios;
}, store, router);
store.$http = app.$http;
store.axios = app.axios;
}, store, router);
// mount
app.mount("#app")
});
// mount
app.mount("#app")

View File

@@ -99,7 +99,7 @@
<script>
import DataTable from "../../../../components/layout/DataTable.vue";
import TaskIcon from "@kestra-io/ui-libs/src/components/misc/TaskIcon.vue";
import {TaskIcon} from "@kestra-io/ui-libs";
import DataTableActions from "../../../../mixins/dataTableActions";
import {shallowRef} from "vue";
import ContentCopy from "vue-material-design-icons/ContentCopy.vue";

View File

@@ -1,82 +1,59 @@
import OnlyLeftMenuLayout from "../components/layout/OnlyLeftMenuLayout.vue"
import ExecutionRoot from "../components/executions/ExecutionRoot.vue"
import Executions from "../components/executions/Executions.vue"
import TaskRuns from "../components/taskruns/TaskRuns.vue"
import FlowRoot from "../components/flows/FlowRoot.vue"
import Flows from "../components/flows/Flows.vue"
import LogsWrapper from "../components/logs/LogsWrapper.vue"
import Plugin from "../components/plugins/Plugin.vue"
import Settings from "override/components/settings/Settings.vue"
import TemplateEdit from "../components/templates/TemplateEdit.vue"
import Templates from "../components/templates/Templates.vue"
import FlowsSearch from "../components/flows/FlowsSearch.vue";
import Errors from "../components/errors/Errors.vue";
import Dashboard from "../components/dashboard/Dashboard.vue";
import DashboardCreate from "../components/dashboard/components/DashboardCreate.vue";
import DashboardEdit from "../components/dashboard/components/DashboardEdit.vue";
import Welcome from "../components/onboarding/Welcome.vue";
import FlowCreate from "../components/flows/FlowCreate.vue";
import Blueprints from "override/components/flows/blueprints/Blueprints.vue";
import BlueprintDetail from "../components/flows/blueprints/BlueprintDetail.vue";
import Triggers from "../components/admin/Triggers.vue";
import Stats from "override/components/admin/stats/Stats.vue";
import Namespaces from "../components/namespace/Namespaces.vue";
import Namespace from "../components/namespace/Namespace.vue";
import Docs from "../components/docs/Docs.vue";
import Errors from "../components/errors/Errors.vue"
export default [
//Initial
{name: "root", path: "/", redirect: {name: "home"}},
{name: "welcome", path: "/:tenant?/welcome", component: Welcome},
{name: "welcome", path: "/:tenant?/welcome", component: () => import("../components/onboarding/Welcome.vue")},
//Dashboards
{name: "home", path: "/:tenant?/dashboards/:id?", component: Dashboard},
{name: "dashboards/create", path: "/:tenant?/dashboards/new", component: DashboardCreate},
{name: "dashboards/update", path: "/:tenant?/dashboards/:id/edit", component: DashboardEdit},
{name: "home", path: "/:tenant?/dashboards/:id?", component: () => import("../components/dashboard/Dashboard.vue")},
{name: "dashboards/create", path: "/:tenant?/dashboards/new", component: () => import("../components/dashboard/components/DashboardCreate.vue")},
{name: "dashboards/update", path: "/:tenant?/dashboards/:id/edit", component: () => import("../components/dashboard/components/DashboardEdit.vue")},
//Flows
{name: "flows/list", path: "/:tenant?/flows", component: Flows},
{name: "flows/search", path: "/:tenant?/flows/search", component: FlowsSearch},
{name: "flows/create", path: "/:tenant?/flows/new", component: FlowCreate},
{name: "flows/update", path: "/:tenant?/flows/edit/:namespace/:id/:tab?", component: FlowRoot},
{name: "flows/list", path: "/:tenant?/flows", component: () => import("../components/flows/Flows.vue")},
{name: "flows/search", path: "/:tenant?/flows/search", component: () => import("../components/flows/FlowsSearch.vue")},
{name: "flows/create", path: "/:tenant?/flows/new", component: () => import("../components/flows/FlowCreate.vue")},
{name: "flows/update", path: "/:tenant?/flows/edit/:namespace/:id/:tab?", component: () => import("../components/flows/FlowRoot.vue")},
//Executions
{name: "executions/list", path: "/:tenant?/executions", component: Executions},
{name: "executions/update", path: "/:tenant?/executions/:namespace/:flowId/:id/:tab?", component: ExecutionRoot},
{name: "executions/list", path: "/:tenant?/executions", component: () => import("../components/executions/Executions.vue")},
{name: "executions/update", path: "/:tenant?/executions/:namespace/:flowId/:id/:tab?", component: () => import("../components/executions/ExecutionRoot.vue")},
//TaskRuns
{name: "taskruns/list", path: "/:tenant?/taskruns", component: TaskRuns},
{name: "taskruns/list", path: "/:tenant?/taskruns", component: () => import("../components/taskruns/TaskRuns.vue")},
//Blueprints
{name: "blueprints", path: "/:tenant?/blueprints", component: Blueprints, props: {topNavbar: false}},
{name: "blueprints/view", path: "/:tenant?/blueprints/:blueprintId", component: BlueprintDetail, props: true},
{name: "blueprints", path: "/:tenant?/blueprints", component: () => import("override/components/flows/blueprints/Blueprints.vue"), props: {topNavbar: false}},
{name: "blueprints/view", path: "/:tenant?/blueprints/:blueprintId", component: () => import("../components/flows/blueprints/BlueprintDetail.vue"), props: true},
//Documentation
{name: "plugins/list", path: "/:tenant?/plugins", component: Plugin},
{name: "plugins/view", path: "/:tenant?/plugins/:cls", component: Plugin},
{name: "plugins/list", path: "/:tenant?/plugins", component: () => import("../components/plugins/Plugin.vue")},
{name: "plugins/view", path: "/:tenant?/plugins/:cls", component: () => import("../components/plugins/Plugin.vue")},
//Templates
{name: "templates/list", path: "/:tenant?/templates", component: Templates},
{name: "templates/create", path: "/:tenant?/templates/new", component: TemplateEdit},
{name: "templates/update", path: "/:tenant?/templates/edit/:namespace/:id", component: TemplateEdit},
{name: "templates/list", path: "/:tenant?/templates", component: () => import("../components/templates/Templates.vue")},
{name: "templates/create", path: "/:tenant?/templates/new", component: () => import("../components/templates/TemplateEdit.vue")},
{name: "templates/update", path: "/:tenant?/templates/edit/:namespace/:id", component: () => import("../components/templates/TemplateEdit.vue")},
//Logs
{name: "logs/list", path: "/:tenant?/logs", component: LogsWrapper},
{name: "logs/list", path: "/:tenant?/logs", component: () => import("../components/logs/LogsWrapper.vue")},
//Namespaces
{name: "namespaces", path: "/:tenant?/namespaces", component: Namespaces},
{name: "namespaces/update", path: "/:tenant?/namespaces/edit/:id/:tab?", component: Namespace},
{name: "namespaces", path: "/:tenant?/namespaces", component: () => import("../components/namespace/Namespaces.vue")},
{name: "namespaces/update", path: "/:tenant?/namespaces/edit/:id/:tab?", component: () => import("../components/namespace/Namespace.vue")},
//Docs
{name: "docs/view", path: "/:tenant?/docs/:path(.*)?", component: Docs, meta: {layout: OnlyLeftMenuLayout}},
{name: "docs/view", path: "/:tenant?/docs/:path(.*)?", component: () => import("../components/docs/Docs.vue"), meta: {layout: OnlyLeftMenuLayout}},
//Settings
{name: "settings", path: "/:tenant?/settings", component: Settings},
{name: "settings", path: "/:tenant?/settings", component: () => import("override/components/settings/Settings.vue")},
//Admin
{name: "admin/triggers", path: "/:tenant?/admin/triggers", component: Triggers},
{name: "admin/stats", path: "/:tenant?/admin/stats", component: Stats},
{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")},
//Errors
{name: "errors/404-wildcard", path: "/:pathMatch(.*)", component: Errors, props: {code: 404}},
]
];

View File

@@ -1,7 +1,7 @@
@use "@kestra-io/ui-libs/src/scss/variables.scss" as global-var;
@use 'element-plus/theme-chalk/src/mixins/mixins' as mixin;
@use "@kestra-io/ui-libs/src/scss/app";
@use "@kestra-io/ui-libs/style.css";
// element-plus
@use "layout/element-plus-overload";
@@ -14,9 +14,6 @@
@use "layout/root-dark";
@use "layout/html-tag" as *;
@use "layout/theme-light";
@use "layout/theme-dark";
// components
@use "layout/charts";
@use "components/vue-material-design-icon";

View File

@@ -1,73 +0,0 @@
$base-blue-100: #a2cdff;
$base-blue-200: #7fbbff;
$base-blue-300: #5bb8ff;
$base-blue-400: #3991ff;
$base-blue-50: #c7fdff;
$base-blue-500: #1761fd;
$base-blue-600: #134ecc;
$base-blue-700: #0e3b9a;
$base-blue-800: #0a2869;
$base-blue-900: #051538;
$base-green-100: #beefe2;
$base-green-200: #7cdfc4;
$base-green-300: #21ce9c;
$base-green-400: #02be8a;
$base-green-50: #e4f9f3;
$base-green-500: #029e73;
$base-green-600: #017f5c;
$base-green-700: #016046;
$base-green-800: #014230;
$base-green-900: #002319;
$base-black: #060709;
$base-gray-100: #cfd3d6;
$base-gray-200: #ecebef;
$base-gray-300: #9797a6;
$base-gray-400: #404559;
$base-gray-50: #f9f9fa;
$base-gray-500: #2f3342;
$base-gray-600: #2c303f;
$base-gray-700: #21242e;
$base-gray-800: #21242e;
$base-gray-900: #1c1e27;
$base-gray-950: #060709;
$base-white: #ffffff;
$base-orange-100: #f3c4a1;
$base-orange-200: #eeae7e;
$base-orange-300: #e9985b;
$base-orange-400: #e58238;
$base-orange-50: #fff2ea;
$base-orange-500: #dd5f00;
$base-orange-600: #c15300;
$base-orange-700: #a64700;
$base-orange-800: #8a3b00;
$base-orange-900: #6f3000;
$base-purple-100: #bbbbff;
$base-purple-200: #a396ff;
$base-purple-300: #9470ff;
$base-purple-400: #8c4bff;
$base-purple-50: #e0e0ff;
$base-purple-500: #8405ff;
$base-purple-600: #7400df;
$base-purple-700: #6300bf;
$base-purple-800: #53009f;
$base-purple-900: #420080;
$base-red-100: #fec9cb;
$base-red-200: #fd9297;
$base-red-300: #fd7278;
$base-red-400: #e3262f;
$base-red-50: #fff2f3;
$base-red-500: #ab0009;
$base-red-600: #870007;
$base-red-700: #5a0005;
$base-red-800: #470004;
$base-red-900: #260002;
$base-yellow-100: #fdedb3;
$base-yellow-200: #fdeaa8;
$base-yellow-300: #fde89d;
$base-yellow-400: #fde592;
$base-yellow-50: #fffbef;
$base-yellow-500: #fce07c;
$base-yellow-600: #ddc46d;
$base-yellow-700: #bda85d;
$base-yellow-800: #9e8c4e;
$base-yellow-900: #7e703e;

View File

@@ -3,8 +3,8 @@
@use 'sass:math';
@use "sass:map";
@use 'element-plus/theme-chalk/src/mixins/mixins' as *;
@import "@kestra-io/ui-libs/src/scss/variables";
@import "../color-palette";
@import "@kestra-io/ui-libs/src/scss/variables.scss";
@import "@kestra-io/ui-libs/src/scss/color-palette.scss";
// button
.el-button {

View File

@@ -4,8 +4,8 @@
@use 'sass:math';
@use 'element-plus/theme-chalk/src/mixins/var' as *;
@import "@kestra-io/ui-libs/src/scss/variables";
@import "../color-palette";
@import "@kestra-io/ui-libs/src/scss/variables.scss";
@import "@kestra-io/ui-libs/src/scss/color-palette.scss";
// use bootstrap for main style
:root {

View File

@@ -1,160 +0,0 @@
@import "../color-palette.scss";
html.dark{
/* background */
#{--ks-background-body}: $base-gray-800;
#{--ks-background-cancelled}: rgba($base-red-200, 0.2);
#{--ks-background-card}: $base-gray-500;
#{--ks-background-card-opacity}: #121319e5;
#{--ks-background-created}: rgba($base-blue-400, 0.2);
#{--ks-background-error}: rgba($base-red-900, 0.2);
#{--ks-background-info}: rgba($base-blue-700, 0.2);
#{--ks-background-input}: $base-gray-900;
#{--ks-background-killed}: rgba($base-yellow-400, 0.1);
#{--ks-background-killing}: rgba($base-yellow-900, 0.2);
#{--ks-background-left-menu}: $base-gray-900;
#{--ks-background-logo}: #2c005900;
#{--ks-background-paused}: $base-gray-500;
#{--ks-background-queued}: $base-gray-700;
#{--ks-background-restarted}: rgba($base-blue-300, 0.2);
#{--ks-background-retried}: #578dff33;
#{--ks-background-retrying}: rgba($base-blue-500, 0.2);
#{--ks-background-running}: rgba($base-blue-500, 0.2);
#{--ks-background-success}: rgba($base-green-900, 0.2);
#{--ks-background-table-header}: $base-gray-600;
#{--ks-background-table-row}: $base-gray-400;
#{--ks-background-table-row-hover}: #2f3342;
#{--ks-background-tag}: $base-gray-400;
#{--ks-background-warning}: rgba($base-orange-900, 0.2);
/* badge */
#{--ks-badge-background}: rgba($base-blue-300, 0.2);
#{--ks-badge-border}: $base-blue-300;
#{--ks-badge-content}: $base-blue-100;
/* border */
#{--ks-border-active}: $base-purple-500;
#{--ks-border-cancelled}: $base-red-200;
#{--ks-border-created}: $base-blue-500;
#{--ks-border-error}: $base-red-400;
#{--ks-border-inactive}: $base-gray-400;
#{--ks-border-info}: $base-blue-500;
#{--ks-border-killed}: $base-yellow-900;
#{--ks-border-killing}: $base-yellow-100;
#{--ks-border-paused}: $base-gray-300;
#{--ks-border-primary}: $base-gray-400;
#{--ks-border-queued}: $base-gray-300;
#{--ks-border-restarted}: $base-blue-100;
#{--ks-border-retried}: $base-blue-100;
#{--ks-border-retrying}: $base-blue-200;
#{--ks-border-running}: $base-blue-400;
#{--ks-border-secondary}: $base-gray-500;
#{--ks-border-success}: $base-green-400;
#{--ks-border-system}: $base-blue-300;
#{--ks-border-warning}: $base-orange-300;
/* button */
#{--ks-button-background-inactive}: $base-gray-600;
#{--ks-button-background-primary}: $base-purple-500;
#{--ks-button-background-primary-active}: $base-purple-600;
#{--ks-button-background-primary-hover}: $base-purple-400;
#{--ks-button-background-secondary}: $base-gray-500;
#{--ks-button-background-secondary-active}: $base-gray-700;
#{--ks-button-background-secondary-hover}: $base-gray-400;
#{--ks-button-background-success}: $base-green-400;
#{--ks-button-background-success-active}: $base-green-500;
#{--ks-button-background-success-hover}: $base-green-300;
#{--ks-button-content-primary}: $base-white;
/* chart */
#{--ks-chart-cancelled}: $base-red-200;
#{--ks-chart-created}: $base-blue-400;
#{--ks-chart-failed}: $base-red-300;
#{--ks-chart-killed}: $base-yellow-600;
#{--ks-chart-killing}: $base-yellow-200;
#{--ks-chart-paused}: $base-gray-300;
#{--ks-chart-queued}: $base-gray-200;
#{--ks-chart-restarted}: $base-blue-50;
#{--ks-chart-retried}: $base-blue-100;
#{--ks-chart-retrying}: $base-blue-200;
#{--ks-chart-running}: $base-blue-300;
#{--ks-chart-success}: $base-green-300;
#{--ks-chart-warning}: $base-orange-200;
/* content */
#{--ks-content-alert}: $base-red-300;
#{--ks-content-cancelled}: $base-red-50;
#{--ks-content-created}: $base-blue-100;
#{--ks-content-error}: $base-red-200;
#{--ks-content-id}: $base-purple-100;
#{--ks-content-inactive}: $base-gray-300;
#{--ks-content-info}: $base-blue-50;
#{--ks-content-inverse}: $base-black;
#{--ks-content-killed}: $base-yellow-200;
#{--ks-content-killing}: $base-yellow-50;
#{--ks-content-link}: $base-purple-100;
#{--ks-content-link-hover}: $base-purple-50;
#{--ks-content-paused}: $base-gray-200;
#{--ks-content-primary}: $base-white;
#{--ks-content-queued}: $base-gray-200;
#{--ks-content-restarted}: $base-blue-200;
#{--ks-content-retried}: $base-blue-50;
#{--ks-content-retrying}: $base-blue-50;
#{--ks-content-running}: $base-blue-100;
#{--ks-content-secondary}: $base-gray-200;
#{--ks-content-success}: $base-green-100;
#{--ks-content-tertiary}: $base-gray-300;
#{--ks-content-warning}: $base-orange-200;
/* dialog */
#{--ks-dialog-background}: $base-gray-500;
#{--ks-dialog-border}: $base-gray-400;
#{--ks-dialog-header}: $base-gray-500;
#{--ks-dialog-headerbtn}: $base-gray-300;
#{--ks-dialog-headerbtn-hover}: $base-purple-200;
/* editor */
#{--ks-editor-number}: $base-orange-100;
#{--ks-editor-pabble}: $base-orange-50;
#{--ks-editor-property}: $base-green-200;
#{--ks-editor-punctuation}: $base-gray-300;
#{--ks-editor-value}: $base-blue-300;
/* log */
#{--ks-log-background-debug}: rgba($base-blue-300, 0.2);
#{--ks-log-background-error}: rgba($base-red-300, 0.2);
#{--ks-log-background-info}: rgba($base-blue-700, 0.2);
#{--ks-log-background-trace}: $base-gray-400;
#{--ks-log-background-warn}: rgba($base-orange-400, 0.2);
#{--ks-log-border-debug}: $base-blue-300;
#{--ks-log-border-error}: $base-red-300;
#{--ks-log-border-info}: $base-blue-500;
#{--ks-log-border-trace}: $base-gray-300;
#{--ks-log-border-warn}: $base-orange-300;
#{--ks-log-chart-debug}: $base-blue-400;
#{--ks-log-chart-error}: $base-red-300;
#{--ks-log-chart-info}: $base-blue-500;
#{--ks-log-chart-log-warn}: $base-orange-200;
#{--ks-log-chart-trace}: $base-gray-300;
#{--ks-log-content-debug}: $base-blue-100;
#{--ks-log-content-error}: $base-red-100;
#{--ks-log-content-info}: $base-blue-50;
#{--ks-log-content-trace}: $base-gray-100;
#{--ks-log-content-warn}: $base-orange-100;
/* select */
#{--ks-select-active}: $base-gray-900;
#{--ks-select-active-icon}: $base-purple-100;
#{--ks-select-background}: $base-gray-800;
#{--ks-select-border}: $base-gray-400;
#{--ks-select-hover}: $base-gray-600;
/* tag */
#{--ks-tag-background}: $base-gray-500;
#{--ks-tag-background-hover}: $base-gray-400;
#{--ks-tag-content}: $base-white;
/* tooltip */
#{--ks-tooltip-background}: $base-gray-700;
#{--ks-tooltip-border}: $base-gray-400;
}

View File

@@ -1,160 +0,0 @@
@import "../color-palette.scss";
:root{
/* background */
#{--ks-background-body}: $base-gray-50;
#{--ks-background-cancelled}: $base-red-100;
#{--ks-background-card}: $base-white;
#{--ks-background-card-opacity}: #1b1c23e5;
#{--ks-background-created}: $base-blue-50;
#{--ks-background-error}: $base-red-50;
#{--ks-background-info}: #c7f0ff;
#{--ks-background-input}: $base-white;
#{--ks-background-killed}: $base-yellow-50;
#{--ks-background-killing}: $base-yellow-50;
#{--ks-background-left-menu}: $base-white;
#{--ks-background-logo}: #2c0059;
#{--ks-background-paused}: #b2b2b542;
#{--ks-background-queued}: $base-yellow-50;
#{--ks-background-restarted}: $base-blue-50;
#{--ks-background-retried}: rgba($base-blue-500, 0.2);
#{--ks-background-retrying}: $base-blue-50;
#{--ks-background-running}: $base-blue-50;
#{--ks-background-success}: $base-green-50;
#{--ks-background-table-header}: $base-gray-50;
#{--ks-background-table-row}: $base-gray-100;
#{--ks-background-table-row-hover}: $base-white;
#{--ks-background-tag}: $base-gray-200;
#{--ks-background-warning}: $base-orange-50;
/* badge */
#{--ks-badge-background}: $base-blue-50;
#{--ks-badge-border}: $base-blue-400;
#{--ks-badge-content}: $base-blue-600;
/* border */
#{--ks-border-active}: $base-purple-500;
#{--ks-border-cancelled}: $base-red-300;
#{--ks-border-created}: $base-blue-300;
#{--ks-border-error}: $base-red-300;
#{--ks-border-inactive}: $base-gray-100;
#{--ks-border-info}: $base-blue-200;
#{--ks-border-killed}: $base-yellow-600;
#{--ks-border-killing}: $base-yellow-400;
#{--ks-border-paused}: $base-gray-200;
#{--ks-border-primary}: $base-gray-200;
#{--ks-border-queued}: $base-yellow-600;
#{--ks-border-restarted}: $base-blue-100;
#{--ks-border-retried}: $base-blue-600;
#{--ks-border-retrying}: $base-blue-500;
#{--ks-border-running}: $base-blue-400;
#{--ks-border-secondary}: $base-gray-100;
#{--ks-border-success}: $base-green-300;
#{--ks-border-system}: $base-blue-400;
#{--ks-border-warning}: $base-orange-300;
/* button */
#{--ks-button-background-inactive}: $base-gray-50;
#{--ks-button-background-primary}: $base-purple-500;
#{--ks-button-background-primary-active}: $base-purple-600;
#{--ks-button-background-primary-hover}: $base-purple-400;
#{--ks-button-background-secondary}: $base-white;
#{--ks-button-background-secondary-active}: $base-gray-100;
#{--ks-button-background-secondary-hover}: $base-gray-50;
#{--ks-button-background-success}: $base-green-500;
#{--ks-button-background-success-active}: $base-green-600;
#{--ks-button-background-success-hover}: $base-green-400;
#{--ks-button-content-primary}: $base-white;
/* chart */
#{--ks-chart-cancelled}: $base-red-200;
#{--ks-chart-created}: $base-blue-500;
#{--ks-chart-failed}: $base-red-300;
#{--ks-chart-killed}: $base-yellow-200;
#{--ks-chart-killing}: $base-yellow-300;
#{--ks-chart-paused}: $base-yellow-500;
#{--ks-chart-queued}: $base-yellow-100;
#{--ks-chart-restarted}: $base-blue-50;
#{--ks-chart-retried}: $base-blue-100;
#{--ks-chart-retrying}: $base-blue-200;
#{--ks-chart-running}: $base-blue-300;
#{--ks-chart-success}: $base-green-400;
#{--ks-chart-warning}: $base-orange-100;
/* content */
#{--ks-content-alert}: $base-red-500;
#{--ks-content-cancelled}: $base-red-500;
#{--ks-content-created}: $base-blue-500;
#{--ks-content-error}: $base-red-500;
#{--ks-content-id}: $base-purple-500;
#{--ks-content-inactive}: $base-gray-300;
#{--ks-content-info}: $base-blue-600;
#{--ks-content-inverse}: $base-white;
#{--ks-content-killed}: $base-yellow-900;
#{--ks-content-killing}: $base-orange-500;
#{--ks-content-link}: $base-purple-500;
#{--ks-content-link-hover}: $base-purple-300;
#{--ks-content-paused}: $base-gray-500;
#{--ks-content-primary}: $base-black;
#{--ks-content-queued}: $base-yellow-800;
#{--ks-content-restarted}: $base-blue-600;
#{--ks-content-retried}: $base-blue-900;
#{--ks-content-retrying}: $base-blue-700;
#{--ks-content-running}: $base-blue-600;
#{--ks-content-secondary}: $base-gray-700;
#{--ks-content-success}: $base-green-700;
#{--ks-content-tertiary}: $base-gray-500;
#{--ks-content-warning}: $base-orange-500;
/* dialog */
#{--ks-dialog-background}: $base-white;
#{--ks-dialog-border}: $base-gray-200;
#{--ks-dialog-header}: $base-white;
#{--ks-dialog-headerbtn}: $base-gray-300;
#{--ks-dialog-headerbtn-hover}: $base-purple-300;
/* editor */
#{--ks-editor-number}: $base-orange-600;
#{--ks-editor-pabble}: $base-orange-400;
#{--ks-editor-property}: $base-green-600;
#{--ks-editor-punctuation}: $base-gray-400;
#{--ks-editor-value}: $base-blue-600;
/* log */
#{--ks-log-background-debug}: $base-blue-50;
#{--ks-log-background-error}: $base-red-50;
#{--ks-log-background-info}: #c7f0ff;
#{--ks-log-background-trace}: $base-gray-50;
#{--ks-log-background-warn}: $base-orange-50;
#{--ks-log-border-debug}: $base-blue-400;
#{--ks-log-border-error}: $base-red-400;
#{--ks-log-border-info}: $base-blue-200;
#{--ks-log-border-trace}: $base-gray-300;
#{--ks-log-border-warn}: $base-orange-400;
#{--ks-log-chart-debug}: $base-blue-200;
#{--ks-log-chart-error}: $base-red-300;
#{--ks-log-chart-info}: $base-blue-300;
#{--ks-log-chart-log-warn}: $base-orange-200;
#{--ks-log-chart-trace}: $base-gray-200;
#{--ks-log-content-debug}: $base-blue-600;
#{--ks-log-content-error}: $base-red-500;
#{--ks-log-content-info}: $base-blue-600;
#{--ks-log-content-trace}: $base-gray-500;
#{--ks-log-content-warn}: $base-orange-800;
/* select */
#{--ks-select-active}: $base-gray-50;
#{--ks-select-active-icon}: $base-purple-500;
#{--ks-select-background}: $base-white;
#{--ks-select-border}: $base-gray-200;
#{--ks-select-hover}: $base-gray-200;
/* tag */
#{--ks-tag-background}: $base-gray-50;
#{--ks-tag-background-hover}: $base-gray-200;
#{--ks-tag-content}: $base-gray-800;
/* tooltip */
#{--ks-tooltip-background}: $base-white;
#{--ks-tooltip-border}: $base-gray-300;
}

View File

@@ -0,0 +1,39 @@
import {nextTick} from "vue"
import {createI18n, type I18n} from "vue-i18n"
const translations = import.meta.glob("./*.json")
export const SUPPORT_LOCALES = ["de","en","es","fr","hi","it","ja","ko","pl","pt","ru","zh_CN"] as const
export function setupI18n(options: {locale: (typeof SUPPORT_LOCALES)[number]} = {locale: "en"}) {
const i18n = createI18n(options)
setI18nLanguage(i18n, options.locale)
return i18n
}
export function setI18nLanguage(i18n: I18n, locale: (typeof SUPPORT_LOCALES)[number]) {
if (i18n.mode === "legacy") {
i18n.global.locale = locale
} else {
// @ts-expect-error vue-i18n is not typed correcly it seems
i18n.global.locale.value = locale
}
/**
* NOTE:
* If you need to specify the language setting for headers, such as the `fetch` API, set it here.
* The following is an example for axios.
*
* axios.defaults.headers.common['Accept-Language'] = locale
*/
document.querySelector("html")?.setAttribute("lang", locale)
}
export async function loadLocaleMessages(i18n: I18n, locale: (typeof SUPPORT_LOCALES)[number]) {
// load locale messages with dynamic import
const messages = await translations[`./${locale}.json`]() as any
// set locale and locale message
i18n.global.setLocaleMessage(locale, messages.default[locale])
return nextTick()
}

10
ui/src/ui-libs.d.ts vendored
View File

@@ -1,10 +0,0 @@
declare module "@kestra-io/ui-libs/src/utils/global" {
export function cssVariable(name: string): string;
}
declare module "@kestra-io/ui-libs/src/utils/Utils" {
export default class Utils {
static getTheme(): string;
static humanDuration(duration: number | string): string;
}
}

View File

@@ -1,7 +1,6 @@
import _merge from "lodash/merge";
import State from "./state";
import Utils from "./utils";
import {cssVariable} from "@kestra-io/ui-libs/src/utils/global";
import {cssVariable, State} from "@kestra-io/ui-libs";
export function tooltip(tooltipModel) {
const titleLines = tooltipModel.title || [];

View File

@@ -1,7 +1,7 @@
import {createStore} from "vuex";
import {createRouter, createWebHistory} from "vue-router";
import VueGtag from "vue-gtag";
import {createI18n} from "vue-i18n";
import {setI18nLanguage, loadLocaleMessages, setupI18n} from "../translations/i18n";
import moment from "moment-timezone";
import "moment/dist/locale/de"
import "moment/dist/locale/es"
@@ -62,7 +62,7 @@ import RouterMd from "../components/utils/RouterMd.vue";
import Utils from "./utils";
import TaskTaskRunner from "../components/flows/tasks/TaskTaskRunner.vue";
export default (app, routes, stores, translations) => {
export default async (app, routes, stores, translations) => {
// charts
Chart.register(
CategoryScale,
@@ -139,14 +139,19 @@ export default (app, routes, stores, translations) => {
// l18n
let locale = Utils.getLang();
let i18n = createI18n({
locale: locale,
let i18n = setupI18n({
locale: "en",
messages: translations,
allowComposition: true,
legacy: false,
warnHtmlMessage: false,
});
if(locale !== "en"){
await loadLocaleMessages(i18n, locale);
await setI18nLanguage(i18n, locale);
}
app.use(i18n);
// moment

View File

@@ -1,4 +1,4 @@
import {cssVariable} from "@kestra-io/ui-libs/src/utils/global";
import {cssVariable} from "@kestra-io/ui-libs";
const LEVELS = [
"ERROR",

View File

@@ -1,17 +1,6 @@
import markdownIt from "markdown-it";
import mark from "markdown-it-mark";
import meta from "markdown-it-meta";
import anchor from "markdown-it-anchor";
import container from "markdown-it-container";
import {fromHighlighter} from "@shikijs/markdown-it/core";
import {createHighlighterCore} from "shiki/core";
import githubDark from "shiki/themes/github-dark.mjs";
import githubLight from "shiki/themes/github-light.mjs";
import {linkTag} from "./markdown_plugins/link";
let highlighter = null;
async function getHighlighter() {
async function getHighlighter(createHighlighterCore, githubDark, githubLight) {
if (!highlighter) {
highlighter = createHighlighterCore({
langs: [import("shiki/langs/yaml.mjs"), import("shiki/langs/python.mjs"), import("shiki/langs/javascript.mjs")],
@@ -22,45 +11,44 @@ async function getHighlighter() {
return highlighter;
}
export default class Markdown {
static async render(markdown, options) {
const highlighter = await getHighlighter();
export async function render(markdown, options) {
const {createHighlighterCore, githubDark, githubLight, markdownIt, mark, meta, anchor, container, fromHighlighter, linkTag} = await import( "./markdownDeps")
const highlighter = await getHighlighter(createHighlighterCore, githubDark, githubLight);
githubDark["colors"]["editor.background"] = "var(--bs-gray-500)";
githubLight["colors"]["editor.background"] = "var(--bs-white)";
githubDark["colors"]["editor.background"] = "var(--bs-gray-500)";
githubLight["colors"]["editor.background"] = "var(--bs-white)";
options = options || {};
options = options || {};
const darkTheme = document.getElementsByTagName("html")[0].className.indexOf("dark") >= 0;
const darkTheme = document.getElementsByTagName("html")[0].className.indexOf("dark") >= 0;
let md;
if (options.onlyLink) {
md = new markdownIt("zero");
md.enable(["link", "linkify", "entity", "html_inline", "newline"]);
} else {
md = new markdownIt();
}
md.use(mark)
.use(meta)
.use(anchor, {permalink: options.permalink ? anchor.permalink.ariaHidden({placement: "before"}) : undefined})
.use(container, "warning")
.use(container, "info")
.use(fromHighlighter(highlighter, {theme: darkTheme ? "github-dark" : "github-light"}))
.use(linkTag);
md.set({
html: true,
xhtmlOut: true,
breaks: true,
linkify: true,
typographer: true,
langPrefix: "language-",
quotes: "“”‘’",
});
md.renderer.rules.table_open = () => "<table class=\"table\">\n";
return md.render(markdown);
let md;
if (options.onlyLink) {
md = new markdownIt("zero");
md.enable(["link", "linkify", "entity", "html_inline", "newline"]);
} else {
md = new markdownIt();
}
md.use(mark)
.use(meta)
.use(anchor, {permalink: options.permalink ? anchor.permalink.ariaHidden({placement: "before"}) : undefined})
.use(container, "warning")
.use(container, "info")
.use(fromHighlighter(highlighter, {theme: darkTheme ? "github-dark" : "github-light"}))
.use(linkTag);
md.set({
html: true,
xhtmlOut: true,
breaks: true,
linkify: true,
typographer: true,
langPrefix: "language-",
quotes: "“”‘’",
});
md.renderer.rules.table_open = () => "<table class=\"table\">\n";
return md.render(markdown);
}

View File

@@ -0,0 +1,23 @@
import markdownIt from "markdown-it";
import mark from "markdown-it-mark";
import meta from "markdown-it-meta";
import anchor from "markdown-it-anchor";
import container from "markdown-it-container";
import {fromHighlighter} from "@shikijs/markdown-it/core";
import {createHighlighterCore} from "shiki/core";
import githubDark from "shiki/themes/github-dark.mjs";
import githubLight from "shiki/themes/github-light.mjs";
import {linkTag} from "./markdown_plugins/link";
export {
markdownIt,
mark,
meta,
anchor,
container,
fromHighlighter,
createHighlighterCore,
githubDark,
githubLight,
linkTag
}

View File

@@ -1,253 +0,0 @@
import _mapValues from "lodash/mapValues";
import PauseCircle from "vue-material-design-icons/PauseCircle.vue";
import CheckCircle from "vue-material-design-icons/CheckCircle.vue";
import PlayCircle from "vue-material-design-icons/PlayCircle.vue";
import CloseCircle from "vue-material-design-icons/CloseCircle.vue";
import StopCircle from "vue-material-design-icons/StopCircle.vue";
import SkipPreviousCircle from "vue-material-design-icons/SkipPreviousCircle.vue";
import AlertCircle from "vue-material-design-icons/AlertCircle.vue";
import DotsVerticalCircle from "vue-material-design-icons/DotsVerticalCircle.vue";
import MotionPauseOutline from "vue-material-design-icons/MotionPauseOutline.vue";
import Refresh from "vue-material-design-icons/Refresh.vue";
import Cancel from "vue-material-design-icons/Cancel.vue";
import {cssVariable} from "@kestra-io/ui-libs/src/utils/global";
const STATE = Object.freeze({
CREATED: {
name: "CREATED",
color: "#1761FD",
colorClass: "cyan",
icon: DotsVerticalCircle,
isRunning: true,
isKillable: true,
isFailed: false,
},
RESTARTED: {
name: "RESTARTED",
color: "#1761FD",
colorClass: "cyan",
icon: SkipPreviousCircle,
isRunning: false,
isKillable: true,
isFailed: false,
},
SUCCESS: {
name: "SUCCESS",
color: "#029E73",
colorClass: "green",
icon: CheckCircle,
isRunning: false,
isKillable: false,
isFailed: false,
},
RUNNING: {
name: "RUNNING",
color: "#8405FF",
colorClass: "purple",
icon: PlayCircle,
isRunning: true,
isKillable: true,
isFailed: false,
},
KILLING: {
name: "KILLING",
color: "#FCE07C",
colorClass: "yellow",
icon: CloseCircle,
isRunning: true,
isKillable: true,
isFailed: true,
},
KILLED: {
name: "KILLED",
color: "#FCE07C",
colorClass: "yellow",
icon: StopCircle,
isRunning: false,
isKillable: false,
isFailed: true,
},
WARNING: {
name: "WARNING",
color: "#DD5F00",
colorClass: "orange",
icon: AlertCircle,
isRunning: false,
isKillable: false,
isFailed: true,
},
FAILED: {
name: "FAILED",
color: "#AB0009",
colorClass: "red",
icon: CloseCircle,
isRunning: false,
isKillable: false,
isFailed: true,
},
PAUSED: {
name: "PAUSED",
color: "#918BA9",
colorClass: "indigo",
icon: PauseCircle,
isRunning: true,
isKillable: true,
isFailed: false,
},
CANCELLED: {
name: "CANCELLED",
color: "#918BA9",
colorClass: "gray",
icon: Cancel,
isRunning: false,
isKillable: false,
isFailed: true,
},
SKIPPED: {
name: "SKIPPED",
color: "#918BA9",
colorClass: "gray",
icon: Cancel,
isRunning: false,
isKillable: false,
isFailed: true,
},
QUEUED: {
name: "QUEUED",
color: "#918BA9",
colorClass: "gray",
icon: MotionPauseOutline,
isRunning: false,
isKillable: false,
isFailed: false,
},
RETRYING: {
name: "RETRYING",
color: "#918BA9",
colorClass: "gray",
icon: Refresh,
isRunning: false,
isKillable: true,
isFailed: false,
},
RETRIED: {
name: "RETRIED",
color: "#918BA9",
colorClass: "gray",
icon: Refresh,
isRunning: false,
isKillable: false,
isFailed: false,
},
});
export default class State {
static get CREATED() {
return STATE.CREATED.name;
}
static get RESTARTED() {
return STATE.RESTARTED.name;
}
static get SUCCESS() {
return STATE.SUCCESS.name;
}
static get RUNNING() {
return STATE.RUNNING.name;
}
static get KILLING() {
return STATE.KILLING.name;
}
static get KILLED() {
return STATE.KILLED.name;
}
static get FAILED() {
return STATE.FAILED.name;
}
static get WARNING() {
return STATE.WARNING.name;
}
static get PAUSED() {
return STATE.PAUSED.name;
}
static get CANCELLED() {
return STATE.CANCELLED.name;
}
static get QUEUED() {
return STATE.QUEUED.name;
}
static get RETRYING() {
return STATE.RETRYING.name;
}
static get RETRIED() {
return STATE.RETRIED.name;
}
static isRunning(state) {
return STATE[state] && STATE[state].isRunning;
}
static isKillable(state) {
return STATE[state] && STATE[state].isKillable;
}
static isPaused(state) {
return STATE[state] && STATE[state] === STATE.PAUSED;
}
static isFailed(state) {
return STATE[state] && STATE[state].isFailed;
}
static isQueued(state) {
return STATE[state] && STATE[state] === STATE.QUEUED;
}
static allStates() {
return _mapValues(STATE, (state) => {
return {
key: state.name,
icon: state.icon,
color: cssVariable("--bs-" + state.colorClass),
colorClass: state.colorClass,
};
});
}
static arrayAllStates() {
return Object.values(STATE);
}
static colorClass() {
return _mapValues(STATE, (state) => state.colorClass);
}
static color() {
return _mapValues(STATE, (state) =>
cssVariable("--bs-" + state.colorClass),
);
}
static getStateColor(state) {
return STATE[state].color;
}
static icon() {
return _mapValues(STATE, (state) => state.icon);
}
static getTerminatedStates() {
return Object.values(STATE).filter(state => !state.isRunning).map(state => state.name);
}
}

1
ui/src/vite.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@@ -5,7 +5,7 @@ export default {
"stylelint-config-recommended-vue/scss"
],
plugins: [
"./theme/lint-custom-properties.mjs",
"./plugins/lint-custom-properties.mjs",
],
rules: {
"color-no-hex": true,

View File

@@ -1,5 +1,4 @@
import ShowCase from "./ShowCase.vue";
import ShowCaseColors from "./ShowCaseColors.vue";
const meta = {
title: "theme/ShowCase",
@@ -13,8 +12,4 @@ export default meta;
*/
export const ElementPlusPlayground = {
render: () => <ShowCase />,
}
export const ColorsPlayground = {
render: () => <ShowCaseColors />,
}

View File

@@ -216,8 +216,7 @@
import Message from "vue-material-design-icons/Message.vue"
import Star from "vue-material-design-icons/Star.vue"
import Delete from "vue-material-design-icons/Delete.vue"
// @ts-expect-error Tabs is not yet TS
import Tabs from "../src/components/Tabs.vue"
import Tabs from "../../../src/components/Tabs.vue"
const app = getCurrentInstance()?.appContext.config.globalProperties as any

View File

@@ -0,0 +1,127 @@
// @ts-check
import valueParser from "postcss-value-parser";
import stylelint from "stylelint";
const {
createPlugin,
utils: {
report,
ruleMessages,
validateOptions,
},
} = stylelint;
const ruleName = "ks/custom-property-pattern-usage";
const messages = ruleMessages(ruleName, {
expected: (propName, pattern) => `Expected "${propName}" to match pattern "${pattern}"`,
});
const VAR_FUNC_REGEX = /var\(/i;
const isCustomProperty = (prop) => prop.startsWith("--");
function isRegExp(value) {
return value instanceof RegExp;
}
function isString(value) {
return value && typeof value === "string";
}
function isVarFunction(node) {
return node.type === "function" && node.value.toLowerCase() === "var";
}
/** @type {import('stylelint').Rule} */
const rule = (primary) => {
return (root, result) => {
const validOptions = validateOptions(result, ruleName, {
actual: primary,
possible: [isRegExp, isString],
});
if (!validOptions) {
return;
}
const regexpPattern = isString(primary) ? new RegExp(primary) : primary;
/**
* @param {string} property
* @returns {boolean}
*/
function check(property) {
return !isCustomProperty(property) || regexpPattern.test(property);
}
root.walkDecls((decl) => {
const {value} = decl;
if (VAR_FUNC_REGEX.test(value)) {
const parsedValue = valueParser(value);
parsedValue.walk((node) => {
if (!isVarFunction(node)) return;
// @ts-expect-error missing type
const {nodes} = node;
const firstNode = nodes[0];
if (!firstNode || check(firstNode.value)) return;
complain(declarationValueIndex(decl) + firstNode.sourceIndex, firstNode.value, decl);
});
}
});
/**
* @param {number} index
* @param {string} propName
* @param {import('postcss').Declaration} decl
*/
function complain(index, propName, decl) {
report({
result,
ruleName,
message: messages.expected,
messageArgs: [propName, primary],
node: decl,
index,
endIndex: index + propName.length,
});
}
};
};
rule.ruleName = ruleName;
rule.messages = messages;
export default createPlugin(ruleName, rule);
function declarationBetweenIndex(decl) {
const {prop} = decl.raws;
const propIsObject = typeof prop === "object";
return countChars([
propIsObject && "prefix" in prop && prop.prefix,
(propIsObject && "raw" in prop && prop.raw) || decl.prop,
propIsObject && "suffix" in prop && prop.suffix,
]);
}
function declarationValueIndex(decl) {
const {between, value} = decl.raws;
return (
declarationBetweenIndex(decl) +
countChars([between || ":", value && "prefix" in value && value.prefix])
);
}
function countChars(values) {
return values.reduce((/** @type {number} */ count, value) => {
if (isString(value)) return count + value.length;
return count;
}, 0);
}

View File

@@ -1,36 +0,0 @@
<template>
<div class="wrapper">
<template v-for="(cssVariables, theme) in cssVariablesThemes" :key="theme">
<h2>
{{ theme }}
</h2>
<div
class="var-theme"
>
<ShowCaseColorsSample
v-for="(color, index) in cssVariables"
:key="index"
:color="color"
/>
</div>
</template>
</div>
</template>
<script lang="ts" setup>
import cssVariablesThemes from "./css-variables.json";
import ShowCaseColorsSample from "./ShowCaseColorsSample.vue";
</script>
<style scoped>
.wrapper {
padding: 1rem;
background-color: var(--ks-background-body);
}
.var-theme {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 1rem;
margin-bottom: 3rem;
}
</style>

View File

@@ -1,51 +0,0 @@
<template>
<div
class="sample-wrapper"
:style="styleComputed"
>
<span class="sample-block" :style="{backgroundColor: `var(--${color})`}" />
<span class="sample-label">
var(--{{ color }})
</span>
</div>
</template>
<script lang="ts" setup>
import {computed} from "vue";
const props = defineProps<{
color: string
}>()
const styleComputed = computed(() => {
return props.color.indexOf("background") > -1
? {background: `var(--${props.color})`}
: props.color.indexOf("border") > -1
? {border: `1px solid var(--${props.color})`, borderRadius: "4px"}
: {color: `var(--${props.color})`};
})
</script>
<style scoped>
.sample-wrapper {
padding:.5rem 1rem;
display: flex;
align-items: center;
gap:.5rem;
color: black;
}
.sample-label{
background-color: rgba(255, 255, 255, 0.5);
padding: 0 .5rem;
border-radius: 4px;
}
.sample-block{
width:24px;
height:24px;
display:block
}
</style>

View File

@@ -1,159 +0,0 @@
{
"background": [
"ks-background-body",
"ks-background-cancelled",
"ks-background-card",
"ks-background-card-opacity",
"ks-background-created",
"ks-background-error",
"ks-background-info",
"ks-background-input",
"ks-background-killed",
"ks-background-killing",
"ks-background-left-menu",
"ks-background-logo",
"ks-background-paused",
"ks-background-queued",
"ks-background-restarted",
"ks-background-retried",
"ks-background-retrying",
"ks-background-running",
"ks-background-success",
"ks-background-table-header",
"ks-background-table-row",
"ks-background-table-row-hover",
"ks-background-tag",
"ks-background-warning"
],
"badge": [
"ks-badge-background",
"ks-badge-border",
"ks-badge-content"
],
"border": [
"ks-border-active",
"ks-border-cancelled",
"ks-border-created",
"ks-border-error",
"ks-border-inactive",
"ks-border-info",
"ks-border-killed",
"ks-border-killing",
"ks-border-paused",
"ks-border-primary",
"ks-border-queued",
"ks-border-restarted",
"ks-border-retried",
"ks-border-retrying",
"ks-border-running",
"ks-border-secondary",
"ks-border-success",
"ks-border-system",
"ks-border-warning"
],
"button": [
"ks-button-background-inactive",
"ks-button-background-primary",
"ks-button-background-primary-active",
"ks-button-background-primary-hover",
"ks-button-background-secondary",
"ks-button-background-secondary-active",
"ks-button-background-secondary-hover",
"ks-button-background-success",
"ks-button-background-success-active",
"ks-button-background-success-hover",
"ks-button-content-primary"
],
"chart": [
"ks-chart-cancelled",
"ks-chart-created",
"ks-chart-failed",
"ks-chart-killed",
"ks-chart-killing",
"ks-chart-paused",
"ks-chart-queued",
"ks-chart-restarted",
"ks-chart-retried",
"ks-chart-retrying",
"ks-chart-running",
"ks-chart-success",
"ks-chart-warning"
],
"content": [
"ks-content-alert",
"ks-content-cancelled",
"ks-content-created",
"ks-content-error",
"ks-content-id",
"ks-content-inactive",
"ks-content-info",
"ks-content-inverse",
"ks-content-killed",
"ks-content-killing",
"ks-content-link",
"ks-content-link-hover",
"ks-content-paused",
"ks-content-primary",
"ks-content-queued",
"ks-content-restarted",
"ks-content-retried",
"ks-content-retrying",
"ks-content-running",
"ks-content-secondary",
"ks-content-success",
"ks-content-tertiary",
"ks-content-warning"
],
"dialog": [
"ks-dialog-background",
"ks-dialog-border",
"ks-dialog-header",
"ks-dialog-headerbtn",
"ks-dialog-headerbtn-hover"
],
"editor": [
"ks-editor-number",
"ks-editor-pabble",
"ks-editor-property",
"ks-editor-punctuation",
"ks-editor-value"
],
"log": [
"ks-log-background-debug",
"ks-log-background-error",
"ks-log-background-info",
"ks-log-background-trace",
"ks-log-background-warn",
"ks-log-border-debug",
"ks-log-border-error",
"ks-log-border-info",
"ks-log-border-trace",
"ks-log-border-warn",
"ks-log-chart-debug",
"ks-log-chart-error",
"ks-log-chart-info",
"ks-log-chart-log-warn",
"ks-log-chart-trace",
"ks-log-content-debug",
"ks-log-content-error",
"ks-log-content-info",
"ks-log-content-trace",
"ks-log-content-warn"
],
"select": [
"ks-select-active",
"ks-select-active-icon",
"ks-select-background",
"ks-select-border",
"ks-select-hover"
],
"tag": [
"ks-tag-background",
"ks-tag-background-hover",
"ks-tag-content"
],
"tooltip": [
"ks-tooltip-background",
"ks-tooltip-border"
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"incremental": true,
/* Bundler mode */
"moduleResolution": "bundler",
@@ -30,7 +31,6 @@
"include": [
".storybook/preview.*",
"src/**/*.ts", "src/**/*.tsx", "src/**/*.vue",
"theme/**/*.ts", "theme/**/*.tsx", "theme/**/*.vue",
"tests/**/*.ts", "tests/**/*.tsx"
]
}

View File

@@ -49,7 +49,13 @@ export default defineConfig({
},
optimizeDeps: {
include: [
"lodash"
"lodash",
// the 3 dependencies below are used by ui-libs
// optimizing them allows storybook to run properly
// without allowing interop in typescript
"dayjs",
"debug",
"@braintree/sanitize-url"
],
exclude: [
"* > @kestra-io/ui-libs"