@xen-orchestra/web-core 0.38.0 → 0.39.1

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.
Files changed (53) hide show
  1. package/lib/components/card/VtsCardRowKeyValue.vue +2 -4
  2. package/lib/components/cell-object/VtsCellObject.vue +1 -1
  3. package/lib/components/console/VtsActionsConsole.vue +3 -3
  4. package/lib/components/console/VtsClipboardConsole.vue +4 -4
  5. package/lib/components/copy-button/VtsCopyButton.vue +1 -1
  6. package/lib/components/dropdown/VtsDropdownTitle.vue +2 -2
  7. package/lib/components/layout/VtsLayoutSidebar.vue +1 -1
  8. package/lib/components/{label-value-list/VtsLabelValueList.vue → recursive-fields/VtsRecursiveFields.vue} +4 -4
  9. package/lib/components/select/VtsSelect.vue +1 -1
  10. package/lib/components/state-hero/VtsStateHero.vue +1 -1
  11. package/lib/components/table/cells/VtsTruncatedTextCell.vue +1 -1
  12. package/lib/components/task/VtsQuickTaskButton.vue +2 -2
  13. package/lib/components/task/VtsQuickTaskList.vue +3 -2
  14. package/lib/components/task/VtsQuickTaskTabBar.vue +6 -6
  15. package/lib/components/ui/account-menu-button/UiAccountMenuButton.vue +1 -1
  16. package/lib/components/ui/breadcrumb/UiBreadcrumb.vue +1 -1
  17. package/lib/components/ui/character-limit/UiCharacterLimit.vue +1 -1
  18. package/lib/components/ui/circle-progress-bar/UiCircleProgressBar.vue +1 -1
  19. package/lib/components/ui/collapsible-list/UiCollapsibleList.vue +1 -1
  20. package/lib/components/ui/input/UiInput.vue +8 -4
  21. package/lib/components/ui/log-entry-viewer/UiLogEntryViewer.vue +1 -1
  22. package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +6 -6
  23. package/lib/components/ui/quick-task-item/UiQuickTaskItem.vue +2 -13
  24. package/lib/components/ui/quick-task-panel/UiQuickTaskPanel.vue +1 -1
  25. package/lib/components/ui/table-pagination/UiTablePagination.vue +3 -3
  26. package/lib/components/ui/task-item/UiTaskItem.vue +30 -17
  27. package/lib/components/ui/task-list/UiTaskList.vue +14 -3
  28. package/lib/components/ui/text-area/UiTextarea.vue +1 -1
  29. package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +3 -3
  30. package/lib/components/ui/tree-item-label/UiTreeItemLabel.vue +1 -1
  31. package/lib/i18n.ts +8 -4
  32. package/lib/layouts/CoreLayout.vue +1 -1
  33. package/lib/locales/cs.json +297 -294
  34. package/lib/locales/da.json +181 -200
  35. package/lib/locales/de.json +243 -251
  36. package/lib/locales/en.json +312 -310
  37. package/lib/locales/es.json +282 -300
  38. package/lib/locales/fa.json +239 -239
  39. package/lib/locales/fr.json +314 -312
  40. package/lib/locales/it.json +190 -186
  41. package/lib/locales/ja.json +23 -0
  42. package/lib/locales/ko.json +23 -1
  43. package/lib/locales/nb-NO.json +696 -0
  44. package/lib/locales/nl.json +296 -295
  45. package/lib/locales/pt-BR.json +170 -0
  46. package/lib/locales/ru.json +209 -206
  47. package/lib/locales/sv.json +244 -254
  48. package/lib/locales/uk.json +151 -149
  49. package/lib/packages/remote-resource/define-remote-resource.ts +37 -4
  50. package/lib/types/task.type.ts +15 -0
  51. package/package.json +1 -1
  52. package/lib/locales/nb_NO.json +0 -1
  53. package/lib/locales/pt_BR.json +0 -158
@@ -26,17 +26,15 @@ const slots = defineSlots<{
26
26
  .vts-card-row-key-value {
27
27
  display: flex;
28
28
  align-items: center;
29
- gap: 1.2rem;
29
+ gap: 1.6rem;
30
30
 
31
31
  .key {
32
- width: 12rem;
33
- min-width: 12rem;
34
32
  overflow-wrap: break-word;
35
33
  color: var(--color-neutral-txt-secondary);
36
34
  }
37
35
 
38
36
  .value {
39
- width: 20rem;
37
+ max-width: 25rem;
40
38
  color: var(--color-neutral-txt-primary);
41
39
  }
42
40
 
@@ -15,7 +15,7 @@
15
15
  accent="brand"
16
16
  @click="copy(id)"
17
17
  >
18
- {{ copied ? t('core.copied') : t('core.copy-id') }}
18
+ {{ copied ? t('copied') : t('action:copy-id') }}
19
19
  </UiButton>
20
20
  </template>
21
21
  </div>
@@ -8,7 +8,7 @@
8
8
  :left-icon="isFullscreen ? 'fa:down-left-and-up-right-to-center' : 'fa:up-right-and-down-left-from-center'"
9
9
  @click="toggleFullScreen"
10
10
  >
11
- {{ t(isFullscreen ? 'exit-fullscreen' : 'fullscreen') }}
11
+ {{ isFullscreen ? t('exit-fullscreen') : t('fullscreen') }}
12
12
  </UiButton>
13
13
  <UiButton
14
14
  class="button"
@@ -18,7 +18,7 @@
18
18
  left-icon="fa:arrow-up-right-from-square"
19
19
  @click="openInNewTab"
20
20
  >
21
- {{ t('open-console-in-new-tab') }}
21
+ {{ t('action:open-console-in-new-tab') }}
22
22
  </UiButton>
23
23
  <UiButton
24
24
  class="button"
@@ -28,7 +28,7 @@
28
28
  left-icon="fa:keyboard"
29
29
  @click="sendCtrlAltDel"
30
30
  >
31
- {{ t('send-ctrl-alt-del') }}
31
+ {{ t('action:send-ctrl-alt-del') }}
32
32
  </UiButton>
33
33
  </template>
34
34
 
@@ -1,12 +1,12 @@
1
1
  <template>
2
2
  <div class="vts-clipboard-console">
3
3
  <UiCardTitle>{{ t('console-clipboard') }}</UiCardTitle>
4
- <UiTextarea v-tooltip="t('coming-soon')" accent="brand" disabled :model-value="modelValue" />
4
+ <UiTextarea v-tooltip="t('coming-soon!')" accent="brand" disabled :model-value="modelValue" />
5
5
  <div class="buttons-container">
6
- <UiButton v-tooltip="t('coming-soon')" accent="brand" variant="primary" size="medium" disabled>
7
- {{ t('send') }}
6
+ <UiButton v-tooltip="t('coming-soon!')" accent="brand" variant="primary" size="medium" disabled>
7
+ {{ t('action:send') }}
8
8
  </UiButton>
9
- <UiButton v-tooltip="t('coming-soon')" accent="brand" variant="secondary" size="medium" disabled>
9
+ <UiButton v-tooltip="t('coming-soon!')" accent="brand" variant="secondary" size="medium" disabled>
10
10
  {{ t('receive') }}
11
11
  </UiButton>
12
12
  </div>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <UiButtonIcon v-tooltip="copied && t('core.copied')" :icon size="small" accent="brand" @click="copy()" />
2
+ <UiButtonIcon v-tooltip="copied && t('copied')" :icon size="small" accent="brand" @click="copy()" />
3
3
  </template>
4
4
 
5
5
  <script setup lang="ts">
@@ -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
- {{ t('core.select.all') }}
13
+ {{ t('action:select-all') }}
14
14
  </span>
15
15
  <span v-if="selected !== 'none'" @click="emit('toggleSelectAll', false)">
16
- {{ t('core.select.none') }}
16
+ {{ t('action:select-none') }}
17
17
  </span>
18
18
  </div>
19
19
  </div>
@@ -6,7 +6,7 @@
6
6
  <div v-if="!ui.isMobile" class="lock">
7
7
  <UiButtonIcon
8
8
  v-tooltip="{
9
- content: sidebar.isLocked ? t('core.sidebar.unlock') : t('core.sidebar.lock'),
9
+ content: sidebar.isLocked ? t('action:sidebar-unlock') : t('action:sidebar-lock'),
10
10
  placement: 'right',
11
11
  }"
12
12
  accent="brand"
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <template v-for="(value, label) in fields" :key="label">
3
- <VtsCardRowKeyValue v-if="isPrimitiveOrBooleanString(value)">
3
+ <VtsCardRowKeyValue v-if="isPrimitiveOrBoolean(value)">
4
4
  <template #key>
5
5
  <span class="label">{{ label }}</span>
6
6
  </template>
@@ -16,7 +16,7 @@
16
16
  <VtsCopyButton :value="String(value)" />
17
17
  </template>
18
18
  </VtsCardRowKeyValue>
19
- <VtsLabelValueList v-else :fields="value" />
19
+ <VtsRecursiveFields v-else :fields="value" />
20
20
  </template>
21
21
  </template>
22
22
 
@@ -35,8 +35,8 @@ const isBooleanLike = (value: unknown): boolean => typeof value === 'boolean' ||
35
35
 
36
36
  const toBoolean = (value: unknown): boolean => value === true || value === 'true'
37
37
 
38
- const isPrimitiveOrBooleanString = (value: unknown): boolean =>
39
- ['number', 'string'].includes(typeof value) || isBooleanString(value)
38
+ const isPrimitiveOrBoolean = (value: unknown): boolean =>
39
+ ['number', 'string'].includes(typeof value) || isBooleanLike(value)
40
40
  </script>
41
41
 
42
42
  <style lang="postcss" scoped>
@@ -28,7 +28,7 @@
28
28
  </div>
29
29
  </template>
30
30
  <UiDropdown v-if="isLoading || options.length === 0" accent="normal" disabled>
31
- {{ isLoading ? t('loading') : t('no-results') }}
31
+ {{ isLoading ? t('loading') : t('no-result') }}
32
32
  </UiDropdown>
33
33
  <template v-for="option of options" :key="option.id">
34
34
  <slot :option="option as FormSelectIdToOption<TSelectId>">
@@ -3,7 +3,7 @@
3
3
  <UiLoader v-if="type === 'busy'" class="loader" />
4
4
  <img v-else-if="imageSrc" :src="imageSrc" :alt="type" class="image" />
5
5
  <div v-if="slots.default || success" :class="typoClass" class="content">
6
- <div v-if="success">{{ t('all-good') }}</div>
6
+ <div v-if="success">{{ t('all-good!') }}</div>
7
7
  <slot />
8
8
  </div>
9
9
  </div>
@@ -13,7 +13,7 @@
13
13
  class="typo-body-regular-small button"
14
14
  @click="toggleExpanded()"
15
15
  >
16
- {{ isExpanded ? t('show-less') : t('show-more') }}
16
+ {{ isExpanded ? t('action:show-less') : t('action:show-more') }}
17
17
  </UiButton>
18
18
  </div>
19
19
  </UiTableCell>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <UiButtonIcon
3
3
  ref="buttonRef"
4
- v-tooltip="{ content: t('tasks.quick-view'), placement: 'bottom-end' }"
4
+ v-tooltip="{ content: t('tasks:overview'), placement: 'bottom-end' }"
5
5
  accent="brand"
6
6
  :dot="hasNewTask"
7
7
  icon="fa:bars-progress"
@@ -18,9 +18,9 @@
18
18
  <script lang="ts" setup>
19
19
  import VtsBackdrop from '@core/components/backdrop/VtsBackdrop.vue'
20
20
  import UiButtonIcon from '@core/components/ui/button-icon/UiButtonIcon.vue'
21
- import type { Task } from '@core/components/ui/quick-task-item/UiQuickTaskItem.vue'
22
21
  import UiQuickTaskPanel from '@core/components/ui/quick-task-panel/UiQuickTaskPanel.vue'
23
22
  import { vTooltip } from '@core/directives/tooltip.directive'
23
+ import type { Task } from '@core/types/task.type.ts'
24
24
  import { unrefElement, watchArray, whenever } from '@vueuse/core'
25
25
  import placementJs from 'placement.js'
26
26
  import { computed, nextTick, ref } from 'vue'
@@ -20,13 +20,14 @@
20
20
  <div>{{ t('loading') }}</div>
21
21
  </div>
22
22
  </li>
23
- <li v-else-if="tasks.length === 0" class="typo-body-bold">{{ t('tasks.no-tasks') }}</li>
23
+ <li v-else-if="tasks.length === 0" class="typo-body-bold">{{ t('no-task') }}</li>
24
24
  </ul>
25
25
  </template>
26
26
 
27
27
  <script lang="ts" setup>
28
28
  import UiLoader from '@core/components/ui/loader/UiLoader.vue'
29
- import UiQuickTaskItem, { type Task } from '@core/components/ui/quick-task-item/UiQuickTaskItem.vue'
29
+ import UiQuickTaskItem from '@core/components/ui/quick-task-item/UiQuickTaskItem.vue'
30
+ import type { Task } from '@core/types/task.type.ts'
30
31
  import { useI18n } from 'vue-i18n'
31
32
  import { DynamicScroller, DynamicScrollerItem } from 'vue-virtual-scroller'
32
33
 
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <TabList :disabled="loading">
3
3
  <TabItem v-bind="tabs.pending.bindings">
4
- {{ t('tasks.quick-view.in-progress') }}
4
+ {{ t('in-progress') }}
5
5
  <UiCounter
6
6
  v-if="pendingCount !== undefined"
7
7
  :value="pendingCount"
@@ -11,7 +11,7 @@
11
11
  />
12
12
  </TabItem>
13
13
  <TabItem v-bind="tabs.success.bindings">
14
- {{ t('tasks.quick-view.done') }}
14
+ {{ t('done') }}
15
15
  <UiCounter
16
16
  v-if="successCount !== undefined"
17
17
  :value="successCount"
@@ -21,7 +21,7 @@
21
21
  />
22
22
  </TabItem>
23
23
  <TabItem v-bind="tabs.failure.bindings">
24
- {{ t('tasks.quick-view.failed') }}
24
+ {{ t('failed') }}
25
25
  <UiCounter
26
26
  v-if="failureCount !== undefined"
27
27
  :value="failureCount"
@@ -32,12 +32,12 @@
32
32
  </TabItem>
33
33
  <VtsDivider type="tab" />
34
34
  <TabItem v-bind="tabs.all.bindings">
35
- {{ t('tasks.quick-view.all') }}
35
+ {{ t('all') }}
36
36
  </TabItem>
37
37
  <!--
38
38
  TODO
39
39
  <UiButton :right-icon="faAngleRight" class="see-all" level="tertiary" size="extra-small">
40
- {{ t('see-all') }}
40
+ {{ t('action:see-all') }}
41
41
  </UiButton>
42
42
  -->
43
43
  </TabList>
@@ -48,8 +48,8 @@ import VtsDivider from '@core/components/divider/VtsDivider.vue'
48
48
  import TabItem from '@core/components/tab/TabItem.vue'
49
49
  import TabList from '@core/components/tab/TabList.vue'
50
50
  import UiCounter from '@core/components/ui/counter/UiCounter.vue'
51
- import type { TaskStatus } from '@core/components/ui/quick-task-item/UiQuickTaskItem.vue'
52
51
  import { useTabList } from '@core/composables/tab-list.composable'
52
+ import type { TaskStatus } from '@core/types/task.type.ts'
53
53
  import { useI18n } from 'vue-i18n'
54
54
 
55
55
  export type TaskTab = TaskStatus | 'all'
@@ -10,7 +10,7 @@ import UiUserLogo from '@core/components/ui/user-logo/UiUserLogo.vue'
10
10
  import { useDisabled } from '@core/composables/disabled.composable'
11
11
 
12
12
  defineProps<{
13
- size: 'small' | 'medium'
13
+ size: 'extra-small' | 'small' | 'medium'
14
14
  selected?: boolean
15
15
  }>()
16
16
 
@@ -1,6 +1,6 @@
1
1
  <!-- v2 -->
2
2
  <template>
3
- <nav class="ui-breadcrumb" :class="className" :aria-label="t('aria.breadcrumb.label')">
3
+ <nav class="ui-breadcrumb" :class="className" :aria-label="t('aria:breadcrumb:label')">
4
4
  <ol>
5
5
  <li v-for="child in slots.default()" :key="child.ctx.uid">
6
6
  <component :is="child" />
@@ -1,7 +1,7 @@
1
1
  <!-- v1 -->
2
2
  <template>
3
3
  <span class="ui-character-limit" :class="classes">
4
- {{ t('core.character-limit', { count, max }) }}
4
+ {{ t('character-limit', { count, max }) }}
5
5
  </span>
6
6
  </template>
7
7
 
@@ -46,7 +46,7 @@ const {
46
46
 
47
47
  const { n } = useI18n()
48
48
 
49
- type CircleProgressBarAccent = 'info' | 'warning' | 'danger'
49
+ export type CircleProgressBarAccent = 'info' | 'warning' | 'danger'
50
50
  type CircleProgressBarSize = 'extra-small' | 'small' | 'medium' | 'large'
51
51
 
52
52
  const circleSizeMap = {
@@ -6,7 +6,7 @@
6
6
  </component>
7
7
  <div v-if="hasMoreItems" class="footer">
8
8
  <UiButton size="small" accent="brand" variant="tertiary" @click="isExpanded = !isExpanded">
9
- {{ isExpanded ? t('see-less') : t('see-n-more', { n: remainingItems }) }}
9
+ {{ isExpanded ? t('action:see-less') : t('action:see-n-more', { n: remainingItems }) }}
10
10
  </UiButton>
11
11
  </div>
12
12
  </div>
@@ -4,12 +4,13 @@
4
4
  <input
5
5
  :id="wrapperController?.id ?? id"
6
6
  ref="inputRef"
7
- v-model.trim="modelValue"
7
+ :value="modelValue"
8
8
  :disabled
9
9
  :required
10
10
  :type
11
11
  class="typo-body-regular input text-ellipsis"
12
12
  v-bind="attrs"
13
+ @input="event => handleInput(event)"
13
14
  />
14
15
  <UiButtonIcon
15
16
  v-if="!disabled && modelValue && clearable"
@@ -42,7 +43,6 @@ export type InputType = 'text' | 'number' | 'password' | 'search'
42
43
  defineOptions({
43
44
  inheritAttrs: false,
44
45
  })
45
-
46
46
  const {
47
47
  accent: _accent,
48
48
  required,
@@ -65,6 +65,10 @@ const slots = defineSlots<{
65
65
  'right-icon'?(): any
66
66
  }>()
67
67
 
68
+ function handleInput(event: Event) {
69
+ modelValue.value = (event.target as HTMLInputElement).value
70
+ }
71
+
68
72
  const attrs = useAttrs()
69
73
 
70
74
  const inputRef = ref<HTMLInputElement>()
@@ -73,11 +77,11 @@ const wrapperController = inject(IK_INPUT_WRAPPER_CONTROLLER, undefined)
73
77
 
74
78
  const accent = useMapper<LabelAccent, InputAccent>(
75
79
  () => wrapperController?.labelAccent,
76
- {
80
+ () => ({
77
81
  neutral: _accent,
78
82
  warning: 'warning',
79
83
  danger: 'danger',
80
- },
84
+ }),
81
85
  'neutral'
82
86
  )
83
87
 
@@ -80,7 +80,7 @@ watch(
80
80
  content => {
81
81
  pre.textContent = content.value
82
82
  },
83
- { immediate: true }
83
+ { immediate: true, deep: true }
84
84
  )
85
85
 
86
86
  function openRawValueInNewTab() {
@@ -2,31 +2,31 @@
2
2
  <template>
3
3
  <form class="ui-query-search-bar" @submit.prevent="emit('search', value)">
4
4
  <label v-if="uiStore.isDesktopLarge" :for="id" class="typo-body-regular-small label">
5
- {{ t('core.query-search-bar.label') }}
5
+ {{ t('query-search-bar:label') }}
6
6
  </label>
7
7
  <UiInput
8
8
  :id
9
9
  v-model="value"
10
10
  type="text"
11
11
  accent="brand"
12
- :aria-label="uiStore.isMobile ? t('core.query-search-bar.label') : undefined"
12
+ :aria-label="uiStore.isMobile ? t('query-search-bar:label') : undefined"
13
13
  :icon="!uiStore.isMobile ? 'fa:magnifying-glass' : undefined"
14
- :placeholder="t('core.query-search-bar.placeholder')"
14
+ :placeholder="t('query-search-bar:placeholder')"
15
15
  />
16
16
  <template v-if="!uiStore.isMobile">
17
17
  <UiButton size="medium" accent="brand" variant="primary" type="submit" class="action-button">
18
- {{ t('core.search') }}
18
+ {{ t('action:search') }}
19
19
  </UiButton>
20
20
  <VtsDivider type="stretch" />
21
21
  <UiButton
22
- v-tooltip="t('coming-soon')"
22
+ v-tooltip="t('coming-soon!')"
23
23
  size="medium"
24
24
  accent="brand"
25
25
  variant="secondary"
26
26
  disabled
27
27
  class="action-button"
28
28
  >
29
- {{ t('core.query-search-bar.use-query-builder') }}
29
+ {{ t('query-search-bar:use-query-builder') }}
30
30
  </UiButton>
31
31
  </template>
32
32
 
@@ -13,7 +13,7 @@
13
13
  <UiTag v-if="task.tag" accent="neutral" variant="primary">{{ task.tag }}</UiTag>
14
14
  <div v-if="hasSubTasks" class="subtasks">
15
15
  <VtsIcon name="fa:circle-notch" size="medium" />
16
- <span class="typo-body-regular-small">{{ t('tasks.n-subtasks', { n: subTasksCount }) }}</span>
16
+ <span class="typo-body-regular-small">{{ t('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">
@@ -34,22 +34,11 @@ 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 type { Task } from '@core/types/task.type.ts'
37
38
  import { useToggle } from '@vueuse/core'
38
39
  import { computed } from 'vue'
39
40
  import { useI18n } from 'vue-i18n'
40
41
 
41
- export type TaskStatus = 'pending' | 'success' | 'failure'
42
-
43
- export type Task = {
44
- id: string | number
45
- name: string
46
- status: TaskStatus
47
- tag?: string
48
- start?: number
49
- end?: number
50
- subtasks?: Task[]
51
- }
52
-
53
42
  const props = defineProps<{
54
43
  task: Task
55
44
  }>()
@@ -15,8 +15,8 @@
15
15
  <script lang="ts" setup>
16
16
  import VtsQuickTaskList from '@core/components/task/VtsQuickTaskList.vue'
17
17
  import VtsQuickTaskTabBar, { type TaskTab } from '@core/components/task/VtsQuickTaskTabBar.vue'
18
- import type { Task } from '@core/components/ui/quick-task-item/UiQuickTaskItem.vue'
19
18
  import { useUiStore } from '@core/stores/ui.store'
19
+ import type { Task } from '@core/types/task.type.ts'
20
20
  import { computed, ref } from 'vue'
21
21
 
22
22
  const props = defineProps<{
@@ -3,7 +3,7 @@
3
3
  <div class="ui-table-pagination" :class="className">
4
4
  <div class="container">
5
5
  <span class="typo-body-regular-small label">
6
- {{ t('core.select.n-object-of', { from, to, total }) }}
6
+ {{ t('action:select-n-objects-of', { from, to, total }) }}
7
7
  </span>
8
8
  <div class="buttons-container">
9
9
  <PaginationButton :disabled="isFirstPage" icon="fa:angle-double-left" @click="emit('first')" />
@@ -13,7 +13,7 @@
13
13
  </div>
14
14
  </div>
15
15
  <div class="container">
16
- <span class="typo-body-regular-small label show">{{ t('core.pagination.show-by') }}</span>
16
+ <span class="typo-body-regular-small label show">{{ t('show-by') }}</span>
17
17
  <VtsSelect :id="showBySelectId" accent="brand" class="typo-body-regular-small show-by-select" />
18
18
  </div>
19
19
  </div>
@@ -54,7 +54,7 @@ const { t } = useI18n()
54
54
  const { id: showBySelectId } = useFormSelect([12, 24, 48, -1], {
55
55
  model: showBy,
56
56
  option: {
57
- label: option => (option === -1 ? t('core.pagination.all') : option.toString()),
57
+ label: option => (option === -1 ? t('pagination:all') : option.toString()),
58
58
  },
59
59
  })
60
60
  </script>
@@ -1,6 +1,6 @@
1
1
  <!-- v10 -->
2
2
  <template>
3
- <li class="ui-task-item" :data-depth="depth">
3
+ <li class="ui-task-item" :data-depth="depth" :class="{ selected }">
4
4
  <div class="container">
5
5
  <div class="tree-section">
6
6
  <div class="tree-lines">
@@ -10,7 +10,7 @@
10
10
  </div>
11
11
  <UiButtonIcon
12
12
  v-if="hasSubTasks"
13
- v-tooltip="expanded ? t('core.close') : t('core.open')"
13
+ v-tooltip="expanded ? t('action:close') : t('action:open')"
14
14
  accent="brand"
15
15
  :icon="expanded ? 'fa:angle-down' : 'fa:angle-right'"
16
16
  size="small"
@@ -35,24 +35,19 @@
35
35
 
36
36
  <div class="content-right typo-body-regular-small">
37
37
  <span v-if="task.end">
38
- {{ `${t('task.ended')} ${end}` }}
38
+ {{ `${t('task:ended')} ${end}` }}
39
39
  </span>
40
40
  <div class="progress">
41
- <UiCircleProgressBar
42
- v-if="task.progress !== undefined"
43
- :accent="progressAccent"
44
- size="small"
45
- :value="task.progress"
46
- />
41
+ <UiCircleProgressBar :accent="progressAccent" size="small" :value="progress" />
47
42
  </div>
48
43
  <div class="actions">
49
- <UiButtonIcon icon="fa:eye" size="medium" accent="brand" @click="emit('select')" />
44
+ <UiButtonIcon icon="fa:eye" size="medium" accent="brand" @click="emit('select', task.id)" />
50
45
  </div>
51
46
  </div>
52
47
  </div>
53
48
  </div>
54
49
  <template v-if="hasSubTasks && expanded">
55
- <UiTaskList :tasks="subTasks" :depth />
50
+ <UiTaskList :tasks="subTasks" :depth :selected-task-id="selectedTaskId" @select="id => emit('select', id)" />
56
51
  </template>
57
52
  </li>
58
53
  </template>
@@ -77,24 +72,26 @@ export type Task = {
77
72
  progress?: number
78
73
  end?: number
79
74
  status: 'failure' | 'interrupted' | 'pending' | 'success'
80
- tasks?: Task[]
81
- warning?: { data: unknown; message: string }[]
75
+ subtasks?: Task[]
76
+ warnings?: { data: unknown; message: string }[]
82
77
  }
83
78
 
84
79
  const { task } = defineProps<{
85
80
  task: Task
86
81
  depth: number
87
82
  expanded?: boolean
83
+ selected?: boolean
84
+ selectedTaskId?: string
88
85
  }>()
89
86
 
90
87
  const emit = defineEmits<{
91
88
  expand: []
92
- select: []
89
+ select: [id: string]
93
90
  }>()
94
91
 
95
92
  const { t } = useI18n()
96
93
 
97
- const subTasks = computed(() => task.tasks ?? [])
94
+ const subTasks = computed(() => task.subtasks ?? [])
98
95
 
99
96
  const subTasksCount = computed(() => subTasks.value.length)
100
97
 
@@ -104,13 +101,22 @@ const isError = computed(() => task.status === 'failure' || task.status === 'int
104
101
 
105
102
  const end = useTimeAgo(() => task.end ?? 0)
106
103
 
107
- const hasWarnings = computed(() => task.warning && task.warning.length > 0)
104
+ const hasWarnings = computed(() => task.warnings && task.warnings.length > 0)
108
105
 
109
106
  const hasInfos = computed(() => task.infos && task.infos.length > 0)
110
107
 
111
108
  const shouldShowInfos = logicOr(isError, hasWarnings, hasInfos)
112
109
 
113
110
  const progressAccent = computed(() => (isError.value ? 'danger' : 'info'))
111
+
112
+ // TODO remove when progress is available for all tasks
113
+ const progress = computed(() => {
114
+ if (task.status === 'pending' && !task.end) {
115
+ return task.progress ? task.progress : 0
116
+ }
117
+
118
+ return task.progress ? task.progress : 100
119
+ })
114
120
  </script>
115
121
 
116
122
  <style lang="postcss" scoped>
@@ -119,6 +125,10 @@ const progressAccent = computed(() => (isError.value ? 'danger' : 'info'))
119
125
  border-bottom: 0.1rem solid var(--color-neutral-border);
120
126
  }
121
127
 
128
+ &.selected {
129
+ background-color: var(--color-brand-background-selected);
130
+ }
131
+
122
132
  .container {
123
133
  display: flex;
124
134
  min-height: 4.8rem;
@@ -134,6 +144,8 @@ const progressAccent = computed(() => (isError.value ? 'danger' : 'info'))
134
144
  }
135
145
 
136
146
  .tree-section {
147
+ --line-container-base-width: 2.8rem;
148
+ --line-width: 0.1rem;
137
149
  display: flex;
138
150
  align-items: center;
139
151
  padding-left: 1.6rem;
@@ -142,10 +154,11 @@ const progressAccent = computed(() => (isError.value ? 'danger' : 'info'))
142
154
  .tree-lines {
143
155
  display: flex;
144
156
  align-self: stretch;
157
+ min-width: calc(var(--line-container-base-width) * v-bind(depth - 1));
145
158
  }
146
159
 
147
160
  .tree-line {
148
- flex: 0 0 2.8rem;
161
+ flex: 0 0 calc(var(--line-container-base-width) + var(--line-width));
149
162
  display: flex;
150
163
  align-items: center;
151
164
  justify-content: center;
@@ -1,24 +1,28 @@
1
1
  <template>
2
- <ul>
2
+ <ul class="ui-task-list">
3
3
  <UiTaskItem
4
4
  v-for="task of tasksItems"
5
5
  :key="task.id"
6
6
  :task="task.source"
7
7
  :expanded="task.flags.expanded"
8
8
  :depth="depth + 1"
9
- @select="emit('select', task.id)"
9
+ :selected="selectedTaskId === task.id"
10
+ :selected-task-id="selectedTaskId"
11
+ @select="emit('select', $event)"
10
12
  @expand="task.toggleFlag('expanded')"
11
13
  />
12
14
  </ul>
13
15
  </template>
14
16
 
15
17
  <script lang="ts" setup>
16
- import UiTaskItem, { type Task } from '@core/components/ui/task-item/UiTaskItem.vue'
18
+ import UiTaskItem from '@core/components/ui/task-item/UiTaskItem.vue'
17
19
  import { useCollection } from '@core/packages/collection'
20
+ import type { Task } from '@core/types/task.type.ts'
18
21
 
19
22
  const { tasks, depth = 0 } = defineProps<{
20
23
  tasks: Task[]
21
24
  depth?: number
25
+ selectedTaskId?: string
22
26
  }>()
23
27
 
24
28
  const emit = defineEmits<{
@@ -29,3 +33,10 @@ const { items: tasksItems } = useCollection(() => tasks, {
29
33
  flags: ['expanded'],
30
34
  })
31
35
  </script>
36
+
37
+ <style scoped lang="postcss">
38
+ .ui-task-list {
39
+ overflow-x: auto;
40
+ overflow-y: hidden;
41
+ }
42
+ </style>