@kestra-io/ui-libs 0.0.27 → 0.0.28

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kestra-io/ui-libs",
3
- "version": "v0.0.27",
3
+ "version": "v0.0.28",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src",
@@ -9,7 +9,6 @@
9
9
  </div>
10
10
  </template>
11
11
  <script>
12
- import {mapState} from "vuex";
13
12
  import {Buffer} from "buffer";
14
13
  import Tooltip from "../misc/Tooltip.vue";
15
14
  import {cssVariable} from "../../utils/global.js";
@@ -32,10 +31,13 @@
32
31
  validator(value) {
33
32
  return ["dark", "light"].includes(value)
34
33
  }
34
+ },
35
+ icons: {
36
+ type: Object,
37
+ default: undefined
35
38
  }
36
39
  },
37
40
  computed: {
38
- ...mapState("plugin", ["icons"]),
39
41
  backgroundImage() {
40
42
  return `data:image/svg+xml;base64,${this.imageBase64}`
41
43
  },
@@ -7,7 +7,7 @@
7
7
  >
8
8
  <div v-if="state" class="status-div" :class="[`bg-${stateColor}`]" />
9
9
  <div class="icon rounded">
10
- <TaskIcon :cls="cls" :class="taskIconBg" class="rounded bg-white" theme="light" />
10
+ <TaskIcon :cls="cls" :class="taskIconBg" class="rounded bg-white" theme="light" :icons="icons" />
11
11
  </div>
12
12
  <div class="node-content">
13
13
  <div class="d-flex node-title">
@@ -22,7 +22,7 @@
22
22
  class="d-flex"
23
23
  v-if="description"
24
24
  >
25
- <tooltip :title="$t('show description')" class="d-flex align-items-center">
25
+ <tooltip :title="Utils.translate('show description')" class="d-flex align-items-center">
26
26
  <InformationOutline
27
27
  @click="$emit(EVENTS.SHOW_DESCRIPTION, {id: trimmedId, description:description})"
28
28
  class="description-button ms-2"
@@ -36,21 +36,21 @@
36
36
  <slot name="badge-button-before" />
37
37
  <span
38
38
  v-if="data.link"
39
- class="rounded-button"
39
+ class="circle-button"
40
40
  :class="[`bg-${data.color}`]"
41
41
  @click="$emit(EVENTS.OPEN_LINK, {link: data.link})"
42
42
  >
43
- <tooltip :title="$t('open')">
43
+ <tooltip :title="Utils.translate('open')">
44
44
  <OpenInNew class="button-icon" alt="Open in new tab" />
45
45
  </tooltip>
46
46
  </span>
47
47
  <span
48
48
  v-if="expandable"
49
- class="rounded-button"
49
+ class="circle-button"
50
50
  :class="[`bg-${data.color}`]"
51
51
  @click="$emit(EVENTS.EXPAND)"
52
52
  >
53
- <tooltip :title="$t('expand')">
53
+ <tooltip :title="Utils.translate('expand')">
54
54
  <ArrowExpand class="button-icon" alt="Expand task" />
55
55
  </tooltip>
56
56
  </span>
@@ -111,6 +111,10 @@
111
111
  data: {
112
112
  type: Object,
113
113
  required: true
114
+ },
115
+ icons: {
116
+ type: Object,
117
+ default: undefined
114
118
  }
115
119
  },
116
120
  methods: {
@@ -128,6 +132,9 @@
128
132
  };
129
133
  },
130
134
  computed: {
135
+ Utils() {
136
+ return Utils
137
+ },
131
138
  ...mapState("execution", ["execution"]),
132
139
  borderColor() {
133
140
  const color = this.data.color ? this.data.color === "default" ? null : this.data.color : null
@@ -235,9 +242,9 @@
235
242
  }
236
243
 
237
244
  .icon {
238
- position: relative;
239
- width: 32px;
240
- height: 30px;
245
+ margin: 0.2rem;
246
+ width: 25px;
247
+ height: 25px;
241
248
  border: 0.4px solid var(--bs-border-color);
242
249
  }
243
250
  }
@@ -263,7 +270,7 @@
263
270
  padding: 1px;
264
271
  }
265
272
 
266
- .rounded-button {
273
+ .circle-button {
267
274
  border-radius: 1rem;
268
275
  width: 1rem;
269
276
  height: 1rem;
@@ -1,14 +1,14 @@
1
1
  <template>
2
2
  <div :class="classes">
3
- <span class="badge rounded-pill text-truncate text-color" :class="[`bg-${data.color}`]">{{ clusterName }}</span>
3
+ <span class="badge rounded-pill text-truncate text-color position-reliative" :class="[`bg-${data.color}`]">{{ clusterName }}</span>
4
4
  <div class="top-button-div text-white d-flex">
5
5
  <span
6
6
  v-if="data.collapsable"
7
- class="rounded-button"
7
+ class="circle-button"
8
8
  :class="[`bg-${data.color}`]"
9
9
  @click="collapse()"
10
10
  >
11
- <tooltip :title="$t('collapse')">
11
+ <tooltip :title="Utils.translate('collapse')">
12
12
  <ArrowCollapse class="button-icon" alt="Collapse task" />
13
13
  </tooltip>
14
14
  </span>
@@ -19,6 +19,7 @@
19
19
  import ArrowCollapse from "vue-material-design-icons/ArrowCollapse.vue"
20
20
  import {EVENTS} from "../../utils/constants.js";
21
21
  import {Position} from "@vue-flow/core";
22
+ import Utils from "../../utils/Utils.js";
22
23
 
23
24
  const props = defineProps({
24
25
  "data": {
@@ -72,7 +73,7 @@
72
73
  }
73
74
  </script>
74
75
  <style scoped lang="scss">
75
- .rounded-button {
76
+ .circle-button {
76
77
  border-radius: 1rem;
77
78
  width: 1rem;
78
79
  height: 1rem;
@@ -102,10 +103,12 @@
102
103
  }
103
104
 
104
105
  .top-button-div {
105
- transform: translate(-50%, -50%) !important;
106
- left: 100% !important;
106
+ position: absolute;
107
+ top: -0.5rem;
108
+ right: -0.5rem;
107
109
  justify-content: center;
108
110
  padding-right: 3px;
111
+ display: flex
109
112
  }
110
113
 
111
114
  </style>
@@ -9,11 +9,11 @@
9
9
  <slot name="badge-button-before" />
10
10
  <span
11
11
  v-if="expandable"
12
- class="rounded-button"
12
+ class="circle-button"
13
13
  :class="[`bg-${data.color}`]"
14
14
  @click="$emit(EVENTS.EXPAND, {id})"
15
15
  >
16
- <tooltip :title="$t('expand')">
16
+ <tooltip :title="Utils.translate('expand')">
17
17
  <ArrowExpand class="button-icon" alt="Expand task" />
18
18
  </tooltip>
19
19
  </span>
@@ -33,6 +33,7 @@
33
33
  import Webhook from "vue-material-design-icons/Webhook.vue";
34
34
  import {Handle} from "@vue-flow/core";
35
35
  import Tooltip from "../misc/Tooltip.vue";
36
+ import Utils from "../../utils/Utils.js";
36
37
 
37
38
  export default {
38
39
  components: {
@@ -102,7 +103,7 @@
102
103
  }
103
104
  }
104
105
 
105
- .rounded-button {
106
+ .circle-button {
106
107
  border-radius: 1rem;
107
108
  width: 1rem;
108
109
  height: 1rem;
@@ -22,20 +22,20 @@
22
22
  <slot name="badge-button-before" />
23
23
  <span
24
24
  v-if="data.link"
25
- class="rounded-button"
25
+ class="circle-button"
26
26
  :class="[`bg-${data.color}`]"
27
27
  @click="$emit(EVENTS.OPEN_LINK, data)"
28
28
  >
29
- <tooltip :title="$t('open')">
29
+ <tooltip :title="Utils.translate('open')">
30
30
  <OpenInNew class="button-icon" alt="Open in new tab" />
31
31
  </tooltip>
32
32
  </span>
33
33
  <span
34
- class="rounded-button"
34
+ class="circle-button"
35
35
  :class="[`bg-${data.color}`]"
36
36
  @click="$emit(EVENTS.EXPAND_DEPENDENCIES, data)"
37
37
  >
38
- <tooltip :title="$t('expand')">
38
+ <tooltip :title="Utils.translate('expand')">
39
39
  <ArrowExpandAll class="button-icon" alt="Expand task" />
40
40
  </tooltip>
41
41
  </span>
@@ -53,6 +53,7 @@
53
53
  import ArrowExpandAll from "vue-material-design-icons/ArrowExpandAll.vue";
54
54
  import {EVENTS} from "../../utils/constants.js";
55
55
  import Tooltip from "../misc/Tooltip.vue";
56
+ import Utils from "../../utils/Utils.js";
56
57
 
57
58
  export default {
58
59
  name: "Dependencies",
@@ -4,6 +4,7 @@
4
4
  import AddTaskButton from "../buttons/AddTaskButton.vue";
5
5
  import {EVENTS} from "../../utils/constants.js";
6
6
  import Tooltip from "../misc/Tooltip.vue";
7
+ import Utils from "../../utils/Utils.js";
7
8
 
8
9
  export default {
9
10
  data() {
@@ -28,6 +29,9 @@
28
29
  Tooltip
29
30
  },
30
31
  computed: {
32
+ Utils() {
33
+ return Utils
34
+ },
31
35
  EVENTS() {
32
36
  return EVENTS
33
37
  },
@@ -71,7 +75,7 @@
71
75
  transform: `translate(-50%, -50%) translate(${path[1]}px,${path[2]}px)`,
72
76
  }"
73
77
  >
74
- <tooltip :title="$t('add task')">
78
+ <tooltip :title="Utils.translate('add task')">
75
79
  <AddTaskButton
76
80
  v-if="data.haveAdd"
77
81
  :add-task="true"
@@ -79,7 +83,6 @@
79
83
  :class="{'text-danger': data.color}"
80
84
  />
81
85
  </tooltip>
82
-
83
86
  </div>
84
87
  </EdgeLabelRenderer>
85
88
  </template>
@@ -5,6 +5,7 @@
5
5
  :data="dataWithLink"
6
6
  :state="state"
7
7
  :class="classes"
8
+ :icons="icons"
8
9
  @show-description="forwardEvent(EVENTS.SHOW_DESCRIPTION, $event)"
9
10
  @expand="forwardEvent(EVENTS.EXPAND, expandData)"
10
11
  @open-link="forwardEvent(EVENTS.OPEN_LINK, $event)"
@@ -17,41 +18,41 @@
17
18
  <template #badge-button-before>
18
19
  <span
19
20
  v-if="taskExecution"
20
- class="rounded-button"
21
+ class="circle-button"
21
22
  :class="[`bg-${color}`]"
22
23
  @click="$emit(EVENTS.SHOW_LOGS, {id: taskId, execution: taskExecution, taskRuns})"
23
24
  >
24
- <tooltip :title="$t('show task logs')">
25
+ <tooltip :title="Utils.translate('show task logs')">
25
26
  <TextBoxSearch class="button-icon" alt="Show logs" />
26
27
  </tooltip>
27
28
  </span>
28
29
  <span
29
30
  v-if="!taskExecution && !data.isReadOnly && data.isFlowable"
30
- class="rounded-button"
31
+ class="circle-button"
31
32
  :class="[`bg-${color}`]"
32
33
  @click="$emit(EVENTS.ADD_ERROR, {task: data.node.task})"
33
34
  >
34
- <tooltip :title="$t('add error handler')">
35
+ <tooltip :title="Utils.translate('add error handler')">
35
36
  <AlertOutline class="button-icon" alt="Edit task" />
36
37
  </tooltip>
37
38
  </span>
38
39
  <span
39
40
  v-if="!taskExecution && !data.isReadOnly"
40
- class="rounded-button"
41
+ class="circle-button"
41
42
  :class="[`bg-${color}`]"
42
43
  @click="$emit(EVENTS.EDIT, {task: data.node.task, section: SECTIONS.TASKS})"
43
44
  >
44
- <tooltip :title="$t('edit')">
45
+ <tooltip :title="Utils.translate('edit')">
45
46
  <Pencil class="button-icon" alt="Edit task" />
46
47
  </tooltip>
47
48
  </span>
48
49
  <span
49
50
  v-if="!taskExecution && !data.isReadOnly"
50
- class="rounded-button"
51
+ class="circle-button"
51
52
  :class="[`bg-${color}`]"
52
53
  @click="$emit(EVENTS.DELETE, {id: taskId, section: SECTIONS.TASKS})"
53
54
  >
54
- <tooltip :title="$t('delete')">
55
+ <tooltip :title="Utils.translate('delete')">
55
56
  <Delete class="button-icon" alt="Delete task" />
56
57
  </tooltip>
57
58
  </span>
@@ -162,7 +163,7 @@
162
163
  }
163
164
  },
164
165
  dataWithLink() {
165
- if(this.data.node.type.endsWith("SubflowGraphTask")){
166
+ if(this.data.node.type.endsWith("SubflowGraphTask") && this.enableSubflowInteraction){
166
167
  return {
167
168
  ...this.data,
168
169
  link: {
@@ -205,6 +206,14 @@
205
206
  id: {
206
207
  type: String,
207
208
  required: true
209
+ },
210
+ icons: {
211
+ type: Object,
212
+ default: undefined
213
+ },
214
+ enableSubflowInteraction: {
215
+ type: Boolean,
216
+ default: true
208
217
  }
209
218
  },
210
219
  methods: {
@@ -4,27 +4,28 @@
4
4
  :id="id"
5
5
  :data="data"
6
6
  :color="color"
7
+ :icons="icons"
7
8
  @show-description="forwardEvent(EVENTS.SHOW_DESCRIPTION, $event)"
8
9
  @expand="forwardEvent(EVENTS.EXPAND, {id})"
9
10
  >
10
- <template #badge-button-before>
11
+ <template #badge-button-before v-if="!data.isReadOnly">
11
12
  <span
12
- v-if="!execution && !data.isReadOnly"
13
- class="rounded-button"
13
+ v-if="!execution"
14
+ class="circle-button"
14
15
  :class="[`bg-${color}`]"
15
16
  @click="$emit(EVENTS.EDIT, {task: data.node.trigger, section: SECTIONS.TRIGGERS})"
16
17
  >
17
- <tooltip :title="$t('edit')">
18
+ <tooltip :title="Utils.translate('edit')">
18
19
  <Pencil class="button-icon" alt="Edit task" />
19
20
  </tooltip>
20
21
  </span>
21
22
  <span
22
- v-if="!execution && !data.isReadOnly"
23
- class="rounded-button"
23
+ v-if="!execution"
24
+ class="circle-button"
24
25
  :class="[`bg-${color}`]"
25
26
  @click="$emit(EVENTS.DELETE, {id, section: SECTIONS.TRIGGERS})"
26
27
  >
27
- <tooltip :title="$t('delete')">
28
+ <tooltip :title="Utils.translate('delete')">
28
29
  <Delete class="button-icon" alt="Delete task" />
29
30
  </tooltip>
30
31
  </span>
@@ -42,6 +43,7 @@
42
43
  import Pencil from "vue-material-design-icons/Pencil.vue";
43
44
  import Delete from "vue-material-design-icons/Delete.vue";
44
45
  import Tooltip from "../misc/Tooltip.vue";
46
+ import Utils from "../../utils/Utils.js";
45
47
 
46
48
  export default {
47
49
  name: "Task",
@@ -82,6 +84,10 @@
82
84
  id: {
83
85
  type: String,
84
86
  required: true
87
+ },
88
+ icons: {
89
+ type: Object,
90
+ default: undefined
85
91
  }
86
92
  },
87
93
  methods: {
@@ -54,6 +54,14 @@
54
54
  expandedSubflows: {
55
55
  type: Array,
56
56
  default: () => []
57
+ },
58
+ icons: {
59
+ type: Object,
60
+ default: undefined
61
+ },
62
+ enableSubflowInteraction: {
63
+ type: Boolean,
64
+ default: true
57
65
  }
58
66
  });
59
67
 
@@ -84,6 +92,7 @@
84
92
 
85
93
  onMounted(() => {
86
94
  generateGraph();
95
+
87
96
  })
88
97
 
89
98
  watch(() => props.flowGraph, () => {
@@ -119,7 +128,8 @@
119
128
  collapsed.value,
120
129
  clusterToNode.value,
121
130
  props.isReadOnly,
122
- props.isAllowedEdit
131
+ props.isAllowedEdit,
132
+ props.enableSubflowInteraction
123
133
  );
124
134
  setElements(elements);
125
135
  fitView();
@@ -195,7 +205,7 @@
195
205
  })
196
206
 
197
207
  const subflowPrefixes = computed(() => {
198
- if(!props.flowGraph) {
208
+ if(!props.flowGraph?.clusters) {
199
209
  return [];
200
210
  }
201
211
 
@@ -206,7 +216,7 @@
206
216
  onNodeDrag((e) => {
207
217
  resetNodesStyle();
208
218
  getNodes.value.filter(n => n.id !== e.node.id).forEach(n => {
209
- if (n.type === "trigger" || (n.type === "task" && (n.id.startsWith(e.node.id + ".") || e.node.id.startsWith(n.id + "."))) || subflowPrefixes.value.some(subflowPrefix => n.id.startsWith(subflowPrefix))) {
219
+ if (n.type === "trigger" || (n.type === "task" && (n.id.startsWith(e.node.id + ".") || e.node.id.startsWith(n.id + "."))) || subflowPrefixes?.value?.some(subflowPrefix => n.id.startsWith(subflowPrefix))) {
210
220
  n.style = {...n.style, opacity: "0.5"}
211
221
  } else {
212
222
  n.style = {...n.style, opacity: "1"}
@@ -313,6 +323,7 @@
313
323
  <template #node-task="taskProps">
314
324
  <TaskNode
315
325
  v-bind="taskProps"
326
+ :icons="icons"
316
327
  @edit="forwardEvent(EVENTS.EDIT, $event)"
317
328
  @delete="forwardEvent(EVENTS.DELETE, $event)"
318
329
  @expand="expand($event)"
@@ -322,12 +333,14 @@
322
333
  @mouseover="onMouseOver($event)"
323
334
  @mouseleave="onMouseLeave()"
324
335
  @add-error="forwardEvent('on-add-flowable-error', $event)"
336
+ :enable-subflow-interaction="enableSubflowInteraction"
325
337
  />
326
338
  </template>
327
339
 
328
340
  <template #node-trigger="triggerProps">
329
341
  <TriggerNode
330
342
  v-bind="triggerProps"
343
+ :icons="icons"
331
344
  :is-read-only="isReadOnly"
332
345
  :is-allowed-edit="isAllowedEdit"
333
346
  @delete="forwardEvent(EVENTS.DELETE, $event)"
package/src/scss/app.scss CHANGED
@@ -5,7 +5,7 @@
5
5
  }
6
6
 
7
7
 
8
- .rounded-button {
8
+ .circle-button {
9
9
  border-radius: 1rem;
10
10
  width: 1rem;
11
11
  height: 1rem;
@@ -46,12 +46,11 @@
46
46
  .vue-flow__container {
47
47
  .top-button-div {
48
48
  position: absolute;
49
- top: 0;
50
- width: 100%;
51
- justify-content: end;
52
- display: flex;
53
- right: -16px;
54
- transform: translate(-5%, -50%) !important;
49
+ top: -0.5rem;
50
+ right: -0.5rem;
51
+ justify-content: center;
52
+ padding-right: 3px;
53
+ display: flex
55
54
  }
56
55
 
57
56
  .vue-flow__node-cluster {
@@ -49,4 +49,12 @@ export default class Utils {
49
49
  static afterLastDot(str) {
50
50
  return str.split(".").pop();
51
51
  }
52
+
53
+ static translate(text) {
54
+ if (typeof $t !== "undefined" && typeof $t === "function") {
55
+ return $t(text);
56
+ } else {
57
+ return text;
58
+ }
59
+ }
52
60
  }
@@ -294,7 +294,7 @@ export default class VueFlowUtils {
294
294
  return null;
295
295
  }
296
296
 
297
- static generateGraph(vueFlowId, flowId, namespace, flowGraph, flowSource, hiddenNodes, isHorizontal, edgeReplacer, collapsed, clusterToNode, isReadOnly, isAllowedEdit) {
297
+ static generateGraph(vueFlowId, flowId, namespace, flowGraph, flowSource, hiddenNodes, isHorizontal, edgeReplacer, collapsed, clusterToNode, isReadOnly, isAllowedEdit, enableSubflowInteraction) {
298
298
  const elements = [];
299
299
 
300
300
  const clustersWithoutRootNode = [CLUSTER_PREFIX + TRIGGERS_NODE_UID];
@@ -422,7 +422,7 @@ export default class VueFlowUtils {
422
422
  flowId: clusterByNodeUid[node.uid]?.taskNode?.task?.flowId ?? flowId,
423
423
  isFlowable: clusterByNodeUid[node.uid]?.uid === CLUSTER_PREFIX + node.uid && !node.type.endsWith("SubflowGraphTask"),
424
424
  color: color,
425
- expandable: this.isExpandableTask(node, clusterByNodeUid, edgeReplacer),
425
+ expandable: this.isExpandableTask(node, clusterByNodeUid, edgeReplacer, enableSubflowInteraction),
426
426
  isReadOnly: isReadOnlyTask,
427
427
  iconComponent: this.isCollapsedCluster(node) ? "webhook" : null,
428
428
  executionId: node.executionId,
@@ -486,7 +486,7 @@ export default class VueFlowUtils {
486
486
  return "blue";
487
487
  }
488
488
 
489
- static isExpandableTask(node, clusterByNodeUid, edgeReplacer) {
489
+ static isExpandableTask(node, clusterByNodeUid, edgeReplacer, enableSubflowInteraction) {
490
490
  if (Object.values(edgeReplacer).includes(node.uid)) {
491
491
  return true;
492
492
  }
@@ -495,6 +495,6 @@ export default class VueFlowUtils {
495
495
  return true;
496
496
  }
497
497
 
498
- return node.type.endsWith("SubflowGraphTask") && clusterByNodeUid[node.uid]?.uid?.replace(CLUSTER_PREFIX, "") !== node.uid;
498
+ return node.type.endsWith("SubflowGraphTask") && clusterByNodeUid[node.uid]?.uid?.replace(CLUSTER_PREFIX, "") !== node.uid && enableSubflowInteraction;
499
499
  }
500
500
  }