@pgcorp/ui-kit 0.9.0 → 0.10.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 (105) hide show
  1. package/README.md +188 -9
  2. package/docs/getting-started.md +135 -0
  3. package/docs/public-api.md +53 -4
  4. package/docs/rich-document.md +216 -0
  5. package/docs/scroll-viewport.md +167 -0
  6. package/package.json +103 -50
  7. package/src/components/layout/SAppShell.vue +3 -1
  8. package/src/components/layout/SDockRegion.vue +5 -3
  9. package/src/components/layout/SWorkbenchPanelShell.vue +4 -2
  10. package/src/components/shared/_internal/SDialogSurface.css +5 -0
  11. package/src/components/shared/_internal/SDialogSurface.vue +3 -1
  12. package/src/components/shared/_internal/SToastItem.css +4 -0
  13. package/src/components/shared/_internal/SToastItem.vue +44 -8
  14. package/src/components/shared/_internal/STreeNode.vue +24 -11
  15. package/src/components/shared/complex/SKanbanLane.vue +4 -2
  16. package/src/components/shared/containers/SCloudChromeRow.vue +3 -2
  17. package/src/components/shared/containers/SDrawer.vue +5 -2
  18. package/src/components/shared/containers/SModal.vue +5 -2
  19. package/src/components/shared/containers/SPanel.vue +4 -2
  20. package/src/components/shared/containers/SPopover.vue +7 -3
  21. package/src/components/shared/containers/SUiKitLocaleProvider.vue +57 -0
  22. package/src/components/shared/controls/SButton.css +14 -10
  23. package/src/components/shared/controls/SCombobox.vue +8 -6
  24. package/src/components/shared/controls/SComboboxTrigger.css +7 -4
  25. package/src/components/shared/controls/SComboboxTrigger.vue +5 -2
  26. package/src/components/shared/controls/SContextToggleButton.vue +6 -4
  27. package/src/components/shared/controls/SDragHandle.vue +8 -4
  28. package/src/components/shared/controls/SDropdownMenu.vue +7 -4
  29. package/src/components/shared/controls/SInputText.css +5 -4
  30. package/src/components/shared/controls/SListbox.vue +4 -2
  31. package/src/components/shared/controls/SSelect.vue +4 -2
  32. package/src/components/shared/controls/_internal/SInlineTokenSurface.vue +4 -2
  33. package/src/components/shared/data-display/SChart.vue +7 -5
  34. package/src/components/shared/data-display/SChip.vue +3 -1
  35. package/src/components/shared/data-display/SCodeBlock.css +4 -0
  36. package/src/components/shared/data-display/SCodeBlock.vue +42 -20
  37. package/src/components/shared/data-display/SCodeEditor.css +17 -0
  38. package/src/components/shared/data-display/SCodeEditor.vue +173 -8
  39. package/src/components/shared/data-display/SCodeSearchPanel.vue +48 -33
  40. package/src/components/shared/data-display/SCodeWorkspaceEditor.css +13 -0
  41. package/src/components/shared/data-display/SCodeWorkspaceEditor.vue +355 -0
  42. package/src/components/shared/data-display/SControlledToastViewport.css +89 -0
  43. package/src/components/shared/data-display/SControlledToastViewport.vue +205 -0
  44. package/src/components/shared/data-display/SCopyField.vue +12 -10
  45. package/src/components/shared/data-display/SDiffViewer.css +122 -0
  46. package/src/components/shared/data-display/SDiffViewer.vue +499 -0
  47. package/src/components/shared/data-display/SDocBlock.vue +99 -71
  48. package/src/components/shared/data-display/SExpandableText.vue +10 -8
  49. package/src/components/shared/data-display/SJsonTree.vue +4 -2
  50. package/src/components/shared/data-display/SLinkedSystemsList.vue +4 -2
  51. package/src/components/shared/data-display/SMessage.vue +6 -6
  52. package/src/components/shared/data-display/SRichDocument.css +8 -0
  53. package/src/components/shared/data-display/SRichDocument.vue +65 -0
  54. package/src/components/shared/data-display/SScrollViewport.css +53 -0
  55. package/src/components/shared/data-display/SScrollViewport.vue +470 -0
  56. package/src/components/shared/data-display/STable.vue +38 -19
  57. package/src/components/shared/data-display/SToastContainer.vue +22 -17
  58. package/src/components/shared/data-display/_internal/SCodeTokenLine.css +72 -0
  59. package/src/components/shared/data-display/_internal/SCodeTokenLine.vue +79 -0
  60. package/src/components/shared/data-display/_internal/SRichBlockNode.css +85 -0
  61. package/src/components/shared/data-display/_internal/SRichBlockNode.vue +282 -0
  62. package/src/components/shared/data-display/_internal/SRichInlineNode.css +6 -0
  63. package/src/components/shared/data-display/_internal/SRichInlineNode.vue +76 -0
  64. package/src/components/shared/data-display/_internal/SRichMath.css +42 -0
  65. package/src/components/shared/data-display/_internal/SRichMath.vue +102 -0
  66. package/src/components/shared/data-display/codeEditor.ts +200 -0
  67. package/src/components/shared/data-display/codeWorkspace.ts +233 -0
  68. package/src/components/shared/data-display/diff.ts +541 -0
  69. package/src/components/shared/data-display/richDocument.ts +876 -0
  70. package/src/components/shared/data-display/scrollViewport.ts +47 -0
  71. package/src/components/shared/data-display/toast.ts +194 -0
  72. package/src/components/shared/database/SDataGrid.vue +7 -4
  73. package/src/components/shared/database/SSqlEditor.vue +39 -39
  74. package/src/components/shared/feedback/SAsyncState.vue +3 -1
  75. package/src/components/shared/graph/SGraphViewport.vue +11 -9
  76. package/src/components/shared/navigation/SBreadcrumbs.vue +8 -5
  77. package/src/components/shared/navigation/SCatalogNavigator.vue +26 -20
  78. package/src/components/shared/navigation/STabList.vue +10 -6
  79. package/src/components/shared/navigation/STabs.vue +15 -11
  80. package/src/components/shared/navigation/SWizardSteps.vue +4 -2
  81. package/src/components/shared/persona/SPersonaProjectPicker.vue +31 -27
  82. package/src/components/shared/persona/SPersonaRunWorkbench.vue +39 -33
  83. package/src/components/shared/persona/_internal/SPersonaRunConsole.vue +8 -6
  84. package/src/components/shared/persona/_internal/labels.ts +66 -57
  85. package/src/components/shared/persona/presentation.ts +140 -110
  86. package/src/composables/useFloatingPosition.ts +39 -2
  87. package/src/composables/useUiKitLocale.ts +17 -0
  88. package/src/internal/codeHighlight.ts +110 -0
  89. package/src/internal/diffEngine.ts +464 -0
  90. package/src/internal/diffRuntime.ts +189 -0
  91. package/src/internal/feedbackPresentation.ts +33 -14
  92. package/src/internal/localeContext.ts +22 -0
  93. package/src/internal/ownedAttrs.ts +8 -0
  94. package/src/internal/runtimeContract.ts +11 -9
  95. package/src/internal/semanticSizing.ts +13 -0
  96. package/src/locales/catalog.ts +634 -0
  97. package/src/locales/locale.ts +472 -0
  98. package/src/locales/messages.generated.ts +1826 -0
  99. package/src/locales/messages.ts +150 -0
  100. package/src/stores/useNotifierStore.ts +61 -44
  101. package/src/styles/tokens.css +20 -2
  102. package/src/theme.ts +59 -32
  103. package/src/workers/diff.worker.ts +73 -0
  104. package/src/workers/diffProtocol.ts +155 -0
  105. package/src/components/shared/data-display/SToastContainer.css +0 -53
@@ -43,6 +43,7 @@ import type {
43
43
  PersonaRunWorkbenchWatcher,
44
44
  } from './types'
45
45
  import { useOwnedAttrs } from '../../../internal/ownedAttrs'
46
+ import { useUiKitLocale } from '../../../composables/useUiKitLocale'
46
47
 
47
48
  defineOptions({ inheritAttrs: false })
48
49
 
@@ -97,12 +98,13 @@ const emit = defineEmits<{
97
98
  'load-more-events': []
98
99
  }>()
99
100
  const ownedAttrs = useOwnedAttrs({ component: 'SPersonaRunWorkbench', owner: 'persona workbench shell' })
101
+ const { locale, t } = useUiKitLocale()
100
102
 
101
103
  const search = ref('')
102
104
  const diagnosticSearch = ref('')
103
105
  const diagnosticSeverity = ref<'all' | 'danger' | 'warn'>('all')
104
106
 
105
- const uiLabels = computed(() => resolvePersonaRunWorkbenchLabels(props.labels))
107
+ const uiLabels = computed(() => resolvePersonaRunWorkbenchLabels(props.labels, t))
106
108
 
107
109
  const consoleOperation = computed<PersonaRunConsoleOperation>(() => {
108
110
  switch (props.operation) {
@@ -127,7 +129,7 @@ const catalogAsyncState = computed(() => resolvePersonaInventoryAsyncState(
127
129
  'SPersonaRunWorkbench.catalogState',
128
130
  props.catalogState,
129
131
  {
130
- loadingMessage: 'Загрузка каталога',
132
+ loadingMessage: t('persona.loadingCatalog'),
131
133
  emptyMessage: uiLabels.value.noCatalogTests,
132
134
  },
133
135
  ))
@@ -150,7 +152,7 @@ const validatedDiagnostics = computed(() => assertPersonaInventory(
150
152
  ))
151
153
 
152
154
  const visibleTests = computed(() => {
153
- const query = search.value.trim().toLocaleLowerCase('ru-RU')
155
+ const query = search.value.trim().toLocaleLowerCase(locale.value)
154
156
  if (!query) return catalogTests.value
155
157
  return catalogTests.value.filter((test) => {
156
158
  const haystack = [
@@ -161,31 +163,31 @@ const visibleTests = computed(() => {
161
163
  test.variantId,
162
164
  test.sourcePath,
163
165
  ...(test.tags ?? []),
164
- ].filter((value): value is string => Boolean(value)).join(' ').toLocaleLowerCase('ru-RU')
166
+ ].filter((value): value is string => Boolean(value)).join(' ').toLocaleLowerCase(locale.value)
165
167
  return haystack.includes(query)
166
168
  })
167
169
  })
168
170
 
169
171
  const diagnosticSeverityOptions = computed<SegmentedControlOption[]>(() => [
170
- { value: 'all', label: `Все ${validatedDiagnostics.value.length}`, title: 'Показать все сообщения' },
172
+ { value: 'all', label: t('persona.allCount', { count: validatedDiagnostics.value.length }), title: t('persona.showAllMessages') },
171
173
  {
172
174
  value: 'danger',
173
- label: `Ошибки ${validatedDiagnostics.value.filter((diagnostic) => diagnostic.statusSeverity === 'danger').length}`,
174
- title: 'Показать ошибки',
175
+ label: t('persona.errorsCount', { count: validatedDiagnostics.value.filter((diagnostic) => diagnostic.statusSeverity === 'danger').length }),
176
+ title: t('persona.showErrors'),
175
177
  },
176
178
  {
177
179
  value: 'warn',
178
- label: `Предупреждения ${validatedDiagnostics.value.filter((diagnostic) => diagnostic.statusSeverity === 'warn').length}`,
179
- title: 'Показать предупреждения',
180
+ label: t('persona.warningsCount', { count: validatedDiagnostics.value.filter((diagnostic) => diagnostic.statusSeverity === 'warn').length }),
181
+ title: t('persona.showWarnings'),
180
182
  },
181
183
  ])
182
184
 
183
- const diagnosticGroupTitles: Record<PersonaRunWorkbenchDiagnostic['category'], string> = {
184
- scenario_import: 'Недоступные сценарии',
185
- component_analysis: 'Ошибки анализа компонентов',
186
- support_quality: 'Замечания качества PageObject',
187
- unclassified: 'Сообщения без классификации',
188
- }
185
+ const diagnosticGroupTitles = computed<Record<PersonaRunWorkbenchDiagnostic['category'], string>>(() => ({
186
+ scenario_import: t('persona.unavailableScenarios'),
187
+ component_analysis: t('persona.componentAnalysisErrors'),
188
+ support_quality: t('persona.pageObjectQualityIssues'),
189
+ unclassified: t('persona.unclassifiedMessages'),
190
+ }))
189
191
 
190
192
  const diagnosticGroups = computed(() => {
191
193
  const categories: PersonaRunWorkbenchDiagnostic['category'][] = [
@@ -202,10 +204,14 @@ const diagnosticGroups = computed(() => {
202
204
  : diagnostics.some((diagnostic) => diagnostic.statusSeverity === 'warn')
203
205
  ? 'warn' as const
204
206
  : 'info' as const
205
- const countLabel = personaCountLabel(diagnostics.length, ['сообщение', 'сообщения', 'сообщений'])
207
+ const countLabel = personaCountLabel(diagnostics.length, [
208
+ t('persona.messageOne'),
209
+ t('persona.messageFew'),
210
+ t('persona.messageMany'),
211
+ ], locale.value)
206
212
  return [{
207
213
  category,
208
- title: diagnosticGroupTitles[category],
214
+ title: diagnosticGroupTitles.value[category],
209
215
  description: countLabel,
210
216
  countLabel,
211
217
  statusSeverity,
@@ -214,7 +220,7 @@ const diagnosticGroups = computed(() => {
214
220
  })
215
221
 
216
222
  const visibleDiagnostics = computed(() => {
217
- const query = diagnosticSearch.value.trim().toLocaleLowerCase('ru-RU')
223
+ const query = diagnosticSearch.value.trim().toLocaleLowerCase(locale.value)
218
224
  return validatedDiagnostics.value.filter((diagnostic) => {
219
225
  if (diagnosticSeverity.value !== 'all' && diagnostic.statusSeverity !== diagnosticSeverity.value) {
220
226
  return false
@@ -231,7 +237,7 @@ const visibleDiagnostics = computed(() => {
231
237
  ]
232
238
  .filter((value): value is string => Boolean(value))
233
239
  .join(' ')
234
- .toLocaleLowerCase('ru-RU')
240
+ .toLocaleLowerCase(locale.value)
235
241
  .includes(query)
236
242
  })
237
243
  })
@@ -304,12 +310,12 @@ function diagnosticDescription(diagnostic: PersonaRunWorkbenchDiagnostic): strin
304
310
  </div>
305
311
  <div v-if="validatedDiagnostics.length > 0" class="s-persona-run-workbench__diagnostics">
306
312
  <SCollapsiblePanel
307
- summary="Диагностика проекта"
313
+ :summary="t('persona.projectDiagnostics')"
308
314
  density="compact"
309
315
  header-variant="minimal"
310
316
  surface="plain"
311
317
  >
312
- <div class="s-persona-run-workbench__diagnostic-groups" aria-label="Сводка причин диагностики">
318
+ <div class="s-persona-run-workbench__diagnostic-groups" :aria-label="t('persona.diagnosticOverview')">
313
319
  <SActionListItem
314
320
  v-for="group in diagnosticGroups"
315
321
  :key="group.category"
@@ -322,11 +328,11 @@ function diagnosticDescription(diagnostic: PersonaRunWorkbenchDiagnostic): strin
322
328
  />
323
329
  </div>
324
330
  <div class="s-persona-run-workbench__diagnostic-controls">
325
- <SInputText v-model="diagnosticSearch" placeholder="Поиск по диагностике" size="sm" />
331
+ <SInputText v-model="diagnosticSearch" :placeholder="t('persona.diagnosticSearch')" size="sm" />
326
332
  <SSegmentedControl
327
333
  v-model="diagnosticSeverity"
328
334
  :options="diagnosticSeverityOptions"
329
- label="Важность диагностических сообщений"
335
+ :label="t('persona.diagnosticImportance')"
330
336
  size="sm"
331
337
  />
332
338
  </div>
@@ -337,7 +343,7 @@ function diagnosticDescription(diagnostic: PersonaRunWorkbenchDiagnostic): strin
337
343
  :item-size="virtualRowSize"
338
344
  :height="diagnosticsViewportHeight"
339
345
  :item-key="(diagnostic) => diagnostic.id"
340
- accessible-label="Диагностические сообщения"
346
+ :accessible-label="t('persona.diagnosticMessages')"
341
347
  :item-label="(diagnostic) => diagnostic.title"
342
348
  >
343
349
  <template #default="{ item }">
@@ -354,7 +360,7 @@ function diagnosticDescription(diagnostic: PersonaRunWorkbenchDiagnostic): strin
354
360
  />
355
361
  </template>
356
362
  </SVirtualList>
357
- <SEmptyState v-else title="Диагностические сообщения не найдены." size="sm" />
363
+ <SEmptyState v-else :title="t('persona.diagnosticNoResults')" size="sm" />
358
364
  </SCollapsiblePanel>
359
365
  </div>
360
366
  </section>
@@ -367,17 +373,17 @@ function diagnosticDescription(diagnostic: PersonaRunWorkbenchDiagnostic): strin
367
373
  trailing-layout="stacked"
368
374
  >
369
375
  <template #badges>
370
- <SBadge severity="info">{{ visibleTests.length }} доступно</SBadge>
376
+ <SBadge severity="info">{{ personaCountLabel(visibleTests.length, [t('persona.availableOne'), t('persona.availableFew'), t('persona.availableMany')], locale) }}</SBadge>
371
377
  <SBadge v-if="catalogOverview?.unavailableTests" severity="danger">
372
- {{ catalogOverview.unavailableTests }} недоступно
378
+ {{ personaCountLabel(catalogOverview.unavailableTests, [t('persona.unavailableOne'), t('persona.unavailableFew'), t('persona.unavailableMany')], locale) }}
373
379
  </SBadge>
374
- <SBadge v-if="catalogOverview" severity="secondary">{{ catalogOverview.components }} компонентов</SBadge>
375
- <SBadge v-if="catalogOverview" severity="secondary">{{ catalogOverview.pages }} страниц</SBadge>
380
+ <SBadge v-if="catalogOverview" severity="secondary">{{ personaCountLabel(catalogOverview.components, [t('persona.componentOne'), t('persona.componentFew'), t('persona.componentMany')], locale) }}</SBadge>
381
+ <SBadge v-if="catalogOverview" severity="secondary">{{ personaCountLabel(catalogOverview.pages, [t('persona.pageOne'), t('persona.pageFew'), t('persona.pageMany')], locale) }}</SBadge>
376
382
  <SBadge v-if="catalogOverview?.diagnosticErrors" severity="danger">
377
- {{ personaCountLabel(catalogOverview.diagnosticErrors, ['ошибка', 'ошибки', 'ошибок']) }}
383
+ {{ personaCountLabel(catalogOverview.diagnosticErrors, [t('persona.errorOne'), t('persona.errorFew'), t('persona.errorMany')], locale) }}
378
384
  </SBadge>
379
385
  <SBadge v-if="catalogOverview?.diagnosticWarnings" severity="warn">
380
- {{ personaCountLabel(catalogOverview.diagnosticWarnings, ['предупреждение', 'предупреждения', 'предупреждений']) }}
386
+ {{ personaCountLabel(catalogOverview.diagnosticWarnings, [t('persona.warningOne'), t('persona.warningFew'), t('persona.warningMany')], locale) }}
381
387
  </SBadge>
382
388
  </template>
383
389
  </SSectionHeader>
@@ -411,7 +417,7 @@ function diagnosticDescription(diagnostic: PersonaRunWorkbenchDiagnostic): strin
411
417
  height-mode="fill"
412
418
  :surface="{
413
419
  mode: 'action',
414
- accessibleLabel: `Выбрать тест ${item.title}`,
420
+ accessibleLabel: t('persona.selectTest', { title: item.title }),
415
421
  pressed: selectedTest?.id === item.id,
416
422
  }"
417
423
  @activate="emit('select-test', item.id)"
@@ -470,7 +476,7 @@ function diagnosticDescription(diagnostic: PersonaRunWorkbenchDiagnostic): strin
470
476
  <nav
471
477
  v-if="selectedTestLinks.length > 0"
472
478
  class="s-persona-run-workbench__links"
473
- aria-label="Связанные материалы теста"
479
+ :aria-label="t('persona.linkedTestMaterials')"
474
480
  >
475
481
  <SLink
476
482
  v-for="link in selectedTestLinks"
@@ -16,6 +16,7 @@ import {
16
16
  resolvePersonaInventoryAsyncState,
17
17
  } from './inventory'
18
18
  import { personaDistinctMessage } from '../presentation'
19
+ import { useUiKitLocale } from '../../../../composables/useUiKitLocale'
19
20
  import { getPersonaRunConsoleFactKey } from '../types'
20
21
  import type {
21
22
  PersonaPaginatedInventoryState,
@@ -64,6 +65,7 @@ const emit = defineEmits<{
64
65
  'append-events': []
65
66
  'load-more-events': []
66
67
  }>()
68
+ const { locale, t } = useUiKitLocale()
67
69
  const runs = computed(() => props.runsState.status === 'ready'
68
70
  ? assertPersonaInventory('SPersonaRunConsole.runsState', props.runsState.items)
69
71
  : [])
@@ -77,7 +79,7 @@ const runsAsyncState = computed(() => resolvePersonaInventoryAsyncState(
77
79
  'SPersonaRunConsole.runsState',
78
80
  props.runsState,
79
81
  {
80
- loadingMessage: 'Загрузка запусков',
82
+ loadingMessage: t('persona.loadingRuns'),
81
83
  emptyMessage: props.resolvedLabels.noRuns,
82
84
  },
83
85
  ))
@@ -85,7 +87,7 @@ const itemsAsyncState = computed(() => resolvePersonaInventoryAsyncState(
85
87
  'SPersonaRunConsole.itemsState',
86
88
  props.itemsState,
87
89
  {
88
- loadingMessage: 'Загрузка рабочих элементов',
90
+ loadingMessage: t('persona.loadingItems'),
89
91
  emptyMessage: props.resolvedLabels.noItems,
90
92
  },
91
93
  ))
@@ -93,7 +95,7 @@ const eventsAsyncState = computed(() => resolvePersonaInventoryAsyncState(
93
95
  'SPersonaRunConsole.eventsState',
94
96
  props.eventsState,
95
97
  {
96
- loadingMessage: 'Загрузка событий',
98
+ loadingMessage: t('persona.loadingEvents'),
97
99
  emptyMessage: props.resolvedLabels.noEvents,
98
100
  },
99
101
  ))
@@ -109,7 +111,7 @@ const itemsViewportHeight = computed(() => Math.min(props.itemsHeight, items.val
109
111
  const eventsViewportHeight = computed(() => Math.min(props.eventsHeight, events.value.length * virtualRowSize))
110
112
 
111
113
  function eventDetail(event: PersonaRunConsoleEvent): string | null {
112
- return personaDistinctMessage(event.title, event.message)
114
+ return personaDistinctMessage(event.title, event.message, locale.value)
113
115
  }
114
116
  </script>
115
117
 
@@ -138,7 +140,7 @@ function eventDetail(event: PersonaRunConsoleEvent): string | null {
138
140
  :status-severity="item.statusSeverity"
139
141
  trailing-layout="inline"
140
142
  height-mode="fill"
141
- :surface="{ mode: 'action', accessibleLabel: `Открыть запуск ${item.title}` }"
143
+ :surface="{ mode: 'action', accessibleLabel: t('persona.openRun', { title: item.title }) }"
142
144
  @activate="emit('select-run', item.id)"
143
145
  />
144
146
  </template>
@@ -184,7 +186,7 @@ function eventDetail(event: PersonaRunConsoleEvent): string | null {
184
186
  </template>
185
187
  </SSectionHeader>
186
188
 
187
- <SMessage v-if="selectedRun.artifactLabel" severity="info" title="Артефакты">
189
+ <SMessage v-if="selectedRun.artifactLabel" severity="info" :title="t('persona.artifacts')">
188
190
  {{ selectedRun.artifactLabel }}
189
191
  </SMessage>
190
192
 
@@ -1,79 +1,88 @@
1
1
  import { validateNonEmptyString } from '../../../../internal/runtimeContract'
2
+ import type { UiKitTranslate } from '../../../../locales/locale'
3
+ import { createUiKitTranslate, UI_KIT_MESSAGES } from '../../../../locales/messages'
2
4
 
3
5
  import type { PersonaRunWorkbenchLabels } from '../types'
4
6
 
5
- const PERSONA_RUN_WORKBENCH_DEFAULT_LABELS = Object.freeze({
6
- projectTitle: 'Проект',
7
- discoveryTitle: 'Discovery',
8
- catalogTitle: 'Каталог тестов',
9
- structureTitle: 'Структура сценария',
10
- selectedTestTitle: 'Выбранный тест',
11
- runSelected: 'Запустить тест',
12
- runAll: 'Запустить каталог',
13
- discover: 'Обнаружить',
14
- watch: 'Наблюдать',
15
- searchPlaceholder: 'Поиск по тестам',
16
- noCatalogTests: 'Тесты не найдены.',
17
- emptyStructure: 'Структура сценария не сохранена.',
18
- runListTitle: 'Запуски',
19
- selectedRunTitle: 'События запуска',
20
- itemsTitle: 'Рабочие элементы',
21
- eventsTitle: 'События',
22
- loadMoreRuns: 'Загрузить ещё',
23
- loadMoreItems: 'Догрузить рабочие элементы',
24
- appendEvents: 'Догрузить новые',
25
- loadMoreEvents: 'Догрузить историю',
26
- refreshEvents: 'Обновить события',
27
- cancelRun: 'Отменить',
28
- reportSummary: 'Сводка отчёта',
29
- emptyRun: 'Выберите запуск для просмотра событий и артефактов.',
30
- noRuns: 'Запуски не найдены.',
31
- noItems: 'Рабочие элементы ещё не появились.',
32
- noEvents: 'События запуска ещё не поступили.',
33
- } satisfies PersonaRunWorkbenchLabels)
7
+ const defaultTranslate = createUiKitTranslate(() => UI_KIT_MESSAGES.ru)
8
+
9
+ function defaultLabels(t: UiKitTranslate): PersonaRunWorkbenchLabels {
10
+ return {
11
+ projectTitle: t('persona.projectTitle'),
12
+ discoveryTitle: t('persona.discoveryTitle'),
13
+ catalogTitle: t('persona.catalogTitle'),
14
+ structureTitle: t('persona.structureTitle'),
15
+ selectedTestTitle: t('persona.selectedTestTitle'),
16
+ runSelected: t('persona.runSelected'),
17
+ runAll: t('persona.runAll'),
18
+ discover: t('persona.discover'),
19
+ watch: t('persona.watch'),
20
+ searchPlaceholder: t('persona.searchTests'),
21
+ noCatalogTests: t('persona.noCatalogTests'),
22
+ emptyStructure: t('persona.emptyStructure'),
23
+ runListTitle: t('persona.runListTitle'),
24
+ selectedRunTitle: t('persona.selectedRunTitle'),
25
+ itemsTitle: t('persona.itemsTitle'),
26
+ eventsTitle: t('persona.eventsTitle'),
27
+ loadMoreRuns: t('persona.loadMoreRuns'),
28
+ loadMoreItems: t('persona.loadMoreItems'),
29
+ appendEvents: t('persona.appendEvents'),
30
+ loadMoreEvents: t('persona.loadMoreEvents'),
31
+ refreshEvents: t('persona.refreshEvents'),
32
+ cancelRun: t('persona.cancelRun'),
33
+ reportSummary: t('persona.reportSummary'),
34
+ emptyRun: t('persona.emptyRun'),
35
+ noRuns: t('persona.noRuns'),
36
+ noItems: t('persona.noItems'),
37
+ noEvents: t('persona.noRunEvents'),
38
+ }
39
+ }
34
40
 
35
41
  type PersonaRunWorkbenchLabelKey = keyof PersonaRunWorkbenchLabels
36
42
 
37
43
  function resolveLabel(
44
+ defaults: Readonly<PersonaRunWorkbenchLabels>,
38
45
  overrides: Readonly<Partial<PersonaRunWorkbenchLabels>>,
39
46
  key: PersonaRunWorkbenchLabelKey,
40
47
  ): string {
41
48
  const override = overrides[key]
42
49
  return override === undefined
43
- ? PERSONA_RUN_WORKBENCH_DEFAULT_LABELS[key]
50
+ ? defaults[key]
44
51
  : validateNonEmptyString('SPersonaRunWorkbench', `labels.${key}`, override)
45
52
  }
46
53
 
47
54
  export function resolvePersonaRunWorkbenchLabels(
48
55
  overrides: Readonly<Partial<PersonaRunWorkbenchLabels>> = {},
56
+ t: UiKitTranslate = defaultTranslate,
49
57
  ): PersonaRunWorkbenchLabels {
58
+ const defaults = defaultLabels(t)
50
59
  return {
51
- projectTitle: resolveLabel(overrides, 'projectTitle'),
52
- discoveryTitle: resolveLabel(overrides, 'discoveryTitle'),
53
- catalogTitle: resolveLabel(overrides, 'catalogTitle'),
54
- structureTitle: resolveLabel(overrides, 'structureTitle'),
55
- selectedTestTitle: resolveLabel(overrides, 'selectedTestTitle'),
56
- runSelected: resolveLabel(overrides, 'runSelected'),
57
- runAll: resolveLabel(overrides, 'runAll'),
58
- discover: resolveLabel(overrides, 'discover'),
59
- watch: resolveLabel(overrides, 'watch'),
60
- searchPlaceholder: resolveLabel(overrides, 'searchPlaceholder'),
61
- noCatalogTests: resolveLabel(overrides, 'noCatalogTests'),
62
- emptyStructure: resolveLabel(overrides, 'emptyStructure'),
63
- runListTitle: resolveLabel(overrides, 'runListTitle'),
64
- selectedRunTitle: resolveLabel(overrides, 'selectedRunTitle'),
65
- itemsTitle: resolveLabel(overrides, 'itemsTitle'),
66
- eventsTitle: resolveLabel(overrides, 'eventsTitle'),
67
- loadMoreRuns: resolveLabel(overrides, 'loadMoreRuns'),
68
- loadMoreItems: resolveLabel(overrides, 'loadMoreItems'),
69
- appendEvents: resolveLabel(overrides, 'appendEvents'),
70
- loadMoreEvents: resolveLabel(overrides, 'loadMoreEvents'),
71
- refreshEvents: resolveLabel(overrides, 'refreshEvents'),
72
- cancelRun: resolveLabel(overrides, 'cancelRun'),
73
- reportSummary: resolveLabel(overrides, 'reportSummary'),
74
- emptyRun: resolveLabel(overrides, 'emptyRun'),
75
- noRuns: resolveLabel(overrides, 'noRuns'),
76
- noItems: resolveLabel(overrides, 'noItems'),
77
- noEvents: resolveLabel(overrides, 'noEvents'),
60
+ projectTitle: resolveLabel(defaults, overrides, 'projectTitle'),
61
+ discoveryTitle: resolveLabel(defaults, overrides, 'discoveryTitle'),
62
+ catalogTitle: resolveLabel(defaults, overrides, 'catalogTitle'),
63
+ structureTitle: resolveLabel(defaults, overrides, 'structureTitle'),
64
+ selectedTestTitle: resolveLabel(defaults, overrides, 'selectedTestTitle'),
65
+ runSelected: resolveLabel(defaults, overrides, 'runSelected'),
66
+ runAll: resolveLabel(defaults, overrides, 'runAll'),
67
+ discover: resolveLabel(defaults, overrides, 'discover'),
68
+ watch: resolveLabel(defaults, overrides, 'watch'),
69
+ searchPlaceholder: resolveLabel(defaults, overrides, 'searchPlaceholder'),
70
+ noCatalogTests: resolveLabel(defaults, overrides, 'noCatalogTests'),
71
+ emptyStructure: resolveLabel(defaults, overrides, 'emptyStructure'),
72
+ runListTitle: resolveLabel(defaults, overrides, 'runListTitle'),
73
+ selectedRunTitle: resolveLabel(defaults, overrides, 'selectedRunTitle'),
74
+ itemsTitle: resolveLabel(defaults, overrides, 'itemsTitle'),
75
+ eventsTitle: resolveLabel(defaults, overrides, 'eventsTitle'),
76
+ loadMoreRuns: resolveLabel(defaults, overrides, 'loadMoreRuns'),
77
+ loadMoreItems: resolveLabel(defaults, overrides, 'loadMoreItems'),
78
+ appendEvents: resolveLabel(defaults, overrides, 'appendEvents'),
79
+ loadMoreEvents: resolveLabel(defaults, overrides, 'loadMoreEvents'),
80
+ refreshEvents: resolveLabel(defaults, overrides, 'refreshEvents'),
81
+ cancelRun: resolveLabel(defaults, overrides, 'cancelRun'),
82
+ reportSummary: resolveLabel(defaults, overrides, 'reportSummary'),
83
+ emptyRun: resolveLabel(defaults, overrides, 'emptyRun'),
84
+ noRuns: resolveLabel(defaults, overrides, 'noRuns'),
85
+ noItems: resolveLabel(defaults, overrides, 'noItems'),
86
+ noEvents: resolveLabel(defaults, overrides, 'noEvents'),
78
87
  }
79
88
  }