@xen-orchestra/web-core 0.26.1 → 0.28.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/lib/components/card/VtsCardRowKeyValue.vue +1 -0
- package/lib/components/cell-object/VtsCellObject.vue +1 -2
- package/lib/components/console/VtsActionsConsole.vue +3 -9
- package/lib/components/copy-button/VtsCopyButton.vue +1 -3
- package/lib/components/dropdown/DropdownTitle.vue +3 -3
- package/lib/components/icon/VtsIcon.vue +32 -76
- package/lib/components/input-wrapper/VtsInputWrapper.vue +2 -2
- package/lib/components/layout/VtsLayoutSidebar.vue +1 -2
- package/lib/components/menu/MenuItem.vue +4 -5
- package/lib/components/menu/MenuTrigger.vue +3 -3
- package/lib/components/object-icon/VtsObjectIcon.vue +2 -2
- package/lib/components/resources/VtsResource.vue +3 -3
- package/lib/components/select/VtsSelect.vue +4 -5
- package/lib/components/table/ColumnTitle.vue +11 -12
- package/lib/components/task/VtsQuickTaskButton.vue +1 -2
- package/lib/components/tree/VtsTreeLoadingItem.vue +3 -3
- package/lib/components/ui/alarm-item/UiAlarmItem.vue +1 -2
- package/lib/components/ui/alert/UiAlert.vue +14 -13
- package/lib/components/ui/button/UiButton.vue +4 -5
- package/lib/components/ui/button-icon/UiButtonIcon.vue +3 -3
- package/lib/components/ui/checkbox/UiCheckbox.vue +2 -9
- package/lib/components/ui/chip/ChipIcon.vue +3 -3
- package/lib/components/ui/chip/ChipRemoveIcon.vue +1 -2
- package/lib/components/ui/chip/UiChip.vue +2 -2
- package/lib/components/ui/circle-progress-bar/UiCircleProgressBar.vue +7 -4
- package/lib/components/ui/collapsible-list/UiCollapsibleList.vue +73 -0
- package/lib/components/ui/donut-chart/UiDonutChart.vue +30 -17
- package/lib/components/ui/dropdown/UiDropdown.vue +5 -7
- package/lib/components/ui/dropdown-button/UiDropdownButton.vue +4 -5
- package/lib/components/ui/head-bar/UiHeadBar.vue +6 -11
- package/lib/components/ui/info/UiInfo.vue +14 -20
- package/lib/components/ui/input/UiInput.vue +6 -7
- package/lib/components/ui/label/UiLabel.vue +3 -3
- package/lib/components/ui/legend/UiLegend.vue +3 -3
- package/lib/components/ui/legend-title/UiLegendTitle.vue +7 -3
- package/lib/components/ui/link/UiLink.vue +4 -5
- package/lib/components/ui/{quoteCode/UiQuoteCode.vue → log-entry-viewer/UiLogEntryViewer.vue} +58 -21
- package/lib/components/ui/object-link/UiObjectLink.vue +4 -4
- package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +3 -4
- package/lib/components/ui/quick-task-item/UiQuickTaskItem.vue +3 -4
- package/lib/components/ui/radio-button/UiRadioButton.vue +1 -2
- package/lib/components/ui/table-pagination/PaginationButton.vue +2 -25
- package/lib/components/ui/table-pagination/UiTablePagination.vue +56 -95
- package/lib/components/ui/tag/UiTag.vue +3 -3
- package/lib/components/ui/text-area/UiTextarea.vue +2 -2
- package/lib/components/ui/toaster/UiToaster.vue +15 -13
- package/lib/components/ui/tree-item-label/UiTreeItemLabel.vue +4 -5
- package/lib/composables/default-tab.composable.md +42 -0
- package/lib/composables/default-tab.composable.ts +26 -0
- package/lib/composables/link-component.composable.ts +3 -2
- package/lib/composables/pagination.composable.ts +5 -0
- package/lib/i18n.ts +4 -0
- package/lib/icons/fa-icons.ts +48 -2
- package/lib/icons/index.ts +4 -0
- package/lib/icons/legacy-icons.ts +10 -0
- package/lib/icons/object-icons.ts +1 -1
- package/lib/layouts/CoreLayout.vue +1 -2
- package/lib/locales/cs.json +29 -10
- package/lib/locales/de.json +70 -7
- package/lib/locales/en.json +25 -0
- package/lib/locales/es.json +3 -3
- package/lib/locales/fr.json +25 -0
- package/lib/locales/it.json +17 -5
- package/lib/locales/nl.json +28 -10
- package/lib/locales/pt_BR.json +67 -0
- package/lib/locales/sv.json +17 -0
- package/lib/packages/form-select/types.ts +3 -0
- package/lib/packages/form-select/use-form-option-controller.ts +5 -6
- package/lib/packages/form-select/use-form-select-controller.ts +1 -0
- package/lib/packages/form-select/use-form-select.ts +153 -109
- package/lib/packages/icon/DisplayIcon.vue +1 -0
- package/lib/packages/progress/README.md +62 -0
- package/lib/packages/progress/types.ts +19 -0
- package/lib/packages/progress/use-progress-group.ts +68 -0
- package/lib/packages/progress/use-progress.ts +22 -0
- package/lib/packages/remote-resource/README.md +115 -0
- package/lib/packages/remote-resource/define-remote-resource.ts +294 -0
- package/lib/packages/remote-resource/types.ts +28 -0
- package/lib/packages/threshold/README.md +30 -0
- package/lib/packages/threshold/type.ts +3 -0
- package/lib/packages/threshold/use-threshold.ts +19 -0
- package/lib/types/object-icon.type.ts +0 -40
- package/package.json +2 -2
- package/lib/components/icon/NewVtsIcon.vue +0 -49
- package/lib/components/ui/complex-icon/UiComplexIcon.vue +0 -45
- package/lib/components/ui/object-icon/UiObjectIcon.vue +0 -251
package/lib/components/ui/{quoteCode/UiQuoteCode.vue → log-entry-viewer/UiLogEntryViewer.vue}
RENAMED
|
@@ -1,44 +1,51 @@
|
|
|
1
|
+
<!-- v2 -->
|
|
1
2
|
<template>
|
|
2
|
-
<div class="ui-
|
|
3
|
+
<div class="ui-log-entry-viewer" :class="className">
|
|
3
4
|
<div class="label-container">
|
|
4
5
|
<div :class="fontClasses.labelClass" class="label">
|
|
5
6
|
{{ label }}
|
|
6
7
|
</div>
|
|
7
|
-
<div
|
|
8
|
-
<VtsCopyButton
|
|
9
|
-
<
|
|
8
|
+
<div class="actions">
|
|
9
|
+
<VtsCopyButton :value="content" />
|
|
10
|
+
<UiButtonIcon
|
|
11
|
+
icon="fa:arrow-up-right-from-square"
|
|
12
|
+
size="medium"
|
|
13
|
+
accent="brand"
|
|
14
|
+
@click="openRawValueInNewTab()"
|
|
15
|
+
/>
|
|
10
16
|
</div>
|
|
11
17
|
</div>
|
|
12
|
-
<code
|
|
13
|
-
|
|
18
|
+
<code :class="fontClasses.codeClass" class="code-container">
|
|
19
|
+
{{ content }}
|
|
14
20
|
</code>
|
|
15
21
|
</div>
|
|
16
22
|
</template>
|
|
17
23
|
|
|
18
24
|
<script setup lang="ts">
|
|
19
25
|
import VtsCopyButton from '@core/components/copy-button/VtsCopyButton.vue'
|
|
26
|
+
import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
|
|
20
27
|
import { useMapper } from '@core/packages/mapper'
|
|
21
28
|
import { toVariants } from '@core/utils/to-variants.util.ts'
|
|
22
|
-
import { computed,
|
|
29
|
+
import { computed, watch } from 'vue'
|
|
23
30
|
|
|
24
|
-
type
|
|
25
|
-
type
|
|
31
|
+
type LogEntryViewerAccent = 'info' | 'warning' | 'danger'
|
|
32
|
+
type LogEntryViewerSize = 'small' | 'medium'
|
|
26
33
|
|
|
27
|
-
const {
|
|
34
|
+
const {
|
|
35
|
+
size,
|
|
36
|
+
accent,
|
|
37
|
+
content: rawContent = '',
|
|
38
|
+
} = defineProps<{
|
|
28
39
|
label: string
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
content: string | object | undefined
|
|
41
|
+
size: LogEntryViewerSize
|
|
42
|
+
accent: LogEntryViewerAccent
|
|
32
43
|
}>()
|
|
33
44
|
|
|
34
|
-
|
|
45
|
+
defineSlots<{
|
|
35
46
|
default(): any
|
|
36
|
-
actions?(): any
|
|
37
47
|
}>()
|
|
38
48
|
|
|
39
|
-
const codeElement = useTemplateRef('code-element')
|
|
40
|
-
const codeTextValue = computed(() => codeElement.value?.textContent)
|
|
41
|
-
|
|
42
49
|
const mapping = {
|
|
43
50
|
small: {
|
|
44
51
|
labelClass: 'typo-body-regular-small',
|
|
@@ -57,10 +64,32 @@ const className = computed(() =>
|
|
|
57
64
|
accent,
|
|
58
65
|
})
|
|
59
66
|
)
|
|
67
|
+
|
|
68
|
+
const content = computed(() => {
|
|
69
|
+
if (typeof rawContent === 'object') {
|
|
70
|
+
return JSON.stringify(rawContent, null, 2)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return rawContent
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
const pre = document.createElement('pre')
|
|
77
|
+
|
|
78
|
+
watch(
|
|
79
|
+
() => content,
|
|
80
|
+
content => {
|
|
81
|
+
pre.textContent = content.value
|
|
82
|
+
},
|
|
83
|
+
{ immediate: true }
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
function openRawValueInNewTab() {
|
|
87
|
+
window.open('', '_blank')?.document.body.appendChild(pre)
|
|
88
|
+
}
|
|
60
89
|
</script>
|
|
61
90
|
|
|
62
91
|
<style lang="postcss" scoped>
|
|
63
|
-
.ui-
|
|
92
|
+
.ui-log-entry-viewer {
|
|
64
93
|
display: flex;
|
|
65
94
|
flex-direction: column;
|
|
66
95
|
gap: 0.4rem;
|
|
@@ -88,11 +117,19 @@ const className = computed(() =>
|
|
|
88
117
|
border-inline-start: 0.2rem solid;
|
|
89
118
|
white-space: pre-wrap;
|
|
90
119
|
word-break: break-word;
|
|
120
|
+
max-height: 18rem;
|
|
121
|
+
overflow: auto;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
&.accent--info {
|
|
125
|
+
.code-container {
|
|
126
|
+
border-inline-start-color: var(--color-info-item-base);
|
|
127
|
+
}
|
|
91
128
|
}
|
|
92
129
|
|
|
93
|
-
&.accent--
|
|
130
|
+
&.accent--warning {
|
|
94
131
|
.code-container {
|
|
95
|
-
border-inline-start-color: var(--color-
|
|
132
|
+
border-inline-start-color: var(--color-warning-item-base);
|
|
96
133
|
}
|
|
97
134
|
}
|
|
98
135
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<RouterLink v-if="route && !disabled" :to="route" class="ui-object-link is-link typo-action-link-small">
|
|
4
4
|
<span class="icon">
|
|
5
5
|
<slot name="icon">
|
|
6
|
-
<VtsIcon :icon
|
|
6
|
+
<VtsIcon :name="icon" size="medium" />
|
|
7
7
|
</slot>
|
|
8
8
|
</span>
|
|
9
9
|
<span v-tooltip class="content text-ellipsis">
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<span v-else :class="{ disabled }" class="ui-object-link typo-action-link-small">
|
|
14
14
|
<span class="icon">
|
|
15
15
|
<slot name="icon">
|
|
16
|
-
<VtsIcon :icon
|
|
16
|
+
<VtsIcon :name="icon" size="medium" />
|
|
17
17
|
</slot>
|
|
18
18
|
</span>
|
|
19
19
|
<slot />
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
<script lang="ts" setup>
|
|
24
24
|
import VtsIcon from '@core/components/icon/VtsIcon.vue'
|
|
25
25
|
import { vTooltip } from '@core/directives/tooltip.directive'
|
|
26
|
-
import type {
|
|
26
|
+
import type { IconName } from '@core/icons'
|
|
27
27
|
import { type RouteLocationRaw } from 'vue-router'
|
|
28
28
|
|
|
29
29
|
defineProps<{
|
|
30
30
|
route?: RouteLocationRaw
|
|
31
31
|
disabled?: boolean
|
|
32
|
-
icon?:
|
|
32
|
+
icon?: IconName
|
|
33
33
|
}>()
|
|
34
34
|
|
|
35
35
|
defineSlots<{
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
type="text"
|
|
11
11
|
accent="brand"
|
|
12
12
|
:aria-label="uiStore.isMobile ? t('core.query-search-bar.label') : undefined"
|
|
13
|
-
:icon="!uiStore.isMobile ?
|
|
13
|
+
:icon="!uiStore.isMobile ? 'fa:magnifying-glass' : undefined"
|
|
14
14
|
:placeholder="t('core.query-search-bar.placeholder')"
|
|
15
15
|
/>
|
|
16
16
|
<template v-if="!uiStore.isMobile">
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
|
|
33
33
|
<!-- Mobile icons: search + filter -->
|
|
34
34
|
<template v-else>
|
|
35
|
-
<UiButtonIcon accent="brand" size="medium" type="submit"
|
|
36
|
-
<UiButtonIcon accent="brand" size="medium" disabled
|
|
35
|
+
<UiButtonIcon accent="brand" size="medium" type="submit" icon="fa:magnifying-glass" class="action-button" />
|
|
36
|
+
<UiButtonIcon accent="brand" size="medium" disabled icon="fa:filter" class="action-button" />
|
|
37
37
|
</template>
|
|
38
38
|
</form>
|
|
39
39
|
</template>
|
|
@@ -46,7 +46,6 @@ import UiInput from '@core/components/ui/input/UiInput.vue'
|
|
|
46
46
|
import { vTooltip } from '@core/directives/tooltip.directive'
|
|
47
47
|
import { useUiStore } from '@core/stores/ui.store'
|
|
48
48
|
import { uniqueId } from '@core/utils/unique-id.util'
|
|
49
|
-
import { faFilter, faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons'
|
|
50
49
|
import { ref } from 'vue'
|
|
51
50
|
import { useI18n } from 'vue-i18n'
|
|
52
51
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<template>
|
|
3
3
|
<li class="ui-quick-task-item">
|
|
4
4
|
<div v-if="hasSubTasks" class="toggle" @click="toggleExpand()">
|
|
5
|
-
<UiButtonIcon accent="brand" :icon="isExpanded ?
|
|
5
|
+
<UiButtonIcon accent="brand" :icon="isExpanded ? 'fa:angle-down' : 'fa:angle-right'" size="small" />
|
|
6
6
|
</div>
|
|
7
7
|
<div class="content">
|
|
8
8
|
<div class="typo-body-bold">
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
<div class="line-1">
|
|
13
13
|
<UiTag v-if="task.tag" accent="neutral" variant="primary">{{ task.tag }}</UiTag>
|
|
14
14
|
<div v-if="hasSubTasks" class="subtasks">
|
|
15
|
-
<VtsIcon
|
|
15
|
+
<VtsIcon name="fa:circle-notch" size="medium" />
|
|
16
16
|
<span class="typo-body-regular-small">{{ t('tasks.n-subtasks', { n: subTasksCount }) }}</span>
|
|
17
17
|
</div>
|
|
18
18
|
</div>
|
|
19
19
|
<div v-if="task.start" class="line-2 typo-body-regular-small">
|
|
20
20
|
{{ d(task.start, 'datetime_short') }}
|
|
21
21
|
<template v-if="task.end">
|
|
22
|
-
<VtsIcon
|
|
22
|
+
<VtsIcon name="fa:arrow-right" size="medium" />
|
|
23
23
|
{{ d(new Date(task.end), 'datetime_short') }}
|
|
24
24
|
</template>
|
|
25
25
|
</div>
|
|
@@ -34,7 +34,6 @@ import VtsIcon from '@core/components/icon/VtsIcon.vue'
|
|
|
34
34
|
import VtsQuickTaskList from '@core/components/task/VtsQuickTaskList.vue'
|
|
35
35
|
import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
|
|
36
36
|
import UiTag from '@core/components/ui/tag/UiTag.vue'
|
|
37
|
-
import { faAngleDown, faAngleRight, faArrowRight, faCircleNotch } from '@fortawesome/free-solid-svg-icons'
|
|
38
37
|
import { useToggle } from '@vueuse/core'
|
|
39
38
|
import { computed } from 'vue'
|
|
40
39
|
import { useI18n } from 'vue-i18n'
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<label :class="variant" class="ui-radio-button typo-body-regular">
|
|
4
4
|
<span class="radio-container">
|
|
5
5
|
<input v-model="model" :disabled="isDisabled" :value class="input" type="radio" />
|
|
6
|
-
<VtsIcon
|
|
6
|
+
<VtsIcon name="fa:circle" size="medium" class="radio-icon" />
|
|
7
7
|
</span>
|
|
8
8
|
<slot />
|
|
9
9
|
</label>
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
import VtsIcon from '@core/components/icon/VtsIcon.vue'
|
|
14
14
|
import { useDisabled } from '@core/composables/disabled.composable'
|
|
15
15
|
import { toVariants } from '@core/utils/to-variants.util'
|
|
16
|
-
import { faCircle } from '@fortawesome/free-solid-svg-icons'
|
|
17
16
|
import { computed } from 'vue'
|
|
18
17
|
|
|
19
18
|
const { accent, value, disabled } = defineProps<{
|
|
@@ -4,33 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
<script setup lang="ts">
|
|
6
6
|
import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
|
|
7
|
-
import type {
|
|
7
|
+
import type { IconName } from '@core/icons'
|
|
8
8
|
|
|
9
9
|
defineProps<{
|
|
10
10
|
disabled: boolean
|
|
11
|
-
icon:
|
|
11
|
+
icon: IconName
|
|
12
12
|
}>()
|
|
13
13
|
</script>
|
|
14
|
-
|
|
15
|
-
<style scoped lang="postcss">
|
|
16
|
-
.pagination-button.accent--brand {
|
|
17
|
-
border: 0.1rem solid var(--color-neutral-border);
|
|
18
|
-
font-size: 1rem;
|
|
19
|
-
/* Override UiButtonIcon size to match DS */
|
|
20
|
-
width: 3rem;
|
|
21
|
-
height: 3rem;
|
|
22
|
-
|
|
23
|
-
&:hover {
|
|
24
|
-
border-color: var(--color-brand-item-hover);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
&:active {
|
|
28
|
-
border-color: var(--color-brand-item-active);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
&:disabled {
|
|
32
|
-
background-color: var(--color-neutral-background-disabled);
|
|
33
|
-
border-color: transparent;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
</style>
|
|
@@ -1,45 +1,41 @@
|
|
|
1
|
-
<!--
|
|
1
|
+
<!-- v5 -->
|
|
2
2
|
<template>
|
|
3
|
-
<div class="ui-table-pagination">
|
|
4
|
-
<div class="
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<
|
|
3
|
+
<div class="ui-table-pagination" :class="className">
|
|
4
|
+
<div class="container">
|
|
5
|
+
<span class="typo-body-regular-small label">
|
|
6
|
+
{{ t('core.select.n-object-of', { from, to, total }) }}
|
|
7
|
+
</span>
|
|
8
|
+
<div class="buttons-container">
|
|
9
|
+
<PaginationButton :disabled="isFirstPage" icon="fa:angle-double-left" @click="emit('first')" />
|
|
10
|
+
<PaginationButton :disabled="isFirstPage" icon="fa:angle-left" @click="emit('previous')" />
|
|
11
|
+
<PaginationButton :disabled="isLastPage" icon="fa:angle-right" @click="emit('next')" />
|
|
12
|
+
<PaginationButton :disabled="isLastPage" icon="fa:angle-double-right" @click="emit('last')" />
|
|
13
|
+
</div>
|
|
9
14
|
</div>
|
|
10
|
-
<
|
|
11
|
-
{{ t('core.
|
|
12
|
-
|
|
13
|
-
<span class="typo-body-regular-small label show">{{ t('core.pagination.show-by') }}</span>
|
|
14
|
-
<div class="dropdown-wrapper">
|
|
15
|
-
<select v-model="showBy" class="dropdown typo-body-regular-small">
|
|
16
|
-
<option v-for="option in [12, 24, 48, -1]" :key="option" :value="option" class="typo-body-bold-small">
|
|
17
|
-
{{ option === -1 ? t('core.pagination.all') : option }}
|
|
18
|
-
</option>
|
|
19
|
-
</select>
|
|
20
|
-
<VtsIcon :icon="faAngleDown" accent="current" class="icon" />
|
|
15
|
+
<div class="container">
|
|
16
|
+
<span class="typo-body-regular-small label show">{{ t('core.pagination.show-by') }}</span>
|
|
17
|
+
<VtsSelect :id="showBySelectId" accent="brand" class="typo-body-regular-small show-by-select" />
|
|
21
18
|
</div>
|
|
22
19
|
</div>
|
|
23
20
|
</template>
|
|
24
21
|
|
|
25
22
|
<script lang="ts" setup>
|
|
26
|
-
import
|
|
23
|
+
import VtsSelect from '@core/components/select/VtsSelect.vue'
|
|
27
24
|
import PaginationButton from '@core/components/ui/table-pagination/PaginationButton.vue'
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
faAngleDown,
|
|
32
|
-
faAngleLeft,
|
|
33
|
-
faAngleRight,
|
|
34
|
-
} from '@fortawesome/free-solid-svg-icons'
|
|
25
|
+
import { useFormSelect } from '@core/packages/form-select'
|
|
26
|
+
import { toVariants } from '@core/utils/to-variants.util.ts'
|
|
27
|
+
import { computed } from 'vue'
|
|
35
28
|
import { useI18n } from 'vue-i18n'
|
|
36
29
|
|
|
37
|
-
|
|
30
|
+
export type TablePaginationSize = 'small' | 'medium'
|
|
31
|
+
|
|
32
|
+
const { size } = defineProps<{
|
|
38
33
|
from: number
|
|
39
34
|
to: number
|
|
40
35
|
total: number
|
|
41
36
|
isFirstPage: boolean
|
|
42
37
|
isLastPage: boolean
|
|
38
|
+
size: TablePaginationSize
|
|
43
39
|
}>()
|
|
44
40
|
|
|
45
41
|
const emit = defineEmits<{
|
|
@@ -51,7 +47,16 @@ const emit = defineEmits<{
|
|
|
51
47
|
|
|
52
48
|
const showBy = defineModel<number>('showBy', { default: 24 })
|
|
53
49
|
|
|
50
|
+
const className = computed(() => toVariants({ size }))
|
|
51
|
+
|
|
54
52
|
const { t } = useI18n()
|
|
53
|
+
|
|
54
|
+
const { id: showBySelectId } = useFormSelect([12, 24, 48, -1], {
|
|
55
|
+
model: showBy,
|
|
56
|
+
option: {
|
|
57
|
+
label: option => (option === -1 ? t('core.pagination.all') : option.toString()),
|
|
58
|
+
},
|
|
59
|
+
})
|
|
55
60
|
</script>
|
|
56
61
|
|
|
57
62
|
<style lang="postcss" scoped>
|
|
@@ -60,6 +65,21 @@ const { t } = useI18n()
|
|
|
60
65
|
align-items: center;
|
|
61
66
|
gap: 0.8rem;
|
|
62
67
|
|
|
68
|
+
&.size--small {
|
|
69
|
+
flex-direction: column;
|
|
70
|
+
align-items: flex-end;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&.size--medium {
|
|
74
|
+
flex-direction: row;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.container {
|
|
78
|
+
display: flex;
|
|
79
|
+
gap: 0.8rem;
|
|
80
|
+
align-items: center;
|
|
81
|
+
}
|
|
82
|
+
|
|
63
83
|
.buttons-container {
|
|
64
84
|
display: flex;
|
|
65
85
|
gap: 0.2rem;
|
|
@@ -69,78 +89,19 @@ const { t } = useI18n()
|
|
|
69
89
|
color: var(--color-neutral-txt-secondary);
|
|
70
90
|
}
|
|
71
91
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.dropdown-wrapper {
|
|
78
|
-
position: relative;
|
|
92
|
+
/* Workaround: we don't have "small" select yet */
|
|
93
|
+
.show-by-select {
|
|
94
|
+
width: 6rem;
|
|
79
95
|
|
|
80
|
-
.
|
|
81
|
-
cursor: pointer;
|
|
82
|
-
padding: 0.2rem 0.6rem;
|
|
96
|
+
&:deep(.ui-input) {
|
|
83
97
|
height: 3rem;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
color: var(--color-brand-txt-base);
|
|
88
|
-
border: 0.1rem solid var(--color-neutral-border);
|
|
89
|
-
background-color: var(--color-neutral-background-primary);
|
|
90
|
-
|
|
91
|
-
&:hover {
|
|
92
|
-
border-color: var(--color-brand-item-hover);
|
|
93
|
-
background-color: var(--color-brand-background-hover);
|
|
94
|
-
color: var(--color-brand-txt-hover);
|
|
95
|
-
|
|
96
|
-
+ .icon {
|
|
97
|
-
color: var(--color-brand-txt-hover);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
&:disabled {
|
|
102
|
-
cursor: not-allowed;
|
|
103
|
-
background-color: var(--color-neutral-background-disabled);
|
|
104
|
-
color: var(--color-neutral-txt-secondary);
|
|
105
|
-
border-color: transparent;
|
|
106
|
-
|
|
107
|
-
+ .icon {
|
|
108
|
-
color: var(--color-neutral-txt-secondary);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
&:active {
|
|
113
|
-
background-color: var(--color-brand-background-active);
|
|
114
|
-
border-color: var(--color-brand-item-active);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
&:focus-visible {
|
|
118
|
-
outline: 0.1rem solid var(--color-brand-item-base);
|
|
119
|
-
border: 0.1rem solid var(--color-brand-item-base);
|
|
120
|
-
color: var(--color-brand-txt-base);
|
|
121
|
-
background-color: var(--color-brand-background-selected);
|
|
122
|
-
|
|
123
|
-
+ .icon {
|
|
124
|
-
color: var(--color-brand-txt-base);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
option {
|
|
129
|
-
background-color: var(--color-neutral-background-primary);
|
|
130
|
-
border: 0.1rem solid var(--color-neutral-border);
|
|
131
|
-
border-radius: 0.4rem;
|
|
132
|
-
color: var(--color-neutral-txt-primary);
|
|
133
|
-
}
|
|
98
|
+
padding-inline: 0.8rem;
|
|
99
|
+
gap: 0.8rem;
|
|
100
|
+
min-width: 6rem;
|
|
134
101
|
}
|
|
135
102
|
|
|
136
|
-
.
|
|
137
|
-
|
|
138
|
-
top: 50%;
|
|
139
|
-
right: 0.8rem;
|
|
140
|
-
transform: translateY(-50%);
|
|
141
|
-
pointer-events: none;
|
|
142
|
-
font-size: 1rem;
|
|
143
|
-
color: var(--color-brand-txt-base);
|
|
103
|
+
&:deep(.input) {
|
|
104
|
+
font-size: 1.4rem;
|
|
144
105
|
}
|
|
145
106
|
}
|
|
146
107
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<template>
|
|
4
4
|
<span :class="toVariants({ accent, variant })" class="ui-tag typo-body-regular-small">
|
|
5
5
|
<slot name="icon">
|
|
6
|
-
<VtsIcon :icon
|
|
6
|
+
<VtsIcon :name="icon" size="medium" />
|
|
7
7
|
</slot>
|
|
8
8
|
<span class="text-ellipsis"><slot /></span>
|
|
9
9
|
</span>
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
<script lang="ts" setup>
|
|
13
13
|
import VtsIcon from '@core/components/icon/VtsIcon.vue'
|
|
14
|
+
import type { IconName } from '@core/icons'
|
|
14
15
|
import { toVariants } from '@core/utils/to-variants.util'
|
|
15
|
-
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
|
16
16
|
|
|
17
17
|
type TagAccent = 'info' | 'neutral' | 'success' | 'warning' | 'danger' | 'muted'
|
|
18
18
|
type TagVariant = 'primary' | 'secondary'
|
|
@@ -20,7 +20,7 @@ type TagVariant = 'primary' | 'secondary'
|
|
|
20
20
|
defineProps<{
|
|
21
21
|
accent: TagAccent
|
|
22
22
|
variant: TagVariant
|
|
23
|
-
icon?:
|
|
23
|
+
icon?: IconName
|
|
24
24
|
}>()
|
|
25
25
|
|
|
26
26
|
defineSlots<{
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
import UiCharacterLimit from '@core/components/ui/character-limit/UiCharacterLimit.vue'
|
|
20
20
|
import UiInfo from '@core/components/ui/info/UiInfo.vue'
|
|
21
21
|
import UiLabel from '@core/components/ui/label/UiLabel.vue'
|
|
22
|
+
import type { IconName } from '@core/icons'
|
|
22
23
|
import { toVariants } from '@core/utils/to-variants.util'
|
|
23
|
-
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
|
24
24
|
import { useFocus } from '@vueuse/core'
|
|
25
25
|
import { computed, useAttrs, useId, useTemplateRef } from 'vue'
|
|
26
26
|
import { useI18n } from 'vue-i18n'
|
|
@@ -39,7 +39,7 @@ const {
|
|
|
39
39
|
maxCharacters?: number
|
|
40
40
|
disabled?: boolean
|
|
41
41
|
href?: string
|
|
42
|
-
icon?:
|
|
42
|
+
icon?: IconName
|
|
43
43
|
required?: boolean
|
|
44
44
|
}>()
|
|
45
45
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<template>
|
|
3
3
|
<div :class="toVariants({ accent })" class="ui-toaster">
|
|
4
4
|
<div class="content">
|
|
5
|
-
<VtsIcon class="information-icon" :
|
|
5
|
+
<VtsIcon class="information-icon" :name="icon" size="medium" />
|
|
6
6
|
<div>
|
|
7
7
|
<div class="typo-h5">
|
|
8
8
|
<slot />
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<slot name="description" />
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
14
|
-
<UiButtonIcon class="close-icon"
|
|
14
|
+
<UiButtonIcon class="close-icon" icon="fa:xmark" accent="brand" size="medium" @click="emit('close')" />
|
|
15
15
|
</div>
|
|
16
16
|
<div v-if="slots.actions" class="actions">
|
|
17
17
|
<slot name="actions" />
|
|
@@ -22,14 +22,13 @@
|
|
|
22
22
|
<script setup lang="ts">
|
|
23
23
|
import VtsIcon from '@core/components/icon/VtsIcon.vue'
|
|
24
24
|
import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
|
|
25
|
+
import type { IconName } from '@core/icons'
|
|
26
|
+
import { useMapper } from '@core/packages/mapper'
|
|
25
27
|
import { toVariants } from '@core/utils/to-variants.util'
|
|
26
|
-
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
|
27
|
-
import { faCheck, faCircle, faExclamation, faInfo, faXmark } from '@fortawesome/free-solid-svg-icons'
|
|
28
|
-
import { computed } from 'vue'
|
|
29
28
|
|
|
30
29
|
type ToasterAccent = 'info' | 'success' | 'warning' | 'danger'
|
|
31
30
|
|
|
32
|
-
const
|
|
31
|
+
const { accent } = defineProps<{
|
|
33
32
|
accent: ToasterAccent
|
|
34
33
|
}>()
|
|
35
34
|
|
|
@@ -43,13 +42,16 @@ const slots = defineSlots<{
|
|
|
43
42
|
actions?(): any
|
|
44
43
|
}>()
|
|
45
44
|
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
const icon = useMapper<ToasterAccent, IconName>(
|
|
46
|
+
() => accent,
|
|
47
|
+
{
|
|
48
|
+
info: 'legacy:status:info',
|
|
49
|
+
success: 'legacy:status:success',
|
|
50
|
+
warning: 'legacy:status:warning',
|
|
51
|
+
danger: 'legacy:status:danger',
|
|
52
|
+
},
|
|
53
|
+
'info'
|
|
54
|
+
)
|
|
53
55
|
</script>
|
|
54
56
|
|
|
55
57
|
<style scoped lang="postcss">
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
v-tooltip="isExpanded ? t('core.close') : t('core.open')"
|
|
20
20
|
class="toggle"
|
|
21
21
|
accent="brand"
|
|
22
|
-
:icon="isExpanded ?
|
|
22
|
+
:icon="isExpanded ? 'fa:angle-down' : 'fa:angle-right'"
|
|
23
23
|
size="small"
|
|
24
24
|
:target-scale="{ x: 1.5, y: 2 }"
|
|
25
25
|
@click="emit('toggle')"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<div v-else class="h-line" />
|
|
28
28
|
<a v-tooltip="{ selector: '.text' }" :href class="link typo-body-bold-small" @click="navigate">
|
|
29
29
|
<slot name="icon">
|
|
30
|
-
<VtsIcon :icon
|
|
30
|
+
<VtsIcon :name="icon" size="medium" class="icon" />
|
|
31
31
|
</slot>
|
|
32
32
|
<div class="text text-ellipsis">
|
|
33
33
|
<slot />
|
|
@@ -43,9 +43,8 @@ import VtsIcon from '@core/components/icon/VtsIcon.vue'
|
|
|
43
43
|
import VtsTreeLine from '@core/components/tree/VtsTreeLine.vue'
|
|
44
44
|
import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
|
|
45
45
|
import { vTooltip } from '@core/directives/tooltip.directive'
|
|
46
|
+
import type { IconName } from '@core/icons'
|
|
46
47
|
import { IK_TREE_ITEM_EXPANDED, IK_TREE_ITEM_HAS_CHILDREN, IK_TREE_LIST_DEPTH } from '@core/utils/injection-keys.util'
|
|
47
|
-
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
|
48
|
-
import { faAngleDown, faAngleRight } from '@fortawesome/free-solid-svg-icons'
|
|
49
48
|
import { inject, ref, useAttrs } from 'vue'
|
|
50
49
|
import { useI18n } from 'vue-i18n'
|
|
51
50
|
import type { RouteLocationRaw } from 'vue-router'
|
|
@@ -56,7 +55,7 @@ defineOptions({
|
|
|
56
55
|
|
|
57
56
|
defineProps<{
|
|
58
57
|
route: RouteLocationRaw
|
|
59
|
-
icon?:
|
|
58
|
+
icon?: IconName
|
|
60
59
|
active?: boolean
|
|
61
60
|
}>()
|
|
62
61
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# `useDefaultTab` Composable
|
|
2
|
+
|
|
3
|
+
This composable manages automatic navigation to default tabs and remembers the last visited tab for a given router dispatcher.
|
|
4
|
+
|
|
5
|
+
## How it works
|
|
6
|
+
|
|
7
|
+
The composable watches route changes and:
|
|
8
|
+
|
|
9
|
+
- Automatically redirects to the remembered or default tab when navigating to the base dispatcher route
|
|
10
|
+
- Stores the current tab in localStorage for future visits
|
|
11
|
+
- Uses the naming convention `{dispatcherRouteName}/{tabName}` for tab route names
|
|
12
|
+
|
|
13
|
+
## Parameters
|
|
14
|
+
|
|
15
|
+
| Name | Type | Required | Description |
|
|
16
|
+
| --------------------- | -------- | :------: | ----------------------------------------------- |
|
|
17
|
+
| `dispatcherRouteName` | `string` | ✓ | Dispatcher page route name (e.g., '/pool/<id>') |
|
|
18
|
+
| `defaultTab` | `string` | ✓ | Default tab name (e.g., 'dashboard') |
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// In the dispatcher page component (e.g., `pages/pool/[id].vue`)
|
|
24
|
+
useDefaultTab('pool/[id]', 'dashboard')
|
|
25
|
+
|
|
26
|
+
// User first navigates to /pool/123
|
|
27
|
+
// → Automatic redirect to /pool/123/dashboard (default tab)
|
|
28
|
+
|
|
29
|
+
// User then navigates to /pool/123/stats
|
|
30
|
+
// → 'stats' is stored as the last visited tab for this route
|
|
31
|
+
|
|
32
|
+
// Finally, user navigates to /pool/456
|
|
33
|
+
// → Automatic redirect to /pool/456/stats
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Storage
|
|
37
|
+
|
|
38
|
+
Tab preferences are stored in localStorage under the key `default-tabs` with the structure:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
Map<string, string> // dispatcherRouteName -> lastVisitedTab
|
|
42
|
+
```
|