@xen-orchestra/web-core 0.38.0 → 0.39.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.
Files changed (52) 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/log-entry-viewer/UiLogEntryViewer.vue +1 -1
  21. package/lib/components/ui/query-search-bar/UiQuerySearchBar.vue +6 -6
  22. package/lib/components/ui/quick-task-item/UiQuickTaskItem.vue +2 -13
  23. package/lib/components/ui/quick-task-panel/UiQuickTaskPanel.vue +1 -1
  24. package/lib/components/ui/table-pagination/UiTablePagination.vue +3 -3
  25. package/lib/components/ui/task-item/UiTaskItem.vue +26 -16
  26. package/lib/components/ui/task-list/UiTaskList.vue +14 -3
  27. package/lib/components/ui/text-area/UiTextarea.vue +1 -1
  28. package/lib/components/ui/top-bottom-table/UiTopBottomTable.vue +3 -3
  29. package/lib/components/ui/tree-item-label/UiTreeItemLabel.vue +1 -1
  30. package/lib/i18n.ts +8 -4
  31. package/lib/layouts/CoreLayout.vue +1 -1
  32. package/lib/locales/cs.json +297 -294
  33. package/lib/locales/da.json +181 -200
  34. package/lib/locales/de.json +243 -251
  35. package/lib/locales/en.json +312 -310
  36. package/lib/locales/es.json +282 -300
  37. package/lib/locales/fa.json +239 -239
  38. package/lib/locales/fr.json +314 -312
  39. package/lib/locales/it.json +190 -186
  40. package/lib/locales/ja.json +23 -0
  41. package/lib/locales/ko.json +23 -1
  42. package/lib/locales/nb-NO.json +696 -0
  43. package/lib/locales/nl.json +296 -295
  44. package/lib/locales/pt-BR.json +170 -0
  45. package/lib/locales/ru.json +209 -206
  46. package/lib/locales/sv.json +244 -254
  47. package/lib/locales/uk.json +151 -149
  48. package/lib/packages/remote-resource/define-remote-resource.ts +37 -4
  49. package/lib/types/task.type.ts +15 -0
  50. package/package.json +1 -1
  51. package/lib/locales/nb_NO.json +0 -1
  52. 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>
@@ -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;
@@ -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>
@@ -7,7 +7,7 @@
7
7
  <textarea v-bind="attrs" :id ref="textarea" v-model="model" :disabled class="textarea" />
8
8
  <UiCharacterLimit v-if="maxCharacters" :count="model.trim().length" :max="maxCharacters" />
9
9
  <UiInfo v-if="isExceedingMaxCharacters" accent="danger">
10
- {{ t('core.textarea.exceeds-max-characters', { max: maxCharacters }) }}
10
+ {{ t('field:exceeds-max-characters', { max: maxCharacters }) }}
11
11
  </UiInfo>
12
12
  <UiInfo v-if="slots.info" :accent="accent === 'brand' ? 'info' : accent">
13
13
  <slot name="info" />
@@ -3,7 +3,7 @@
3
3
  <div class="ui-top-bottom-table" :class="{ 'no-content': totalItems === 0 }">
4
4
  <div v-if="totalItems > 0" class="content">
5
5
  <span class="typo-body-regular-small label">
6
- {{ t('core.select.n-selected-of', { count: selectedItems, total: totalItems }) }}
6
+ {{ t('n-selected-of', { count: selectedItems, total: totalItems }) }}
7
7
  </span>
8
8
 
9
9
  <UiButton
@@ -13,7 +13,7 @@
13
13
  variant="tertiary"
14
14
  @click="emit('toggleSelectAll', true)"
15
15
  >
16
- {{ t('core.select.all') }}
16
+ {{ t('action:select-all') }}
17
17
  </UiButton>
18
18
  <UiButton
19
19
  :disabled="selectedItems === 0"
@@ -22,7 +22,7 @@
22
22
  variant="tertiary"
23
23
  @click="emit('toggleSelectAll', false)"
24
24
  >
25
- {{ t('core.select.unselect') }}
25
+ {{ t('action:unselect-all') }}
26
26
  </UiButton>
27
27
  </div>
28
28
  <slot />
@@ -11,7 +11,7 @@
11
11
  </template>
12
12
  <UiButtonIcon
13
13
  v-if="hasToggle"
14
- v-tooltip="isExpanded ? t('core.close') : t('core.open')"
14
+ v-tooltip="isExpanded ? t('action:close') : t('action:open')"
15
15
  class="toggle"
16
16
  accent="brand"
17
17
  :icon="isExpanded ? 'fa:angle-down' : 'fa:angle-right'"