@nixweb/nixloc-ui 1.1.0 → 1.2.0
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 +1 -1
- package/src/component/forms/ButtonFilter.vue +1 -0
- package/src/component/forms/InputTextEdit.vue +1 -1
- package/src/component/forms/Modal.vue +5 -1
- package/src/component/layout/BottomActionsBar.vue +193 -0
- package/src/component/layout/ColorPicker.vue +175 -0
- package/src/component/layout/IconPicker.vue +161 -0
- package/src/component/shared/Pagination.vue +6 -1
- package/src/component/shared/Table.vue +61 -3
- package/src/component/shared/TableItem.vue +2 -1
- package/src/component/shared/TableTotalPerPage.vue +84 -48
- package/src/component/shared/TableTotalization.vue +11 -11
- package/src/component/shared/actions/ActionButtons.vue +29 -0
- package/src/component/shared/actions/ActionErrorContent.vue +103 -0
- package/src/component/shared/actions/ActionFooter.vue +55 -0
- package/src/component/shared/actions/ActionHeader.vue +110 -0
- package/src/component/shared/actions/ActionItemList.vue +121 -0
- package/src/component/shared/actions/ActionsOptions.vue +159 -0
- package/src/component/shared/actions/ActionsSelected.vue +213 -0
- package/src/component/template/ListViewWithDataHandler.vue +21 -17
- package/src/component/template/ViewTemplateConfiguration.vue +6 -2
- package/src/component/template/ViewTemplateWithTable.vue +5 -1
- package/src/store/modules/generic.js +12 -4
|
@@ -18,10 +18,11 @@
|
|
|
18
18
|
{{ row[obj.field] }}
|
|
19
19
|
</div>
|
|
20
20
|
</div>
|
|
21
|
-
<div v-if="obj.type === 'html'" :style="obj.styleBody"
|
|
21
|
+
<div v-if="obj.type === 'html' && row[obj.field]" :style="obj.styleBody"
|
|
22
22
|
:class="convertClass(row[obj.fieldComparison], obj.classCssBody)">
|
|
23
23
|
<div v-if="row[obj.field]" v-html="row[obj.field]"></div>
|
|
24
24
|
<div v-else v-html="obj.html"></div>
|
|
25
|
+
<div v-html="row[obj.fieldSecond]"></div>
|
|
25
26
|
</div>
|
|
26
27
|
<div v-if="obj.type === 'select'" :style="obj.styleBody"
|
|
27
28
|
:class="convertClass(row[obj.fieldComparison], obj.classCssBody)">
|
|
@@ -1,78 +1,114 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="
|
|
3
|
-
<
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
{ content: '100', id: 100 },
|
|
12
|
-
]" v-model="totalPerPage" />
|
|
13
|
-
</div>
|
|
14
|
-
|
|
2
|
+
<div v-if="showTotalPerPage && totalRecords > 0" class="pagination-wrapper">
|
|
3
|
+
<ul class="pagination-list">
|
|
4
|
+
<li v-for="opt in filteredOptions" :key="opt">
|
|
5
|
+
<button class="pagination-pill" :class="{ 'is-selected': value === opt }" type="button"
|
|
6
|
+
@click="select(opt)">
|
|
7
|
+
{{ opt }}
|
|
8
|
+
</button>
|
|
9
|
+
</li>
|
|
10
|
+
</ul>
|
|
15
11
|
</div>
|
|
16
12
|
</template>
|
|
17
13
|
|
|
18
14
|
<script>
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
import { mapMutations, mapState } from "vuex";
|
|
15
|
+
import { mapState, mapMutations } from "vuex";
|
|
22
16
|
|
|
23
17
|
export default {
|
|
24
|
-
name: "
|
|
25
|
-
components: { SelectStatic },
|
|
18
|
+
name: "PaginationPerPage",
|
|
26
19
|
props: {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
default: true,
|
|
30
|
-
},
|
|
20
|
+
totalRecords: { type: Number, default: 0 },
|
|
21
|
+
showTotalPerPage: { type: Boolean, default: true },
|
|
31
22
|
},
|
|
32
23
|
data() {
|
|
33
24
|
return {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
created() {
|
|
38
|
-
this.initialValue = { content: this.paginations.totalPerPage, id: this.paginations.totalPerPage }
|
|
25
|
+
value: 10,
|
|
26
|
+
options: [10, 20, 50, 100],
|
|
27
|
+
};
|
|
39
28
|
},
|
|
40
29
|
computed: {
|
|
41
30
|
...mapState("generic", ["paginations"]),
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
31
|
+
filteredOptions() {
|
|
32
|
+
const total = this.totalRecords;
|
|
33
|
+
|
|
34
|
+
if (total <= 10) return [10];
|
|
35
|
+
if (total <= 20) return [10, 20];
|
|
36
|
+
if (total <= 50) return [10, 20, 50];
|
|
37
|
+
if (total <= 100) return [10, 20, 50, 100];
|
|
38
|
+
return this.options;
|
|
49
39
|
},
|
|
50
40
|
},
|
|
41
|
+
created() {
|
|
42
|
+
const fromStore = Number(this.paginations?.totalPerPage);
|
|
43
|
+
if (Number.isFinite(fromStore)) {
|
|
44
|
+
this.value = fromStore;
|
|
45
|
+
}
|
|
46
|
+
this.updateTotalPerPage({ content: String(this.value), id: this.value });
|
|
47
|
+
},
|
|
51
48
|
methods: {
|
|
52
|
-
...mapMutations("generic", [
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
...mapMutations("generic", ["executedSearch", "updateTotalPerPage"]),
|
|
50
|
+
select(opt) {
|
|
51
|
+
if (this.value === opt) return;
|
|
52
|
+
this.value = opt;
|
|
53
|
+
this.updateTotalPerPage({ content: String(opt), id: opt });
|
|
54
|
+
this.executedSearch();
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
watch: {
|
|
58
|
+
totalRecords() {
|
|
59
|
+
if (this.totalRecords <= 0) return;
|
|
60
|
+
if (!this.filteredOptions.includes(this.value)) {
|
|
61
|
+
const next = this.filteredOptions[this.filteredOptions.length - 1];
|
|
62
|
+
this.value = next;
|
|
63
|
+
this.updateTotalPerPage({ content: String(next), id: next });
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
},
|
|
56
67
|
};
|
|
57
68
|
</script>
|
|
58
69
|
|
|
59
70
|
<style scoped>
|
|
60
|
-
.
|
|
71
|
+
.pagination-wrapper {
|
|
61
72
|
display: flex;
|
|
73
|
+
align-items: center;
|
|
62
74
|
justify-content: flex-end;
|
|
63
|
-
|
|
75
|
+
gap: 8px;
|
|
76
|
+
width: 100%;
|
|
77
|
+
font-family: inherit;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.pagination-list {
|
|
81
|
+
display: flex;
|
|
82
|
+
align-items: center;
|
|
83
|
+
gap: 6px;
|
|
84
|
+
margin: 0;
|
|
85
|
+
padding: 0;
|
|
86
|
+
list-style: none;
|
|
64
87
|
}
|
|
65
88
|
|
|
66
|
-
.
|
|
67
|
-
|
|
68
|
-
|
|
89
|
+
.pagination-pill {
|
|
90
|
+
width: 31px;
|
|
91
|
+
height: 31px;
|
|
92
|
+
border-radius: 50%;
|
|
93
|
+
background: #f5f5f5;
|
|
94
|
+
border: none;
|
|
95
|
+
color: #444;
|
|
96
|
+
font-size: 13px;
|
|
97
|
+
font-weight: 500;
|
|
98
|
+
cursor: pointer;
|
|
99
|
+
transition: background 0.2s, color 0.2s, transform 0.1s;
|
|
69
100
|
}
|
|
70
101
|
|
|
71
|
-
.
|
|
72
|
-
|
|
102
|
+
.pagination-pill:hover {
|
|
103
|
+
background: #e0e0e0;
|
|
73
104
|
}
|
|
74
105
|
|
|
75
|
-
.
|
|
76
|
-
|
|
106
|
+
.pagination-pill.is-selected {
|
|
107
|
+
background: #D98621;
|
|
108
|
+
color: #fff;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.pagination-pill:active {
|
|
112
|
+
transform: scale(0.95);
|
|
77
113
|
}
|
|
78
|
-
</style>
|
|
114
|
+
</style>
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div
|
|
4
|
-
class="badge-side-by-side text-center"
|
|
5
|
-
v-for="item in totalization"
|
|
6
|
-
:key="item.title"
|
|
7
|
-
>
|
|
3
|
+
<div class="badge-side-by-side text-center" v-for="item in totalization" :key="item.title">
|
|
8
4
|
<div class="badge-totalization" :class="item.classCss">
|
|
9
|
-
<
|
|
5
|
+
<i :class="item.classIcon"></i>
|
|
6
|
+
<span class="title-totalization"> {{ item.title }} </span>
|
|
10
7
|
<span>{{ item.value | currency }}</span>
|
|
11
8
|
</div>
|
|
12
9
|
</div>
|
|
@@ -25,16 +22,19 @@ export default {
|
|
|
25
22
|
<style scoped>
|
|
26
23
|
.badge-side-by-side {
|
|
27
24
|
display: inline-block;
|
|
28
|
-
margin-right:
|
|
25
|
+
margin-right: 8px;
|
|
29
26
|
margin-bottom: 10px;
|
|
30
27
|
}
|
|
31
28
|
|
|
32
29
|
.badge-totalization {
|
|
33
|
-
border: 1px solid #
|
|
34
|
-
padding
|
|
35
|
-
padding-right: 5px;
|
|
30
|
+
border: 1px solid #e6e7eb;
|
|
31
|
+
padding: 3px 8px 3px 8px;
|
|
36
32
|
border-radius: 30px;
|
|
37
|
-
font-size:
|
|
33
|
+
font-size: 13px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.title-totalization{
|
|
37
|
+
margin-left: 1px;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
.revenue {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div class="side-by-side" v-for="item in actions" :key="item.type">
|
|
4
|
+
|
|
5
|
+
<Button v-if="item.type === 'delete'" key="remove" classIcon="fa-solid fa-trash" :title="item.title"
|
|
6
|
+
type="danger" size="small" :params="item" :clicked="() => $emit('confirm', item)" />
|
|
7
|
+
|
|
8
|
+
<Button v-if="item.type === 'options'" key="options" :title="item.title" :classIcon="item.classIcon"
|
|
9
|
+
type="primary" size="small" :params="item" :clicked="() => $emit('confirm', item)" />
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script>
|
|
16
|
+
import Button from "@nixweb/nixloc-ui/src/component/forms/Button";
|
|
17
|
+
|
|
18
|
+
export default {
|
|
19
|
+
name: "ActionButtons",
|
|
20
|
+
components: { Button },
|
|
21
|
+
props: {
|
|
22
|
+
actions: { type: Array, default: () => [] },
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<style scoped>
|
|
28
|
+
|
|
29
|
+
</style>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div class="error-details-header">
|
|
4
|
+
<i class="fas fa-triangle-exclamation"></i>
|
|
5
|
+
<div>
|
|
6
|
+
<div class="error-details-title title">O que deu errado?</div>
|
|
7
|
+
<!-- <div class="error-details-sub">ID: {{ id }}</div> -->
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<ScrollBar :minHeight="190" :maxHeight="190">
|
|
12
|
+
<ul class="error-list">
|
|
13
|
+
<li v-for="(msg, i) in safeMessages" :key="i" class="error-item">
|
|
14
|
+
<i class="fas fa-info-circle"></i>
|
|
15
|
+
<span>{{ msg }}</span>
|
|
16
|
+
</li>
|
|
17
|
+
|
|
18
|
+
<li v-if="safeMessages.length === 0" class="error-item muted">
|
|
19
|
+
<i class="fas fa-info-circle"></i>
|
|
20
|
+
<span>Algo deu errado, mas não recebemos detalhes do servidor.</span>
|
|
21
|
+
</li>
|
|
22
|
+
</ul>
|
|
23
|
+
</ScrollBar>
|
|
24
|
+
|
|
25
|
+
<div class="text-center">
|
|
26
|
+
<Button key="closeErrors" title="Fechar" color="white" backGroundColor="#6B7280" size="small"
|
|
27
|
+
:clicked="() => $emit('close')" />
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script>
|
|
33
|
+
import ScrollBar from "@nixweb/nixloc-ui/src/component/layout/ScrollBar.vue";
|
|
34
|
+
import Button from "@nixweb/nixloc-ui/src/component/forms/Button";
|
|
35
|
+
|
|
36
|
+
export default {
|
|
37
|
+
name: "ActionErrorContent",
|
|
38
|
+
components: { ScrollBar, Button },
|
|
39
|
+
props: {
|
|
40
|
+
id: { type: [String, Number], required: true },
|
|
41
|
+
index: { type: Number, default: -1 },
|
|
42
|
+
messages: { type: Array, default: () => [] },
|
|
43
|
+
},
|
|
44
|
+
computed: {
|
|
45
|
+
safeMessages() {
|
|
46
|
+
return (this.messages || []).filter(Boolean);
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<style scoped>
|
|
53
|
+
.error-details-header {
|
|
54
|
+
display: flex;
|
|
55
|
+
gap: 10px;
|
|
56
|
+
align-items: center;
|
|
57
|
+
margin-bottom: 12px;
|
|
58
|
+
color: #dc2626;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.error-details-header i {
|
|
62
|
+
font-size: 18px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.error-details-title {
|
|
66
|
+
font-weight: 600;
|
|
67
|
+
color: #111827;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.error-details-sub {
|
|
71
|
+
font-size: 12px;
|
|
72
|
+
color: #6b7280;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.error-list {
|
|
76
|
+
list-style: none;
|
|
77
|
+
margin: 0;
|
|
78
|
+
padding: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.error-item {
|
|
82
|
+
display: flex;
|
|
83
|
+
gap: 8px;
|
|
84
|
+
align-items: flex-start;
|
|
85
|
+
padding: 8px 10px;
|
|
86
|
+
background: #fff7f7;
|
|
87
|
+
border: 1px solid #fde2e2;
|
|
88
|
+
border-radius: 8px;
|
|
89
|
+
margin-bottom: 8px;
|
|
90
|
+
font-size: 13px;
|
|
91
|
+
color: #dc2626;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.error-item i {
|
|
95
|
+
margin-top: 2px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.error-item.muted {
|
|
99
|
+
background: #f9fafb;
|
|
100
|
+
border-color: #e5e7eb;
|
|
101
|
+
color: #6b7280;
|
|
102
|
+
}
|
|
103
|
+
</style>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div v-if="!isFinished" class="actions">
|
|
4
|
+
<div class="side-by-side">
|
|
5
|
+
<Button key="cancel" title="Cancelar" type="danger" size="small"
|
|
6
|
+
:disabled="processing || selected.length === 0" :clicked="hideModal" />
|
|
7
|
+
<Button key="ok" title="Processar" color="white" classIcon="fa-solid fa-play" backGroundColor="#007BFF" size="large"
|
|
8
|
+
:disabled="processing || selected.length === 0" :clicked="ok" />
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div v-else class="text-center">
|
|
13
|
+
<Button key="finish" title="Fechar" classIcon="fa-solid fa-xmark" color="white" backGroundColor="#6D757B" size="medium"
|
|
14
|
+
:clicked="finished" />
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script>
|
|
20
|
+
import Button from "@nixweb/nixloc-ui/src/component/forms/Button";
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
name: "ActionFooter",
|
|
24
|
+
components: { Button },
|
|
25
|
+
props: {
|
|
26
|
+
isFinished: { type: Boolean, default: false },
|
|
27
|
+
processing: { type: Boolean, default: false },
|
|
28
|
+
selected: { type: Array, default: () => [] },
|
|
29
|
+
},
|
|
30
|
+
emits: ["ok", "cancel", "finish"],
|
|
31
|
+
methods: {
|
|
32
|
+
ok() {
|
|
33
|
+
this.$emit("ok");
|
|
34
|
+
},
|
|
35
|
+
hideModal() {
|
|
36
|
+
this.$emit("cancel");
|
|
37
|
+
},
|
|
38
|
+
finished() {
|
|
39
|
+
this.$emit("finish");
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<style scoped>
|
|
46
|
+
.actions {
|
|
47
|
+
text-align: center;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.side-by-side {
|
|
51
|
+
display: inline-flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
gap: 8px;
|
|
54
|
+
}
|
|
55
|
+
</style>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div class="action-banner">
|
|
4
|
+
<span class="action-accent"></span>
|
|
5
|
+
<span class="action-label">Ação</span>
|
|
6
|
+
<strong class="action-value title">{{ description }}</strong>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div class="status-header">
|
|
10
|
+
<div class="status-chip">
|
|
11
|
+
<i class="fas fa-list"></i>
|
|
12
|
+
<span>Total {{ total }}</span>
|
|
13
|
+
</div>
|
|
14
|
+
<div class="status-chip success">
|
|
15
|
+
<i class="fas fa-check-circle"></i>
|
|
16
|
+
<span>Concluídos {{ done }}</span>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="status-chip error-chip">
|
|
19
|
+
<i class="fas fa-times-circle"></i>
|
|
20
|
+
<span>Falhas {{ errors }}</span>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script>
|
|
27
|
+
export default {
|
|
28
|
+
name: "ActionModalHeader",
|
|
29
|
+
props: {
|
|
30
|
+
description: { type: String, default: "" },
|
|
31
|
+
total: { type: Number, default: 0 },
|
|
32
|
+
done: { type: Number, default: 0 },
|
|
33
|
+
errors: { type: Number, default: 0 },
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<style scoped>
|
|
39
|
+
.status-header {
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
gap: 10px;
|
|
43
|
+
flex-wrap: wrap;
|
|
44
|
+
margin-bottom: 10px;
|
|
45
|
+
padding: 8px 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.status-chip {
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
gap: 6px;
|
|
52
|
+
background: #f3f4f6;
|
|
53
|
+
border: 1px solid #e5e7eb;
|
|
54
|
+
border-radius: 20px;
|
|
55
|
+
padding: 6px 10px;
|
|
56
|
+
font-size: 13px;
|
|
57
|
+
color: #374151;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.status-chip.success {
|
|
61
|
+
background: #ecfdf5;
|
|
62
|
+
border-color: #a7f3d0;
|
|
63
|
+
color: #065f46;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.status-chip.success i {
|
|
67
|
+
color: #16a34a;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.status-chip.error-chip {
|
|
71
|
+
background: #fef2f2;
|
|
72
|
+
border-color: #fecaca;
|
|
73
|
+
color: #b91c1c;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.status-chip.error-chip i {
|
|
77
|
+
color: #dc2626;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.action-banner {
|
|
81
|
+
display: flex;
|
|
82
|
+
align-items: center;
|
|
83
|
+
gap: 10px;
|
|
84
|
+
padding: 10px 12px;
|
|
85
|
+
margin-bottom: 12px;
|
|
86
|
+
background: #f8fafc;
|
|
87
|
+
border: 1px solid #e5e7eb;
|
|
88
|
+
border-radius: 12px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.action-accent {
|
|
92
|
+
width: 4px;
|
|
93
|
+
align-self: stretch;
|
|
94
|
+
background: #3b82f6;
|
|
95
|
+
border-radius: 8px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.action-label {
|
|
99
|
+
font-size: 12px;
|
|
100
|
+
text-transform: uppercase;
|
|
101
|
+
letter-spacing: 0.06em;
|
|
102
|
+
color: #64748b;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.action-value {
|
|
106
|
+
font-size: 14px;
|
|
107
|
+
color: #0f172a;
|
|
108
|
+
font-weight: 700;
|
|
109
|
+
}
|
|
110
|
+
</style>
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ScrollBar :minHeight="300" :maxHeight="300">
|
|
3
|
+
<div v-for="(id, index) in selected" :key="id" class="item-row">
|
|
4
|
+
<div class="item-left title">Item {{ index + 1 }}</div>
|
|
5
|
+
<div class="item-right">
|
|
6
|
+
<span v-if="status[id] === 'waiting'" class="waiting">
|
|
7
|
+
<i class="fas fa-hourglass-half"></i>
|
|
8
|
+
</span>
|
|
9
|
+
|
|
10
|
+
<span v-else-if="status[id] === 'running'" class="loading">
|
|
11
|
+
<span class="spinner"></span> Processando...
|
|
12
|
+
</span>
|
|
13
|
+
|
|
14
|
+
<span v-else-if="status[id] === 'done'" class="done">
|
|
15
|
+
<i class="fas fa-check-circle done-icon"></i> Sucesso!
|
|
16
|
+
</span>
|
|
17
|
+
|
|
18
|
+
<span v-else-if="status[id] === 'error'" class="error">
|
|
19
|
+
<i class="fas fa-times-circle"></i> Falhou!
|
|
20
|
+
<button class="error-link" @click="$emit('show-error', { id, index })"><span class="title">Ver
|
|
21
|
+
detalhes</span></button>
|
|
22
|
+
</span>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</ScrollBar>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script>
|
|
29
|
+
import ScrollBar from "@nixweb/nixloc-ui/src/component/layout/ScrollBar.vue";
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
name: "ActionItemList",
|
|
33
|
+
components: { ScrollBar },
|
|
34
|
+
props: { selected: Array, status: Object, errorsMap: Object },
|
|
35
|
+
};
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<style scoped>
|
|
39
|
+
.item-row {
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
justify-content: space-between;
|
|
43
|
+
padding: 8px 10px;
|
|
44
|
+
border: 1px solid #eee;
|
|
45
|
+
border-radius: 8px;
|
|
46
|
+
background: #fafafa;
|
|
47
|
+
margin: 6px 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.item-left {
|
|
51
|
+
font-weight: 500;
|
|
52
|
+
color: #334155;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.item-right {
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: 8px;
|
|
59
|
+
font-size: 13px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.waiting {
|
|
63
|
+
color: #6b7280;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.loading {
|
|
67
|
+
color: #007BFF;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.done {
|
|
71
|
+
color: #16a34a;
|
|
72
|
+
font-weight: 500;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.done-icon {
|
|
76
|
+
color: #22c55e;
|
|
77
|
+
font-size: 14px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.error {
|
|
81
|
+
color: #dc2626;
|
|
82
|
+
font-weight: 500;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.error-link {
|
|
86
|
+
margin-left: 10px;
|
|
87
|
+
background: transparent;
|
|
88
|
+
border: none;
|
|
89
|
+
padding: 0;
|
|
90
|
+
font-size: 13px;
|
|
91
|
+
text-decoration: underline;
|
|
92
|
+
cursor: pointer;
|
|
93
|
+
color: #1f2937;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.error-link:hover {
|
|
97
|
+
opacity: 0.9;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.spinner {
|
|
101
|
+
display: inline-block;
|
|
102
|
+
width: 14px;
|
|
103
|
+
height: 14px;
|
|
104
|
+
border: 2px solid #007bff;
|
|
105
|
+
border-top: 2px solid transparent;
|
|
106
|
+
border-radius: 50%;
|
|
107
|
+
animation: spin 0.8s linear infinite;
|
|
108
|
+
vertical-align: middle;
|
|
109
|
+
margin-right: 6px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@keyframes spin {
|
|
113
|
+
0% {
|
|
114
|
+
transform: rotate(0deg);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
100% {
|
|
118
|
+
transform: rotate(360deg);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
</style>
|