@kestra-io/ui-libs 0.0.12 → 0.0.14

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.12",
3
+ "version": "v0.0.14",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src",
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <g clip-path="url(#clip0_796_3996)">
4
- <path d="M13.367 1.979C13.7368 1.979 14.0366 2.27881 14.0366 2.64863V13.3626C14.0366 13.7324 13.7368 14.0322 13.367 14.0322H2.65302C2.2832 14.0322 1.9834 13.7324 1.9834 13.3626V2.64863C1.9834 2.27881 2.2832 1.979 2.65302 1.979H13.367ZM7.34039 3.31825H3.32265V12.693H7.34039V10.0145H8.67963V12.693H12.6974V3.31825H8.67963V5.99675H7.34039V3.31825ZM10.0189 5.99675L12.0278 8.00562L10.0189 10.0145V8.67524H6.00114V10.0145L3.99227 8.00562L6.00114 5.99675V7.33599H10.0189V5.99675Z" fill="#CAC5DA" />
4
+ <path d="M13.367 1.979C13.7368 1.979 14.0366 2.27881 14.0366 2.64863V13.3626C14.0366 13.7324 13.7368 14.0322 13.367 14.0322H2.65302C2.2832 14.0322 1.9834 13.7324 1.9834 13.3626V2.64863C1.9834 2.27881 2.2832 1.979 2.65302 1.979H13.367ZM7.34039 3.31825H3.32265V12.693H7.34039V10.0145H8.67963V12.693H12.6974V3.31825H8.67963V5.99675H7.34039V3.31825ZM10.0189 5.99675L12.0278 8.00562L10.0189 10.0145V8.67524H6.00114V10.0145L3.99227 8.00562L6.00114 5.99675V7.33599H10.0189V5.99675Z" fill="currentColor" />
5
5
  </g>
6
6
  <defs>
7
7
  <clipPath id="clip0_796_3996">
@@ -21,4 +21,4 @@
21
21
  svg {
22
22
  transform: scale(1.5);
23
23
  }
24
- </style>
24
+ </style>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <g clip-path="url(#clip0_1111_7266)">
4
- <path d="M1.97852 2.63349C1.97852 2.26366 2.27832 1.96387 2.64814 1.96387L13.3621 1.96387C13.7319 1.96387 14.0317 2.26366 14.0317 2.63349L14.0317 13.3475C14.0317 13.7173 13.7319 14.0171 13.3621 14.0171L2.64814 14.0171C2.27832 14.0171 1.97852 13.7173 1.97852 13.3475L1.97852 2.63349ZM3.31776 8.6601L3.31776 12.6778L12.6925 12.6778L12.6925 8.6601L10.014 8.6601L10.014 7.32085L12.6925 7.32085L12.6925 3.30311L3.31776 3.30311L3.31776 7.32086L5.99626 7.32085L5.99626 8.6601L3.31776 8.6601ZM5.99626 5.98161L8.00513 3.97274L10.014 5.98161L8.67475 5.98161L8.67475 9.99935L10.014 9.99935L8.00513 12.0082L5.99626 9.99935L7.3355 9.99935L7.3355 5.98161L5.99626 5.98161Z" fill="#CAC5DA" />
4
+ <path d="M1.97852 2.63349C1.97852 2.26366 2.27832 1.96387 2.64814 1.96387L13.3621 1.96387C13.7319 1.96387 14.0317 2.26366 14.0317 2.63349L14.0317 13.3475C14.0317 13.7173 13.7319 14.0171 13.3621 14.0171L2.64814 14.0171C2.27832 14.0171 1.97852 13.7173 1.97852 13.3475L1.97852 2.63349ZM3.31776 8.6601L3.31776 12.6778L12.6925 12.6778L12.6925 8.6601L10.014 8.6601L10.014 7.32085L12.6925 7.32085L12.6925 3.30311L3.31776 3.30311L3.31776 7.32086L5.99626 7.32085L5.99626 8.6601L3.31776 8.6601ZM5.99626 5.98161L8.00513 3.97274L10.014 5.98161L8.67475 5.98161L8.67475 9.99935L10.014 9.99935L8.00513 12.0082L5.99626 9.99935L7.3355 9.99935L7.3355 5.98161L5.99626 5.98161Z" fill="currentColor" />
5
5
  </g>
6
6
  <defs>
7
7
  <clipPath id="clip0_1111_7266">
@@ -1,25 +1,27 @@
1
1
  <template>
2
- <span>
3
- <el-tooltip v-if="histories" popper-class="duration-tt" :persistent="false" transition="" :hide-after="0">
4
- <template #content>
5
- <span v-for="(history, index) in histories" :key="'tt-' + index">
6
- <span class="square" :class="squareClass(history.state)" />
7
- <strong>{{ history.state }}:</strong>{{ $filters.date(history.date, 'iso') }} <br>
8
- </span>
9
- </template>
2
+ <tooltip>
3
+ <template #content>
4
+ <span v-for="(history, index) in filteredHistories" :key="'tt-' + index" class="duration-tt">
5
+ <span class="square" :class="squareClass(history.state)" />
6
+ <strong>{{ history.state }}: </strong>{{ $filters.date(history.date, 'iso') }} <br>
7
+ </span>
8
+ </template>
10
9
 
11
- <span>{{ duration }}</span>
12
- </el-tooltip>
13
- </span>
10
+ <template #default>
11
+ <span v-html="duration" />
12
+ </template>
13
+ </tooltip>
14
14
  </template>
15
15
 
16
16
  <script>
17
17
  import State from "../../utils/state";
18
18
  import Utils from "../../utils/Utils";
19
+ import Tooltip from "../misc/Tooltip.vue";
19
20
 
20
21
  const ts = date => new Date(date).getTime();
21
22
 
22
23
  export default {
24
+ components: {Tooltip},
23
25
  props: {
24
26
  histories: {
25
27
  type: Array,
@@ -46,9 +48,11 @@
46
48
  start() {
47
49
  return this.histories && this.histories.length && ts(this.histories[0].date);
48
50
  },
49
-
50
51
  lastStep() {
51
52
  return this.histories[this.histories.length - 1]
53
+ },
54
+ filteredHistories() {
55
+ return this.histories.filter(h => h.date && h.date.isValid() && h.state)
52
56
  }
53
57
  },
54
58
  methods: {
@@ -78,7 +82,7 @@
78
82
  return ts(this.lastStep.date)
79
83
  },
80
84
  computeDuration() {
81
- this.duration = Utils.humanDuration(this.delta() / 1000)
85
+ this.duration = this.filteredHistories.length === 0 ? "&nbsp;" : Utils.humanDuration(this.delta() / 1000)
82
86
  },
83
87
  squareClass(state) {
84
88
  return [
@@ -93,18 +97,16 @@
93
97
  </script>
94
98
 
95
99
  <style lang="scss">
96
- .duration-tt {
97
- .tooltip-inner {
100
+ .duration-tt {
98
101
  text-align: left;
99
102
  white-space: nowrap;
100
103
  max-width: none;
101
- }
102
104
 
103
- .square {
104
- display: inline-block;
105
- width: 10px;
106
- height: 10px;
107
- margin-right: 5px;
105
+ .square {
106
+ display: inline-block;
107
+ width: 10px;
108
+ height: 10px;
109
+ margin-right: 5px;
110
+ }
108
111
  }
109
- }
110
112
  </style>
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <div class="btn-group content rounded-1 content-children">
2
+ <div class="btn-group content rounded-1 content-children text-truncate">
3
3
  <span v-if="taskRuns.length > 0" class="taskRunCount">{{ taskRuns.length }} task runs</span>
4
- <span v-if="taskRuns.length > 0">|</span>
4
+ <span v-if="taskRuns.length > 0"> | </span>
5
5
  <span><duration :histories="histories" /></span>
6
6
  </div>
7
7
  </template>
@@ -95,28 +95,10 @@
95
95
  </script>
96
96
  <style scoped>
97
97
  .content {
98
- display: flex;
99
98
  color: var(--bs-gray-700);
100
-
101
- *:not(:first-child)::before {
102
- content: "";
103
- position: absolute;
104
- left: 0;
105
- top: 50%;
106
- height: 50%;
107
- transform: translateY(-50%);
108
- z-index: 500;
109
- }
110
99
  }
111
100
 
112
101
  .content-children {
113
- flex-grow: 1;
114
- display: flex;
115
- height: 1.25rem;
116
- gap: 0.5rem;
117
- align-self: stretch;
118
- pointer-events: none;
119
- cursor: default;
120
102
  font-size: 0.70rem;
121
103
  }
122
104
  </style>
@@ -1,21 +1,22 @@
1
1
  <template>
2
2
  <div
3
- :class="[color ? `bg-${color}`: 'bg-white']"
4
- class="div-icon rounded d-flex justify-content-center"
5
- data-bs-toggle="tooltip"
6
- data-bs-placement="top"
7
- :title="cls"
3
+ :class="classes"
4
+ class="wrapper"
8
5
  >
9
- <img :src="backgroundImage" alt="task icon">
6
+ <Tooltip :title="cls">
7
+ <div class="icon" :style="styles" />
8
+ </Tooltip>
10
9
  </div>
11
10
  </template>
12
11
  <script>
13
12
  import {mapState} from "vuex";
14
13
  import {Buffer} from "buffer";
15
- import {Tooltip} from "bootstrap";
14
+ import Tooltip from "../misc/Tooltip.vue";
15
+ import {cssVariable} from "../../utils/global.js";
16
16
 
17
17
  export default {
18
18
  name: "TaskIcon",
19
+ components: {Tooltip},
19
20
  props: {
20
21
  customIcon: {
21
22
  type: Object,
@@ -25,41 +26,52 @@
25
26
  type: String,
26
27
  default: undefined
27
28
  },
28
- color: {
29
+ theme: {
29
30
  type: String,
30
- default: undefined
31
- }
32
- },
33
- mounted(){
34
- const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
35
- this.tooltips = tooltipTriggerList.map(function (tooltipTriggerEl) {
36
- return new Tooltip(tooltipTriggerEl, {
37
- trigger : "hover"
38
- })
39
- })
40
- },
41
- beforeUnmount() {
42
- document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
43
- const tooltip = Tooltip.getInstance(el);
44
- if (tooltip) {
45
- tooltip.dispose();
31
+ default: undefined,
32
+ validator(value) {
33
+ return ["dark", "light"].includes(value)
46
34
  }
47
- });
35
+ }
48
36
  },
49
37
  computed: {
50
38
  ...mapState("plugin", ["icons"]),
51
39
  backgroundImage() {
52
40
  return `data:image/svg+xml;base64,${this.imageBase64}`
53
41
  },
42
+ classes() {
43
+ return {
44
+ "flowable": this.icon ? this.icon.flowable : false,
45
+ }
46
+ },
47
+ styles() {
48
+ return {
49
+ backgroundImage: `url(data:image/svg+xml;base64,${this.imageBase64})`
50
+ }
51
+ },
54
52
  imageBase64() {
55
- const icon = this.icon ? this.icon.icon : undefined;
56
- return icon ? icon : Buffer.from("<svg xmlns=\"http://www.w3.org/2000/svg\" " +
57
- "xmlns:xlink=\"http://www.w3.org/1999/xlink\" aria-hidden=\"true\" " +
58
- "focusable=\"false\" width=\"0.75em\" height=\"1em\" style=\"-ms-transform: " +
59
- "rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);\" " +
60
- "preserveAspectRatio=\"xMidYMid meet\" viewBox=\"0 0 384 512\">" +
61
- "<path d=\"M288 32H0v448h384V128l-96-96zm64 416H32V64h224l96 96v288z\" fill=\"#0D1523FF\"/>" +
62
- "</svg>", "utf8").toString("base64");
53
+ let icon = this.icon && this.icon.icon ? Buffer.from(this.icon.icon, "base64").toString("utf8") : undefined;
54
+
55
+ if (!icon) {
56
+ icon = "<svg xmlns=\"http://www.w3.org/2000/svg\" " +
57
+ "xmlns:xlink=\"http://www.w3.org/1999/xlink\" aria-hidden=\"true\" " +
58
+ "focusable=\"false\" width=\"0.75em\" height=\"1em\" style=\"-ms-transform: " +
59
+ "rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);\" " +
60
+ "preserveAspectRatio=\"xMidYMid meet\" viewBox=\"0 0 384 512\">" +
61
+ "<path d=\"M288 32H0v448h384V128l-96-96zm64 416H32V64h224l96 96v288z\" fill=\"currentColor\"/>" +
62
+ "</svg>";
63
+ }
64
+
65
+ const darkTheme = document.getElementsByTagName("html")[0].className.indexOf("dark") >= 0;
66
+ let color = darkTheme ? cssVariable("--bs-gray-900") : cssVariable("--bs-black");
67
+
68
+ if (this.theme) {
69
+ color = this.theme === "dark" ? cssVariable("--bs-gray-900") : cssVariable("--bs-black");
70
+ }
71
+
72
+ icon = icon.replaceAll("currentColor", color);
73
+
74
+ return Buffer.from(icon, "utf8").toString("base64");
63
75
  },
64
76
  icon() {
65
77
  return this.cls ? (this.icons || {})[this.cls] : this.customIcon;
@@ -67,12 +79,30 @@
67
79
  }
68
80
  }
69
81
  </script>
70
- <style scoped>
71
- .div-icon {
72
- padding: 0.3rem;
73
- margin: 0.2rem;
74
- width: 25px;
75
- height: 25px;
76
- border: 0.4px solid var(--bs-border-color);
82
+
83
+ <style lang="scss" scoped>
84
+ .wrapper {
85
+ display: inline-block;
86
+ width: 100%;
87
+ height: 100%;
88
+ position: relative;
89
+
90
+ :deep(span) {
91
+ position: absolute;
92
+ padding: 1px;
93
+ left: 0;
94
+ display: block;
95
+ width: 100%;
96
+ height: 100%;
97
+ }
98
+
99
+ :deep(.icon) {
100
+ width: 100%;
101
+ height: 100%;
102
+ display: block;
103
+ background-size: contain;
104
+ background-repeat: no-repeat;
105
+ background-position: center center;
106
+ }
77
107
  }
78
108
  </style>
@@ -0,0 +1,51 @@
1
+ <template>
2
+ <span ref="tooltip">
3
+ <slot name="default" />
4
+ </span>
5
+ <span class="d-none" ref="tooltipContent">
6
+ <slot name="content">
7
+ {{ title }}
8
+ </slot>
9
+ </span>
10
+ </template>
11
+ <script>
12
+ import {Tooltip} from "bootstrap";
13
+
14
+ export default {
15
+ props: {
16
+ title: {
17
+ type: String,
18
+ default: undefined
19
+ },
20
+ placement: {
21
+ type: String,
22
+ default: "top"
23
+ },
24
+ },
25
+ mounted() {
26
+ new Tooltip(this.$refs.tooltip, {
27
+ trigger: "hover",
28
+ html: true,
29
+ placement: this.placement,
30
+ title: this.$refs.tooltipContent.innerHTML,
31
+ customClass: "tooltip-custom"
32
+ })
33
+ },
34
+ beforeUnmount() {
35
+ if (this.$refs.tooltip) {
36
+ const tooltip = Tooltip.getInstance(this.$refs.tooltip);
37
+ if (tooltip) {
38
+ tooltip.dispose();
39
+ }
40
+ }
41
+ }
42
+ }
43
+ </script>
44
+
45
+ <style lang="scss">
46
+ .tooltip-custom {
47
+ .tooltip-inner {
48
+ max-width: none;
49
+ }
50
+ }
51
+ </style>
@@ -6,57 +6,53 @@
6
6
  @mouseleave="mouseleave"
7
7
  >
8
8
  <div v-if="state" class="status-div" :class="[`bg-${stateColor}`]" />
9
- <div>
10
- <TaskIcon :icon="data.icon" :cls="cls" :class="taskIconBg" />
9
+ <div class="icon rounded">
10
+ <TaskIcon :icon="data.icon" :cls="cls" :class="taskIconBg" class="rounded bg-white" theme="light" />
11
11
  </div>
12
12
  <div class="node-content">
13
13
  <div class="d-flex node-title">
14
14
  <div
15
15
  class="text-truncate task-title"
16
- data-bs-toggle="tooltip"
17
- data-bs-placement="top"
18
- :title="id"
19
16
  >
20
- <span>{{ id }}</span>
17
+ <tooltip :title="id">
18
+ {{ id }}
19
+ </tooltip>
21
20
  </div>
22
21
  <span
23
22
  class="d-flex"
24
23
  v-if="description"
25
- data-bs-toggle="tooltip"
26
- data-bs-placement="top"
27
- :title="$t('show description')"
28
24
  >
29
- <InformationOutline
30
- @click="$emit(EVENTS.SHOW_DESCRIPTION, {id: id, description:description})"
31
- class="description-button ms-2"
32
- />
25
+ <tooltip :title="$t('show description')">
26
+ <InformationOutline
27
+ @click="$emit(EVENTS.SHOW_DESCRIPTION, {id: id, description:description})"
28
+ class="description-button ms-2"
29
+ />
30
+ </tooltip>
33
31
  </span>
34
32
  </div>
35
33
  <slot name="content" />
36
34
  </div>
37
- <div class="position-absolute top-0 text-white d-flex top-button-div">
35
+ <div class="text-white top-button-div">
38
36
  <slot name="badge-button-before" />
39
37
  <span
40
38
  v-if="link"
41
39
  class="rounded-button"
42
40
  :class="[`bg-${data.color}`]"
43
41
  @click="$emit(EVENTS.OPEN_LINK, linkData)"
44
- data-bs-toggle="tooltip"
45
- data-bs-placement="top"
46
- :title="$t('open')"
47
42
  >
48
- <OpenInNew class="button-icon" alt="Open in new tab" />
43
+ <tooltip :title="$t('open')">
44
+ <OpenInNew class="button-icon" alt="Open in new tab" />
45
+ </tooltip>
49
46
  </span>
50
47
  <span
51
48
  v-if="expandable"
52
49
  class="rounded-button"
53
50
  :class="[`bg-${data.color}`]"
54
51
  @click="$emit(EVENTS.EXPAND)"
55
- data-bs-toggle="tooltip"
56
- data-bs-placement="top"
57
- :title="$t('expand')"
58
52
  >
59
- <ArrowExpand class="button-icon" alt="Expand task" />
53
+ <tooltip :title="$t('expand')">
54
+ <ArrowExpand class="button-icon" alt="Expand task" />
55
+ </tooltip>
60
56
  </span>
61
57
  <slot name="badge-button-after" />
62
58
  </div>
@@ -69,7 +65,7 @@
69
65
  import {EVENTS} from "../../utils/constants.js";
70
66
  import ArrowExpand from "vue-material-design-icons/ArrowExpand.vue";
71
67
  import OpenInNew from "vue-material-design-icons/OpenInNew.vue";
72
- import {Tooltip} from "bootstrap";
68
+ import Tooltip from "../misc/Tooltip.vue";
73
69
  import {VueFlowUtils} from "../../index.js";
74
70
  import {mapState} from "vuex";
75
71
 
@@ -78,24 +74,10 @@
78
74
  ArrowExpand,
79
75
  TaskIcon,
80
76
  InformationOutline,
81
- OpenInNew
82
- },
83
- mounted() {
84
- const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
85
- this.tooltips = tooltipTriggerList.map(function (tooltipTriggerEl) {
86
- return new Tooltip(tooltipTriggerEl, {
87
- trigger: "hover"
88
- })
89
- })
90
- },
91
- beforeUnmount() {
92
- document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
93
- const tooltip = Tooltip.getInstance(el);
94
- if (tooltip) {
95
- tooltip.dispose();
96
- }
97
- });
77
+ OpenInNew,
78
+ Tooltip
98
79
  },
80
+
99
81
  emits: [
100
82
  EVENTS.EXPAND,
101
83
  EVENTS.OPEN_LINK,
@@ -226,8 +208,12 @@
226
208
  align-items: center;
227
209
  box-shadow: 0 12px 12px 0 rgba(130, 103, 158, 0.10);
228
210
 
229
- &.execution-no-taskrun {
230
- opacity: 0.6;
211
+ &.execution-no-taskrun, &.disabled {
212
+ background-color: var(--bs-gray-200);
213
+
214
+ html.dark & {
215
+ background-color: var(--bs-gray-500);
216
+ }
231
217
  }
232
218
 
233
219
  &.disabled {
@@ -239,8 +225,13 @@
239
225
  color: var(--bs-gray-600);
240
226
  }
241
227
  }
228
+ }
242
229
 
243
- opacity: 0.4;
230
+ .icon {
231
+ margin: 0.2rem;
232
+ width: 25px;
233
+ height: 25px;
234
+ border: 0.4px solid var(--bs-border-color);
244
235
  }
245
236
  }
246
237
 
@@ -283,18 +274,13 @@
283
274
  font-size: 0.75rem;
284
275
  font-weight: 700;
285
276
  color: var(--bs-black);
277
+ flex-grow: 1;
286
278
 
287
279
  html.dark & {
288
280
  color: var(--bs-white);
289
281
  }
290
282
  }
291
283
 
292
- .top-button-div {
293
- width: 100%;
294
- justify-content: end;
295
- transform: translate(-5%, -50%) !important;
296
- }
297
-
298
284
  .status-div {
299
285
  width: 8px;
300
286
  height: 100%;
@@ -1,16 +1,16 @@
1
1
  <template>
2
2
  <span class="badge rounded-pill text-color" :class="[`bg-${data.color}`]">{{ id.replace("cluster_", "") }}</span>
3
- <div class="position-absolute top-0 start-100 translate-middle text-white d-flex">
3
+ <div class="top-button-div text-white d-flex">
4
4
  <span
5
5
  v-if="data.collapsable"
6
6
  class="rounded-button"
7
7
  :class="[`bg-${data.color}`]"
8
8
  @click="collapse()"
9
- data-bs-toggle="tooltip"
10
- data-bs-trigger="hover"
11
- :title="$t('collapse')"
9
+
12
10
  >
13
- <ArrowCollapse class="button-icon" alt="Collapse task"/>
11
+ <tooltip :title="$t('collapse')">
12
+ <ArrowCollapse class="button-icon" alt="Collapse task" />
13
+ </tooltip>
14
14
  </span>
15
15
  </div>
16
16
  </template>
@@ -27,31 +27,16 @@
27
27
 
28
28
  </script>
29
29
  <script>
30
- import {Tooltip} from "bootstrap";
30
+ import Tooltip from "../misc/Tooltip.vue";
31
31
 
32
32
  export default {
33
33
  inheritAttrs: false,
34
+ components: {Tooltip},
34
35
  data() {
35
36
  return {
36
37
  tooltips: [],
37
38
  }
38
39
  },
39
- mounted() {
40
- const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
41
- this.tooltips = tooltipTriggerList.map(function (tooltipTriggerEl) {
42
- return new Tooltip(tooltipTriggerEl, {
43
- placement: "top"
44
- })
45
- })
46
- },
47
- beforeUnmount() {
48
- document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
49
- const tooltip = Tooltip.getInstance(el);
50
- if (tooltip) {
51
- tooltip.dispose();
52
- }
53
- });
54
- }
55
40
  }
56
41
  </script>
57
42
  <style scoped lang="scss">
@@ -82,4 +67,11 @@
82
67
  padding: 0.25rem 0.5rem;
83
68
  }
84
69
 
70
+ .top-button-div {
71
+ transform: translate(-50%, -50%) !important;
72
+ left: 100% !important;
73
+ justify-content: center;
74
+ padding-right: 3px;
75
+ }
76
+
85
77
  </style>
@@ -5,7 +5,7 @@
5
5
  <component v-if="data.iconComponent" :is="data.iconComponent" :class="`text-${data.color} me-2`" />
6
6
  {{ id }}
7
7
  </span>
8
- <div class="position-absolute top-0 text-white d-flex top-button-div">
8
+ <div class="text-white top-button-div">
9
9
  <slot name="badge-button-before"/>
10
10
  <span
11
11
  v-if="expandable"
@@ -105,10 +105,4 @@
105
105
  font-size: 0.75rem;
106
106
  }
107
107
 
108
- .top-button-div {
109
- width: 100%;
110
- justify-content: end;
111
- transform: translate(-5%, -50%) !important;
112
- }
113
-
114
108
  </style>
@@ -4,48 +4,40 @@
4
4
  :class="[`border-${data.color}`]"
5
5
  class="dependency-node-wrapper rounded-3 border"
6
6
  >
7
- <TaskIcon color="pink" :custom-icon="{icon: icon}" />
7
+ <TaskIcon :custom-icon="{icon: icon}" class="bg-pink rounded" theme="light" />
8
8
  <div class="dependency-text d-flex flex-column">
9
- <div
10
- class="dependency-flow-text text-truncate"
11
- data-bs-toggle="tooltip"
12
- data-bs-placement="top"
13
- :title="data.flowId"
14
- >
15
- {{ data.flowId }}
9
+ <div class="dependency-flow-text text-truncate">
10
+ <tooltip :title="data.flowId">
11
+ {{ data.flowId }}
12
+ </tooltip>
16
13
  </div>
17
- <div
18
- class="dependency-namespace-text text-truncate"
19
- data-bs-toggle="tooltip"
20
- data-bs-placement="top"
21
- :title="data.namespace"
22
- >
23
- {{ data.namespace }}
14
+ <div class="dependency-namespace-text text-truncate">
15
+ <tooltip :title="data.namespace">
16
+ {{ data.namespace }}
17
+ </tooltip>
24
18
  </div>
25
19
  </div>
26
20
 
27
- <div class="position-absolute top-0 text-white d-flex top-button-div">
21
+ <div class="text-white top-button-div">
28
22
  <slot name="badge-button-before" />
29
23
  <span
30
24
  v-if="data.link"
31
25
  class="rounded-button"
32
26
  :class="[`bg-${data.color}`]"
33
27
  @click="$emit(EVENTS.OPEN_LINK, data)"
34
- data-bs-toggle="tooltip"
35
- data-bs-placement="top"
36
- :title="$t('open')"
37
28
  >
38
- <OpenInNew class="button-icon" alt="Open in new tab" />
29
+ <tooltip :title="$t('open')">
30
+ <OpenInNew class="button-icon" alt="Open in new tab" />
31
+ </tooltip>
39
32
  </span>
40
33
  <span
41
34
  class="rounded-button"
42
35
  :class="[`bg-${data.color}`]"
43
36
  @click="$emit(EVENTS.EXPAND_DEPENDENCIES, data)"
44
- data-bs-toggle="tooltip"
45
- data-bs-placement="top"
46
- :title="$t('expand')"
47
37
  >
48
- <ArrowExpandAll class="button-icon" alt="Expand task" />
38
+ <tooltip :title="$t('expand')">
39
+ <ArrowExpandAll class="button-icon" alt="Expand task" />
40
+ </tooltip>
49
41
  </span>
50
42
  <slot name="badge-button-after" />
51
43
  </div>
@@ -60,11 +52,11 @@
60
52
  import OpenInNew from "vue-material-design-icons/OpenInNew.vue";
61
53
  import ArrowExpandAll from "vue-material-design-icons/ArrowExpandAll.vue";
62
54
  import {EVENTS} from "../../utils/constants.js";
63
- import {Tooltip} from "bootstrap";
55
+ import Tooltip from "../misc/Tooltip.vue";
64
56
 
65
57
  export default {
66
58
  name: "Dependencies",
67
- components: {ArrowExpandAll, OpenInNew, TaskIcon, Handle},
59
+ components: {ArrowExpandAll, OpenInNew, TaskIcon, Handle, Tooltip},
68
60
  inheritAttrs: false,
69
61
  emits: [
70
62
  EVENTS.EXPAND_DEPENDENCIES,
@@ -72,22 +64,6 @@
72
64
  EVENTS.MOUSE_OVER,
73
65
  EVENTS.MOUSE_LEAVE,
74
66
  ],
75
- mounted() {
76
- const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
77
- this.tooltips = tooltipTriggerList.map(function (tooltipTriggerEl) {
78
- return new Tooltip(tooltipTriggerEl, {
79
- trigger: "hover"
80
- })
81
- })
82
- },
83
- beforeUnmount() {
84
- document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
85
- const tooltip = Tooltip.getInstance(el);
86
- if (tooltip) {
87
- tooltip.dispose();
88
- }
89
- });
90
- },
91
67
  computed: {
92
68
  EVENTS() {
93
69
  return EVENTS
@@ -159,11 +135,4 @@
159
135
  }
160
136
  }
161
137
 
162
- .top-button-div {
163
- width: 100%;
164
- justify-content: end;
165
- transform: translate(-5%, -50%) !important;
166
- }
167
-
168
-
169
138
  </style>
@@ -3,7 +3,7 @@
3
3
  import {EdgeLabelRenderer, getSmoothStepPath} from "@vue-flow/core";
4
4
  import AddTaskButton from "../buttons/AddTaskButton.vue";
5
5
  import {EVENTS} from "../../utils/constants.js";
6
- import {Tooltip} from "bootstrap";
6
+ import Tooltip from "../misc/Tooltip.vue";
7
7
 
8
8
  export default {
9
9
  data() {
@@ -24,12 +24,19 @@
24
24
  },
25
25
  components: {
26
26
  AddTaskButton,
27
- EdgeLabelRenderer
27
+ EdgeLabelRenderer,
28
+ Tooltip
28
29
  },
29
30
  computed: {
30
31
  EVENTS() {
31
32
  return EVENTS
32
33
  },
34
+ classes() {
35
+ return {
36
+ "vue-flow__edge-path": true,
37
+ ["stroke-" + this.data.color]: this.data.color,
38
+ }
39
+ },
33
40
  },
34
41
  setup(props) {
35
42
  const path = computed(() => getSmoothStepPath(props));
@@ -38,22 +45,6 @@
38
45
  path,
39
46
  };
40
47
  },
41
- mounted(){
42
- const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
43
- this.tooltips = tooltipTriggerList.map(function (tooltipTriggerEl) {
44
- return new Tooltip(tooltipTriggerEl, {
45
- trigger : "hover"
46
- })
47
- })
48
- },
49
- beforeUnmount() {
50
- document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
51
- const tooltip = Tooltip.getInstance(el);
52
- if (tooltip) {
53
- tooltip.dispose();
54
- }
55
- });
56
- },
57
48
  inheritAttrs: false,
58
49
  };
59
50
  </script>
@@ -79,14 +70,14 @@
79
70
  transform: `translate(-50%, -50%) translate(${path[1]}px,${path[2]}px)`,
80
71
  }"
81
72
  >
82
- <AddTaskButton
83
- v-if="!data.disabled && data.haveAdd != undefined"
84
- :add-task="true"
85
- @click="$emit(EVENTS.ADD_TASK, data.haveAdd)"
86
- data-bs-toggle="tooltip"
87
- data-bs-placement="top"
88
- :title="$t('add task')"
89
- />
73
+ <tooltip :title="$t('add task')">
74
+ <AddTaskButton
75
+ v-if="!data.disabled && data.haveAdd != undefined"
76
+ :add-task="true"
77
+ @click="$emit(EVENTS.ADD_TASK, data.haveAdd)"
78
+ />
79
+ </tooltip>
80
+
90
81
  </div>
91
82
  </EdgeLabelRenderer>
92
- </template>
83
+ </template>
@@ -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"
@@ -12,7 +12,7 @@
12
12
  @mouseleave="forwardEvent(EVENTS.MOUSE_LEAVE)"
13
13
  >
14
14
  <template #content>
15
- <execution-informations v-if="execution" :execution="execution" :task="data.node.task" :color="color"/>
15
+ <execution-informations v-if="execution" :execution="execution" :task="data.node.task" :color="color" />
16
16
  </template>
17
17
  <template #badge-button-before>
18
18
  <span
@@ -20,48 +20,44 @@
20
20
  class="rounded-button"
21
21
  :class="[`bg-${color}`]"
22
22
  @click="$emit(EVENTS.SHOW_LOGS, {id, taskRuns})"
23
- data-bs-toggle="tooltip"
24
- data-bs-placement="top"
25
- :title="$t('show task logs')"
26
23
  >
27
- <TextBoxSearch class="button-icon" alt="Show logs"/>
24
+ <tooltip :title="$t('show task logs')">
25
+ <TextBoxSearch class="button-icon" alt="Show logs" />
26
+ </tooltip>
28
27
  </span>
29
28
  <span
30
29
  v-if="!execution && !data.isReadOnly && data.isFlowable"
31
30
  class="rounded-button"
32
31
  :class="[`bg-${color}`]"
33
32
  @click="$emit(EVENTS.ADD_ERROR, {task: data.node.task})"
34
- data-bs-toggle="tooltip"
35
- data-bs-placement="top"
36
- :title="$t('add error handler')"
37
33
  >
38
- <AlertOutline class="button-icon" alt="Edit task"/>
34
+ <tooltip :title="$t('add error handler')">
35
+ <AlertOutline class="button-icon" alt="Edit task" />
36
+ </tooltip>
39
37
  </span>
40
38
  <span
41
39
  v-if="!execution && !data.isReadOnly"
42
40
  class="rounded-button"
43
41
  :class="[`bg-${color}`]"
44
42
  @click="$emit(EVENTS.EDIT, {task: data.node.task, section: SECTIONS.TASKS})"
45
- data-bs-toggle="tooltip"
46
- data-bs-placement="top"
47
- :title="$t('edit')"
48
43
  >
49
- <Pencil class="button-icon" alt="Edit task"/>
44
+ <tooltip :title="$t('edit')">
45
+ <Pencil class="button-icon" alt="Edit task" />
46
+ </tooltip>
50
47
  </span>
51
48
  <span
52
49
  v-if="!execution && !data.isReadOnly"
53
50
  class="rounded-button"
54
51
  :class="[`bg-${color}`]"
55
52
  @click="$emit(EVENTS.DELETE, {id, section: SECTIONS.TASKS})"
56
- data-bs-toggle="tooltip"
57
- data-bs-placement="top"
58
- :title="$t('delete')"
59
53
  >
60
- <Delete class="button-icon" alt="Delete task"/>
54
+ <tooltip :title="$t('delete')">
55
+ <Delete class="button-icon" alt="Delete task" />
56
+ </tooltip>
61
57
  </span>
62
58
  </template>
63
59
  </basic-node>
64
- <Handle type="target" :position="targetPosition"/>
60
+ <Handle type="target" :position="targetPosition" />
65
61
  </template>
66
62
  <script setup>
67
63
  import BasicNode from "./BasicNode.vue";
@@ -76,7 +72,7 @@
76
72
  import TextBoxSearch from "vue-material-design-icons/TextBoxSearch.vue";
77
73
  import AlertOutline from "vue-material-design-icons/AlertOutline.vue"
78
74
  import {mapState} from "vuex";
79
- import {Tooltip} from "bootstrap"
75
+ import Tooltip from "../misc/Tooltip.vue"
80
76
 
81
77
  export default {
82
78
  name: "Task",
@@ -87,22 +83,9 @@
87
83
  Handle,
88
84
  TextBoxSearch,
89
85
  AlertOutline,
86
+ Tooltip
90
87
  },
91
88
  inheritAttrs: false,
92
- mounted(){
93
- const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
94
- tooltipTriggerList.map(function (tooltipTriggerEl) {
95
- return new Tooltip(tooltipTriggerEl)
96
- })
97
- },
98
- beforeUnmount() {
99
- document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
100
- const tooltip = Tooltip.getInstance(el);
101
- if (tooltip) {
102
- tooltip.dispose();
103
- }
104
- });
105
- },
106
89
  computed: {
107
90
  ...mapState("execution", ["execution"]),
108
91
  SECTIONS() {
@@ -13,22 +13,20 @@
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')"
19
16
  >
20
- <Pencil class="button-icon" alt="Edit task" />
17
+ <tooltip :title="$t('edit')">
18
+ <Pencil class="button-icon" alt="Edit task" />
19
+ </tooltip>
21
20
  </span>
22
21
  <span
23
22
  v-if="!execution && !data.isReadOnly"
24
23
  class="rounded-button"
25
24
  :class="[`bg-${color}`]"
26
25
  @click="$emit(EVENTS.DELETE, {id, section: SECTIONS.TRIGGERS})"
27
- data-bs-toggle="tooltip"
28
- data-bs-placement="top"
29
- :title="$t('delete')"
30
26
  >
31
- <Delete class="button-icon" alt="Delete task" />
27
+ <tooltip :title="$t('delete')">
28
+ <Delete class="button-icon" alt="Delete task" />
29
+ </tooltip>
32
30
  </span>
33
31
  </template>
34
32
  </basic-node>
@@ -43,27 +41,11 @@
43
41
  import {EVENTS, SECTIONS} from "../../utils/constants.js";
44
42
  import Pencil from "vue-material-design-icons/Pencil.vue";
45
43
  import Delete from "vue-material-design-icons/Delete.vue";
46
- import {Tooltip} from "bootstrap";
44
+ import Tooltip from "../misc/Tooltip.vue";
47
45
 
48
46
  export default {
49
47
  name: "Task",
50
48
  inheritAttrs: false,
51
- mounted(){
52
- const tooltipTriggerList = [].slice.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"));
53
- this.tooltips = tooltipTriggerList.map(function (tooltipTriggerEl) {
54
- return new Tooltip(tooltipTriggerEl, {
55
- trigger : "hover"
56
- })
57
- })
58
- },
59
- beforeUnmount() {
60
- document.querySelectorAll("[data-bs-toggle=\"tooltip\"]").forEach((el) => {
61
- const tooltip = Tooltip.getInstance(el);
62
- if (tooltip) {
63
- tooltip.dispose();
64
- }
65
- });
66
- },
67
49
  computed: {
68
50
  ...mapState("execution", ["execution"]),
69
51
  SECTIONS() {
@@ -82,8 +64,7 @@
82
64
  EVENTS.SHOW_DESCRIPTION
83
65
  ],
84
66
  components: {
85
- Delete, Pencil,
86
- Handle,
67
+ Delete, Pencil, Handle, Tooltip
87
68
  },
88
69
  props: {
89
70
  data: {
@@ -1,8 +1,8 @@
1
1
  <script setup>
2
2
  import {
3
3
  ref,
4
- defineProps,
5
- defineEmits, watch, nextTick,
4
+ watch,
5
+ nextTick,
6
6
  onMounted
7
7
  } from "vue";
8
8
  import {
@@ -279,6 +279,9 @@
279
279
  const flowables = () => {
280
280
  return props.flowGraph && props.flowGraph.flowables ? props.flowGraph.flowables : [];
281
281
  }
282
+
283
+ const darkTheme = document.getElementsByTagName("html")[0].className.indexOf("dark") >= 0;
284
+
282
285
  </script>
283
286
  <template>
284
287
  <VueFlow
@@ -290,7 +293,8 @@
290
293
  :elevate-nodes-on-select="false"
291
294
  :elevate-edges-on-select="false"
292
295
  >
293
- <Background />
296
+ <Background :pattern-color="darkTheme ? cssVariable('--bs-grey-500') : cssVariable('--bs-grey-300')" />
297
+
294
298
  <template #node-cluster="clusterProps">
295
299
  <ClusterNode
296
300
  v-bind="clusterProps"
package/src/scss/app.scss CHANGED
@@ -4,27 +4,6 @@
4
4
  bottom: 0;
5
5
  }
6
6
 
7
- .vue-flow__node-cluster {
8
- pointer-events: none !important;
9
- }
10
-
11
- marker[id*='id=marker-custom&type=arrowclosed'] polyline {
12
- stroke: $gray-700;
13
- fill: $gray-700;
14
- }
15
-
16
- marker[id*='id=marker-danger&type=arrowclosed'] polyline {
17
- stroke: $danger;
18
- fill: $danger;
19
- }
20
-
21
- .vue-flow__handle {
22
- opacity: 0 !important;
23
- }
24
-
25
- .vue-flow__edge-path {
26
- stroke: #9A8EB4;
27
- }
28
7
 
29
8
  .rounded-button {
30
9
  border-radius: 1rem;
@@ -41,4 +20,36 @@ marker[id*='id=marker-danger&type=arrowclosed'] polyline {
41
20
  font-size: 0.66rem;
42
21
  }
43
22
 
23
+ .vue-flow__container {
24
+ .top-button-div {
25
+ position: absolute;
26
+ top: 0;
27
+ width: 100%;
28
+ justify-content: end;
29
+ display: flex;
30
+ right: -16px;
31
+ transform: translate(-5%, -50%) !important;
32
+ }
33
+
34
+ .vue-flow__node-cluster {
35
+ pointer-events: none !important;
36
+ }
37
+
38
+ marker[id*='id=marker-custom&type=arrowclosed'] polyline {
39
+ stroke: #9A8EB4;
40
+ fill: #9A8EB4;
41
+ }
44
42
 
43
+ marker[id*='id=marker-danger&type=arrowclosed'] polyline {
44
+ stroke: #9A8EB4;
45
+ fill: #9A8EB4;
46
+ }
47
+
48
+ .vue-flow__handle {
49
+ opacity: 0 !important;
50
+ }
51
+
52
+ .vue-flow__edge-path {
53
+ stroke: #9A8EB4;
54
+ }
55
+ }