@kestra-io/ui-libs 0.0.6 → 0.0.8

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": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src",
@@ -27,9 +27,10 @@
27
27
  "moment": "^2.29.4",
28
28
  "vue": "^3.3.4",
29
29
  "vue-material-design-icons": "^5.2.0",
30
+ "vue3-popper": "^1.5.0",
30
31
  "vuex": "^4.1.0",
31
32
  "yaml": "^2.3.1",
32
- "vue3-popper": "^1.5.0"
33
+ "dagre": "^0.8.5"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@vitejs/plugin-vue": "^4.2.3",
@@ -4,7 +4,7 @@
4
4
  <template #content>
5
5
  <span v-for="(history, index) in histories" :key="'tt-' + index">
6
6
  <span class="square" :class="squareClass(history.state)" />
7
- <strong>{{ history.state }}:</strong> {{ $filters.date(history.date, 'iso') }} <br>
7
+ <strong>{{ history.state }}:</strong>{{ $filters.date(history.date, 'iso') }} <br>
8
8
  </span>
9
9
  </template>
10
10
 
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <div class="btn-group content rounded-1 content-children">
3
- <span v-if="taskRuns.length > 0">{{ taskRuns.length }} task runs</span>
3
+ <span v-if="taskRuns.length > 0" class="taskRunCount">{{ taskRuns.length }} task runs</span>
4
+ <span v-if="taskRuns.length > 0">|</span>
4
5
  <span><duration :histories="histories" /></span>
5
6
  </div>
6
7
  </template>
@@ -115,6 +116,6 @@
115
116
  align-self: stretch;
116
117
  pointer-events: none;
117
118
  cursor: default;
118
- font-size: 0.75rem;
119
+ font-size: 0.70rem;
119
120
  }
120
121
  </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div
3
- :class="[color ? `bg-${color}`: '']"
3
+ :class="[color ? `bg-${color}`: 'bg-white']"
4
4
  class="div-icon rounded d-flex justify-content-center"
5
5
  data-bs-toggle="tooltip"
6
6
  data-bs-placement="top"
@@ -18,7 +18,7 @@
18
18
  name: "TaskIcon",
19
19
  props: {
20
20
  customIcon: {
21
- type: String,
21
+ type: Object,
22
22
  default: undefined
23
23
  },
24
24
  cls: {
@@ -73,7 +73,9 @@
73
73
  margin: 0.2rem;
74
74
  width: 25px;
75
75
  height: 25px;
76
- background-color: var(--bs-white);
77
76
  border: 0.4px solid var(--bs-border-color);
78
77
  }
78
+ .bg-white {
79
+ background-color: var(--bs-white);
80
+ }
79
81
  </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div
3
- :class="[`border-${!expandable ? data.color : 'blue'}`]"
3
+ :class="[`border-${borderColor}`]"
4
4
  class="node-wrapper rounded-3 border"
5
5
  @mouseover="mouseover"
6
6
  @mouseleave="mouseleave"
@@ -151,6 +151,10 @@
151
151
  },
152
152
  computed: {
153
153
  ...mapState("execution", ["execution"]),
154
+ borderColor() {
155
+ const color = this.data.color ? this.data.color === "default" ? null : this.data.color : null
156
+ return color ? color : this.expandable ? "blue" : null
157
+ },
154
158
  EVENTS() {
155
159
  return EVENTS
156
160
  },
@@ -223,7 +227,7 @@
223
227
  }
224
228
 
225
229
  .description-button {
226
- color: var(--bs-gray-600);
230
+ color: var(--bs-gray-700);
227
231
  cursor: pointer;
228
232
  width: 25px;
229
233
  }
@@ -1,32 +1,40 @@
1
1
  <template>
2
- <Handle type="source" :position="sourcePosition" />
2
+ <Handle type="source" :position="sourcePosition"/>
3
3
  <div class="collapsed-cluster-node">
4
- <span>{{ id }}</span>
5
- <div class="position-absolute top-0 start-100 translate-middle text-white d-flex top-button-div">
6
- <slot name="badge-button-before" />
4
+ <span class="node-text">
5
+ <component v-if="data.iconComponent" :is="data.iconComponent" :class="`text-${data.color} me-2`" />
6
+ {{ id }}
7
+ </span>
8
+ <div class="position-absolute top-0 text-white d-flex top-button-div">
9
+ <slot name="badge-button-before"/>
7
10
  <span
8
11
  v-if="expandable"
9
12
  class="rounded-button"
10
13
  :class="[`bg-${data.color}`]"
11
14
  @click="$emit(EVENTS.EXPAND, id)"
12
15
  >
13
- <ArrowExpand class="button-icon" alt="Expand task" />
16
+ <ArrowExpand class="button-icon" alt="Expand task"/>
14
17
  </span>
15
- <slot name="badge-button-after" />
18
+ <slot name="badge-button-after"/>
16
19
  </div>
17
20
  </div>
18
- <Handle type="target" :position="targetPosition" />
21
+ <Handle type="target" :position="targetPosition"/>
19
22
  </template>
20
23
 
21
24
  <script>
22
25
  import {EVENTS} from "../../utils/constants.js";
23
26
  import ArrowExpand from "vue-material-design-icons/ArrowExpand.vue";
27
+ import Webhook from "vue-material-design-icons/Webhook.vue";
24
28
  import {Handle} from "@vue-flow/core";
25
29
 
26
30
  export default {
27
31
  components: {
28
32
  Handle,
29
- ArrowExpand
33
+ ArrowExpand,
34
+ Webhook
35
+ },
36
+ created(){
37
+ console.log(this.data)
30
38
  },
31
39
  inheritAttrs: false,
32
40
  props: {
@@ -45,7 +53,7 @@
45
53
  data: {
46
54
  type: Object,
47
55
  required: true
48
- }
56
+ },
49
57
  },
50
58
  data() {
51
59
  return {
@@ -75,6 +83,16 @@
75
83
  .collapsed-cluster-node {
76
84
  width: 150px;
77
85
  height: 44px;
86
+ padding: 8px;
87
+ }
88
+
89
+ .node-text {
90
+ color: black;
91
+ font-size: 0.90rem;
92
+ display: flex;
93
+ html.dark & {
94
+ color: white;
95
+ }
78
96
  }
79
97
 
80
98
  .rounded-button {
@@ -108,19 +108,4 @@
108
108
  }
109
109
  }
110
110
  }
111
- </script>
112
- <style scoped lang="scss">
113
- .rounded-button {
114
- border-radius: 1rem;
115
- width: 1rem;
116
- height: 1rem;
117
- display: flex;
118
- justify-content: center;
119
- align-items: center;
120
- margin-left: 0.25rem;
121
- }
122
-
123
- .button-icon {
124
- font-size: 0.75rem;
125
- }
126
- </style>
111
+ </script>
@@ -22,6 +22,7 @@
22
22
  import Utils from "../../utils/Utils.js";
23
23
  import VueflowUtils from "../../utils/VueFlowUtils.js";
24
24
  import {CLUSTER_UID_SEPARATOR} from "../../utils/constants.js";
25
+ import {Background} from "@vue-flow/background";
25
26
 
26
27
  const props = defineProps({
27
28
  id: {
@@ -101,6 +102,10 @@
101
102
  generateGraph();
102
103
  })
103
104
 
105
+ watch(() => props.isHorizontal, () => {
106
+ generateGraph();
107
+ })
108
+
104
109
  const generateGraph = () => {
105
110
  VueFlowUtils.cleanGraph(props.id);
106
111
 
@@ -285,6 +290,7 @@
285
290
  :elevate-nodes-on-select="false"
286
291
  :elevate-edges-on-select="false"
287
292
  >
293
+ <Background />
288
294
  <template #node-cluster="clusterProps">
289
295
  <ClusterNode
290
296
  v-bind="clusterProps"
package/src/scss/app.scss CHANGED
@@ -13,10 +13,19 @@ marker[id*='id=marker-custom&type=arrowclosed'] polyline {
13
13
  fill: $gray-700;
14
14
  }
15
15
 
16
+ marker[id*='id=marker-danger&type=arrowclosed'] polyline {
17
+ stroke: $danger;
18
+ fill: $danger;
19
+ }
20
+
16
21
  .vue-flow__handle {
17
22
  opacity: 0 !important;
18
23
  }
19
24
 
25
+ .vue-flow__edge-path {
26
+ stroke: $gray-700;
27
+ }
28
+
20
29
 
21
30
  .top-button-div {
22
31
  width: 100%;
@@ -32,10 +41,11 @@ marker[id*='id=marker-custom&type=arrowclosed'] polyline {
32
41
  justify-content: center;
33
42
  align-items: center;
34
43
  margin-left: 0.25rem;
44
+ z-index: 2000;
35
45
  }
36
46
 
37
47
  .button-icon {
38
- font-size: 0.75rem;
48
+ font-size: 0.66rem;
39
49
  }
40
50
 
41
51
 
@@ -212,12 +212,12 @@ export default class VueFlowUtils {
212
212
 
213
213
  static nodeColor(node, collapsed, flowSource) {
214
214
  if (this.isTaskNode(node)) {
215
- if (collapsed.includes(node.uid)) {
216
- return "blue";
217
- }
218
215
  if (YamlUtils.isTaskError(flowSource, node.task.id)) {
219
216
  return "danger"
220
217
  }
218
+ if (collapsed.includes(node.uid)) {
219
+ return "blue";
220
+ }
221
221
  if (node.task.type === "io.kestra.core.tasks.flows.Flow") {
222
222
  return "primary"
223
223
  }
@@ -230,8 +230,10 @@ export default class VueFlowUtils {
230
230
  static getClusterTaskIdWithEndNodeUid (nodeUid, flowGraph) {
231
231
  const cluster = flowGraph.clusters.find(cluster => cluster.end === nodeUid);
232
232
  if (cluster) {
233
+
233
234
  return Utils.splitFirst(cluster.cluster.uid, CLUSTER_UID_SEPARATOR);
234
235
  }
236
+
235
237
  return undefined;
236
238
  }
237
239
 
@@ -274,6 +276,9 @@ export default class VueFlowUtils {
274
276
  if (YamlUtils.isTaskError(flowSource, edge.source) || YamlUtils.isTaskError(flowSource, edge.target)) {
275
277
  return "danger"
276
278
  }
279
+ if (this.isClusterError(flowSource, edge.source) || this.isClusterError(flowSource, edge.target)) {
280
+ return "danger"
281
+ }
277
282
  return null;
278
283
  }
279
284
 
@@ -339,6 +344,7 @@ export default class VueFlowUtils {
339
344
  }
340
345
 
341
346
  const clusterUid = cluster.cluster.uid;
347
+ const isClusterError = YamlUtils.isTaskError(flowSource, Utils.splitFirst(clusterUid, CLUSTER_UID_SEPARATOR))
342
348
  const dagreNode = dagreGraph.node(clusterUid)
343
349
  const parentNode = cluster.parents ? cluster.parents[cluster.parents.length - 1] : undefined;
344
350
 
@@ -353,9 +359,9 @@ export default class VueFlowUtils {
353
359
  },
354
360
  data: {
355
361
  collapsable: true,
356
- color: clusterUid === "Triggers" ? "success" : "blue"
362
+ color: clusterUid === "Triggers" ? "success" : isClusterError ? "danger" : "blue"
357
363
  },
358
- class: `bg-light-${clusterUid === "Triggers" ? "success" : "blue"}-border rounded p-2`,
364
+ class: `bg-light-${clusterUid === "Triggers" ? "success" : isClusterError ? "danger" : "blue"}-border rounded p-2`,
359
365
  })
360
366
  }
361
367
  }
@@ -405,11 +411,12 @@ export default class VueFlowUtils {
405
411
  flowId: flowId,
406
412
  isFlowable: this.isTaskNode(node) ? flowables.includes(taskId) : false,
407
413
  color: nodeType != "dot" ? this.nodeColor(node, collapsed, flowSource) : null,
408
- expandable: taskId ? flowables.includes(taskId) && edgeReplacer[CLUSTER_UID_SEPARATOR + taskId] !== undefined : this.isCollapsedCluster(node),
414
+ expandable: taskId ? edgeReplacer[CLUSTER_UID_SEPARATOR + taskId] !== undefined : this.isCollapsedCluster(node),
409
415
  isReadOnly: isReadOnly,
410
- link: node.task?.type === "io.kestra.core.tasks.flows.Flow" ? this.linkDatas(node.task) : false
416
+ link: node.task?.type === "io.kestra.core.tasks.flows.Flow" ? this.linkDatas(node.task) : false,
417
+ iconComponent: this.isCollapsedCluster(node) ? "webhook" : null
411
418
  },
412
- class: node.type === "collapsedcluster" ? `bg-light-${node.uid === "Triggers" ? "success" : "blue"}-border rounded p-2` : "",
419
+ class: node.type === "collapsedcluster" ? `bg-light-${node.uid === "Triggers" ? "success" : YamlUtils.isTaskError(flowSource, taskId) ? "danger" : "blue"}-border rounded` : "",
413
420
  })
414
421
  }
415
422
  }
@@ -422,7 +429,7 @@ export default class VueFlowUtils {
422
429
  target: newEdge.target,
423
430
  type: "edge",
424
431
  markerEnd: YamlUtils.extractTask(flowSource, newEdge.target) ? {
425
- id: "marker-custom",
432
+ id: YamlUtils.isTaskError(flowSource, newEdge.target) ? "marker-danger" : "marker-custom",
426
433
  type: MarkerType.ArrowClosed,
427
434
  } : "",
428
435
  data: {
@@ -442,4 +449,19 @@ export default class VueFlowUtils {
442
449
  return elements;
443
450
  }
444
451
 
452
+ static isClusterError(flowSource, clusterUid) {
453
+ if(clusterUid.startsWith(CLUSTER_UID_SEPARATOR)) {
454
+ if(clusterUid.endsWith("_end")) {
455
+
456
+ return YamlUtils.isTaskError(flowSource, Utils.splitFirst(clusterUid.substring(0, clusterUid.length - 4), CLUSTER_UID_SEPARATOR));
457
+ }
458
+ if(clusterUid.endsWith("_start")) {
459
+
460
+ return YamlUtils.isTaskError(flowSource, Utils.splitFirst(clusterUid.substring(0, clusterUid.length - 6), CLUSTER_UID_SEPARATOR));
461
+ }
462
+ }
463
+
464
+ return false
465
+ }
466
+
445
467
  }
@@ -1,6 +1,6 @@
1
1
  import JsYaml from "js-yaml";
2
2
  import yaml, {Document, YAMLMap, isSeq, isMap, Pair, Scalar, YAMLSeq, LineCounter} from "yaml";
3
- import _cloneDeep from "lodash/cloneDeep"
3
+ import {cloneDeep} from "lodash/cloneDeep"
4
4
  import {SECTIONS} from "./constants.js";
5
5
 
6
6
  const TOSTRING_OPTIONS = {lineWidth: 0};
@@ -15,7 +15,7 @@ export default class YamlUtils {
15
15
  delete value.deleted
16
16
  }
17
17
 
18
- return JsYaml.dump(YamlUtils._transform(_cloneDeep(value)), {
18
+ return JsYaml.dump(YamlUtils._transform(cloneDeep(value)), {
19
19
  lineWidth: -1,
20
20
  noCompatMode: true,
21
21
  quotingType: "\"",