@appscode/design-system 1.1.0-alpha.2 → 1.1.0-alpha.20
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/base/utilities/_all.scss +1 -0
- package/base/utilities/_extended.scss +38 -0
- package/base/utilities/_initial-variables.scss +1 -1
- package/components/_ac-alert-box.scss +1 -2
- package/components/_all.scss +1 -0
- package/components/_basic-card.scss +118 -0
- package/components/ui-builder/_ui-builder.scss +7 -1
- package/package.json +1 -1
- package/vue-components/v2/content/ContentTable.vue +14 -9
- package/vue-components/v2/modal/Modal.vue +6 -5
- package/vue-components/v2/table/Table.vue +5 -0
- package/vue-components/v3/cards/FeatureCard.vue +40 -0
- package/vue-components/v3/cards/FeatureCards.vue +5 -0
- package/vue-components/v3/cards/ResourceCard.vue +27 -0
- package/vue-components/v3/cards/ResourceCardBody.vue +6 -0
- package/vue-components/v3/cards/ResourceCards.vue +5 -0
- package/vue-components/v3/content/ContentTable.vue +5 -0
- package/vue-components/v3/modal/Modal.vue +5 -0
- package/vue-components/v3/modals/LongRunningTasksModal.vue +52 -25
- package/vue-components/v3/notification/AlertBox.vue +61 -0
- package/vue-components/v3/table/Table.vue +5 -0
package/base/utilities/_all.scss
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
.has-hover-style{
|
|
2
|
+
cursor: pointer;
|
|
3
|
+
|
|
4
|
+
&::before {
|
|
5
|
+
content: "";
|
|
6
|
+
position: absolute;
|
|
7
|
+
top: 0;
|
|
8
|
+
right: 0;
|
|
9
|
+
bottom: 0;
|
|
10
|
+
left: 0;
|
|
11
|
+
border-top: solid 1px;
|
|
12
|
+
border-bottom: solid 1px;
|
|
13
|
+
transition: 0.3s;
|
|
14
|
+
transform: scaleX(0);
|
|
15
|
+
border-color: #1971bd;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
&::after {
|
|
19
|
+
content: "";
|
|
20
|
+
position: absolute;
|
|
21
|
+
top: 0;
|
|
22
|
+
right: 0;
|
|
23
|
+
bottom: 0;
|
|
24
|
+
left: 0;
|
|
25
|
+
border-left: solid 1px;
|
|
26
|
+
border-right: solid 1px;
|
|
27
|
+
transition: 0.3s;
|
|
28
|
+
transform: scaleY(0);
|
|
29
|
+
border-color: #1971bd;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&:hover {
|
|
33
|
+
&::before,
|
|
34
|
+
&::after {
|
|
35
|
+
transform: scale(1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
justify-content: flex-start;
|
|
14
14
|
position: relative;
|
|
15
15
|
z-index: 1;
|
|
16
|
-
|
|
16
|
+
justify-content: flex-start;
|
|
17
17
|
|
|
18
18
|
p {
|
|
19
19
|
color: $ac-primary;
|
|
@@ -55,7 +55,6 @@
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
59
58
|
.toast {
|
|
60
59
|
box-shadow: $ac-shadow-sm;
|
|
61
60
|
border: 1px solid $ac-white-light;
|
package/components/_all.scss
CHANGED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
.card-details {
|
|
2
|
+
border: 1px solid #d2e7f9;
|
|
3
|
+
padding: 30px 20px;
|
|
4
|
+
width: calc(33.3% - 8px);
|
|
5
|
+
min-width: 400px;
|
|
6
|
+
max-width: 525px;
|
|
7
|
+
// border-radius: 4px;
|
|
8
|
+
transition: 0.3s ease-in-out;
|
|
9
|
+
position: relative;
|
|
10
|
+
z-index: 1;
|
|
11
|
+
|
|
12
|
+
.c-header {
|
|
13
|
+
display: flex;
|
|
14
|
+
margin-bottom: 20px;
|
|
15
|
+
|
|
16
|
+
.c-logo {
|
|
17
|
+
width: 54px;
|
|
18
|
+
height: 54px;
|
|
19
|
+
background: #e8f3fc;
|
|
20
|
+
border-radius: 50%;
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
margin-right: 24px;
|
|
25
|
+
|
|
26
|
+
img {
|
|
27
|
+
height: 24px;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.c-content {
|
|
32
|
+
width: calc(100% - 78px);
|
|
33
|
+
h4 {
|
|
34
|
+
font-size: 18px;
|
|
35
|
+
line-height: 130%;
|
|
36
|
+
color: #030d17;
|
|
37
|
+
}
|
|
38
|
+
.icon {
|
|
39
|
+
color: #0c365a;
|
|
40
|
+
cursor: pointer;
|
|
41
|
+
position: relative;
|
|
42
|
+
z-index: 1;
|
|
43
|
+
&:after {
|
|
44
|
+
position: absolute;
|
|
45
|
+
content: "";
|
|
46
|
+
border-radius: 50%;
|
|
47
|
+
width: 32px;
|
|
48
|
+
height: 32px;
|
|
49
|
+
background: #e8f3fc;
|
|
50
|
+
opacity: 0;
|
|
51
|
+
visibility: hidden;
|
|
52
|
+
transition: 0.3s ease-in-out;
|
|
53
|
+
z-index: -1;
|
|
54
|
+
}
|
|
55
|
+
&:hover {
|
|
56
|
+
&:after {
|
|
57
|
+
opacity: 1;
|
|
58
|
+
visibility: visible;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
.tags {
|
|
63
|
+
margin-top: 12px;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.c-body {
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-wrap: wrap;
|
|
71
|
+
gap: 20px;
|
|
72
|
+
justify-content: space-between;
|
|
73
|
+
p {
|
|
74
|
+
width: calc(25% - 16px);
|
|
75
|
+
|
|
76
|
+
span {
|
|
77
|
+
font-size: 11px;
|
|
78
|
+
color: #666666;
|
|
79
|
+
display: block;
|
|
80
|
+
}
|
|
81
|
+
strong {
|
|
82
|
+
color: #061b2d;
|
|
83
|
+
font-size: 13px;
|
|
84
|
+
font-weight: 400;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ac card
|
|
91
|
+
.card-basic {
|
|
92
|
+
padding: 20px;
|
|
93
|
+
width: calc(25% - 8px);
|
|
94
|
+
max-width: 390px;
|
|
95
|
+
min-width: 290px;
|
|
96
|
+
position: relative;
|
|
97
|
+
|
|
98
|
+
.required {
|
|
99
|
+
position: absolute;
|
|
100
|
+
left: 20px;
|
|
101
|
+
top: -9px;
|
|
102
|
+
}
|
|
103
|
+
.c-header {
|
|
104
|
+
.c-title {
|
|
105
|
+
|
|
106
|
+
h4 {
|
|
107
|
+
font-size: 18px;
|
|
108
|
+
color: #061b2d;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.c-body {
|
|
114
|
+
p {
|
|
115
|
+
color: #0C365A;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
margin-bottom: 10px;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
p {
|
|
20
|
+
p :not(.ac-notification *){
|
|
21
21
|
font-size: 13px;
|
|
22
22
|
margin-bottom: 10px;
|
|
23
23
|
color: $ac-color-value;
|
|
@@ -237,6 +237,12 @@
|
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
.pass-strength {
|
|
241
|
+
position: absolute;
|
|
242
|
+
right: 30px;
|
|
243
|
+
top: 7px;
|
|
244
|
+
}
|
|
245
|
+
|
|
240
246
|
// dark theme end
|
|
241
247
|
/****************************************
|
|
242
248
|
Responsive Classes
|
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
v-if="!hideHeader"
|
|
6
6
|
:header-title="tableTitle"
|
|
7
7
|
:header-sub-title="tableSubTitle"
|
|
8
|
+
:remove-border-bottom="removeBorderBottom"
|
|
8
9
|
:class="{ 'pl-0 pr-0': removeTableHeaderPadding }"
|
|
9
10
|
>
|
|
10
11
|
<header-item>
|
|
@@ -22,36 +23,40 @@ export default {
|
|
|
22
23
|
props: {
|
|
23
24
|
removeTableHeaderPadding: {
|
|
24
25
|
type: Boolean,
|
|
25
|
-
default: false
|
|
26
|
+
default: false,
|
|
26
27
|
},
|
|
27
28
|
tableTitle: {
|
|
28
29
|
type: String,
|
|
29
|
-
default: "Table"
|
|
30
|
+
default: "Table",
|
|
30
31
|
},
|
|
31
32
|
tableSubTitle: {
|
|
32
33
|
type: String,
|
|
33
|
-
default: ""
|
|
34
|
+
default: "",
|
|
34
35
|
},
|
|
35
36
|
searchable: {
|
|
36
37
|
type: Boolean,
|
|
37
|
-
default: true
|
|
38
|
+
default: true,
|
|
38
39
|
},
|
|
39
40
|
hideHeader: {
|
|
40
41
|
type: Boolean,
|
|
41
|
-
default: false
|
|
42
|
-
}
|
|
42
|
+
default: false,
|
|
43
|
+
},
|
|
44
|
+
removeBorderBottom: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
default: false,
|
|
47
|
+
},
|
|
43
48
|
},
|
|
44
49
|
components: {
|
|
45
50
|
ContentLayout: () => import("./ContentLayout.vue"),
|
|
46
51
|
ContentHeader: () => import("./ContentHeader.vue"),
|
|
47
52
|
HeaderItem: () => import("../header/HeaderItem.vue"),
|
|
48
|
-
SearchBar: () => import("../searchbars/SearchBar.vue")
|
|
53
|
+
SearchBar: () => import("../searchbars/SearchBar.vue"),
|
|
49
54
|
},
|
|
50
55
|
|
|
51
56
|
data() {
|
|
52
57
|
return {
|
|
53
|
-
searchText: ""
|
|
58
|
+
searchText: "",
|
|
54
59
|
};
|
|
55
|
-
}
|
|
60
|
+
},
|
|
56
61
|
};
|
|
57
62
|
</script>
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
<!-- modal body start -->
|
|
33
33
|
<div
|
|
34
34
|
class="ac-modal-body ac-vscrollbar"
|
|
35
|
+
:class="modifierBodyClasses"
|
|
35
36
|
data-testid="ac-modal-content-with-scroll"
|
|
36
37
|
>
|
|
37
38
|
<div class="ac-modal-content">
|
|
@@ -45,11 +46,7 @@
|
|
|
45
46
|
<!-- modal footer start -->
|
|
46
47
|
<div
|
|
47
48
|
v-if="!hideActionFooter"
|
|
48
|
-
class="
|
|
49
|
-
ac-modal-footer
|
|
50
|
-
action-footer
|
|
51
|
-
is-flex is-align-items-center is-justify-content-space-between
|
|
52
|
-
"
|
|
49
|
+
class="ac-modal-footer action-footer is-flex is-align-items-center is-justify-content-space-between"
|
|
53
50
|
>
|
|
54
51
|
<div>
|
|
55
52
|
<slot name="modal-footer-left" />
|
|
@@ -91,6 +88,10 @@ export default {
|
|
|
91
88
|
type: Boolean,
|
|
92
89
|
default: false,
|
|
93
90
|
},
|
|
91
|
+
modifierBodyClasses: {
|
|
92
|
+
type: String,
|
|
93
|
+
default: "",
|
|
94
|
+
},
|
|
94
95
|
},
|
|
95
96
|
|
|
96
97
|
components: {
|
|
@@ -110,6 +110,11 @@
|
|
|
110
110
|
</tbody>
|
|
111
111
|
</template>
|
|
112
112
|
</table>
|
|
113
|
+
|
|
114
|
+
<!-- table footer info start -->
|
|
115
|
+
<slot name="table-footer-info" />
|
|
116
|
+
<!-- table footer info end -->
|
|
117
|
+
|
|
113
118
|
<!-- pagination start -->
|
|
114
119
|
<slot name="table-pagination" />
|
|
115
120
|
<!-- pagination end -->
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- single card wrapper start -->
|
|
3
|
+
<div class="card-basic b-1">
|
|
4
|
+
<div class="c-header is-flex is-justify-content-space-between">
|
|
5
|
+
<div
|
|
6
|
+
v-if="isRequired"
|
|
7
|
+
class="tag has-background-warning has-text-secondary is-rounded required"
|
|
8
|
+
>
|
|
9
|
+
Required
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div class="c-title is-flex is-align-items-center">
|
|
13
|
+
<div class="icon mr-8">
|
|
14
|
+
<slot name="card-logo" />
|
|
15
|
+
</div>
|
|
16
|
+
<h4><slot name="card-title" /></h4>
|
|
17
|
+
</div>
|
|
18
|
+
<!-- <span class="tag has-background-dark-light has-text-dark is-rounded"
|
|
19
|
+
>Dark</span
|
|
20
|
+
> -->
|
|
21
|
+
<slot name="card-status" />
|
|
22
|
+
</div>
|
|
23
|
+
<div class="c-body">
|
|
24
|
+
<p><slot name="card-sub-title" /></p>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
<!-- single card wrapper end -->
|
|
28
|
+
</template>
|
|
29
|
+
<script setup lang="ts">
|
|
30
|
+
withDefaults(
|
|
31
|
+
defineProps<{
|
|
32
|
+
isRequired: boolean
|
|
33
|
+
statusClass: string
|
|
34
|
+
}>(),
|
|
35
|
+
{
|
|
36
|
+
isRequired: false,
|
|
37
|
+
statusClass: 'has-background-primary-light has-text-primary',
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
</script>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const { hasOptionButtons } = withDefaults(
|
|
3
|
+
defineProps<{ hasOptionButtons: boolean }>(),
|
|
4
|
+
{ hasOptionButtons: false }
|
|
5
|
+
)
|
|
6
|
+
</script>
|
|
7
|
+
<template>
|
|
8
|
+
<div class="card-details">
|
|
9
|
+
<div class="c-header">
|
|
10
|
+
<div class="c-logo">
|
|
11
|
+
<slot name="card-logo" />
|
|
12
|
+
</div>
|
|
13
|
+
<div class="c-content">
|
|
14
|
+
<div class="is-flex is-justify-content-space-between">
|
|
15
|
+
<h4><slot name="card-title" /></h4>
|
|
16
|
+
<slot v-if="hasOptionButtons" name="option-buttons" />
|
|
17
|
+
</div>
|
|
18
|
+
<div class="tags">
|
|
19
|
+
<slot name="card-tags" />
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="c-body">
|
|
24
|
+
<slot name="card-body" />
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
v-if="!hideHeader"
|
|
6
6
|
:header-title="tableTitle"
|
|
7
7
|
:header-sub-title="tableSubTitle"
|
|
8
|
+
:remove-border-bottom="removeBorderBottom"
|
|
8
9
|
:class="{ 'pl-0 pr-0': removeTableHeaderPadding }"
|
|
9
10
|
>
|
|
10
11
|
<template #title-right-actions>
|
|
@@ -50,6 +51,10 @@ export default defineComponent({
|
|
|
50
51
|
type: Boolean,
|
|
51
52
|
default: false,
|
|
52
53
|
},
|
|
54
|
+
removeBorderBottom: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
default: false,
|
|
57
|
+
},
|
|
53
58
|
},
|
|
54
59
|
components: {
|
|
55
60
|
ContentLayout: defineAsyncComponent(() =>
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
<!-- modal body start -->
|
|
31
31
|
<div
|
|
32
32
|
class="ac-modal-body ac-vscrollbar"
|
|
33
|
+
:class="modifierBodyClasses"
|
|
33
34
|
data-testid="ac-modal-content-with-scroll"
|
|
34
35
|
>
|
|
35
36
|
<div class="ac-modal-content">
|
|
@@ -92,6 +93,10 @@ export default defineComponent({
|
|
|
92
93
|
type: Boolean,
|
|
93
94
|
default: false,
|
|
94
95
|
},
|
|
96
|
+
modifierBodyClasses: {
|
|
97
|
+
type: String,
|
|
98
|
+
default: "",
|
|
99
|
+
},
|
|
95
100
|
},
|
|
96
101
|
emits: ["closemodal"],
|
|
97
102
|
|
|
@@ -110,7 +110,6 @@ import {
|
|
|
110
110
|
Ref,
|
|
111
111
|
toRefs,
|
|
112
112
|
watch,
|
|
113
|
-
watchEffect,
|
|
114
113
|
} from "vue";
|
|
115
114
|
import { defineAsyncComponent, ref } from "vue";
|
|
116
115
|
import { Task, TaskLog } from "../../../typings/long-running-tasks.ts";
|
|
@@ -173,7 +172,7 @@ const activeStepId: Ref<string> = ref("");
|
|
|
173
172
|
// to find active task faster
|
|
174
173
|
const idToStepIndex: Ref<Record<string, number>> = ref({});
|
|
175
174
|
const activeTask = computed(() => {
|
|
176
|
-
const task = tasks.value.
|
|
175
|
+
const task = tasks.value[idToStepIndex.value[activeStepId.value]];
|
|
177
176
|
return task;
|
|
178
177
|
});
|
|
179
178
|
|
|
@@ -207,6 +206,7 @@ function handleTaskLog(log: TaskLog) {
|
|
|
207
206
|
task.status = log.status;
|
|
208
207
|
if (log.status === "Failed") {
|
|
209
208
|
task.logs.push(log.error || "");
|
|
209
|
+
errorCtx.value?.onError(log.error);
|
|
210
210
|
} else {
|
|
211
211
|
task.logs.push(log.msg || "");
|
|
212
212
|
}
|
|
@@ -252,12 +252,36 @@ onBeforeUnmount(() => {
|
|
|
252
252
|
subscription && subscription.unsubscribe();
|
|
253
253
|
});
|
|
254
254
|
|
|
255
|
+
const longRunningTaskStatus = computed(() => {
|
|
256
|
+
let successTaskCount = 0;
|
|
257
|
+
let failedTaskCount = 0;
|
|
258
|
+
|
|
259
|
+
// get count of success and failed task
|
|
260
|
+
tasks.value.forEach((task) => {
|
|
261
|
+
if (task?.status === "Success") successTaskCount++;
|
|
262
|
+
else if (task?.status === "Failed") failedTaskCount++;
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
if (tasks.value.length === 0) return "NotStarted";
|
|
266
|
+
// if all the task has been successful
|
|
267
|
+
else if (successTaskCount === tasks.value.length) {
|
|
268
|
+
return "Success";
|
|
269
|
+
}
|
|
270
|
+
// if all the task has been completed and some tasks are failed
|
|
271
|
+
else if (
|
|
272
|
+
failedTaskCount &&
|
|
273
|
+
successTaskCount + failedTaskCount === tasks.value.length
|
|
274
|
+
) {
|
|
275
|
+
return "Failed";
|
|
276
|
+
} else return "Pending";
|
|
277
|
+
});
|
|
278
|
+
|
|
255
279
|
// modal close / footer feature
|
|
256
280
|
const enableModalClose = computed(() => {
|
|
257
281
|
return (
|
|
258
282
|
connectionError.value ||
|
|
259
|
-
|
|
260
|
-
|
|
283
|
+
longRunningTaskStatus.value === "Failed" ||
|
|
284
|
+
longRunningTaskStatus.value === "Success"
|
|
261
285
|
);
|
|
262
286
|
});
|
|
263
287
|
const enableModalFooter = computed(() => {
|
|
@@ -265,47 +289,50 @@ const enableModalFooter = computed(() => {
|
|
|
265
289
|
});
|
|
266
290
|
|
|
267
291
|
// generate report issue title with error step title
|
|
268
|
-
const
|
|
292
|
+
const getReportIssueInfo = (): { title: string; body: string } => {
|
|
269
293
|
const stepTitlesFromErrorTasks: Array<string> = [];
|
|
294
|
+
const stepLogsFromErrorTasks: Array<string> = [];
|
|
270
295
|
tasks.value.forEach((task) => {
|
|
271
296
|
// if this taskLog is error task, push it to array
|
|
272
297
|
if (task.error) {
|
|
273
|
-
stepTitlesFromErrorTasks.push(task
|
|
298
|
+
stepTitlesFromErrorTasks.push(task?.step);
|
|
299
|
+
stepLogsFromErrorTasks.push(task?.logs[task?.logs?.length - 1] || "");
|
|
274
300
|
}
|
|
275
301
|
});
|
|
276
|
-
// return final
|
|
277
|
-
return
|
|
302
|
+
// return final object
|
|
303
|
+
return {
|
|
304
|
+
title: stepTitlesFromErrorTasks.join(", "),
|
|
305
|
+
body: stepLogsFromErrorTasks.join(", "),
|
|
306
|
+
};
|
|
278
307
|
};
|
|
279
308
|
|
|
280
309
|
// report button
|
|
281
|
-
const showReportButton = computed(
|
|
310
|
+
const showReportButton = computed(
|
|
311
|
+
() => longRunningTaskStatus.value === "Failed"
|
|
312
|
+
);
|
|
282
313
|
function onReportIssueClick() {
|
|
283
|
-
const url = `https://github.com/bytebuilders/community/issues/new?title=Chart Install: ${
|
|
284
|
-
|
|
285
|
-
} %0A%0A %60%60%60 %0A ${
|
|
286
|
-
|
|
314
|
+
const url = `https://github.com/bytebuilders/community/issues/new?title=Chart Install: ${
|
|
315
|
+
getReportIssueInfo().title
|
|
316
|
+
}&labels[]=bug&body=${window.location.href} %0A%0A %60%60%60 %0A ${
|
|
317
|
+
getReportIssueInfo().body
|
|
287
318
|
} %0A %60%60%60`;
|
|
288
319
|
window.open(url, "_blank");
|
|
289
320
|
}
|
|
290
321
|
|
|
291
322
|
// success button
|
|
292
323
|
const showSuccessButton = computed(
|
|
293
|
-
() =>
|
|
324
|
+
() =>
|
|
325
|
+
longRunningTaskStatus.value === "Success" && !!successCtx.value?.btnTitle
|
|
294
326
|
);
|
|
295
327
|
|
|
296
328
|
// execute on success and on error functions
|
|
297
|
-
watch(
|
|
298
|
-
()
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
} else if (n === "Failed") {
|
|
303
|
-
errorCtx.value.onError(
|
|
304
|
-
activeTask.value?.logs[activeTask.value?.logs.length - 1 || 0] || ""
|
|
305
|
-
);
|
|
306
|
-
}
|
|
329
|
+
watch(longRunningTaskStatus, (n) => {
|
|
330
|
+
if (n === "Success") {
|
|
331
|
+
successCtx.value.onSuccess();
|
|
332
|
+
} else if (n === "Failed") {
|
|
333
|
+
errorCtx.value?.onError("Operation Failed");
|
|
307
334
|
}
|
|
308
|
-
);
|
|
335
|
+
});
|
|
309
336
|
</script>
|
|
310
337
|
|
|
311
338
|
<style scoped lang="scss">
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- alert-message area start -->
|
|
3
|
+
<!-- plsease, use this class name ('.is-info' 'is-success', 'is-error', 'is-warning') -->
|
|
4
|
+
<div :class="`ac-notification is-${notificationType} mb-15`">
|
|
5
|
+
<p>
|
|
6
|
+
<i v-if="!hideIcon" :class="`fa ${iconClass} mr-5`"></i
|
|
7
|
+
><span v-html="getSanitizedHtml(content)"></span>
|
|
8
|
+
<ac-button
|
|
9
|
+
v-if="actionButton?.show"
|
|
10
|
+
:title="actionButton?.title"
|
|
11
|
+
:icon-class="actionButton?.iconClass"
|
|
12
|
+
data-testid="notification-action-button"
|
|
13
|
+
@click.prevent="actionButton?.action()"
|
|
14
|
+
>
|
|
15
|
+
</ac-button>
|
|
16
|
+
</p>
|
|
17
|
+
</div>
|
|
18
|
+
<!-- alert-message area end -->
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script setup lang="ts">
|
|
22
|
+
import { toRefs, computed, defineAsyncComponent } from "vue";
|
|
23
|
+
import DOMPurify from "dompurify";
|
|
24
|
+
|
|
25
|
+
const AcButton = defineAsyncComponent(
|
|
26
|
+
() => import("@appscode/design-system/vue-components/v3/button/Button.vue")
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const props = withDefaults(
|
|
30
|
+
defineProps<{
|
|
31
|
+
notificationType: string;
|
|
32
|
+
content: string;
|
|
33
|
+
hideIcon: boolean;
|
|
34
|
+
actionButton?: {
|
|
35
|
+
show: boolean;
|
|
36
|
+
title: string;
|
|
37
|
+
iconClass: string;
|
|
38
|
+
action: (...args: any) => void | undefined;
|
|
39
|
+
};
|
|
40
|
+
}>(),
|
|
41
|
+
{
|
|
42
|
+
notificationType: "",
|
|
43
|
+
content: "",
|
|
44
|
+
hideIcon: false,
|
|
45
|
+
actionButton: undefined,
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const { notificationType, content, hideIcon, actionButton } = toRefs(props);
|
|
50
|
+
|
|
51
|
+
const iconClass = computed(() => {
|
|
52
|
+
if (notificationType.value === "success") return "fa-check-circle";
|
|
53
|
+
else if (notificationType.value === "info") return "fa-info-circle";
|
|
54
|
+
else if (notificationType.value === "error") return "fa-times-circle";
|
|
55
|
+
else return "fa-info-circle";
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const getSanitizedHtml = (content: string) => {
|
|
59
|
+
return DOMPurify.sanitize(content || "");
|
|
60
|
+
};
|
|
61
|
+
</script>
|
|
@@ -109,6 +109,11 @@
|
|
|
109
109
|
</tbody>
|
|
110
110
|
</template>
|
|
111
111
|
</table>
|
|
112
|
+
|
|
113
|
+
<!-- table footer info start -->
|
|
114
|
+
<slot name="table-footer-info" />
|
|
115
|
+
<!-- table footer info end -->
|
|
116
|
+
|
|
112
117
|
<!-- pagination start -->
|
|
113
118
|
<slot name="table-pagination" />
|
|
114
119
|
<!-- pagination end -->
|