dashboard-shell-shell 1.0.113 → 1.0.114

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 (119) hide show
  1. package/components/ActionDropdown.vue +1 -1
  2. package/components/ActionMenu.vue +2 -2
  3. package/components/ActionMenuShell.vue +0 -1
  4. package/components/AppModal.vue +6 -78
  5. package/components/AssignTo.vue +11 -25
  6. package/components/AsyncButton.vue +7 -24
  7. package/components/BannerGraphic.vue +0 -1
  8. package/components/ButtonDropdown.vue +4 -26
  9. package/components/ButtonGroup.vue +0 -4
  10. package/components/ButtonMultiAction.vue +0 -1
  11. package/components/CommunityLinks.vue +3 -3
  12. package/components/ConsumptionGauge.vue +5 -24
  13. package/components/CopyToClipboardText.vue +1 -2
  14. package/components/CruResource.vue +7 -12
  15. package/components/CruResourceFooter.vue +2 -2
  16. package/components/DashboardOptions.vue +15 -21
  17. package/components/DetailText.vue +0 -5
  18. package/components/DisableAuthProviderModal.vue +0 -1
  19. package/components/ExplorerMembers.vue +1 -1
  20. package/components/ExplorerProjectsNamespaces.vue +14 -56
  21. package/components/FixedBanner.vue +12 -19
  22. package/components/GlobalRoleBindings.vue +1 -5
  23. package/components/GrafanaDashboard.vue +4 -4
  24. package/components/GrowlManager.vue +1 -4
  25. package/components/HardwareResourceGauge.vue +3 -39
  26. package/components/InfoBox.vue +3 -3
  27. package/components/InputOrDisplay.vue +2 -28
  28. package/components/LabelValue.vue +1 -16
  29. package/components/LandingPagePreference.vue +3 -5
  30. package/components/LocaleSelector.vue +93 -39
  31. package/components/ModalWithCard.vue +0 -2
  32. package/components/MoveModal.vue +0 -1
  33. package/components/PromptChangePassword.vue +1 -1
  34. package/components/PromptModal.vue +2 -15
  35. package/components/PromptRemove.vue +8 -28
  36. package/components/PromptRestore.vue +0 -1
  37. package/components/ResourceCancelModal.vue +0 -1
  38. package/components/ResourceDetail/Masthead.vue +43 -188
  39. package/components/ResourceDetail/__tests__/Masthead.test.ts +1 -5
  40. package/components/ResourceDetail/index.vue +14 -49
  41. package/components/ResourceList/Masthead.vue +18 -80
  42. package/components/ResourceTable.vue +19 -60
  43. package/components/SideNav.vue +12 -32
  44. package/components/SortableTable/THead.vue +5 -34
  45. package/components/SortableTable/actions.js +1 -1
  46. package/components/SortableTable/index.vue +142 -649
  47. package/components/SortableTable/paging.js +28 -36
  48. package/components/SortableTable/selection.js +11 -0
  49. package/components/Tabbed/Tab.vue +3 -3
  50. package/components/Tabbed/index.vue +26 -44
  51. package/components/Wizard.vue +2 -2
  52. package/components/__tests__/AsyncButton.test.ts +2 -2
  53. package/components/__tests__/FixedBanner.test.ts +3 -3
  54. package/components/auth/Principal.vue +3 -10
  55. package/components/auth/__tests__/RoleDetailEdit.test.ts +2 -3
  56. package/components/form/ArrayList.vue +85 -123
  57. package/components/form/ArrayListGrouped.vue +2 -10
  58. package/components/form/Command.vue +15 -6
  59. package/components/form/EnvVars.vue +8 -16
  60. package/components/form/Footer.vue +5 -8
  61. package/components/form/HealthCheck.vue +3 -3
  62. package/components/form/HookOption.vue +16 -11
  63. package/components/form/KeyValue.vue +7 -16
  64. package/components/form/LabeledSelect.vue +76 -59
  65. package/components/form/LifecycleHooks.vue +3 -3
  66. package/components/form/MatchExpressions.vue +12 -35
  67. package/components/form/NameNsDescription.vue +115 -147
  68. package/components/form/Networking.vue +12 -20
  69. package/components/form/NodeAffinity.vue +23 -31
  70. package/components/form/NodeScheduling.vue +3 -13
  71. package/components/form/Password.vue +5 -11
  72. package/components/form/PodAffinity.vue +44 -43
  73. package/components/form/Probe.vue +66 -68
  74. package/components/form/ResourceQuota/Project.vue +1 -5
  75. package/components/form/ResourceSelector.vue +9 -7
  76. package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +3 -6
  77. package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +1 -12
  78. package/components/form/SSHKnownHosts/index.vue +2 -16
  79. package/components/form/Security.vue +56 -54
  80. package/components/form/Select.vue +7 -41
  81. package/components/form/ShellInput.vue +1 -5
  82. package/components/form/Tolerations.vue +1 -5
  83. package/components/form/UnitInput.vue +2 -2
  84. package/components/form/ValueFromResource.vue +121 -134
  85. package/components/form/WorkloadPorts.vue +18 -18
  86. package/components/form/__tests__/ArrayList.test.ts +2 -5
  87. package/components/form/__tests__/MatchExpressions.test.ts +12 -12
  88. package/components/form/__tests__/NameNsDescription.test.ts +14 -115
  89. package/components/form/__tests__/Probe.test.ts +8 -12
  90. package/components/form/__tests__/SSHKnownHosts.test.ts +0 -11
  91. package/components/form/__tests__/Select.test.ts +0 -37
  92. package/components/form/__tests__/UnitInput.test.ts +5 -4
  93. package/components/formatter/BadgeStateFormatter.vue +5 -8
  94. package/components/formatter/ExtensionCache.vue +74 -0
  95. package/components/formatter/InternalExternalIP.vue +0 -2
  96. package/components/formatter/Port.vue +24 -0
  97. package/components/formatter/SecretData.vue +7 -20
  98. package/components/formatter/SecretType.vue +41 -0
  99. package/components/nav/Favorite.vue +1 -5
  100. package/components/nav/Group.vue +27 -60
  101. package/components/nav/Header.vue +13 -39
  102. package/components/nav/Jump.vue +0 -7
  103. package/components/nav/NamespaceFilter.vue +8 -14
  104. package/components/nav/Pinned.vue +1 -1
  105. package/components/nav/TopLevelMenu.vue +17 -5
  106. package/components/nav/Type.vue +35 -32
  107. package/components/nav/__tests__/TopLevelMenu.test.ts +40 -0
  108. package/components/templates/blank.vue +1 -4
  109. package/components/templates/default.vue +0 -8
  110. package/components/templates/home.vue +1 -10
  111. package/components/templates/plain.vue +1 -10
  112. package/package.json +1 -1
  113. package/components/ActionDropdownShell.vue +0 -71
  114. package/components/DotState.vue +0 -84
  115. package/components/ModalManager.vue +0 -55
  116. package/components/SlideInPanelManager.vue +0 -126
  117. package/components/StatusBadge.vue +0 -77
  118. package/components/__tests__/ModalManager.spec.ts +0 -176
  119. package/components/__tests__/SlideInPanelManager.spec.ts +0 -166
@@ -63,7 +63,7 @@ export default {
63
63
  }
64
64
 
65
65
  if (projectRoleTemplateBindingSchema) {
66
- this.$store.dispatch('rancher/findAll', { type: NORMAN.PROJECT_ROLE_TEMPLATE_BINDING, opt: { force: true } }, { root: true })
66
+ this.$store.dispatch('rancher/findAll', { type: NORMAN.PROJECT_ROLE_TEMPLATE_BINDING }, { root: true })
67
67
  .then((bindings) => {
68
68
  this['projectRoleTemplateBindings'] = bindings;
69
69
  this.loadingProjectBindings = false;
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { mapGetters, useStore } from 'vuex';
2
+ import { mapGetters } from 'vuex';
3
3
  import ResourceTable, { defaultTableSortGenerationFn } from '@shell/components/ResourceTable';
4
4
  import { STATE, AGE, NAME, NS_SNAPSHOT_QUOTA } from '@shell/config/table-headers';
5
5
  import { uniq } from '@shell/utils/array';
@@ -11,13 +11,11 @@ import Masthead from '@shell/components/ResourceList/Masthead';
11
11
  import { mapPref, GROUP_RESOURCES, ALL_NAMESPACES, DEV } from '@shell/store/prefs';
12
12
  import MoveModal from '@shell/components/MoveModal';
13
13
  import ButtonMultiAction from '@shell/components/ButtonMultiAction.vue';
14
- import { escapeHtml } from '@shell/utils/string';
14
+
15
15
  import { NAMESPACE_FILTER_ALL_ORPHANS } from '@shell/utils/namespace-filter';
16
16
  import ResourceFetch from '@shell/mixins/resource-fetch';
17
17
  import DOMPurify from 'dompurify';
18
18
  import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
19
- import ActionMenu from '@shell/components/ActionMenuShell.vue';
20
- import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
21
19
 
22
20
  export default {
23
21
  name: 'ListProjectNamespace',
@@ -27,7 +25,6 @@ export default {
27
25
  MoveModal,
28
26
  ResourceTable,
29
27
  ButtonMultiAction,
30
- ActionMenu,
31
28
  },
32
29
  mixins: [ResourceFetch],
33
30
 
@@ -61,13 +58,6 @@ export default {
61
58
  this.projects = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.PROJECT, opt: { force: true } });
62
59
  },
63
60
 
64
- setup() {
65
- const store = useStore();
66
- const { featureDropdownMenu } = useRuntimeFlag(store);
67
-
68
- return { featureDropdownMenu };
69
- },
70
-
71
61
  data() {
72
62
  return {
73
63
  loadResources: [NAMESPACE],
@@ -165,7 +155,7 @@ export default {
165
155
  rowsWithFakeNamespaces() {
166
156
  const fakeRows = this.projectsWithoutNamespaces.map((project) => {
167
157
  return {
168
- groupById: `${ ('resourceTable.groupLabel.notInAProject') }-${ project.id }`,
158
+ groupByLabel: `${ ('resourceTable.groupLabel.notInAProject') }-${ project.id }`,
169
159
  isFake: true,
170
160
  mainRowKey: project.id,
171
161
  nameDisplay: project.spec?.displayName, // Enable filtering by the project name
@@ -176,8 +166,8 @@ export default {
176
166
 
177
167
  if (this.showMockNotInProjectGroup) {
178
168
  fakeRows.push( {
179
- groupById: this.t('resourceTable.groupLabel.notInAProject'),
180
- mainRowKey: 'fake-empty',
169
+ groupByLabel: this.t('resourceTable.groupLabel.notInAProject'), // Same as the groupByLabel for the namespace model
170
+ mainRowKey: 'fake-empty',
181
171
  });
182
172
  }
183
173
 
@@ -283,9 +273,6 @@ export default {
283
273
  },
284
274
  showCreateNsButton() {
285
275
  return this.groupPreference !== 'namespace';
286
- },
287
- projectGroupBy() {
288
- return this.groupPreference === 'none' ? null : 'groupById';
289
276
  }
290
277
  },
291
278
  methods: {
@@ -349,10 +336,6 @@ export default {
349
336
  return location;
350
337
  },
351
338
 
352
- getProjectActions(group) {
353
- return group.rows[0].project;
354
- },
355
-
356
339
  showProjectAction(event, group) {
357
340
  const project = group.rows[0].project;
358
341
 
@@ -376,13 +359,7 @@ export default {
376
359
  );
377
360
  }
378
361
 
379
- if ( row.groupById === this.notInProjectKey) {
380
- return this.t('resourceTable.groupLabel.notInAProject');
381
- }
382
-
383
- const project = row.project?.nameDisplay || row.project?.id || '';
384
-
385
- return this.t('resourceTable.groupLabel.project', { name: escapeHtml(project) }, true);
362
+ return row.groupByLabel;
386
363
  },
387
364
 
388
365
  projectDescription(group) {
@@ -454,7 +431,6 @@ export default {
454
431
  :schema="schema"
455
432
  :headers="headers"
456
433
  :rows="filteredRows"
457
- :group-by="projectGroupBy"
458
434
  :groupable="true"
459
435
  :sort-generation-fn="sortGenerationFn"
460
436
  :loading="loading"
@@ -481,7 +457,7 @@ export default {
481
457
  {{ projectDescription(group.group) }}
482
458
  </div>
483
459
  </div>
484
- <div class="right mr-10">
460
+ <div class="right">
485
461
  <router-link
486
462
  v-if="isNamespaceCreatable && (canSeeProjectlessNamespaces || group.group.key !== notInProjectKey)"
487
463
  class="create-namespace btn btn-sm role-secondary mr-5"
@@ -489,26 +465,13 @@ export default {
489
465
  >
490
466
  {{ t('projectNamespaces.createNamespace') }}
491
467
  </router-link>
492
- <template v-if="featureDropdownMenu">
493
- <ActionMenu
494
- v-if="showProjectActionButton(group.group)"
495
- :resource="getProjectActions(group.group)"
496
- :button-aria-label="t('projectNamespaces.tableActionsLabel', { resource: projectResource(group.group) })"
497
- />
498
- <div
499
- v-else
500
- class="invisible"
501
- />
502
- </template>
503
- <template v-else>
504
- <ButtonMultiAction
505
- class="project-action"
506
- :borderless="true"
507
- :aria-label="t('projectNamespaces.tableActionsLabel', { resource: projectResource(group.group) })"
508
- :invisible="!showProjectActionButton(group.group)"
509
- @click="showProjectAction($event, group.group)"
510
- />
511
- </template>
468
+ <ButtonMultiAction
469
+ class="project-action mr-10"
470
+ :borderless="true"
471
+ :aria-label="t('projectNamespaces.tableActionsLabel', { resource: projectResource(group.group) })"
472
+ :invisible="!showProjectActionButton(group.group)"
473
+ @click="showProjectAction($event, group.group)"
474
+ />
512
475
  </div>
513
476
  </div>
514
477
  </template>
@@ -573,11 +536,6 @@ export default {
573
536
  </div>
574
537
  </template>
575
538
  <style lang="scss" scoped>
576
- .invisible {
577
- display: inline-block;
578
- min-width: 28px;
579
- }
580
-
581
539
  .project-namespaces {
582
540
  & :deep() {
583
541
  .project-namespaces-table table {
@@ -37,7 +37,7 @@ export default {
37
37
  handleLineBreaksConsentText(banner) {
38
38
  if (banner.text?.length) {
39
39
  // split text by newline char
40
- const textArray = banner.text.split('\n').filter((element) => element);
40
+ const textArray = banner.text.split(/\\n/).filter((element) => element);
41
41
 
42
42
  if (textArray.length > 1) {
43
43
  textArray.forEach((str, i) => {
@@ -130,11 +130,11 @@ export default {
130
130
 
131
131
  if (isEmpty(banner)) {
132
132
  if (showHeader && this.header) {
133
- bannerContent = this.handleLineBreaksConsentText(bannerHeader) || {};
133
+ bannerContent = bannerHeader || {};
134
134
  } else if (showConsent && this.consent) {
135
135
  bannerContent = this.handleLineBreaksConsentText(bannerConsent) || {};
136
136
  } else if (showFooter && this.footer) {
137
- bannerContent = this.handleLineBreaksConsentText(bannerFooter) || {};
137
+ bannerContent = bannerFooter || {};
138
138
  } else {
139
139
  bannerContent = {};
140
140
  }
@@ -168,20 +168,16 @@ export default {
168
168
  >
169
169
  <!-- text as array to support line breaks programmatically rather than just exposing HTML -->
170
170
  <div v-if="isTextAnArray">
171
- <div
171
+ <p
172
172
  v-for="(text, index) in banner.text"
173
173
  :key="index"
174
- class="array-row"
175
174
  >
176
175
  {{ text }}
177
- </div>
176
+ </p>
178
177
  </div>
179
- <div
180
- v-else
181
- class="single-row"
182
- >
178
+ <p v-else>
183
179
  {{ banner.text }}
184
- </div>
180
+ </p>
185
181
  </div>
186
182
  <div v-else-if="showDialog">
187
183
  <div class="banner-dialog-glass" />
@@ -196,20 +192,16 @@ export default {
196
192
  >
197
193
  <!-- text as array to support line breaks programmatically rather than just exposing HTML -->
198
194
  <div v-if="isTextAnArray">
199
- <div
195
+ <p
200
196
  v-for="(text, index) in banner.text"
201
197
  :key="index"
202
- class="array-row"
203
198
  >
204
199
  {{ text }}
205
- </div>
200
+ </p>
206
201
  </div>
207
- <div
208
- v-else
209
- class="single-row"
210
- >
202
+ <p v-else>
211
203
  {{ banner.text }}
212
- </div>
204
+ </p>
213
205
  </div>
214
206
  <button
215
207
  class="btn role-primary"
@@ -231,6 +223,7 @@ export default {
231
223
  padding: 0 20px;
232
224
 
233
225
  &.banner-consent {
226
+ position: absolute;
234
227
  height: unset;
235
228
  min-height: 2em;
236
229
  overflow: hidden;
@@ -49,10 +49,6 @@ export default {
49
49
  userId: {
50
50
  type: String,
51
51
  default: ''
52
- },
53
- watchOverride: {
54
- type: Boolean,
55
- default: true,
56
52
  }
57
53
  },
58
54
  async fetch() {
@@ -142,7 +138,7 @@ export default {
142
138
  this.update();
143
139
  },
144
140
  userId(userId, oldUserId) {
145
- if (userId === oldUserId || this.watchOverride === true) {
141
+ if (userId === oldUserId) {
146
142
  return;
147
143
  }
148
144
  this.update();
@@ -262,22 +262,22 @@ export default {
262
262
  <div v-if="loading">
263
263
  <Loading />
264
264
  </div>
265
- <!-- <div
265
+ <div
266
266
  v-if="!loading && !error"
267
267
  class="external-link"
268
- > -->
268
+ >
269
269
  <!-- https://github.com/harvester/harvester-installer/pull/512/files -->
270
270
  <!-- It is necessary to include the parameter referer when accessing the Grafana page. -->
271
271
  <!-- This parameter is required by the backend to identify the origin of the request from which cluster -->
272
272
  <!-- The matching mechanism as follows: -->
273
273
  <!-- ~.*/k8s/clusters/(c-m-.+)/.* -->
274
274
  <!-- ~.*/dashboard/harvester/c/(c-m-.+)/.* -->
275
- <!-- <a
275
+ <a
276
276
  :href="grafanaUrl"
277
277
  target="_blank"
278
278
  rel="noopener nofollow"
279
279
  >{{ t('grafanaDashboard.grafana') }} <i class="icon icon-external-link" /></a>
280
- </div> -->
280
+ </div>
281
281
  </div>
282
282
  </template>
283
283
 
@@ -1,6 +1,5 @@
1
1
  <script>
2
2
  import { mapState } from 'vuex';
3
- import { translateError } from '@shell/utils/error'
4
3
 
5
4
  export default {
6
5
  data() {
@@ -26,7 +25,6 @@ export default {
26
25
  },
27
26
 
28
27
  methods: {
29
- translateError,
30
28
  close(growl) {
31
29
  this.$store.dispatch('growl/remove', growl.id);
32
30
  },
@@ -109,7 +107,6 @@ export default {
109
107
  @click="close(growl)"
110
108
  />
111
109
  <div
112
- v-if="growl.title"
113
110
  :id="`growl-title-${ growl.id }`"
114
111
  class="growl-text-title"
115
112
  >
@@ -120,7 +117,7 @@ export default {
120
117
  :id="`growl-message-${ growl.id }`"
121
118
  :class="{ 'has-title': !!growl.title }"
122
119
  >
123
- {{ translateError(growl.message) }}
120
+ {{ growl.message }}
124
121
  </p>
125
122
  </div>
126
123
  </div>
@@ -85,9 +85,8 @@ export default {
85
85
  :capacity="reserved.total"
86
86
  :used="reserved.useful"
87
87
  :color-stops="colorStops"
88
- :reserveText="`已分配`"
89
88
  >
90
- <!-- <template #title>
89
+ <template #title>
91
90
  <span>
92
91
  {{ reservedTitle ?? t('clusterIndexPage.hardwareResourceGauge.reserved') }}
93
92
  <span class="values text-muted">
@@ -109,23 +108,6 @@ export default {
109
108
  <span>
110
109
  {{ percentage(reserved) }}
111
110
  </span>
112
- </template> -->
113
- <template #content>
114
- <span>
115
- {{ percentage(reserved) }}(
116
- 共 <span v-if="reserved.formattedTotal">
117
- {{ reserved.formattedTotal }}
118
- </span>
119
- <span v-else>
120
- {{ maxDecimalPlaces(reserved.total) }} {{ reserved.units }}
121
- </span>,{{ reservedTitle === '分配'? '已分配': '预留' }} <span v-if="reserved.formattedUseful">
122
- {{ reserved.formattedUseful }} {{ reserved.units }}
123
- </span>
124
- <span v-else>
125
- {{ maxDecimalPlaces(reserved.useful) }} {{ reserved.units }}
126
- </span>
127
- )
128
- </span>
129
111
  </template>
130
112
  </ConsumptionGauge>
131
113
  </div>
@@ -137,26 +119,8 @@ export default {
137
119
  :capacity="used.total"
138
120
  :used="used.useful"
139
121
  :color-stops="colorStops"
140
- :reserveText="`已使用`"
141
122
  >
142
- <template #content>
143
- <span>
144
- {{ percentage(used) }}(
145
- 共 <span v-if="used.formattedTotal">
146
- {{ used.formattedTotal }}
147
- </span>
148
- <span v-else>
149
- {{ maxDecimalPlaces(used.total) }} {{ used.units }}
150
- </span>,已使用 <span v-if="used.formattedUseful">
151
- {{ used.formattedUseful }} {{ used.units }}
152
- </span>
153
- <span v-else>
154
- {{ maxDecimalPlaces(used.useful) }} {{ used.units }}
155
- </span>
156
- )
157
- </span>
158
- </template>
159
- <!-- <template #title>
123
+ <template #title>
160
124
  <span>
161
125
  {{ usedTitle ?? t('clusterIndexPage.hardwareResourceGauge.used') }}
162
126
  <span class="values text-muted">
@@ -178,7 +142,7 @@ export default {
178
142
  <span>
179
143
  {{ percentage(used) }}
180
144
  </span>
181
- </template> -->
145
+ </template>
182
146
  </ConsumptionGauge>
183
147
  </div>
184
148
  </div>
@@ -26,8 +26,8 @@ export default {
26
26
 
27
27
  <style lang="scss" scoped>
28
28
  .info-box {
29
- border: 1px solid var(--tabbed-border);
30
- padding: 20px;
29
+ border: 2px solid var(--tabbed-border);
30
+ padding: 10px;
31
31
  margin-bottom: 20px;
32
32
  border-radius: var(--border-radius);
33
33
  flex-grow: 1;
@@ -81,4 +81,4 @@ export default {
81
81
  }
82
82
  }
83
83
  }
84
- </style>
84
+ </style>
@@ -45,9 +45,7 @@ export default {
45
45
  </div>
46
46
  <div class="value">
47
47
  <slot name="value">
48
- <span v-clean-tooltip="displayValue">
49
- {{ displayValue }}
50
- </span>
48
+ {{ displayValue }}
51
49
  </slot>
52
50
  </div>
53
51
  </div>
@@ -55,7 +53,7 @@ export default {
55
53
  </template>
56
54
 
57
55
  <style lang="scss" scoped>
58
- /* .label {
56
+ .label {
59
57
  display: flex;
60
58
  flex-direction: column;
61
59
 
@@ -63,29 +61,5 @@ export default {
63
61
  font-size: 14px;
64
62
  line-height: $input-line-height;
65
63
  }
66
- } */
67
- .label {
68
- display: flex;
69
- /* align-items: center; */
70
- /* flex-direction: column; */
71
-
72
- .text-label{
73
- width: 160px;
74
- line-height: 32px;
75
- }
76
- .value {
77
- /* font-size: 14px; */
78
- /* line-height: $input-line-height; */
79
- line-height: 32px;
80
- flex: 1;
81
- overflow: hidden;
82
- text-overflow: ellipsis;
83
- white-space: nowrap;
84
-
85
- ul{
86
- line-height: $input-line-height;
87
- list-style:none;
88
- }
89
- }
90
64
  }
91
65
  </style>
@@ -30,7 +30,7 @@ export default {
30
30
  </template>
31
31
 
32
32
  <style lang="scss" scoped>
33
- /* .label {
33
+ .label {
34
34
  display: flex;
35
35
  flex-direction: column;
36
36
 
@@ -38,20 +38,5 @@ export default {
38
38
  font-size: 14px;
39
39
  line-height: $input-line-height;
40
40
  }
41
- } */
42
- .label {
43
- display: flex;
44
- /* flex-direction: column; */
45
- align-items: center;
46
- .text-label{
47
- width: 160px;
48
- line-height: 32px;
49
- }
50
- .value {
51
- line-height: $input-line-height;
52
- overflow: hidden;
53
- text-overflow: ellipsis;
54
- white-space: nowrap;
55
- }
56
41
  }
57
42
  </style>
@@ -103,6 +103,9 @@ export default {
103
103
 
104
104
  <template>
105
105
  <div>
106
+ <p class="set-landing-leadin">
107
+ {{ t('landing.landingPrefs.body') }}
108
+ </p>
106
109
  <RadioGroup
107
110
  id="login-route"
108
111
  :value="afterLoginRoute"
@@ -110,11 +113,6 @@ export default {
110
113
  :options="routeRadioOptions"
111
114
  @update:value="updateLoginRoute"
112
115
  >
113
- <template #label>
114
- <p class="set-landing-leadin">
115
- {{ t('landing.landingPrefs.body') }}
116
- </p>
117
- </template>
118
116
  <template #2="{option}">
119
117
  <div class="custom-page">
120
118
  <RadioButton
@@ -1,17 +1,11 @@
1
1
  <script>
2
2
  import { mapGetters } from 'vuex';
3
3
  import Select from '@shell/components/form/Select.vue';
4
- import { RcDropdown, RcDropdownTrigger, RcDropdownItem } from '@components/RcDropdown';
5
4
 
6
5
  export default {
7
6
  name: 'LocalSelector',
8
7
 
9
- components: {
10
- Select,
11
- RcDropdown,
12
- RcDropdownItem,
13
- RcDropdownTrigger,
14
- },
8
+ components: { Select },
15
9
 
16
10
  props: {
17
11
  mode: {
@@ -71,51 +65,111 @@ export default {
71
65
  <template>
72
66
  <div>
73
67
  <div v-if="mode === 'login'">
74
- <rc-dropdown v-if="showLocale">
75
- <rc-dropdown-trigger
76
- data-testid="locale-selector"
77
- link
78
- class="baseline"
79
- :aria-label="t('locale.menu')"
68
+ <div
69
+ v-if="showLocale"
70
+ role="menu"
71
+ :aria-label="t('locale.menu')"
72
+ class="locale-login-container"
73
+ tabindex="0"
74
+ @click="openLocaleSelector"
75
+ @blur.capture="closeLocaleSelector"
76
+ @keyup.enter="openLocaleSelector"
77
+ @keyup.space="openLocaleSelector"
78
+ >
79
+ <v-dropdown
80
+ popperClass="localeSelector"
81
+ :shown="isLocaleSelectorOpen"
82
+ placement="top"
83
+ distance="8"
84
+ skidding="12"
85
+ :triggers="[]"
86
+ :autoHide="false"
87
+ :flip="false"
88
+ :container="false"
89
+ @focus.capture="openLocaleSelector"
80
90
  >
81
- {{ selectedLocaleLabel }}
82
- <template
83
- v-if="showIcon"
84
- #after
91
+ <a
92
+ data-testid="locale-selector"
93
+ class="locale-chooser"
85
94
  >
86
- <i class="icon icon-fw icon-sort-down" />
95
+ {{ selectedLocaleLabel }}
96
+ <i
97
+ v-if="showIcon"
98
+ class="icon icon-fw icon-sort-down"
99
+ />
100
+ </a>
101
+ <template #popper>
102
+ <ul
103
+ class="list-unstyled dropdown"
104
+ style="margin: -1px;"
105
+ >
106
+ <li
107
+ v-if="showNone"
108
+ v-t="'locale.none'"
109
+ class="hand"
110
+ tabindex="0"
111
+ role="menuitem"
112
+ @click.stop="switchLocale('none')"
113
+ @keyup.enter.stop="switchLocale('none')"
114
+ @keyup.space.stop="switchLocale('none')"
115
+ />
116
+ <li
117
+ v-for="(label, name) in availableLocales"
118
+ :key="name"
119
+ tabindex="0"
120
+ role="menuitem"
121
+ class="hand"
122
+ @click.stop="switchLocale(name)"
123
+ @keyup.enter.stop="switchLocale(name)"
124
+ @keyup.space.stop="switchLocale(name)"
125
+ >
126
+ {{ label }}
127
+ </li>
128
+ </ul>
87
129
  </template>
88
- </rc-dropdown-trigger>
89
- <template #dropdownCollection>
90
- <rc-dropdown-item
91
- v-if="showNone"
92
- v-t="'locale.none'"
93
- @click="switchLocale('none')"
94
- />
95
- <rc-dropdown-item
96
- v-for="(label, name) in availableLocales"
97
- :key="name"
98
- :lang="name"
99
- @click.stop="switchLocale(name)"
100
- >
101
- {{ label }}
102
- </rc-dropdown-item>
103
- </template>
104
- </rc-dropdown>
130
+ </v-dropdown>
131
+ </div>
105
132
  </div>
106
133
  <div v-else>
107
134
  <Select
108
135
  :value="selectedOption"
109
136
  :options="localesOptions"
110
- :is-lang-select="true"
111
137
  @update:value="switchLocale($event)"
112
138
  />
113
139
  </div>
114
140
  </div>
115
141
  </template>
116
142
 
117
- <style lang="scss">
118
- .baseline {
119
- align-items: baseline;
143
+ <style lang="scss" scoped>
144
+ .advanced {
145
+ user-select: none;
146
+ padding: 0 5px;
147
+ line-height: 40px;
148
+ font-size: 15px;
149
+ font-weight: 500;
150
+ }
151
+ .content {
152
+ background: var(--nav-active);
153
+ padding: 10px;
154
+ margin-top: 6px;
155
+ border-radius: 4px;
156
+ }
157
+
158
+ .hand:focus-visible {
159
+ @include focus-outline;
160
+ outline-offset: 4px;
161
+ }
162
+
163
+ .locale-chooser {
164
+ cursor: pointer;
165
+
166
+ &:hover {
167
+ text-decoration: none;
120
168
  }
169
+ }
170
+
171
+ .locale-login-container:focus-visible {
172
+ @include focus-outline;
173
+ outline-offset: 2px;
174
+ }
121
175
  </style>