@webitel/ui-sdk 24.10.48 → 24.10.49
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/dist/ui-sdk.css +1 -1
- package/dist/ui-sdk.js +15643 -15660
- package/dist/ui-sdk.umd.cjs +17 -17
- package/package.json +7 -3
- package/src/components/index.js +2 -0
- package/src/components/wt-action-bar/WtActionBarActionsOrder.js +15 -0
- package/src/components/wt-action-bar/wt-action-bar.vue +29 -23
- package/src/components/wt-empty/_variables.scss +5 -0
- package/src/components/wt-empty/wt-empty.vue +232 -29
- package/src/components/wt-icon-action/IActionData.js +36 -0
- package/src/components/wt-icon-action/wt-icon-action.vue +23 -29
- package/src/composables/useAccessControl/useAccessControl.js +33 -0
- package/src/composables/useCachedItemInstanceName/useCachedItemInstanceName.js +33 -0
- package/src/composables/useCard/useCardComponent.js +88 -0
- package/src/composables/useCard/useCardTabs.js +28 -0
- package/src/composables/useClose/useClose.js +13 -0
- package/src/composables/useValidate/useValidate.js +10 -0
- package/src/css/main.scss +2 -5
- package/src/css/pages/card-page.scss +47 -0
- package/src/css/pages/table-page.scss +67 -0
- package/src/enums/ComponentSize/ComponentSize.enum.js +13 -0
- package/src/enums/index.js +39 -0
- package/src/scripts/compareSize.js +64 -0
- package/src/components/wt-icon-action/_internals/__tests__/WtAddIconAction.spec.js +0 -9
- package/src/components/wt-icon-action/_internals/__tests__/WtDeleteIconAction.spec.js +0 -9
- package/src/components/wt-icon-action/_internals/__tests__/WtDownloadIconAction.spec.js +0 -9
- package/src/components/wt-icon-action/_internals/__tests__/WtEditIconAction.spec.js +0 -9
- package/src/components/wt-icon-action/_internals/__tests__/WtHistoryIconAction.spec.js +0 -9
- package/src/components/wt-icon-action/_internals/__tests__/WtRefreshIconAction.spec.js +0 -9
- package/src/components/wt-icon-action/_internals/wt-add-icon-action.vue +0 -27
- package/src/components/wt-icon-action/_internals/wt-delete-icon-action.vue +0 -27
- package/src/components/wt-icon-action/_internals/wt-download-icon-action.vue +0 -27
- package/src/components/wt-icon-action/_internals/wt-edit-icon-action.vue +0 -27
- package/src/components/wt-icon-action/_internals/wt-history-icon-action.vue +0 -27
- package/src/components/wt-icon-action/_internals/wt-refresh-icon-action.vue +0 -27
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webitel/ui-sdk",
|
|
3
|
-
"version": "24.10.
|
|
3
|
+
"version": "24.10.49",
|
|
4
4
|
"private": false,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"test:unit": "vitest",
|
|
10
10
|
"lint-all": "npx @biomejs/biome check --write ./src",
|
|
11
11
|
"lint-all:unsafe": "npx @biomejs/biome check --write --unsafe ./src",
|
|
12
|
-
"lint-changed:unsafe": "npx @biomejs/biome check --write --unsafe --changed",
|
|
13
|
-
"lint:pre-commit": "npx @biomejs/biome check --write --unsafe --changed --no-errors-on-unmatched",
|
|
12
|
+
"lint-changed:unsafe": "npx @biomejs/biome check --write --unsafe --changed ./src",
|
|
13
|
+
"lint:pre-commit": "npx @biomejs/biome check --write ./src --unsafe --changed --no-errors-on-unmatched",
|
|
14
14
|
"publish-lib": "npm run test:unit && npm run build && npm publish --access public",
|
|
15
15
|
"publish-lib:testless": "npm run build && npm publish --access public",
|
|
16
16
|
"docs:dev": "vitepress dev docs --port 8080",
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"import": "./src/store/new/index.js",
|
|
29
29
|
"require": "./src/store/new/index.js"
|
|
30
30
|
},
|
|
31
|
+
"./enums": {
|
|
32
|
+
"import": "./src/enums/index.js",
|
|
33
|
+
"require": "./src/enums/index.js"
|
|
34
|
+
},
|
|
31
35
|
"./dist*": {
|
|
32
36
|
"import": "./dist*"
|
|
33
37
|
},
|
package/src/components/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import WtActionBar from './wt-action-bar/wt-action-bar.vue';
|
|
1
2
|
import WtAppHeader from './wt-app-header/wt-app-header.vue';
|
|
2
3
|
import WtAppNavigator from './wt-app-header/wt-app-navigator.vue';
|
|
3
4
|
import WtHeaderActions from './wt-app-header/wt-header-actions.vue';
|
|
@@ -64,6 +65,7 @@ import WtTimepicker from './wt-timepicker/wt-timepicker.vue';
|
|
|
64
65
|
import WtTooltip from './wt-tooltip/wt-tooltip.vue';
|
|
65
66
|
|
|
66
67
|
const Components = {
|
|
68
|
+
WtActionBar,
|
|
67
69
|
WtImage,
|
|
68
70
|
WtEmpty,
|
|
69
71
|
WtLogo,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import IconAction from '../../enums/IconAction/IconAction.enum.js';
|
|
2
|
+
|
|
3
|
+
export const tableActionsOrder = [
|
|
4
|
+
IconAction.ADD,
|
|
5
|
+
IconAction.COLUMNS,
|
|
6
|
+
IconAction.COPY,
|
|
7
|
+
IconAction.DOWNLOAD,
|
|
8
|
+
IconAction.UPLOAD,
|
|
9
|
+
IconAction.FILTERS,
|
|
10
|
+
IconAction.DELETE,
|
|
11
|
+
IconAction.REFRESH,
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
// TODO
|
|
15
|
+
export const cardActionsOrder = tableActionsOrder;
|
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="wt-action-bar">
|
|
3
|
-
<!-- @slot
|
|
4
|
-
|
|
3
|
+
<!-- @slot searchbar here
|
|
4
|
+
@scope `{ size<ComponentSize> }`
|
|
5
|
+
-->
|
|
6
|
+
<slot
|
|
7
|
+
name="search-bar"
|
|
8
|
+
v-bind="{ size }"
|
|
9
|
+
/>
|
|
10
|
+
|
|
11
|
+
<!-- @slot custom actions here
|
|
12
|
+
@scope `{ size<ComponentSize> }`
|
|
13
|
+
-->
|
|
14
|
+
<slot
|
|
15
|
+
v-bind="{ size }"
|
|
16
|
+
/>
|
|
5
17
|
|
|
6
|
-
<!-- @slot
|
|
7
|
-
@scope
|
|
18
|
+
<!-- @slot May be useful to set complex component which draws the same `wt-icon-action`
|
|
19
|
+
@scope `{ action<IconAction>, size<ComponentSize> }`
|
|
8
20
|
-->
|
|
9
21
|
<slot
|
|
10
22
|
v-for="action in shownActions"
|
|
11
|
-
|
|
23
|
+
:name="action"
|
|
24
|
+
v-bind="{ action, size }"
|
|
12
25
|
>
|
|
13
26
|
<wt-icon-action
|
|
14
27
|
:action="action"
|
|
@@ -22,45 +35,38 @@
|
|
|
22
35
|
import { computed } from 'vue';
|
|
23
36
|
import IconAction from '../../enums/IconAction/IconAction.enum.js';
|
|
24
37
|
import WtIconAction from '../wt-icon-action/wt-icon-action.vue';
|
|
38
|
+
import { tableActionsOrder, cardActionsOrder } from './WtActionBarActionsOrder.js';
|
|
25
39
|
|
|
26
40
|
const props = defineProps({
|
|
27
|
-
|
|
41
|
+
/**
|
|
42
|
+
* [`'table'`, `'card'`]
|
|
43
|
+
* */
|
|
28
44
|
mode: {
|
|
29
45
|
type: String,
|
|
30
46
|
default: 'table',
|
|
31
47
|
validator: (v) => ['table', 'card'].includes(v),
|
|
32
48
|
},
|
|
33
49
|
/**
|
|
34
|
-
* see IconAction enum
|
|
50
|
+
* see `IconAction` enum
|
|
35
51
|
*/
|
|
36
52
|
actions: {
|
|
37
53
|
type: Array,
|
|
38
54
|
default: () => [],
|
|
39
55
|
validator: (v) => v.every((action) => Object.values(IconAction).includes(action)),
|
|
40
56
|
},
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Not implemented
|
|
60
|
+
*/
|
|
41
61
|
size: {
|
|
42
62
|
type: String,
|
|
43
|
-
default: 'md',
|
|
44
|
-
validator: (v) => ['
|
|
63
|
+
// default: 'md',
|
|
64
|
+
// validator: (v) => ['sm', 'md', 'lg'].includes(v),
|
|
45
65
|
},
|
|
46
66
|
});
|
|
47
67
|
|
|
48
68
|
const emit = defineEmits(Object.values(IconAction).map((action) => `click:${action}`));
|
|
49
69
|
|
|
50
|
-
const tableActionsOrder = [
|
|
51
|
-
IconAction.ADD,
|
|
52
|
-
IconAction.COLUMNS,
|
|
53
|
-
IconAction.COPY,
|
|
54
|
-
IconAction.DOWNLOAD,
|
|
55
|
-
IconAction.UPLOAD,
|
|
56
|
-
IconAction.FILTERS,
|
|
57
|
-
IconAction.DELETE,
|
|
58
|
-
IconAction.REFRESH,
|
|
59
|
-
];
|
|
60
|
-
|
|
61
|
-
// TODO
|
|
62
|
-
const cardActionsOrder = tableActionsOrder;
|
|
63
|
-
|
|
64
70
|
const shownActions = computed(() => {
|
|
65
71
|
const actionsOrder = props.mode === 'card' ? cardActionsOrder : tableActionsOrder;
|
|
66
72
|
|
|
@@ -1,63 +1,119 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<section
|
|
3
|
-
:class="[`wt-empty
|
|
3
|
+
:class="[`wt-empty--size-${size}`]"
|
|
4
4
|
class="wt-empty"
|
|
5
5
|
>
|
|
6
6
|
<div
|
|
7
|
-
v-if="
|
|
7
|
+
v-if="showMedia"
|
|
8
8
|
class="wt-empty__media"
|
|
9
9
|
>
|
|
10
|
-
|
|
10
|
+
<!-- @slot for custom media, replaces image
|
|
11
|
+
@scope `{ size: mediaSize }`
|
|
12
|
+
-->
|
|
13
|
+
<slot name="media" v-bind="{ size: mediaSize }">
|
|
11
14
|
<wt-image
|
|
12
15
|
:src="image"
|
|
16
|
+
:size="mediaSize"
|
|
13
17
|
alt="empty-state"
|
|
14
18
|
/>
|
|
15
19
|
</slot>
|
|
16
20
|
</div>
|
|
17
21
|
|
|
22
|
+
<div
|
|
23
|
+
v-if="showHeadline || showTitle || showText"
|
|
24
|
+
class="wt-empty__info"
|
|
25
|
+
>
|
|
18
26
|
<h2
|
|
19
|
-
v-if="
|
|
27
|
+
v-if="showHeadline"
|
|
20
28
|
class="wt-empty__headline"
|
|
21
29
|
>
|
|
22
|
-
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<!-- @slot for custom headline, replaces headline
|
|
33
|
+
@scope `{ headline }`
|
|
34
|
+
-->
|
|
35
|
+
<slot name="headline" v-bind="{ headline }">
|
|
23
36
|
{{ headline }}
|
|
24
37
|
</slot>
|
|
25
38
|
</h2>
|
|
26
39
|
|
|
27
40
|
<h3
|
|
28
|
-
v-if="
|
|
41
|
+
v-if="showTitle"
|
|
29
42
|
class="wt-empty__title"
|
|
30
43
|
>
|
|
31
|
-
|
|
44
|
+
|
|
45
|
+
<!-- @slot for custom title, replaces title
|
|
46
|
+
@scope `{ title }`
|
|
47
|
+
-->
|
|
48
|
+
<slot name="title" v-bind="{ title }">
|
|
32
49
|
{{ title }}
|
|
33
50
|
</slot>
|
|
34
51
|
</h3>
|
|
35
52
|
|
|
36
|
-
<slot></slot>
|
|
37
|
-
|
|
38
53
|
<p
|
|
39
|
-
v-if="
|
|
54
|
+
v-if="showText"
|
|
40
55
|
class="wt-empty__text"
|
|
41
56
|
>
|
|
42
|
-
|
|
57
|
+
|
|
58
|
+
<!-- @slot for custom text, replaces text
|
|
59
|
+
@scope `{ text }`
|
|
60
|
+
-->
|
|
61
|
+
<slot name="text" v-bind="{ text }">
|
|
43
62
|
{{ text }}
|
|
44
63
|
</slot>
|
|
45
64
|
</p>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<!-- @slot custom content, between text and actions
|
|
68
|
+
@scope `{ size }`
|
|
69
|
+
-->
|
|
70
|
+
<slot v-bind="{ size }"></slot>
|
|
46
71
|
|
|
47
72
|
<div
|
|
48
|
-
v-if="
|
|
73
|
+
v-if="showActions"
|
|
49
74
|
class="wt-empty__actions"
|
|
50
75
|
>
|
|
76
|
+
<!-- @slot for custom actions, replaces primary and secondary actions
|
|
77
|
+
@scope `{ onPrimaryClick, onSecondaryClick }`
|
|
78
|
+
-->
|
|
51
79
|
<slot
|
|
52
80
|
name="actions"
|
|
53
|
-
v-bind="{
|
|
81
|
+
v-bind="{ onPrimaryClick, onSecondaryClick }"
|
|
54
82
|
>
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
83
|
+
|
|
84
|
+
<!-- @slot for custom primary action, replaces primaryAction
|
|
85
|
+
@scope `{ onPrimaryClick }`
|
|
86
|
+
-->
|
|
87
|
+
<slot
|
|
88
|
+
name="primary-action"
|
|
89
|
+
v-bind="{ onPrimaryClick }"
|
|
58
90
|
>
|
|
59
|
-
|
|
60
|
-
|
|
91
|
+
<wt-button
|
|
92
|
+
v-if="primaryActionText"
|
|
93
|
+
:size="buttonSize"
|
|
94
|
+
color="primary"
|
|
95
|
+
@click="() => onPrimaryClick()"
|
|
96
|
+
>
|
|
97
|
+
{{ primaryActionText }}
|
|
98
|
+
</wt-button>
|
|
99
|
+
</slot>
|
|
100
|
+
|
|
101
|
+
<!-- @slot for custom secondary action, replaces secondaryAction
|
|
102
|
+
@scope `{ onSecondaryClick }`
|
|
103
|
+
-->
|
|
104
|
+
<slot
|
|
105
|
+
name="secondary-action"
|
|
106
|
+
v-bind="{ onSecondaryClick }"
|
|
107
|
+
>
|
|
108
|
+
<wt-button
|
|
109
|
+
v-if="secondaryActionText"
|
|
110
|
+
:size="buttonSize"
|
|
111
|
+
color="secondary"
|
|
112
|
+
@click="() => onSecondaryClick()"
|
|
113
|
+
>
|
|
114
|
+
{{ secondaryActionText }}
|
|
115
|
+
</wt-button>
|
|
116
|
+
</slot>
|
|
61
117
|
</slot>
|
|
62
118
|
</div>
|
|
63
119
|
</section>
|
|
@@ -66,51 +122,125 @@
|
|
|
66
122
|
<script setup>
|
|
67
123
|
// based on https://vuetifyjs.com/en/components/empty-states/
|
|
68
124
|
|
|
69
|
-
import { useSlots } from 'vue';
|
|
125
|
+
import { computed, useSlots } from 'vue';
|
|
126
|
+
import ComponentSize from '../../enums/ComponentSize/ComponentSize.enum.js';
|
|
127
|
+
import { greaterOrEqual, smallerOrEqual } from '../../scripts/compareSize.js';
|
|
70
128
|
import WtImage from '../wt-image/wt-image.vue';
|
|
71
129
|
|
|
72
130
|
const props = defineProps({
|
|
73
131
|
image: {
|
|
74
132
|
type: [Object, null],
|
|
75
133
|
},
|
|
134
|
+
/**
|
|
135
|
+
* @values 'sm', 'md', 'lg'
|
|
136
|
+
*/
|
|
76
137
|
size: {
|
|
77
138
|
type: String,
|
|
78
|
-
default:
|
|
79
|
-
validator: (v) => [
|
|
139
|
+
default: ComponentSize.MD,
|
|
140
|
+
validator: (v) => [ComponentSize.SM, ComponentSize.MD, ComponentSize.LG].includes(v),
|
|
80
141
|
},
|
|
142
|
+
/**
|
|
143
|
+
* shown only if prop or slot is provided
|
|
144
|
+
*/
|
|
81
145
|
headline: {
|
|
82
146
|
type: [String, null],
|
|
83
147
|
default: '',
|
|
84
148
|
},
|
|
149
|
+
/**
|
|
150
|
+
* shown only if prop or slot is provided
|
|
151
|
+
*/
|
|
85
152
|
title: {
|
|
86
153
|
type: [String, null],
|
|
87
154
|
default: '',
|
|
88
155
|
},
|
|
156
|
+
/**
|
|
157
|
+
* shown only if prop or slot is provided
|
|
158
|
+
*/
|
|
89
159
|
text: {
|
|
90
160
|
type: [String, null],
|
|
91
161
|
default: '',
|
|
92
162
|
},
|
|
93
|
-
|
|
163
|
+
/**
|
|
164
|
+
* primary action is shown only if prop or slot is provided
|
|
165
|
+
*/
|
|
166
|
+
primaryActionText: {
|
|
94
167
|
type: [String, null],
|
|
95
168
|
default: '',
|
|
96
169
|
},
|
|
97
|
-
|
|
170
|
+
/**
|
|
171
|
+
* secondary action shown only if prop or slot is provided
|
|
172
|
+
*/
|
|
173
|
+
secondaryActionText: {
|
|
98
174
|
type: [String, null],
|
|
99
|
-
default: '
|
|
175
|
+
default: '',
|
|
100
176
|
},
|
|
101
177
|
});
|
|
102
178
|
|
|
103
179
|
const emit = defineEmits([
|
|
104
|
-
|
|
180
|
+
/**
|
|
181
|
+
* emitted without a parameter, but could accept one, if used in a slot
|
|
182
|
+
*/
|
|
183
|
+
'click:primary',
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* emitted without a parameter, but could accept one, if used in a slot
|
|
187
|
+
*/
|
|
188
|
+
'click:secondary',
|
|
105
189
|
]);
|
|
106
190
|
|
|
107
191
|
const slots = useSlots();
|
|
108
192
|
|
|
109
|
-
const
|
|
110
|
-
|
|
193
|
+
const showMedia = computed(() => props.image || slots.media);
|
|
194
|
+
|
|
195
|
+
const showHeadline = computed(() => props.headline || slots.headline);
|
|
196
|
+
|
|
197
|
+
const showTitle = computed(() => props.title || slots.title);
|
|
198
|
+
|
|
199
|
+
const showText = computed(() => props.text || slots.text);
|
|
200
|
+
|
|
201
|
+
const showActions = computed(() => {
|
|
202
|
+
return [
|
|
203
|
+
props.primaryActionText,
|
|
204
|
+
props.secondaryActionText,
|
|
205
|
+
slots.actions,
|
|
206
|
+
slots['primary-action'],
|
|
207
|
+
slots['secondary-action'],
|
|
208
|
+
].some((v) => v);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const mediaSize = computed(() => {
|
|
212
|
+
if (smallerOrEqual(props.size, ComponentSize.SM)) {
|
|
213
|
+
return ComponentSize.XXS;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (greaterOrEqual(props.size, ComponentSize.LG)) {
|
|
217
|
+
return ComponentSize.MD;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return ComponentSize.SM;
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
const buttonSize = computed(() => {
|
|
224
|
+
if (smallerOrEqual(props.size, ComponentSize.SM)) {
|
|
225
|
+
return ComponentSize.SM;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return ComponentSize.MD;
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
const onClick = (action) => (params) => {
|
|
232
|
+
emit(`click:${action}`, params);
|
|
111
233
|
};
|
|
234
|
+
|
|
235
|
+
const onPrimaryClick = onClick('primary');
|
|
236
|
+
|
|
237
|
+
const onSecondaryClick = onClick('secondary');
|
|
112
238
|
</script>
|
|
113
239
|
|
|
240
|
+
<style lang="scss">
|
|
241
|
+
@import './variables.scss';
|
|
242
|
+
</style>
|
|
243
|
+
|
|
114
244
|
<style lang="scss" scoped>
|
|
115
245
|
@import '../../../src/css/main.scss';
|
|
116
246
|
|
|
@@ -118,23 +248,96 @@ const onClick = (params) => {
|
|
|
118
248
|
display: flex;
|
|
119
249
|
align-items: center;
|
|
120
250
|
flex-direction: column;
|
|
251
|
+
flex-wrap: wrap;
|
|
121
252
|
justify-content: center;
|
|
253
|
+
width: var(--wt-empty-width);
|
|
254
|
+
min-width: var(--wt-empty-min-width);
|
|
255
|
+
max-width: var(--wt-empty-max-width);
|
|
256
|
+
padding: var(--spacing-md);
|
|
122
257
|
text-align: center;
|
|
123
|
-
gap: var(--spacing-
|
|
258
|
+
gap: var(--spacing-md);
|
|
259
|
+
|
|
260
|
+
&__info {
|
|
261
|
+
display: flex;
|
|
262
|
+
flex-direction: column;
|
|
263
|
+
flex-wrap: wrap;
|
|
264
|
+
gap: var(--spacing-sm);
|
|
265
|
+
}
|
|
124
266
|
|
|
125
|
-
&
|
|
267
|
+
&__headline,
|
|
268
|
+
&__title,
|
|
269
|
+
&__text {
|
|
270
|
+
text-align: center;
|
|
126
271
|
}
|
|
127
272
|
|
|
128
273
|
&__headline {
|
|
274
|
+
@extend %typo-heading-4;
|
|
129
275
|
}
|
|
130
276
|
|
|
131
277
|
&__title {
|
|
278
|
+
@extend %typo-subtitle-1;
|
|
132
279
|
}
|
|
133
280
|
|
|
134
281
|
&__text {
|
|
282
|
+
@extend %typo-body-1;
|
|
135
283
|
}
|
|
136
284
|
|
|
137
285
|
&__actions {
|
|
286
|
+
display: flex;
|
|
287
|
+
gap: var(--spacing-sm);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
&--size {
|
|
291
|
+
&-sm.wt-empty {
|
|
292
|
+
padding: var(--spacing-sm);
|
|
293
|
+
gap: var(--spacing-sm);
|
|
294
|
+
|
|
295
|
+
&__headline {
|
|
296
|
+
@extend %typo-heading-4;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
&__title {
|
|
300
|
+
@extend %typo-subtitle-2;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
&__text {
|
|
304
|
+
@extend %typo-body-2;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
&-md.wt-empty {
|
|
309
|
+
padding: var(--spacing-md);
|
|
310
|
+
gap: var(--spacing-md);
|
|
311
|
+
|
|
312
|
+
&__headline {
|
|
313
|
+
@extend %typo-heading-4;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
&__title {
|
|
317
|
+
@extend %typo-subtitle-1;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
&__text {
|
|
321
|
+
@extend %typo-body-1;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
&-lg.wt-empty {
|
|
326
|
+
padding: var(--spacing-lg);
|
|
327
|
+
gap: var(--spacing-lg);
|
|
328
|
+
|
|
329
|
+
&__headline {
|
|
330
|
+
@extend %typo-heading-4;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
&__title {
|
|
334
|
+
@extend %typo-subtitle-1;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
&__text {
|
|
338
|
+
@extend %typo-body-1;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
138
341
|
}
|
|
139
342
|
}
|
|
140
343
|
</style>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import IconAction from '../../enums/IconAction/IconAction.enum.js';
|
|
2
|
+
|
|
3
|
+
const IActionData = Object.freeze({
|
|
4
|
+
[IconAction.ADD]: {
|
|
5
|
+
value: IconAction.ADD,
|
|
6
|
+
icon: 'plus',
|
|
7
|
+
hint: 'webitelUI.iconAction.addActionHint',
|
|
8
|
+
},
|
|
9
|
+
[IconAction.DELETE]: {
|
|
10
|
+
value: IconAction.DELETE,
|
|
11
|
+
icon: 'bucket',
|
|
12
|
+
hint: 'webitelUI.iconAction.deleteActionHint',
|
|
13
|
+
},
|
|
14
|
+
[IconAction.DOWNLOAD]: {
|
|
15
|
+
value: IconAction.DOWNLOAD,
|
|
16
|
+
icon: 'download',
|
|
17
|
+
hint: 'webitelUI.iconAction.downloadActionHint',
|
|
18
|
+
},
|
|
19
|
+
[IconAction.EDIT]: {
|
|
20
|
+
value: IconAction.EDIT,
|
|
21
|
+
icon: 'edit',
|
|
22
|
+
hint: 'webitelUI.iconAction.editActionHint',
|
|
23
|
+
},
|
|
24
|
+
[IconAction.HISTORY]: {
|
|
25
|
+
value: IconAction.HISTORY,
|
|
26
|
+
icon: 'history',
|
|
27
|
+
hint: 'webitelUI.iconAction.historyActionHint',
|
|
28
|
+
},
|
|
29
|
+
[IconAction.REFRESH]: {
|
|
30
|
+
value: IconAction.REFRESH,
|
|
31
|
+
icon: 'refresh',
|
|
32
|
+
hint: 'reusable.refresh',
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export { IActionData };
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
<wt-tooltip>
|
|
3
|
+
<template #activator>
|
|
4
|
+
<wt-icon-btn
|
|
5
|
+
:disabled="disabled"
|
|
6
|
+
:icon="iconAction.icon"
|
|
7
|
+
@click="emit('click')"
|
|
8
|
+
/>
|
|
9
|
+
</template>
|
|
10
|
+
{{ t(iconAction.hint) }}
|
|
11
|
+
</wt-tooltip>
|
|
7
12
|
</template>
|
|
8
13
|
|
|
9
14
|
<script setup>
|
|
10
15
|
import { computed } from 'vue';
|
|
16
|
+
import { useI18n } from 'vue-i18n';
|
|
17
|
+
import { IActionData } from './IActionData.js';
|
|
11
18
|
import IconAction from '../../enums/IconAction/IconAction.enum.js';
|
|
12
|
-
import WtAddIconAction from './_internals/wt-add-icon-action.vue';
|
|
13
|
-
import WtDeleteIconAction from './_internals/wt-delete-icon-action.vue';
|
|
14
|
-
import WtDownloadIconAction from './_internals/wt-download-icon-action.vue';
|
|
15
|
-
import WtEditIconAction from './_internals/wt-edit-icon-action.vue';
|
|
16
|
-
import WtHistoryIconAction from './_internals/wt-history-icon-action.vue';
|
|
17
|
-
import WtRefreshIconAction from './_internals/wt-refresh-icon-action.vue';
|
|
18
19
|
|
|
19
20
|
const props = defineProps({
|
|
20
21
|
/**
|
|
21
|
-
*
|
|
22
|
+
* `IconAction` enum value
|
|
22
23
|
*/
|
|
23
24
|
action: {
|
|
24
25
|
type: String,
|
|
@@ -40,24 +41,17 @@ const props = defineProps({
|
|
|
40
41
|
|
|
41
42
|
const emit = defineEmits(['click']);
|
|
42
43
|
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
case IconAction.HISTORY:
|
|
52
|
-
return WtHistoryIconAction;
|
|
53
|
-
case IconAction.DOWNLOAD:
|
|
54
|
-
return WtDownloadIconAction;
|
|
55
|
-
case IconAction.REFRESH:
|
|
56
|
-
return WtRefreshIconAction;
|
|
57
|
-
default:
|
|
58
|
-
console.error(`Unknown action for wt-icon-action component: ${props.action}`);
|
|
59
|
-
return WtEditIconAction;
|
|
44
|
+
const { t } = useI18n();
|
|
45
|
+
|
|
46
|
+
const iconAction = computed(() => {
|
|
47
|
+
const data = IActionData[props.action];
|
|
48
|
+
|
|
49
|
+
if (!data) {
|
|
50
|
+
console.error(`Unknown action for wt-icon-action component: ${props.action}`);
|
|
51
|
+
return { icon: 'edit', hint: props.action };
|
|
60
52
|
}
|
|
53
|
+
|
|
54
|
+
return data;
|
|
61
55
|
});
|
|
62
56
|
</script>
|
|
63
57
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { computed } from 'vue';
|
|
2
|
+
import { useRoute } from 'vue-router';
|
|
3
|
+
import { useStore } from 'vuex';
|
|
4
|
+
|
|
5
|
+
export const useAccessControl = () => {
|
|
6
|
+
const store = useStore();
|
|
7
|
+
const route = useRoute();
|
|
8
|
+
|
|
9
|
+
const hasReadAccess = computed(() => store.getters['userinfo/HAS_READ_ACCESS']({ route }));
|
|
10
|
+
const hasCreateAccess = computed(() => store.getters['userinfo/HAS_CREATE_ACCESS']({ route }));
|
|
11
|
+
const hasEditAccess = computed(() => store.getters['userinfo/HAS_EDIT_ACCESS']({ route }));
|
|
12
|
+
const hasDeleteAccess = computed(() => store.getters['userinfo/HAS_DELETE_ACCESS']({ route }));
|
|
13
|
+
|
|
14
|
+
const hasSaveActionAccess = computed(() => {
|
|
15
|
+
if (route.params.id === 'new') return hasEditAccess.value;
|
|
16
|
+
return hasCreateAccess.value;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const disableUserInput = computed(() => {
|
|
20
|
+
if (route.params.id === 'new') return !hasEditAccess.value;
|
|
21
|
+
return !hasCreateAccess.value;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
hasReadAccess,
|
|
26
|
+
hasCreateAccess,
|
|
27
|
+
hasEditAccess,
|
|
28
|
+
hasDeleteAccess,
|
|
29
|
+
|
|
30
|
+
hasSaveActionAccess,
|
|
31
|
+
disableUserInput,
|
|
32
|
+
};
|
|
33
|
+
};
|