@xen-orchestra/web-core 0.20.1 → 0.21.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/backup-state/VtsBackupState.vue +20 -17
- package/lib/components/cell-object/VtsCellObject.vue +4 -1
- package/lib/components/console/VtsActionsConsole.vue +7 -4
- package/lib/components/console/VtsClipboardConsole.vue +9 -6
- package/lib/components/copy-button/VtsCopyButton.vue +7 -14
- package/lib/components/dropdown/DropdownTitle.vue +5 -2
- package/lib/components/icon/NewVtsIcon.vue +49 -0
- package/lib/components/input-group/VtsInputGroup.vue +41 -0
- package/lib/components/input-wrapper/VtsInputWrapper.vue +2 -2
- package/lib/components/layout/VtsLayoutSidebar.vue +6 -3
- package/lib/components/linear-chart/VtsLinearChart.vue +4 -0
- package/lib/components/object-icon/VtsObjectIcon.vue +22 -0
- package/lib/components/quick-info-card/VtsQuickInfoCard.vue +4 -1
- package/lib/components/select/VtsOption.vue +10 -6
- package/lib/components/select/VtsSelect.vue +74 -50
- package/lib/components/state-hero/VtsAllDoneHero.vue +4 -1
- package/lib/components/state-hero/VtsAllGoodHero.vue +4 -1
- package/lib/components/state-hero/VtsComingSoonHero.vue +4 -1
- package/lib/components/state-hero/VtsErrorNoDataHero.vue +4 -1
- package/lib/components/state-hero/VtsLoadingHero.vue +4 -1
- package/lib/components/state-hero/VtsNoDataHero.vue +4 -1
- package/lib/components/state-hero/VtsNoSelectionHero.vue +4 -1
- package/lib/components/state-hero/VtsObjectNotFoundHero.vue +4 -1
- package/lib/components/state-hero/VtsOfflineHero.vue +4 -1
- package/lib/components/state-hero/VtsPageNotFoundHero.vue +4 -1
- package/lib/components/table/ColumnTitle.vue +2 -2
- package/lib/components/task/VtsQuickTaskButton.vue +4 -1
- package/lib/components/task/VtsQuickTaskList.vue +5 -2
- package/lib/components/task/VtsQuickTaskTabBar.vue +8 -5
- package/lib/components/ui/card-numbers/UiCardNumbers.vue +4 -1
- package/lib/components/ui/character-limit/UiCharacterLimit.vue +4 -1
- package/lib/components/ui/input/UiInput.vue +2 -2
- package/lib/components/ui/label/UiLabel.vue +4 -1
- package/lib/components/ui/progress-bar/UiProgressBar.vue +5 -2
- package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +9 -6
- package/lib/components/ui/quick-task-item/UiQuickTaskItem.vue +6 -3
- package/lib/components/ui/stacked-bar/StackedBarSegment.vue +4 -1
- package/lib/components/ui/table-pagination/UiTablePagination.vue +6 -3
- package/lib/components/ui/text-area/UiTextarea.vue +4 -1
- package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +6 -3
- package/lib/components/ui/tree-item-label/UiTreeItemLabel.vue +4 -1
- package/lib/composables/local-time-ago.composable.ts +53 -0
- package/lib/composables/locale-time-ago.composable.ts +53 -0
- package/lib/icons/fa-icons.ts +164 -0
- package/lib/icons/index.ts +15 -0
- package/lib/icons/legacy-icons.ts +80 -0
- package/lib/icons/object-icons.ts +187 -0
- package/lib/layouts/CoreLayout.vue +7 -3
- package/lib/locales/cs.json +0 -1
- package/lib/locales/de.json +1 -1
- package/lib/locales/en.json +32 -4
- package/lib/locales/es.json +1 -1
- package/lib/locales/fr.json +31 -3
- package/lib/locales/it.json +1 -1
- package/lib/locales/nl.json +1 -1
- package/lib/locales/ru.json +1 -1
- package/lib/locales/sv.json +1 -2
- package/lib/packages/collection/README.md +23 -18
- package/lib/packages/collection/create-collection.ts +22 -21
- package/lib/packages/collection/create-item.ts +21 -20
- package/lib/packages/collection/create-use-subset.ts +23 -0
- package/lib/packages/collection/guess-item-id.ts +26 -16
- package/lib/packages/collection/index.ts +4 -0
- package/lib/packages/collection/types.ts +65 -37
- package/lib/packages/collection/use-collection.ts +68 -18
- package/lib/packages/collection/use-flag-registry.ts +38 -17
- package/lib/packages/form-select/guess-label.ts +45 -0
- package/lib/packages/form-select/guess-value.ts +23 -0
- package/lib/packages/form-select/index.ts +6 -0
- package/lib/packages/form-select/normalize-search-term.ts +11 -0
- package/lib/packages/form-select/types.ts +90 -42
- package/lib/packages/form-select/use-form-option-controller.ts +7 -3
- package/lib/packages/form-select/use-form-select-controller.ts +38 -27
- package/lib/packages/form-select/use-form-select-keyboard-navigation.ts +1 -1
- package/lib/packages/form-select/use-form-select.ts +308 -130
- package/lib/packages/icon/DisplayIcon.vue +25 -0
- package/lib/packages/icon/DisplayIconAny.vue +16 -0
- package/lib/packages/icon/DisplayIconSingle.vue +35 -0
- package/lib/packages/icon/DisplayIconStack.vue +34 -0
- package/lib/packages/icon/README.md +286 -0
- package/lib/packages/icon/create-icon-bindings.ts +27 -0
- package/lib/packages/icon/define-icon-pack.ts +23 -0
- package/lib/packages/icon/define-icon-single.ts +17 -0
- package/lib/packages/icon/define-icon-stack.ts +20 -0
- package/lib/packages/icon/define-icon.ts +40 -0
- package/lib/packages/icon/generate-icon-variants.ts +17 -0
- package/lib/packages/icon/index.ts +8 -0
- package/lib/packages/icon/is-icon-stack.ts +5 -0
- package/lib/packages/icon/merge-icons.ts +25 -0
- package/lib/packages/icon/merge-transforms.ts +12 -0
- package/lib/packages/icon/normalize-icon.ts +25 -0
- package/lib/packages/icon/to-tuple.ts +7 -0
- package/lib/packages/icon/types.ts +72 -0
- package/lib/packages/job/README.md +2 -2
- package/lib/packages/mapper/README.md +166 -0
- package/lib/packages/mapper/convert-to-map.ts +5 -0
- package/lib/packages/mapper/create-mapper.ts +30 -0
- package/lib/packages/mapper/index.ts +4 -0
- package/lib/packages/mapper/types.ts +1 -0
- package/lib/packages/mapper/use-mapper.ts +31 -0
- package/lib/stores/sidebar.store.ts +1 -1
- package/lib/types/chart.ts +2 -2
- package/lib/types/utility.type.ts +9 -0
- package/lib/utils/object.util.ts +16 -0
- package/lib/utils/size.util.ts +4 -2
- package/package.json +2 -1
- package/lib/components/backup-item/VtsBackupItem.vue +0 -47
- package/lib/composables/mapper.composable.md +0 -74
- package/lib/composables/mapper.composable.ts +0 -18
|
@@ -1,29 +1,32 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<UiInfo :accent="state.accent" class="vts-backup-state">
|
|
3
|
+
{{ state.text }}
|
|
4
|
+
</UiInfo>
|
|
3
5
|
</template>
|
|
4
6
|
|
|
5
7
|
<script lang="ts" setup>
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import { computed } from 'vue'
|
|
8
|
+
import UiInfo, { type InfoAccent } from '@core/components/ui/info/UiInfo.vue'
|
|
9
|
+
import { useMapper } from '@core/packages/mapper'
|
|
10
|
+
import { useI18n } from 'vue-i18n'
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
type Props = {
|
|
12
|
+
const { state: _state } = defineProps<{
|
|
14
13
|
state: BackupState
|
|
15
|
-
}
|
|
14
|
+
}>()
|
|
16
15
|
|
|
17
|
-
const
|
|
16
|
+
const { t } = useI18n()
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
success: { icon: faCheckCircle, color: 'success' },
|
|
21
|
-
partial: { icon: faCircleMinus, color: 'warning' },
|
|
22
|
-
failure: { icon: faCircleXmark, color: 'danger' },
|
|
23
|
-
}
|
|
18
|
+
type BackupState = 'success' | 'failure' | 'skipped' | 'interrupted'
|
|
24
19
|
|
|
25
|
-
const
|
|
26
|
-
|
|
20
|
+
const state = useMapper<BackupState, { text: string; accent: InfoAccent }>(
|
|
21
|
+
() => _state,
|
|
22
|
+
{
|
|
23
|
+
success: { text: t('success'), accent: 'success' },
|
|
24
|
+
failure: { text: t('failure'), accent: 'danger' },
|
|
25
|
+
skipped: { text: t('skipped'), accent: 'warning' },
|
|
26
|
+
interrupted: { text: t('interrupted'), accent: 'danger' },
|
|
27
|
+
},
|
|
28
|
+
'failure'
|
|
29
|
+
)
|
|
27
30
|
</script>
|
|
28
31
|
|
|
29
32
|
<style lang="postcss" scoped>
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
accent="brand"
|
|
16
16
|
@click="copy(id)"
|
|
17
17
|
>
|
|
18
|
-
{{ copied ?
|
|
18
|
+
{{ copied ? t('core.copied') : t('core.copy-id') }}
|
|
19
19
|
</UiButton>
|
|
20
20
|
</template>
|
|
21
21
|
</div>
|
|
@@ -27,12 +27,15 @@ import UiButton from '@core/components/ui/button/UiButton.vue'
|
|
|
27
27
|
import { vTooltip } from '@core/directives/tooltip.directive'
|
|
28
28
|
import { faCopy } from '@fortawesome/free-solid-svg-icons'
|
|
29
29
|
import { useClipboard } from '@vueuse/core'
|
|
30
|
+
import { useI18n } from 'vue-i18n'
|
|
30
31
|
|
|
31
32
|
defineProps<{
|
|
32
33
|
id?: string
|
|
33
34
|
copiableId?: boolean
|
|
34
35
|
}>()
|
|
35
36
|
|
|
37
|
+
const { t } = useI18n()
|
|
38
|
+
|
|
36
39
|
const { isSupported, copy, copied } = useClipboard()
|
|
37
40
|
</script>
|
|
38
41
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<UiCardTitle>{{
|
|
2
|
+
<UiCardTitle>{{ t('console-actions') }}</UiCardTitle>
|
|
3
3
|
<UiButton
|
|
4
4
|
class="button"
|
|
5
5
|
accent="brand"
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
:left-icon="isFullscreen ? faDownLeftAndUpRightToCenter : faUpRightAndDownLeftFromCenter"
|
|
9
9
|
@click="toggleFullScreen"
|
|
10
10
|
>
|
|
11
|
-
{{
|
|
11
|
+
{{ t(isFullscreen ? 'exit-fullscreen' : 'fullscreen') }}
|
|
12
12
|
</UiButton>
|
|
13
13
|
<UiButton
|
|
14
14
|
class="button"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
:left-icon="faArrowUpRightFromSquare"
|
|
19
19
|
@click="openInNewTab"
|
|
20
20
|
>
|
|
21
|
-
{{
|
|
21
|
+
{{ t('open-console-in-new-tab') }}
|
|
22
22
|
</UiButton>
|
|
23
23
|
<UiButton
|
|
24
24
|
class="button"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
:left-icon="faKeyboard"
|
|
29
29
|
@click="sendCtrlAltDel"
|
|
30
30
|
>
|
|
31
|
-
{{
|
|
31
|
+
{{ t('send-ctrl-alt-del') }}
|
|
32
32
|
</UiButton>
|
|
33
33
|
</template>
|
|
34
34
|
|
|
@@ -45,12 +45,15 @@ import {
|
|
|
45
45
|
import { useActiveElement, useMagicKeys, whenever } from '@vueuse/core'
|
|
46
46
|
import { logicAnd } from '@vueuse/math'
|
|
47
47
|
import { computed } from 'vue'
|
|
48
|
+
import { useI18n } from 'vue-i18n'
|
|
48
49
|
import { useRouter } from 'vue-router'
|
|
49
50
|
|
|
50
51
|
defineProps<{
|
|
51
52
|
sendCtrlAltDel: () => void
|
|
52
53
|
}>()
|
|
53
54
|
|
|
55
|
+
const { t } = useI18n()
|
|
56
|
+
|
|
54
57
|
const router = useRouter()
|
|
55
58
|
const uiStore = useUiStore()
|
|
56
59
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="vts-clipboard-console">
|
|
3
|
-
<UiCardTitle>{{
|
|
4
|
-
<UiTextarea v-tooltip="
|
|
3
|
+
<UiCardTitle>{{ t('console-clipboard') }}</UiCardTitle>
|
|
4
|
+
<UiTextarea v-tooltip="t('coming-soon')" accent="brand" disabled :model-value="modelValue" />
|
|
5
5
|
<div class="buttons-container">
|
|
6
|
-
<UiButton v-tooltip="
|
|
7
|
-
{{
|
|
6
|
+
<UiButton v-tooltip="t('coming-soon')" accent="brand" variant="primary" size="medium" disabled>
|
|
7
|
+
{{ t('send') }}
|
|
8
8
|
</UiButton>
|
|
9
|
-
<UiButton v-tooltip="
|
|
10
|
-
{{
|
|
9
|
+
<UiButton v-tooltip="t('coming-soon')" accent="brand" variant="secondary" size="medium" disabled>
|
|
10
|
+
{{ t('receive') }}
|
|
11
11
|
</UiButton>
|
|
12
12
|
</div>
|
|
13
13
|
</div>
|
|
@@ -19,8 +19,11 @@ import UiCardTitle from '@core/components/ui/card-title/UiCardTitle.vue'
|
|
|
19
19
|
import UiTextarea from '@core/components/ui/text-area/UiTextarea.vue'
|
|
20
20
|
import { vTooltip } from '@core/directives/tooltip.directive'
|
|
21
21
|
import { ref } from 'vue'
|
|
22
|
+
import { useI18n } from 'vue-i18n'
|
|
22
23
|
|
|
23
24
|
const modelValue = ref('')
|
|
25
|
+
|
|
26
|
+
const { t } = useI18n()
|
|
24
27
|
</script>
|
|
25
28
|
|
|
26
29
|
<style lang="postcss" scoped>
|
|
@@ -1,29 +1,22 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<UiButtonIcon v-tooltip="copied &&
|
|
2
|
+
<UiButtonIcon v-tooltip="copied && t('core.copied')" :icon size="medium" accent="brand" @click="copy()" />
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script setup lang="ts">
|
|
6
6
|
import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
|
|
7
7
|
import { vTooltip } from '@core/directives/tooltip.directive'
|
|
8
8
|
import { faCheckCircle, faCopy } from '@fortawesome/free-solid-svg-icons'
|
|
9
|
-
import { useClipboard
|
|
10
|
-
import {
|
|
9
|
+
import { useClipboard } from '@vueuse/core'
|
|
10
|
+
import { computed } from 'vue'
|
|
11
|
+
import { useI18n } from 'vue-i18n'
|
|
11
12
|
|
|
12
13
|
const { value } = defineProps<{
|
|
13
14
|
value: string
|
|
14
15
|
}>()
|
|
15
16
|
|
|
16
|
-
const {
|
|
17
|
+
const { t } = useI18n()
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
+
const { copy, copied } = useClipboard({ source: () => value })
|
|
19
20
|
|
|
20
|
-
const
|
|
21
|
-
icon.value = faCopy
|
|
22
|
-
}, 1_500) // 1.5s is time to toltips is visible
|
|
23
|
-
|
|
24
|
-
function copyToClipboard() {
|
|
25
|
-
copy(value)
|
|
26
|
-
icon.value = faCheckCircle
|
|
27
|
-
changeIcon()
|
|
28
|
-
}
|
|
21
|
+
const icon = computed(() => (copied.value ? faCheckCircle : faCopy))
|
|
29
22
|
</script>
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
</div>
|
|
11
11
|
<div v-if="onToggleSelectAll" class="buttons">
|
|
12
12
|
<span v-if="selected !== 'all'" @click="emit('toggleSelectAll', true)">
|
|
13
|
-
{{
|
|
13
|
+
{{ t('core.select.all') }}
|
|
14
14
|
</span>
|
|
15
15
|
<span v-if="selected !== 'none'" @click="emit('toggleSelectAll', false)">
|
|
16
|
-
{{
|
|
16
|
+
{{ t('core.select.none') }}
|
|
17
17
|
</span>
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
<script lang="ts" setup>
|
|
23
23
|
import VtsIcon from '@core/components/icon/VtsIcon.vue'
|
|
24
24
|
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
|
25
|
+
import { useI18n } from 'vue-i18n'
|
|
25
26
|
|
|
26
27
|
withDefaults(
|
|
27
28
|
defineProps<{
|
|
@@ -35,6 +36,8 @@ withDefaults(
|
|
|
35
36
|
const emit = defineEmits<{
|
|
36
37
|
toggleSelectAll: [value: boolean]
|
|
37
38
|
}>()
|
|
39
|
+
|
|
40
|
+
const { t } = useI18n()
|
|
38
41
|
</script>
|
|
39
42
|
|
|
40
43
|
<style lang="postcss" scoped>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<DisplayIcon v-if="icon" class="vts-icon" :class="className" :icon />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script lang="ts" setup>
|
|
6
|
+
import { type IconName, icons } from '@core/icons'
|
|
7
|
+
import { DisplayIcon } from '@core/packages/icon'
|
|
8
|
+
import { toVariants } from '@core/utils/to-variants.util.ts'
|
|
9
|
+
import { computed } from 'vue'
|
|
10
|
+
|
|
11
|
+
export type IconSize = 'small' | 'medium' | 'large' | 'current'
|
|
12
|
+
|
|
13
|
+
const { size, name } = defineProps<{
|
|
14
|
+
size: IconSize
|
|
15
|
+
name: IconName
|
|
16
|
+
}>()
|
|
17
|
+
|
|
18
|
+
const className = computed(() =>
|
|
19
|
+
toVariants({
|
|
20
|
+
size: size === 'current' ? undefined : size,
|
|
21
|
+
})
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
const icon = computed(() => {
|
|
25
|
+
const icon = icons[name]
|
|
26
|
+
|
|
27
|
+
if (icon === undefined) {
|
|
28
|
+
console.warn(`Icon "${name}" not found.`)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return icon
|
|
32
|
+
})
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<style lang="postcss" scoped>
|
|
36
|
+
.vts-icon {
|
|
37
|
+
&.size--small {
|
|
38
|
+
font-size: 1.2rem;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&.size--medium {
|
|
42
|
+
font-size: 1.6rem;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&.size--large {
|
|
46
|
+
font-size: 2rem;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
</style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="vts-input-group">
|
|
3
|
+
<slot />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<style lang="postcss" scoped>
|
|
8
|
+
.vts-input-group {
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
|
|
12
|
+
:slotted(> .ui-input),
|
|
13
|
+
:slotted(> .vts-select) {
|
|
14
|
+
&:hover {
|
|
15
|
+
z-index: 1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
&:focus-within {
|
|
19
|
+
z-index: 2;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&:not(:first-child) {
|
|
23
|
+
margin-left: -1px;
|
|
24
|
+
|
|
25
|
+
&,
|
|
26
|
+
.ui-input {
|
|
27
|
+
border-start-start-radius: 0;
|
|
28
|
+
border-end-start-radius: 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&:not(:last-child) {
|
|
33
|
+
&,
|
|
34
|
+
.ui-input {
|
|
35
|
+
border-start-end-radius: 0;
|
|
36
|
+
border-end-end-radius: 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
</style>
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
<script lang="ts" setup>
|
|
21
21
|
import UiInfo, { type InfoAccent } from '@core/components/ui/info/UiInfo.vue'
|
|
22
22
|
import UiLabel, { type LabelAccent } from '@core/components/ui/label/UiLabel.vue'
|
|
23
|
-
import { useMapper } from '@core/composables/mapper.composable'
|
|
24
23
|
import { useRanked } from '@core/composables/ranked.composable.ts'
|
|
24
|
+
import { useMapper } from '@core/packages/mapper/use-mapper.ts'
|
|
25
25
|
import type { MaybeArray } from '@core/types/utility.type'
|
|
26
26
|
import { IK_INPUT_WRAPPER_CONTROLLER } from '@core/utils/injection-keys.util'
|
|
27
27
|
import { toArray } from '@core/utils/to-array.utils'
|
|
@@ -70,7 +70,7 @@ const labelAccent = useMapper<InfoAccent, LabelAccent>(
|
|
|
70
70
|
danger: 'danger',
|
|
71
71
|
muted: 'neutral',
|
|
72
72
|
},
|
|
73
|
-
'
|
|
73
|
+
'info'
|
|
74
74
|
)
|
|
75
75
|
|
|
76
76
|
const wrapperController = reactive({
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
<div v-if="!ui.isMobile" class="lock">
|
|
7
7
|
<UiButtonIcon
|
|
8
8
|
v-tooltip="{
|
|
9
|
-
content: sidebar.isLocked ?
|
|
9
|
+
content: sidebar.isLocked ? t('core.sidebar.unlock') : t('core.sidebar.lock'),
|
|
10
10
|
placement: 'right',
|
|
11
11
|
}"
|
|
12
12
|
accent="brand"
|
|
13
13
|
size="medium"
|
|
14
|
-
:icon="sidebar.isLocked ?
|
|
14
|
+
:icon="sidebar.isLocked ? faThumbTackSlash : faThumbTack"
|
|
15
15
|
@click="sidebar.toggleLock()"
|
|
16
16
|
/>
|
|
17
17
|
</div>
|
|
@@ -38,7 +38,8 @@ import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
|
|
|
38
38
|
import { vTooltip } from '@core/directives/tooltip.directive'
|
|
39
39
|
import { useSidebarStore } from '@core/stores/sidebar.store'
|
|
40
40
|
import { useUiStore } from '@core/stores/ui.store'
|
|
41
|
-
import {
|
|
41
|
+
import { faThumbTack, faThumbTackSlash } from '@fortawesome/free-solid-svg-icons'
|
|
42
|
+
import { useI18n } from 'vue-i18n'
|
|
42
43
|
|
|
43
44
|
const slots = defineSlots<{
|
|
44
45
|
default(): any
|
|
@@ -46,6 +47,8 @@ const slots = defineSlots<{
|
|
|
46
47
|
footer?(): any
|
|
47
48
|
}>()
|
|
48
49
|
|
|
50
|
+
const { t } = useI18n()
|
|
51
|
+
|
|
49
52
|
const sidebar = useSidebarStore()
|
|
50
53
|
const ui = useUiStore()
|
|
51
54
|
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<NewVtsIcon :name="iconName" :size />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script generic="TType extends ObjectIconType" lang="ts" setup>
|
|
6
|
+
import NewVtsIcon, { type IconSize } from '@core/components/icon/NewVtsIcon.vue'
|
|
7
|
+
import type { ObjectIconName } from '@core/icons'
|
|
8
|
+
import { computed } from 'vue'
|
|
9
|
+
|
|
10
|
+
export type ObjectIconType = ObjectIconName extends `object:${infer TType}:${string}` ? TType : never
|
|
11
|
+
|
|
12
|
+
export type ObjectIconState<TType extends ObjectIconType> =
|
|
13
|
+
Extract<ObjectIconName, `object:${TType}:${string}`> extends `object:${TType}:${infer TState}` ? TState : never
|
|
14
|
+
|
|
15
|
+
const { type, state } = defineProps<{
|
|
16
|
+
type: TType
|
|
17
|
+
state: ObjectIconState<TType>
|
|
18
|
+
size: IconSize
|
|
19
|
+
}>()
|
|
20
|
+
|
|
21
|
+
const iconName = computed(() => `object:${type}:${state}` as ObjectIconName)
|
|
22
|
+
</script>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<UiCard class="vts-quick-info-card">
|
|
3
|
-
<UiCardTitle>{{
|
|
3
|
+
<UiCardTitle>{{ t('quick-info') }}</UiCardTitle>
|
|
4
4
|
<VtsLoadingHero v-if="loading" type="card" />
|
|
5
5
|
<div v-else class="info-container">
|
|
6
6
|
<slot />
|
|
@@ -12,10 +12,13 @@
|
|
|
12
12
|
import VtsLoadingHero from '@core/components/state-hero/VtsLoadingHero.vue'
|
|
13
13
|
import UiCard from '@core/components/ui/card/UiCard.vue'
|
|
14
14
|
import UiCardTitle from '@core/components/ui/card-title/UiCardTitle.vue'
|
|
15
|
+
import { useI18n } from 'vue-i18n'
|
|
15
16
|
|
|
16
17
|
defineProps<{
|
|
17
18
|
loading: boolean
|
|
18
19
|
}>()
|
|
20
|
+
|
|
21
|
+
const { t } = useI18n()
|
|
19
22
|
</script>
|
|
20
23
|
|
|
21
24
|
<style lang="postcss" scoped>
|
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<UiDropdown
|
|
3
3
|
ref="elementRef"
|
|
4
|
-
:
|
|
4
|
+
:accent
|
|
5
|
+
:checkbox="isMultiple"
|
|
5
6
|
:disabled="option.properties.disabled"
|
|
6
7
|
:hover="option.flags.active"
|
|
7
8
|
:selected="option.flags.selected"
|
|
8
|
-
accent="normal"
|
|
9
9
|
>
|
|
10
10
|
<slot>{{ option.properties.label }}</slot>
|
|
11
11
|
</UiDropdown>
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
|
-
<script generic="TOption extends FormOption" lang="ts" setup>
|
|
15
|
-
import UiDropdown from '@core/components/ui/dropdown/UiDropdown.vue'
|
|
16
|
-
import type
|
|
17
|
-
import {
|
|
14
|
+
<script generic="TOption extends FormOption<{ accent?: DropdownAccent }>" lang="ts" setup>
|
|
15
|
+
import UiDropdown, { type DropdownAccent } from '@core/components/ui/dropdown/UiDropdown.vue'
|
|
16
|
+
import { type FormOption, IK_FORM_SELECT_CONTROLLER, useFormOptionController } from '@core/packages/form-select'
|
|
17
|
+
import { computed, inject } from 'vue'
|
|
18
18
|
|
|
19
19
|
const { option } = defineProps<{
|
|
20
20
|
option: TOption
|
|
21
21
|
}>()
|
|
22
22
|
|
|
23
|
+
const accent = computed(() => option.properties.accent ?? 'normal')
|
|
24
|
+
|
|
23
25
|
const { elementRef } = useFormOptionController(() => option)
|
|
26
|
+
|
|
27
|
+
const { isMultiple } = inject(IK_FORM_SELECT_CONTROLLER)!
|
|
24
28
|
</script>
|
|
@@ -1,78 +1,101 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :class="className" class="vts-select">
|
|
3
|
-
<VtsBackdrop v-if="isOpen" />
|
|
4
|
-
|
|
5
3
|
<UiInput
|
|
6
4
|
ref="triggerRef"
|
|
7
5
|
:accent
|
|
6
|
+
:disabled="isDisabled"
|
|
7
|
+
:icon
|
|
8
8
|
:model-value="selectedLabel"
|
|
9
9
|
:placeholder
|
|
10
|
-
:required
|
|
10
|
+
:required="isRequired"
|
|
11
11
|
:right-icon="faAngleDown"
|
|
12
12
|
readonly
|
|
13
13
|
/>
|
|
14
14
|
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
15
|
+
<Teleport v-if="isOpen" to="body">
|
|
16
|
+
<VtsBackdrop />
|
|
17
|
+
|
|
18
|
+
<UiDropdownList ref="dropdownRef" :style="floatingStyles" class="dropdown-list">
|
|
19
|
+
<template v-if="isSearchable" #before>
|
|
20
|
+
<div class="search-container">
|
|
21
|
+
<UiInput
|
|
22
|
+
ref="searchRef"
|
|
23
|
+
v-model="searchTerm"
|
|
24
|
+
:placeholder="searchPlaceholder"
|
|
25
|
+
:right-icon="faMagnifyingGlass"
|
|
26
|
+
accent="brand"
|
|
27
|
+
/>
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
<UiDropdown v-if="isLoading || options.length === 0" accent="normal" disabled>
|
|
31
|
+
{{ isLoading ? t('loading-in-progress') : t('no-results') }}
|
|
32
|
+
</UiDropdown>
|
|
33
|
+
<template v-for="option of options" :key="option.id">
|
|
34
|
+
<slot :option="option as FormSelectIdToOption<TSelectId>">
|
|
35
|
+
<VtsOption :option />
|
|
36
|
+
</slot>
|
|
37
|
+
</template>
|
|
38
|
+
</UiDropdownList>
|
|
39
|
+
</Teleport>
|
|
36
40
|
</div>
|
|
37
41
|
</template>
|
|
38
42
|
|
|
39
|
-
<script generic="
|
|
43
|
+
<script generic="TSelectId extends FormSelectId" lang="ts" setup>
|
|
40
44
|
import VtsBackdrop from '@core/components/backdrop/VtsBackdrop.vue'
|
|
41
45
|
import VtsOption from '@core/components/select/VtsOption.vue'
|
|
42
46
|
import UiDropdown from '@core/components/ui/dropdown/UiDropdown.vue'
|
|
43
47
|
import UiDropdownList from '@core/components/ui/dropdown/UiDropdownList.vue'
|
|
44
48
|
import UiInput from '@core/components/ui/input/UiInput.vue'
|
|
45
|
-
import
|
|
46
|
-
|
|
49
|
+
import {
|
|
50
|
+
type FormSelect,
|
|
51
|
+
type FormSelectId,
|
|
52
|
+
type FormSelectIdToOption,
|
|
53
|
+
useFormSelectController,
|
|
54
|
+
} from '@core/packages/form-select'
|
|
47
55
|
import { toVariants } from '@core/utils/to-variants.util.ts'
|
|
56
|
+
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
|
48
57
|
import { faAngleDown, faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons'
|
|
49
|
-
import {
|
|
58
|
+
import { useCurrentElement, useElementSize } from '@vueuse/core'
|
|
59
|
+
import { computed, inject } from 'vue'
|
|
50
60
|
import { useI18n } from 'vue-i18n'
|
|
51
61
|
|
|
52
|
-
const { accent,
|
|
62
|
+
const { accent, id } = defineProps<{
|
|
53
63
|
accent: 'brand' | 'warning' | 'danger'
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
required?: boolean
|
|
57
|
-
placeholder?: string
|
|
58
|
-
searchPlaceholder?: string
|
|
59
|
-
loading?: boolean
|
|
64
|
+
id: TSelectId
|
|
65
|
+
icon?: IconDefinition
|
|
60
66
|
}>()
|
|
61
67
|
|
|
62
|
-
const searchTerm = defineModel<string>('search')
|
|
63
|
-
|
|
64
68
|
defineSlots<{
|
|
65
|
-
default(props: { option:
|
|
69
|
+
default(props: { option: FormSelectIdToOption<TSelectId> }): any
|
|
66
70
|
}>()
|
|
67
71
|
|
|
68
72
|
const { t } = useI18n()
|
|
69
73
|
|
|
70
|
-
const
|
|
71
|
-
|
|
74
|
+
const select = inject(id)
|
|
75
|
+
|
|
76
|
+
if (!select) {
|
|
77
|
+
throw new Error(`No select configuration has been found for this ID`)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const {
|
|
81
|
+
options,
|
|
72
82
|
searchTerm,
|
|
73
|
-
|
|
83
|
+
selectedLabel,
|
|
84
|
+
isSearchable,
|
|
85
|
+
isDisabled,
|
|
86
|
+
isRequired,
|
|
87
|
+
placeholder,
|
|
88
|
+
searchPlaceholder,
|
|
89
|
+
isLoading,
|
|
90
|
+
} = select as FormSelect
|
|
91
|
+
|
|
92
|
+
const { triggerRef, dropdownRef, searchRef, isOpen, floatingStyles } = useFormSelectController(select as FormSelect)
|
|
74
93
|
|
|
75
94
|
const className = computed(() => toVariants({ accent }))
|
|
95
|
+
|
|
96
|
+
const { width } = useElementSize(useCurrentElement())
|
|
97
|
+
|
|
98
|
+
const minWidth = computed(() => `${width.value}px`)
|
|
76
99
|
</script>
|
|
77
100
|
|
|
78
101
|
<style lang="postcss" scoped>
|
|
@@ -80,17 +103,18 @@ const className = computed(() => toVariants({ accent }))
|
|
|
80
103
|
.ui-input:deep(input) {
|
|
81
104
|
cursor: default;
|
|
82
105
|
}
|
|
106
|
+
}
|
|
83
107
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
108
|
+
/* Teleported */
|
|
109
|
+
.dropdown-list {
|
|
110
|
+
min-width: v-bind(minWidth);
|
|
111
|
+
max-height: 36.2rem; /* 8 Dropdown items */
|
|
112
|
+
overflow: auto;
|
|
113
|
+
z-index: 1020;
|
|
89
114
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
115
|
+
.search-container {
|
|
116
|
+
background-color: var(--color-neutral-background-primary);
|
|
117
|
+
padding: 0.4rem;
|
|
94
118
|
}
|
|
95
119
|
}
|
|
96
120
|
</style>
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<VtsStateHero :type class="vts-all-done-hero" image="all-done">
|
|
3
|
-
{{
|
|
3
|
+
{{ t('all-done') }}
|
|
4
4
|
</VtsStateHero>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script lang="ts" setup>
|
|
8
8
|
import VtsStateHero, { type StateHeroType } from '@core/components/state-hero/VtsStateHero.vue'
|
|
9
|
+
import { useI18n } from 'vue-i18n'
|
|
9
10
|
|
|
10
11
|
defineProps<{
|
|
11
12
|
type: StateHeroType
|
|
12
13
|
}>()
|
|
14
|
+
|
|
15
|
+
const { t } = useI18n()
|
|
13
16
|
</script>
|