@kestra-io/ui-libs 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -7
- package/src/assets/icons/SplitCellsHorizontal.vue +24 -0
- package/src/assets/icons/SplitCellsVertical.vue +24 -0
- package/src/components/index.js +4 -0
- package/src/components/misc/ExecutionInformations.vue +4 -3
- package/src/components/misc/TaskIcon.vue +32 -3
- package/src/components/nodes/BasicNode.vue +73 -28
- package/src/components/nodes/ClusterNode.vue +28 -2
- package/src/components/nodes/DependenciesNode.vue +39 -5
- package/src/components/nodes/DotNode.vue +2 -1
- package/src/components/nodes/EdgeNode.vue +25 -0
- package/src/components/nodes/TaskNode.vue +42 -18
- package/src/components/nodes/TriggerNode.vue +27 -2
- package/src/components/topology/Topology.vue +355 -0
- package/src/index.js +4 -5
- package/src/scss/_variables.scss +68 -11
- package/src/scss/{custom.scss → app.scss} +3 -4
- package/src/scss/bootstrap-dark.scss +12 -0
- package/src/scss/bootstrap.scss +10 -0
- package/src/scss/vendor.scss +12 -0
- package/src/utils/VueFlowUtils.js +445 -0
- package/src/utils/YamlUtils.js +78 -1
- package/src/utils/constants.js +17 -0
- package/src/utils/global.js +5 -5
- package/src/utils/state.js +3 -3
- package/src/scss/index.scss +0 -8
- package/src/utils/GraphUtils.js +0 -390
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<Handle type="source" :position="sourcePosition"
|
|
2
|
+
<Handle type="source" :position="sourcePosition"/>
|
|
3
3
|
<basic-node
|
|
4
4
|
:id="id"
|
|
5
5
|
:data="data"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
@mouseleave="forwardEvent(EVENTS.MOUSE_LEAVE)"
|
|
12
12
|
>
|
|
13
13
|
<template #content>
|
|
14
|
-
<execution-informations v-if="data.
|
|
14
|
+
<execution-informations v-if="execution" :execution="execution" :task="data.node.task" :color="color"/>
|
|
15
15
|
</template>
|
|
16
16
|
<template #badge-button-before>
|
|
17
17
|
<span
|
|
@@ -19,36 +19,48 @@
|
|
|
19
19
|
class="rounded-button"
|
|
20
20
|
:class="[`bg-${color}`]"
|
|
21
21
|
@click="$emit(EVENTS.SHOW_LOGS, {id, taskRuns})"
|
|
22
|
+
data-bs-toggle="tooltip"
|
|
23
|
+
data-bs-placement="top"
|
|
24
|
+
:title="$t('show task logs')"
|
|
22
25
|
>
|
|
23
|
-
<TextBoxSearch class="button-icon" alt="Show logs"
|
|
26
|
+
<TextBoxSearch class="button-icon" alt="Show logs"/>
|
|
24
27
|
</span>
|
|
25
28
|
<span
|
|
26
|
-
v-if="!
|
|
29
|
+
v-if="!execution && !data.isReadOnly && data.isFlowable"
|
|
27
30
|
class="rounded-button"
|
|
28
31
|
:class="[`bg-${color}`]"
|
|
29
32
|
@click="$emit(EVENTS.ADD_ERROR, {task: data.node.task})"
|
|
33
|
+
data-bs-toggle="tooltip"
|
|
34
|
+
data-bs-placement="top"
|
|
35
|
+
:title="$t('add error handler')"
|
|
30
36
|
>
|
|
31
|
-
<
|
|
37
|
+
<AlertOutline class="button-icon" alt="Edit task"/>
|
|
32
38
|
</span>
|
|
33
39
|
<span
|
|
34
|
-
v-if="!
|
|
40
|
+
v-if="!execution && !data.isReadOnly"
|
|
35
41
|
class="rounded-button"
|
|
36
42
|
:class="[`bg-${color}`]"
|
|
37
43
|
@click="$emit(EVENTS.EDIT, {task: data.node.task, section: SECTIONS.TASKS})"
|
|
44
|
+
data-bs-toggle="tooltip"
|
|
45
|
+
data-bs-placement="top"
|
|
46
|
+
:title="$t('edit')"
|
|
38
47
|
>
|
|
39
|
-
<Pencil class="button-icon" alt="Edit task"
|
|
48
|
+
<Pencil class="button-icon" alt="Edit task"/>
|
|
40
49
|
</span>
|
|
41
50
|
<span
|
|
42
|
-
v-if="!
|
|
51
|
+
v-if="!execution && !data.isReadOnly"
|
|
43
52
|
class="rounded-button"
|
|
44
53
|
:class="[`bg-${color}`]"
|
|
45
54
|
@click="$emit(EVENTS.DELETE, {id, section: SECTIONS.TASKS})"
|
|
55
|
+
data-bs-toggle="tooltip"
|
|
56
|
+
data-bs-placement="top"
|
|
57
|
+
:title="$t('delete')"
|
|
46
58
|
>
|
|
47
|
-
<Delete class="button-icon" alt="Delete task"
|
|
59
|
+
<Delete class="button-icon" alt="Delete task"/>
|
|
48
60
|
</span>
|
|
49
61
|
</template>
|
|
50
62
|
</basic-node>
|
|
51
|
-
<Handle type="target" :position="targetPosition"
|
|
63
|
+
<Handle type="target" :position="targetPosition"/>
|
|
52
64
|
</template>
|
|
53
65
|
|
|
54
66
|
<script>
|
|
@@ -60,12 +72,29 @@
|
|
|
60
72
|
import Pencil from "vue-material-design-icons/Pencil.vue";
|
|
61
73
|
import Delete from "vue-material-design-icons/Delete.vue";
|
|
62
74
|
import TextBoxSearch from "vue-material-design-icons/TextBoxSearch.vue";
|
|
63
|
-
import
|
|
75
|
+
import AlertOutline from "vue-material-design-icons/AlertOutline.vue"
|
|
76
|
+
import {mapState} from "vuex";
|
|
77
|
+
import {Tooltip} from "bootstrap"
|
|
64
78
|
|
|
65
79
|
export default {
|
|
66
80
|
name: "Task",
|
|
67
81
|
inheritAttrs: false,
|
|
82
|
+
mounted(){
|
|
83
|
+
const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
|
|
84
|
+
tooltipTriggerList.map(function (tooltipTriggerEl) {
|
|
85
|
+
return new Tooltip(tooltipTriggerEl)
|
|
86
|
+
})
|
|
87
|
+
},
|
|
88
|
+
beforeUnmount() {
|
|
89
|
+
document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
|
|
90
|
+
const tooltip = Tooltip.getInstance(el);
|
|
91
|
+
if (tooltip) {
|
|
92
|
+
tooltip.dispose();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
},
|
|
68
96
|
computed: {
|
|
97
|
+
...mapState("execution", ["execution"]),
|
|
69
98
|
SECTIONS() {
|
|
70
99
|
return SECTIONS
|
|
71
100
|
},
|
|
@@ -75,9 +104,6 @@
|
|
|
75
104
|
color() {
|
|
76
105
|
return this.data.color ?? "primary"
|
|
77
106
|
},
|
|
78
|
-
execution() {
|
|
79
|
-
return this.data.execution
|
|
80
|
-
},
|
|
81
107
|
taskRunList() {
|
|
82
108
|
return this.execution && this.execution.taskRunList ? this.execution.taskRunList : []
|
|
83
109
|
},
|
|
@@ -136,7 +162,7 @@
|
|
|
136
162
|
Handle,
|
|
137
163
|
BasicNode,
|
|
138
164
|
TextBoxSearch,
|
|
139
|
-
|
|
165
|
+
AlertOutline,
|
|
140
166
|
},
|
|
141
167
|
props: {
|
|
142
168
|
data: {
|
|
@@ -163,6 +189,4 @@
|
|
|
163
189
|
}
|
|
164
190
|
}
|
|
165
191
|
</script>
|
|
166
|
-
|
|
167
|
-
@import "../../scss/custom";
|
|
168
|
-
</style>
|
|
192
|
+
|
|
@@ -9,18 +9,24 @@
|
|
|
9
9
|
>
|
|
10
10
|
<template #badge-button-before>
|
|
11
11
|
<span
|
|
12
|
-
v-if="!
|
|
12
|
+
v-if="!execution && !data.isReadOnly"
|
|
13
13
|
class="rounded-button"
|
|
14
14
|
:class="[`bg-${color}`]"
|
|
15
15
|
@click="$emit(EVENTS.EDIT, {task: data.node.trigger, section: SECTIONS.TRIGGERS})"
|
|
16
|
+
data-bs-toggle="tooltip"
|
|
17
|
+
data-bs-placement="top"
|
|
18
|
+
:title="$t('edit')"
|
|
16
19
|
>
|
|
17
20
|
<Pencil class="button-icon" alt="Edit task" />
|
|
18
21
|
</span>
|
|
19
22
|
<span
|
|
20
|
-
v-if="!
|
|
23
|
+
v-if="!execution && !data.isReadOnly"
|
|
21
24
|
class="rounded-button"
|
|
22
25
|
:class="[`bg-${color}`]"
|
|
23
26
|
@click="$emit(EVENTS.DELETE, {id, section: SECTIONS.TRIGGERS})"
|
|
27
|
+
data-bs-toggle="tooltip"
|
|
28
|
+
data-bs-placement="top"
|
|
29
|
+
:title="$t('delete')"
|
|
24
30
|
>
|
|
25
31
|
<Delete class="button-icon" alt="Delete task" />
|
|
26
32
|
</span>
|
|
@@ -32,14 +38,33 @@
|
|
|
32
38
|
<script>
|
|
33
39
|
import BasicNode from "./BasicNode.vue";
|
|
34
40
|
import {Handle} from "@vue-flow/core";
|
|
41
|
+
import {mapState} from "vuex";
|
|
35
42
|
import {EVENTS, SECTIONS} from "../../utils/constants.js";
|
|
36
43
|
import Pencil from "vue-material-design-icons/Pencil.vue";
|
|
37
44
|
import Delete from "vue-material-design-icons/Delete.vue";
|
|
45
|
+
import {Tooltip} from "bootstrap";
|
|
38
46
|
|
|
39
47
|
export default {
|
|
40
48
|
name: "Task",
|
|
41
49
|
inheritAttrs: false,
|
|
50
|
+
mounted(){
|
|
51
|
+
const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
|
|
52
|
+
this.tooltips = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
|
53
|
+
return new Tooltip(tooltipTriggerEl, {
|
|
54
|
+
trigger : "hover"
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
},
|
|
58
|
+
beforeUnmount() {
|
|
59
|
+
document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
|
|
60
|
+
const tooltip = Tooltip.getInstance(el);
|
|
61
|
+
if (tooltip) {
|
|
62
|
+
tooltip.dispose();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
},
|
|
42
66
|
computed: {
|
|
67
|
+
...mapState("execution", ["execution"]),
|
|
43
68
|
SECTIONS() {
|
|
44
69
|
return SECTIONS
|
|
45
70
|
},
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import {
|
|
3
|
+
ref,
|
|
4
|
+
defineProps,
|
|
5
|
+
defineEmits, watch, nextTick,
|
|
6
|
+
onMounted
|
|
7
|
+
} from "vue";
|
|
8
|
+
import {
|
|
9
|
+
ClusterNode,
|
|
10
|
+
DotNode,
|
|
11
|
+
TaskNode,
|
|
12
|
+
TriggerNode,
|
|
13
|
+
CollapsedClusterNode,
|
|
14
|
+
EdgeNode,
|
|
15
|
+
} from "../index.js";
|
|
16
|
+
import {useVueFlow, VueFlow} from "@vue-flow/core";
|
|
17
|
+
import {ControlButton, Controls} from "@vue-flow/controls";
|
|
18
|
+
import SplitCellsVertical from "../../assets/icons/SplitCellsVertical.vue";
|
|
19
|
+
import SplitCellsHorizontal from "../../assets/icons/SplitCellsHorizontal.vue";
|
|
20
|
+
import {cssVariable} from "../../utils/global.js";
|
|
21
|
+
import {VueFlowUtils, YamlUtils} from "../../index.js";
|
|
22
|
+
import Utils from "../../utils/Utils.js";
|
|
23
|
+
import VueflowUtils from "../../utils/VueFlowUtils.js";
|
|
24
|
+
import {CLUSTER_UID_SEPARATOR} from "../../utils/constants.js";
|
|
25
|
+
|
|
26
|
+
const props = defineProps({
|
|
27
|
+
id: {
|
|
28
|
+
type: String,
|
|
29
|
+
required: true
|
|
30
|
+
},
|
|
31
|
+
isHorizontal: {
|
|
32
|
+
type: Boolean,
|
|
33
|
+
default: true,
|
|
34
|
+
},
|
|
35
|
+
isReadOnly: {
|
|
36
|
+
type: Boolean,
|
|
37
|
+
default: true,
|
|
38
|
+
},
|
|
39
|
+
isAllowedEdit: {
|
|
40
|
+
type: Boolean,
|
|
41
|
+
default: false,
|
|
42
|
+
},
|
|
43
|
+
flowables: {
|
|
44
|
+
type: Array,
|
|
45
|
+
default: () => [],
|
|
46
|
+
},
|
|
47
|
+
source: {
|
|
48
|
+
type: String,
|
|
49
|
+
default: undefined,
|
|
50
|
+
required: true,
|
|
51
|
+
},
|
|
52
|
+
toggleOrientationButton: {
|
|
53
|
+
type: Boolean,
|
|
54
|
+
default: false,
|
|
55
|
+
},
|
|
56
|
+
flowGraph: {
|
|
57
|
+
type: Object,
|
|
58
|
+
required: true
|
|
59
|
+
},
|
|
60
|
+
flowId: {
|
|
61
|
+
type: String,
|
|
62
|
+
required: false,
|
|
63
|
+
default: undefined
|
|
64
|
+
},
|
|
65
|
+
namespace: {
|
|
66
|
+
type: String,
|
|
67
|
+
required: false,
|
|
68
|
+
default: undefined
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const dragging = ref(false);
|
|
73
|
+
const lastPosition = ref(null)
|
|
74
|
+
const {getNodes, onNodeDrag, onNodeDragStart, onNodeDragStop, fitView, setElements} = useVueFlow({id: props.id});
|
|
75
|
+
const edgeReplacer = ref({});
|
|
76
|
+
const hiddenNodes = ref([]);
|
|
77
|
+
const collapsed = ref([]);
|
|
78
|
+
const clusterToNode = ref([])
|
|
79
|
+
|
|
80
|
+
const emit = defineEmits(
|
|
81
|
+
[
|
|
82
|
+
"edit",
|
|
83
|
+
"delete",
|
|
84
|
+
"open-link",
|
|
85
|
+
"show-logs",
|
|
86
|
+
"show-description",
|
|
87
|
+
"on-add-flowable-error",
|
|
88
|
+
"add-task",
|
|
89
|
+
"toggle-orientation",
|
|
90
|
+
"loading",
|
|
91
|
+
"swapped-task",
|
|
92
|
+
"message"
|
|
93
|
+
]
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
onMounted( () => {
|
|
97
|
+
generateGraph();
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
watch(() => props.flowGraph, () => {
|
|
101
|
+
generateGraph();
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const generateGraph = () => {
|
|
105
|
+
VueFlowUtils.cleanGraph(props.id);
|
|
106
|
+
|
|
107
|
+
nextTick(() => {
|
|
108
|
+
forwardEvent("loading", true);
|
|
109
|
+
const elements = VueflowUtils.generateGraph(
|
|
110
|
+
props.id,
|
|
111
|
+
props.flowId,
|
|
112
|
+
props.namespace,
|
|
113
|
+
props.flowGraph,
|
|
114
|
+
props.source,
|
|
115
|
+
hiddenNodes.value,
|
|
116
|
+
props.isHorizontal,
|
|
117
|
+
edgeReplacer.value,
|
|
118
|
+
collapsed.value,
|
|
119
|
+
clusterToNode.value,
|
|
120
|
+
props.isReadOnly,
|
|
121
|
+
props.isAllowedEdit,
|
|
122
|
+
flowables()
|
|
123
|
+
);
|
|
124
|
+
setElements(elements);
|
|
125
|
+
fitView();
|
|
126
|
+
forwardEvent("loading", false);
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const forwardEvent = (type, payload) => {
|
|
131
|
+
emit(type, payload);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Graph interactions functions
|
|
135
|
+
const onMouseOver = (node) => {
|
|
136
|
+
if (!dragging.value) {
|
|
137
|
+
VueFlowUtils.linkedElements(props.id, node.uid).forEach((n) => {
|
|
138
|
+
if (n.type === "task") {
|
|
139
|
+
n.style = {...n.style, outline: "0.5px solid " + cssVariable("--bs-gray-900")}
|
|
140
|
+
n.class = "rounded-3"
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const onMouseLeave = () => {
|
|
148
|
+
resetNodesStyle();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const resetNodesStyle = () => {
|
|
152
|
+
getNodes.value.filter(n => n.type === "task" || n.type === "trigger")
|
|
153
|
+
.forEach(n => {
|
|
154
|
+
n.style = {...n.style, opacity: "1", outline: "none"}
|
|
155
|
+
n.class = ""
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
onNodeDragStart((e) => {
|
|
160
|
+
dragging.value = true;
|
|
161
|
+
resetNodesStyle();
|
|
162
|
+
e.node.style = {...e.node.style, zIndex: 1976}
|
|
163
|
+
lastPosition.value = e.node.position;
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
onNodeDragStop((e) => {
|
|
167
|
+
dragging.value = false;
|
|
168
|
+
if (checkIntersections(e.intersections, e.node) === null) {
|
|
169
|
+
const taskNode1 = e.node;
|
|
170
|
+
// check multiple intersection with task
|
|
171
|
+
const taskNode2 = e.intersections.find(n => n.type === "task");
|
|
172
|
+
if (taskNode2) {
|
|
173
|
+
try {
|
|
174
|
+
emit("swapped-task", YamlUtils.swapTasks(props.source, taskNode1.id, taskNode2.id))
|
|
175
|
+
} catch (e) {
|
|
176
|
+
emit("message", {
|
|
177
|
+
variant: "error",
|
|
178
|
+
title: "cannot swap tasks",
|
|
179
|
+
message: `${e.message}, ${e.messageOptions}`
|
|
180
|
+
});
|
|
181
|
+
taskNode1.position = lastPosition.value;
|
|
182
|
+
}
|
|
183
|
+
} else {
|
|
184
|
+
taskNode1.position = lastPosition.value;
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
e.node.position = lastPosition.value;
|
|
188
|
+
}
|
|
189
|
+
resetNodesStyle();
|
|
190
|
+
e.node.style = {...e.node.style, zIndex: 5}
|
|
191
|
+
lastPosition.value = null;
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
onNodeDrag((e) => {
|
|
195
|
+
resetNodesStyle();
|
|
196
|
+
getNodes.value.filter(n => n.id !== e.node.id).forEach(n => {
|
|
197
|
+
if (n.type === "trigger" || (n.type === "task" && YamlUtils.isParentChildrenRelation(props.source, n.id, e.node.id))) {
|
|
198
|
+
n.style = {...n.style, opacity: "0.5"}
|
|
199
|
+
} else {
|
|
200
|
+
n.style = {...n.style, opacity: "1"}
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
if (!checkIntersections(e.intersections, e.node) && e.intersections.filter(n => n.type === "task").length === 1) {
|
|
204
|
+
e.intersections.forEach(n => {
|
|
205
|
+
if (n.type === "task") {
|
|
206
|
+
n.style = {...n.style, outline: "0.5px solid " + cssVariable("--bs-primary")}
|
|
207
|
+
n.class = "rounded-3"
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
e.node.style = {...e.node.style, outline: "0.5px solid " + cssVariable("--bs-primary")}
|
|
211
|
+
e.node.class = "rounded-3"
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
const checkIntersections = (intersections, node) => {
|
|
216
|
+
const tasksMeet = intersections.filter(n => n.type === "task").map(n => n.id);
|
|
217
|
+
if (tasksMeet.length > 1) {
|
|
218
|
+
return "toomuchtaskerror";
|
|
219
|
+
}
|
|
220
|
+
if (tasksMeet.length === 1 && YamlUtils.isParentChildrenRelation(props.source, tasksMeet[0], node.id)) {
|
|
221
|
+
return "parentchildrenerror";
|
|
222
|
+
}
|
|
223
|
+
if (intersections.filter(n => n.type === "trigger").length > 0) {
|
|
224
|
+
return "triggererror";
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const collapseCluster = (clusterUid, regenerate, recursive) => {
|
|
230
|
+
|
|
231
|
+
const cluster = props.flowGraph.clusters.find(cluster => cluster.cluster.uid === clusterUid)
|
|
232
|
+
const nodeId = clusterUid === "Triggers" ? "Triggers" : Utils.splitFirst(clusterUid, CLUSTER_UID_SEPARATOR);
|
|
233
|
+
collapsed.value = collapsed.value.concat([nodeId])
|
|
234
|
+
|
|
235
|
+
hiddenNodes.value = hiddenNodes.value.concat(cluster.nodes.filter(e => e !== nodeId || recursive));
|
|
236
|
+
if (clusterUid !== "Triggers") {
|
|
237
|
+
hiddenNodes.value = hiddenNodes.value.concat([cluster.cluster.uid])
|
|
238
|
+
edgeReplacer.value = {
|
|
239
|
+
...edgeReplacer.value,
|
|
240
|
+
[cluster.cluster.uid]: nodeId,
|
|
241
|
+
[cluster.start]: nodeId,
|
|
242
|
+
[cluster.end]: nodeId
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
for (let child of cluster.nodes) {
|
|
246
|
+
if (props.flowGraph.clusters.map(cluster => cluster.cluster.uid).includes(child)) {
|
|
247
|
+
collapseCluster(child, false, true);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
edgeReplacer.value = {
|
|
252
|
+
...edgeReplacer.value,
|
|
253
|
+
[cluster.start]: nodeId,
|
|
254
|
+
[cluster.end]: nodeId
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (regenerate) {
|
|
259
|
+
generateGraph();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const expand = (taskId) => {
|
|
264
|
+
edgeReplacer.value = {}
|
|
265
|
+
hiddenNodes.value = []
|
|
266
|
+
clusterToNode.value = []
|
|
267
|
+
collapsed.value = collapsed.value.filter(n => n != taskId)
|
|
268
|
+
|
|
269
|
+
collapsed.value.forEach(n => collapseCluster(CLUSTER_UID_SEPARATOR + n, false, false))
|
|
270
|
+
|
|
271
|
+
generateGraph();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const flowables = () => {
|
|
275
|
+
return props.flowGraph && props.flowGraph.flowables ? props.flowGraph.flowables : [];
|
|
276
|
+
}
|
|
277
|
+
</script>
|
|
278
|
+
<template>
|
|
279
|
+
<VueFlow
|
|
280
|
+
:id="id"
|
|
281
|
+
:default-marker-color="cssVariable('--bs-cyan')"
|
|
282
|
+
fit-view-on-init
|
|
283
|
+
:nodes-draggable="false"
|
|
284
|
+
:nodes-connectable="false"
|
|
285
|
+
:elevate-nodes-on-select="false"
|
|
286
|
+
:elevate-edges-on-select="false"
|
|
287
|
+
>
|
|
288
|
+
<template #node-cluster="clusterProps">
|
|
289
|
+
<ClusterNode
|
|
290
|
+
v-bind="clusterProps"
|
|
291
|
+
@collapse="collapseCluster($event, true)"
|
|
292
|
+
/>
|
|
293
|
+
</template>
|
|
294
|
+
|
|
295
|
+
<template #node-dot="dotProps">
|
|
296
|
+
<DotNode
|
|
297
|
+
v-bind="dotProps"
|
|
298
|
+
/>
|
|
299
|
+
</template>
|
|
300
|
+
|
|
301
|
+
<template #node-task="taskProps">
|
|
302
|
+
<TaskNode
|
|
303
|
+
v-bind="taskProps"
|
|
304
|
+
@edit="forwardEvent('edit', $event)"
|
|
305
|
+
@delete="forwardEvent('delete', $event)"
|
|
306
|
+
@expand="expand($event)"
|
|
307
|
+
@open-link="forwardEvent('open-link', $event)"
|
|
308
|
+
@show-logs="forwardEvent('show-logs', $event)"
|
|
309
|
+
@show-description="forwardEvent('show-description', $event)"
|
|
310
|
+
@mouseover="onMouseOver($event)"
|
|
311
|
+
@mouseleave="onMouseLeave()"
|
|
312
|
+
@add-error="forwardEvent('on-add-flowable-error', $event)"
|
|
313
|
+
/>
|
|
314
|
+
</template>
|
|
315
|
+
|
|
316
|
+
<template #node-trigger="triggerProps">
|
|
317
|
+
<TriggerNode
|
|
318
|
+
v-bind="triggerProps"
|
|
319
|
+
:is-read-only="isReadOnly"
|
|
320
|
+
:is-allowed-edit="isAllowedEdit"
|
|
321
|
+
@delete="forwardEvent('delete', $event)"
|
|
322
|
+
@edit="forwardEvent('edit', $event)"
|
|
323
|
+
/>
|
|
324
|
+
</template>
|
|
325
|
+
|
|
326
|
+
<template #node-collapsedcluster="CollapsedProps">
|
|
327
|
+
<CollapsedClusterNode
|
|
328
|
+
v-bind="CollapsedProps"
|
|
329
|
+
@expand="expand($event)"
|
|
330
|
+
/>
|
|
331
|
+
</template>
|
|
332
|
+
|
|
333
|
+
<template #edge-edge="EdgeProps">
|
|
334
|
+
<EdgeNode
|
|
335
|
+
v-bind="EdgeProps"
|
|
336
|
+
:yaml-source="source"
|
|
337
|
+
:flowables-ids="flowables"
|
|
338
|
+
@add-task="forwardEvent('add-task', $event)"
|
|
339
|
+
:is-read-only="isReadOnly"
|
|
340
|
+
:is-allowed-edit="isAllowedEdit"
|
|
341
|
+
/>
|
|
342
|
+
</template>
|
|
343
|
+
|
|
344
|
+
<Controls :show-interactive="false">
|
|
345
|
+
<ControlButton @click="forwardEvent('toggle-orientation', $event)" v-if="toggleOrientationButton">
|
|
346
|
+
<SplitCellsVertical :size="48" v-if="!isHorizontal" />
|
|
347
|
+
<SplitCellsHorizontal v-if="isHorizontal" />
|
|
348
|
+
</ControlButton>
|
|
349
|
+
</Controls>
|
|
350
|
+
</VueFlow>
|
|
351
|
+
</template>
|
|
352
|
+
|
|
353
|
+
<style scoped lang="scss">
|
|
354
|
+
|
|
355
|
+
</style>
|
package/src/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import "./
|
|
1
|
+
import YamlUtils from "./utils/YamlUtils.js";
|
|
2
|
+
import Utils from "./utils/Utils.js";
|
|
3
|
+
import VueFlowUtils from "./utils/VueFlowUtils.js";
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
// import YamlUtils from "./utils/YamlUtils";
|
|
5
|
-
// import Utils from "./utils/Utils";
|
|
5
|
+
export {YamlUtils, Utils, VueFlowUtils};
|
|
6
6
|
|
|
7
7
|
export * from "./components/index.js";
|
|
8
|
-
// export { GraphUtils, YamlUtils, Utils };
|
package/src/scss/_variables.scss
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
// primary color
|
|
2
|
+
$primary: #8405FF !default;
|
|
3
|
+
$secondary: #C182FF !default;
|
|
4
|
+
$tertiary: #2F3342 !default;
|
|
5
|
+
|
|
1
6
|
// color system
|
|
2
7
|
$blue: #1761FD !default;
|
|
3
8
|
$indigo: #8405FF !default;
|
|
@@ -11,22 +16,18 @@ $green: #03DABA !default;
|
|
|
11
16
|
$teal: #03D87F !default;
|
|
12
17
|
$cyan: #60C5FE !default;
|
|
13
18
|
|
|
14
|
-
// primary color
|
|
15
|
-
$primary: #8405FF !default;
|
|
16
|
-
$secondary: #C182FF !default;
|
|
17
|
-
$tertiary: #2F3342 !default;
|
|
18
19
|
|
|
19
20
|
// gray
|
|
20
21
|
$white: #FFF !default;
|
|
21
22
|
$gray-100: #F5F5FF !default;
|
|
22
|
-
$gray-200: #
|
|
23
|
+
$gray-200: #F0F0FF !default;
|
|
23
24
|
$gray-300: #E5E4F7 !default;
|
|
24
|
-
$gray-400: #
|
|
25
|
-
$gray-500: #
|
|
26
|
-
$gray-600: #
|
|
27
|
-
$gray-700: #
|
|
28
|
-
$gray-800: #
|
|
29
|
-
$gray-900: #
|
|
25
|
+
$gray-400: #D1CFE9 !default;
|
|
26
|
+
$gray-500: #B8B6D9 !default;
|
|
27
|
+
$gray-600: #A6A4CA !default;
|
|
28
|
+
$gray-700: #9A8EB4 !default;
|
|
29
|
+
$gray-800: #7E719F !default;
|
|
30
|
+
$gray-900: #564A75 !default;
|
|
30
31
|
$black: #26282D !default;
|
|
31
32
|
|
|
32
33
|
$light: $gray-200 !default;
|
|
@@ -34,10 +35,21 @@ $dark: $gray-900 !default;
|
|
|
34
35
|
|
|
35
36
|
// fonts
|
|
36
37
|
$font-size-base: 1rem !default;
|
|
38
|
+
$font-size-xs: $font-size-base * .75;
|
|
39
|
+
$font-size-sm: $font-size-base * .875;
|
|
40
|
+
$font-size-lg: $font-size-base * 1.25;
|
|
41
|
+
$font-size-xl: $font-size-base * 1.375;
|
|
37
42
|
$font-family-sans-serif: "Public Sans", sans-serif;
|
|
38
43
|
$font-family-monospace: "Source Code Pro", monospace;
|
|
39
44
|
$font-size-xs: $font-size-base * 0.75 !default;
|
|
40
45
|
|
|
46
|
+
$h1-font-size: $font-size-base * 3.375;
|
|
47
|
+
$h2-font-size: $font-size-base * 2.5;
|
|
48
|
+
$h3-font-size: $font-size-base * 2;
|
|
49
|
+
$h4-font-size: $font-size-base * 1.375;
|
|
50
|
+
$h5-font-size: $font-size-base * 1.25;
|
|
51
|
+
$h6-font-size: $font-size-base * 1.125;
|
|
52
|
+
|
|
41
53
|
// border radius
|
|
42
54
|
$border-radius: 0.25rem !default;
|
|
43
55
|
$border-radius-lg: 0.5rem !default;
|
|
@@ -49,12 +61,16 @@ $spacer: 1rem !default;
|
|
|
49
61
|
|
|
50
62
|
// body
|
|
51
63
|
$body-color: $gray-800 !default;
|
|
64
|
+
$body-tertiary-color: #FFFFFF;
|
|
65
|
+
$body-tertiary-bg: #785EEA;
|
|
52
66
|
$border-color: $gray-300 !default;
|
|
53
67
|
$body-bg: $gray-100 !default;
|
|
54
68
|
$card-bg: $white !default;
|
|
55
69
|
$input-bg: $white !default;
|
|
56
70
|
|
|
71
|
+
// link
|
|
57
72
|
$link-color: $primary !default;
|
|
73
|
+
$link-decoration: none;
|
|
58
74
|
|
|
59
75
|
// border radius
|
|
60
76
|
$border-radius: .25rem !default;
|
|
@@ -65,6 +81,45 @@ $box-shadow-sm: 0 .125rem .25rem rgba($black, .075);
|
|
|
65
81
|
$box-shadow: 0 .5rem 1rem rgba($black, .15);
|
|
66
82
|
$box-shadow-lg: 0 1rem 3rem rgba($black, .175);
|
|
67
83
|
|
|
84
|
+
// button
|
|
85
|
+
$btn-font-size-lg: 18px;
|
|
86
|
+
|
|
87
|
+
// grid
|
|
88
|
+
$grid-gutter-width: 1.75rem;
|
|
89
|
+
|
|
90
|
+
// nav
|
|
91
|
+
$nav-pills-border-radius: 50rem;
|
|
92
|
+
|
|
93
|
+
// accordion
|
|
94
|
+
$accordion-icon-color: $white;
|
|
95
|
+
$accordion-icon-active-color: $white;
|
|
96
|
+
|
|
97
|
+
// purples
|
|
98
|
+
$purple-1: #382369;
|
|
99
|
+
$purple-2: #FBC7F4;
|
|
100
|
+
$purple-3: #9580EE;
|
|
101
|
+
$purple-4: linear-gradient(160.34deg, rgba(130, 0, 255, 0.12) 5.3%, rgba(130, 0, 255, 0) 75.43%), #201838;
|
|
102
|
+
$purple-5: #362762;
|
|
103
|
+
$purple-6: #6113BC;
|
|
104
|
+
$purple-7: #1A1223;
|
|
105
|
+
$purple-8: #EEEDFF;
|
|
106
|
+
$purple-9: 0px 12.972px 39.7269px rgba(90, 0, 176, 0.1);
|
|
107
|
+
$purple-10: #150E1C;
|
|
108
|
+
$purple-11: #332C3B;
|
|
109
|
+
$purple-12: #432A71;
|
|
110
|
+
$purple-16: #281A35;
|
|
111
|
+
$purple-19: conic-gradient(from 90deg at 50% 50%, #BE79FF 0deg, #7136F6 360deg);
|
|
112
|
+
$purple-20: #291E39;
|
|
113
|
+
$purple-21: #A42DCD;
|
|
114
|
+
$purple-22: #FCF7FE;
|
|
115
|
+
$purple-23: #EDE8F3;
|
|
116
|
+
$purple-24: #15023F;
|
|
117
|
+
$purple-26: #DCCDEB;
|
|
118
|
+
$purple-27: #8200FF;
|
|
119
|
+
$purple-28: #2D313E;
|
|
120
|
+
$purple-29: #F1F5FF;
|
|
121
|
+
$purple-30: rgba(255, 255, 255, 0.1);
|
|
122
|
+
|
|
68
123
|
// boostrap flags
|
|
69
124
|
$enable-reduced-motion: false;
|
|
70
125
|
|
|
@@ -93,6 +148,8 @@ $element-colors: (
|
|
|
93
148
|
),
|
|
94
149
|
);
|
|
95
150
|
|
|
151
|
+
$baseline-max-width: 730px;
|
|
152
|
+
|
|
96
153
|
// bootstrap
|
|
97
154
|
@import "bootstrap/scss/functions";
|
|
98
155
|
@import "bootstrap/scss/mixins";
|