dashboard-shell-shell 3.0.5-test.5 → 3.0.5-test.50

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 (169) hide show
  1. package/assets/brand/csp/favicon.png +0 -0
  2. package/assets/icons/iconfont.css +4 -1
  3. package/assets/images/pl/dark/logo.png +0 -0
  4. package/assets/styles/all.scss +23 -3
  5. package/assets/styles/base/_variables.scss +5 -5
  6. package/assets/styles/fonts/_icons.scss +3 -2
  7. package/assets/styles/global/_button.scss +2 -2
  8. package/assets/styles/global/_form.scss +1 -0
  9. package/assets/styles/global/_select.scss +1 -1
  10. package/assets/styles/global/_tooltip.scss +5 -1
  11. package/assets/styles/themes/_light.scss +3 -3
  12. package/assets/styles/vendor/vue-select.scss +2 -1
  13. package/assets/translations/en-us.yaml +64 -0
  14. package/assets/translations/zh-hans.yaml +206 -21
  15. package/components/ButtonDropdown.vue +3 -1
  16. package/components/ClusterIconMenu.vue +1 -1
  17. package/components/CodeMirror.vue +6 -4
  18. package/components/ConsumptionGauge.vue +1 -1
  19. package/components/ContainerResourceLimit.vue +2 -2
  20. package/components/CruResource.vue +3 -2
  21. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +10 -7
  22. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +1 -1
  23. package/components/Drawer/ResourceDetailDrawer/index.vue +3 -2
  24. package/components/ExplorerMembers.vue +10 -1
  25. package/components/GlobalRoleBindings.vue +69 -114
  26. package/components/PodSecurityAdmission.vue +1 -1
  27. package/components/PromptRemove.vue +23 -1
  28. package/components/RelatedResources.vue +3 -0
  29. package/components/Resource/Detail/Metadata/index.vue +1 -0
  30. package/components/Resource/Detail/TitleBar/Top.vue +2 -0
  31. package/components/Resource/Detail/TitleBar/composables.ts +16 -1
  32. package/components/Resource/Detail/TitleBar/index.vue +42 -23
  33. package/components/ResourceDetail/Masthead/index.vue +1 -1
  34. package/components/ResourceDetail/Masthead/latest.vue +1 -1
  35. package/components/ResourceDetail/Masthead/legacy.vue +8 -7
  36. package/components/ResourceDetail/legacy.vue +15 -15
  37. package/components/ResourceList/Masthead.vue +13 -17
  38. package/components/ResourceTable.vue +16 -0
  39. package/components/SideNav.vue +21 -21
  40. package/components/SingleClusterInfo.vue +2 -1
  41. package/components/SortableTable/THead.vue +46 -1
  42. package/components/SortableTable/index.vue +55 -19
  43. package/components/Tabbed/index.vue +7 -2
  44. package/components/auth/Principal.vue +16 -8
  45. package/components/auth/RoleDetailEdit.vue +11 -7
  46. package/components/breadcrumb/index.vue +15 -236
  47. package/components/form/ArrayList.vue +164 -147
  48. package/components/form/ArrayListGrouped.vue +5 -3
  49. package/components/form/ChangePassword.vue +1 -1
  50. package/components/form/ClusterAppearance.vue +4 -3
  51. package/components/form/Command.vue +4 -5
  52. package/components/form/Conditions.vue +15 -1
  53. package/components/form/Footer.vue +1 -0
  54. package/components/form/HealthCheck.vue +0 -2
  55. package/components/form/HookOption.vue +87 -58
  56. package/components/form/InputWithSelect.vue +8 -7
  57. package/components/form/KeyValue.vue +20 -2
  58. package/components/form/LabeledSelect.vue +3 -1
  59. package/components/form/Labels.vue +2 -2
  60. package/components/form/MatchExpressions.vue +4 -4
  61. package/components/form/Members/ClusterMembershipEditor.vue +1 -1
  62. package/components/form/Members/ClusterPermissionsEditor.vue +60 -41
  63. package/components/form/Members/MembershipEditor.vue +4 -4
  64. package/components/form/Members/ProjectMembershipEditor.vue +1 -1
  65. package/components/form/NameNsDescription.vue +4 -2
  66. package/components/form/Networking.vue +6 -9
  67. package/components/form/NodeAffinity.vue +29 -28
  68. package/components/form/PodAffinity.vue +23 -23
  69. package/components/form/Probe.vue +15 -11
  70. package/components/form/ProjectMemberEditor.vue +66 -48
  71. package/components/form/ResourceQuota/Namespace.vue +4 -4
  72. package/components/form/ResourceQuota/NamespaceRow.vue +11 -9
  73. package/components/form/ResourceQuota/Project.vue +4 -4
  74. package/components/form/ResourceQuota/ProjectRow.vue +36 -30
  75. package/components/form/ResourceSelector.vue +1 -1
  76. package/components/form/Security.vue +1 -3
  77. package/components/form/Select.vue +7 -1
  78. package/components/form/ServiceNameSelect.vue +2 -5
  79. package/components/form/ServicePorts.vue +149 -75
  80. package/components/form/Tolerations.vue +13 -9
  81. package/components/form/ValueFromResource.vue +110 -96
  82. package/components/formatter/WorkloadHealthScale.vue +4 -3
  83. package/components/nav/Group.vue +6 -0
  84. package/components/nav/Header.vue +17 -137
  85. package/components/nav/NamespaceFilter.vue +15 -21
  86. package/components/nav/TopLevelMenu.vue +99 -125
  87. package/components/nav/Type.vue +11 -3
  88. package/config/menuRouteMap.js +10 -0
  89. package/config/product/explorer.js +32 -10
  90. package/config/product/manager.js +28 -17
  91. package/config/router/navigation-guards/index.js +61 -3
  92. package/detail/node.vue +28 -23
  93. package/dialog/AddCustomBadgeDialog.vue +17 -9
  94. package/dialog/RollbackWorkloadDialog.vue +1 -1
  95. package/edit/autoscaling.horizontalpodautoscaler/external-metric.vue +1 -1
  96. package/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue +9 -6
  97. package/edit/autoscaling.horizontalpodautoscaler/index.vue +3 -1
  98. package/edit/autoscaling.horizontalpodautoscaler/metric-identifier.vue +2 -2
  99. package/edit/autoscaling.horizontalpodautoscaler/metric-object-reference.vue +7 -5
  100. package/edit/autoscaling.horizontalpodautoscaler/metric-target.vue +5 -3
  101. package/edit/autoscaling.horizontalpodautoscaler/metrics-row.vue +2 -2
  102. package/edit/autoscaling.horizontalpodautoscaler/object-metric.vue +2 -2
  103. package/edit/autoscaling.horizontalpodautoscaler/pod-metric.vue +1 -1
  104. package/edit/autoscaling.horizontalpodautoscaler/resource-metric.vue +2 -2
  105. package/edit/configmap.vue +4 -0
  106. package/edit/networking.k8s.io.ingress/Certificate.vue +14 -5
  107. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +2 -2
  108. package/edit/networking.k8s.io.ingress/Rule.vue +5 -11
  109. package/edit/networking.k8s.io.ingress/RulePath.vue +105 -96
  110. package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +3 -3
  111. package/edit/networking.k8s.io.networkpolicy/PolicyRulePort.vue +4 -2
  112. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +12 -11
  113. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  114. package/edit/persistentvolume/index.vue +3 -1
  115. package/edit/persistentvolumeclaim.vue +2 -0
  116. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +1 -1
  117. package/edit/secret/index.vue +2 -2
  118. package/edit/service.vue +4 -1
  119. package/edit/storage.k8s.io.storageclass/index.vue +10 -8
  120. package/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/aws-ebs.vue +34 -27
  121. package/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/gce-pd.vue +15 -13
  122. package/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/vsphere-volume.vue +41 -39
  123. package/edit/workload/Job.vue +31 -34
  124. package/edit/workload/Upgrading.vue +5 -5
  125. package/edit/workload/index.vue +19 -15
  126. package/edit/workload/storage/Mount.vue +1 -0
  127. package/edit/workload/storage/awsElasticBlockStore.vue +9 -7
  128. package/edit/workload/storage/azureDisk.vue +14 -10
  129. package/edit/workload/storage/azureFile.vue +9 -7
  130. package/edit/workload/storage/csi/index.vue +6 -9
  131. package/edit/workload/storage/emptyDir.vue +7 -5
  132. package/edit/workload/storage/gcePersistentDisk.vue +9 -7
  133. package/edit/workload/storage/hostPath.vue +7 -5
  134. package/edit/workload/storage/nfs.vue +8 -6
  135. package/edit/workload/storage/persistentVolumeClaim/index.vue +12 -10
  136. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +20 -15
  137. package/edit/workload/storage/secret.vue +9 -6
  138. package/edit/workload/storage/vsphereVolume.vue +11 -7
  139. package/initialize/app-extended.js +7 -1
  140. package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +8 -6
  141. package/mixins/create-edit-view/impl.js +10 -0
  142. package/models/provisioning.cattle.io.cluster.js +19 -18
  143. package/models/workload.js +2 -2
  144. package/package.json +1 -1
  145. package/pages/account/index.vue +96 -115
  146. package/pages/auth/login.vue +1 -1
  147. package/pages/auth/setup.vue +36 -17
  148. package/pages/c/_cluster/auth/roles/index.vue +65 -8
  149. package/pages/c/_cluster/explorer/ConfigBadge.vue +1 -1
  150. package/pages/c/_cluster/explorer/index.vue +2 -1
  151. package/pages/c/_cluster/explorer/tools/index.vue +6 -6
  152. package/pages/home.vue +55 -13
  153. package/pkg/tsconfig.json +9 -9
  154. package/pkg/vue.config.js +1 -1
  155. package/plugins/dashboard-store/actions.js +1 -1
  156. package/plugins/dashboard-store/resource-class.js +28 -27
  157. package/rancher-components/Banner/Banner.vue +14 -2
  158. package/rancher-components/Form/Radio/RadioGroup.vue +9 -1
  159. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +31 -2
  160. package/scripts/build-pkg.sh +18 -23
  161. package/scripts/publish-shell.sh +1 -1
  162. package/store/i18n.js +1 -0
  163. package/store/type-map.js +1 -3
  164. package/types/shell/index.d.ts +12 -30
  165. package/utils/error.js +26 -4
  166. package/utils/errorTranslate.json +390 -6
  167. package/utils/errorTranslateNew.json +39 -0
  168. package/utils/roleFiltering.js +33 -0
  169. package/vue.config.js +1 -1
@@ -1,69 +1,18 @@
1
1
  <script>
2
- import { KUBERNETES, PROJECT } from '@shell/config/labels-annotations';
3
- import { FLEET, NAMESPACE, MANAGEMENT, HELM } from '@shell/config/types';
4
- import ButtonGroup from '@shell/components/ButtonGroup';
5
- // import { BadgeState } from '@components/BadgeState';
6
- import DotState from '@shell/components/DotState.vue';
7
- import { Banner } from '@components/Banner';
8
- import { get } from '@shell/utils/object';
9
- import { NAME as FLEET_NAME } from '@shell/config/product/fleet';
10
- import { HIDE_SENSITIVE } from '@shell/store/prefs';
11
- import {
12
- AS, _DETAIL, _CONFIG, _YAML, MODE, _CREATE, _EDIT, _VIEW, _UNFLAG, _GRAPH
13
- } from '@shell/config/query-params';
14
- import { ExtensionPoint, PanelLocation } from '@shell/core/types';
15
- import ExtensionPanel from '@shell/components/ExtensionPanel';
16
- import TabTitle from '@shell/components/TabTitle';
17
- import ActionMenu from '@shell/components/ActionMenuShell.vue';
2
+ import { get } from '@shell/utils/object';;
18
3
  import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
19
4
  import { useStore } from 'vuex';
20
5
 
21
- // i18n-uses resourceDetail.header.*
22
-
23
- /**
24
- * Resource Detail Masthead component.
25
- *
26
- * ToDo: this component seem to be picking up a lot of logic from special cases, could be simplified down to parameters and then customized per use-case via wrapper component
27
- */
28
6
  export default {
29
7
 
30
- name: 'MastheadResourceDetail',
8
+ name: 'MastheadBreadcrumb',
31
9
 
32
10
  components: {
33
- // BadgeState,
34
- DotState,
35
- Banner,
36
- ButtonGroup,
37
- ExtensionPanel,
38
- TabTitle,
39
- ActionMenu,
40
11
  },
41
12
  props: {
42
- value: {
43
- type: Object,
44
- default: () => {
45
- return {};
46
- }
47
- },
48
-
49
- mode: {
50
- type: String,
51
- default: 'view'
52
- },
53
-
54
- realMode: {
55
- type: String,
56
- default: 'view'
57
- },
58
-
59
- as: {
13
+ resourceTypeLabel: {
60
14
  type: String,
61
- default: _YAML,
62
- },
63
-
64
- storeOverride: {
65
- type: String,
66
- default: null,
15
+ default: ''
67
16
  },
68
17
 
69
18
  resource: {
@@ -71,15 +20,10 @@ export default {
71
20
  default: null,
72
21
  },
73
22
 
74
- resourceSubtype: {
75
- type: String,
76
- default: null,
77
- },
78
-
79
- parentRouteOverride: {
23
+ realMode: {
80
24
  type: String,
81
- default: null,
82
- },
25
+ default: 'view',
26
+ }
83
27
 
84
28
  },
85
29
 
@@ -92,98 +36,21 @@ export default {
92
36
 
93
37
  data() {
94
38
  return {
95
- DETAIL_VIEW: _DETAIL,
96
- extensionType: ExtensionPoint.PANEL,
97
- extensionLocation: PanelLocation.DETAILS_MASTHEAD,
98
- Svg: require('~shell/assets/images/API.svg')
99
39
  };
100
40
  },
101
41
 
102
42
  computed: {
103
- dev() {
104
- return this.$store.getters['prefs/dev'];
105
- },
106
-
107
- schema() {
108
- const inStore = this.storeOverride || this.$store.getters['currentStore'](this.resource);
109
-
110
- return this.$store.getters[`${ inStore }/schemaFor`]( this.resource );
111
- },
112
-
113
- isProjectHelmChart() {
114
- return this.schema?.id === HELM.PROJECTHELMCHART;
115
- },
116
-
117
- shouldHifenize() {
118
- return (this.mode === 'view' || this.mode === 'edit') && this.resourceSubtype?.length && this.value?.nameDisplay?.length;
119
- },
120
-
121
- parent() {
122
- const displayName = this.value?.parentNameOverride || this.$store.getters['type-map/labelFor'](this.schema);
123
- const product = this.$store.getters['currentProduct'].name;
124
-
125
- const defaultLocation = {
126
- name: 'c-cluster-product-resource',
127
- params: {
128
- resource: this.resource,
129
- product,
130
- }
131
- };
132
-
133
- const location = this.value?.parentLocationOverride || defaultLocation;
134
-
135
- if (this.parentRouteOverride) {
136
- location.name = this.parentRouteOverride;
137
- }
138
-
139
- const typeOptions = this.$store.getters[`type-map/optionsFor`]( this.resource );
140
-
141
- // 转换为中文
142
- const displayName_zh_hans = {
143
- 'GlobalRole': '全局角色',
144
- 'RoleTemplate': '集群角色',
145
- }
146
- if (displayName_zh_hans[displayName]) {
147
- displayName = displayName_zh_hans[displayName]
148
- }
149
-
150
- if (displayName == '集群角色' && (this.$route.query?.roleContext == 'NAMESPACE' || location.hash == '#NAMESPACE')) {
151
- displayName = '项目或资源组角色'
152
- }
153
-
154
- const out = {
155
- displayName, location, ...typeOptions
156
- };
157
-
158
- return out;
159
- },
160
-
161
-
162
- displayName() {
163
- let displayName = this.value.nameDisplay;
164
-
165
- if (this.isProjectHelmChart) {
166
- displayName = this.value.projectDisplayName;
167
- }
168
-
169
- return this.shouldHifenize ? ` - ${ displayName }` : displayName;
170
- },
171
43
 
172
44
  demoDisplay() {
173
- const product = this.$store.getters['productId'];
174
-
175
- const resources = this.location?.params?.resource || ''
176
45
 
177
- const productId = this.$store.getters['type-map/groupForBasicType'](this.$store.getters['productId'], resources);
46
+ const resources = this.$route.params?.resource || ''
178
47
 
179
- if (productId === undefined) {
180
- return '';
181
- }
182
- const parts = productId.split('::');
48
+ let productId = this.$store.getters['type-map/groupForBasicType'](this.$store.getters['productId'], resources);
49
+ const parts = productId?.split('::') || [];
183
50
  const newString = 'root';
184
51
 
185
52
  if (!parts?.includes(newString)) {
186
- parts.unshift(newString); // 将字符串添加到数组第一位
53
+ parts?.unshift(newString); // 将字符串添加到数组第一位
187
54
  }
188
55
 
189
56
  const partsEn = parts.map((item) => {
@@ -192,19 +59,6 @@ export default {
192
59
 
193
60
  return partsEn;
194
61
  },
195
- menuIcon() {
196
- const product = this.$store.getters['productId'];
197
-
198
- const resources = this.location?.params?.resource || ''
199
-
200
- return this.$store.getters['type-map/groupsForVirTypes'](product, resources);
201
- },
202
-
203
- location() {
204
- const { parent } = this;
205
-
206
- return parent?.location;
207
- },
208
62
 
209
63
  },
210
64
 
@@ -217,9 +71,8 @@ export default {
217
71
  <template>
218
72
  <div class="masthead">
219
73
  <div class="title">
220
- <!-- 创建api密钥不需要面包屑 -->
74
+ <!-- 标题区域 -->
221
75
  <div
222
- v-if="!(parentRouteOverride === 'account' && resource=== 'token')"
223
76
  class="excram-list"
224
77
  >
225
78
  <span
@@ -230,7 +83,7 @@ export default {
230
83
  <span>/</span>
231
84
  </span>
232
85
  <span class="excram-last-name">
233
- {{ (realMode === 'view'? '查看': realMode === 'edit' ? '编辑':'创建') + parent.displayName }}
86
+ {{ (realMode === 'view'? '查看': realMode === 'edit' ? '编辑':'创建') + resourceTypeLabel }}
234
87
  </span>
235
88
  </div>
236
89
  </div>
@@ -239,71 +92,6 @@ export default {
239
92
 
240
93
  <style lang='scss' scoped>
241
94
 
242
- HEADER {
243
- margin: 0;
244
- }
245
-
246
- .primaryheader {
247
- display: flex;
248
- flex-direction: row;
249
- align-items: center;
250
- font-size:14px;
251
- height: 50px;
252
-
253
- h1 {
254
- margin: 0;
255
- }
256
- }
257
-
258
- .subheader{
259
- display: flex;
260
- flex-direction: row;
261
- color: var(--input-label);
262
- & > * {
263
- margin: 5px 20px 5px 0px;
264
- }
265
-
266
- .live-data {
267
- color: var(--body-text)
268
- }
269
- }
270
-
271
- .state-banner {
272
- margin: 3px 0 0 0;
273
- }
274
-
275
- .masthead-state {
276
- font-size: initial;
277
- display: inline-block;
278
- position: relative;
279
- /* top: -2px; */
280
- font-size: 12px;
281
- margin-left: 5px;
282
- }
283
-
284
- .masthead-istio {
285
- .icon {
286
- vertical-align: middle;
287
- color: var(--primary);
288
- }
289
- }
290
-
291
- .left-right-split {
292
- display: grid;
293
- align-items: center;
294
-
295
- .left-half {
296
- grid-column: 1;
297
- }
298
-
299
- .right-half {
300
- grid-column: 2;
301
- }
302
- }
303
-
304
- .resource-external {
305
- font-size: 18px;
306
- }
307
95
  .excram-list{
308
96
  font-size: 14px;
309
97
  margin-bottom: 20px;
@@ -311,10 +99,7 @@ export default {
311
99
  .excram-last-name{
312
100
  color: var(--link);
313
101
  }
314
- .valid{
315
- color: #d7d7d7;
316
- margin: 0px 10px;
317
- }
102
+
318
103
  .detailIcon-span{
319
104
  width: 24px;
320
105
  height: 24px;
@@ -330,11 +115,5 @@ export default {
330
115
  left: 4px;
331
116
  top: -2px;
332
117
  }
333
- .primary-title{
334
- display: flex;
335
- align-items: center;
336
- }
337
- .detailIcon-span-title{
338
- font-weight: bold;
339
- }
118
+
340
119
  </style>
@@ -263,174 +263,180 @@ export default {
263
263
  role="group"
264
264
  :aria-label="title || t('generic.ariaLabel.arrayList')"
265
265
  >
266
- <div
267
- v-if="title"
268
- class="clearfix"
269
- role="group"
270
- >
271
- <slot name="title">
272
- <h3>
273
- {{ title }}
274
- <span
275
- v-if="required"
276
- class="required"
277
- aria-hidden="true"
278
- >*</span>
279
- <i
280
- v-if="showProtip"
281
- v-clean-tooltip="{content: protip, triggers: ['hover', 'touch', 'focus'] }"
282
- class="icon icon-info"
283
- tabindex="0"
284
- />
285
- </h3>
286
- </slot>
287
- </div>
288
266
 
289
- <div>
290
- <div
291
- v-if="showAdd && !isView"
292
- class="footer mmt-6"
293
- >
294
- <slot
295
- v-if="showAdd"
296
- name="add"
297
- :add="add"
298
- >
299
- <button
300
- type="button"
301
- class="btn role-tertiary add"
302
- :class="[addClass]"
303
- :disabled="loading || disableAdd"
304
- :data-testid="`${componentTestid}-button`"
305
- :aria-label="_addLabel"
306
- role="button"
307
- @click="add()"
308
- >
309
- <i
310
- class="mr-5 icon"
311
- :class="loading ? ['icon-lg', 'icon-spinner','icon-spin']: [addIcon]"
312
- />
313
- {{ _addLabel }}
314
- </button>
315
- </slot>
316
- </div>
317
- <template v-if="rows.length">
267
+ <div class="row">
268
+ <div v-if="title" style="width: 100%;" class="col">
318
269
  <div
319
- v-if="showHeader"
320
- class="array-list-header-group"
270
+ class="clearfix"
321
271
  role="group"
322
272
  >
323
- <slot name="column-headers">
324
- <label class="value text-label mb-10">
325
- {{ valueLabel }}
326
- </label>
273
+ <slot name="title">
274
+ <h3>
275
+ {{ title }}
276
+ <span
277
+ v-if="required"
278
+ class="required"
279
+ aria-hidden="true"
280
+ >*</span>
281
+ <i
282
+ v-if="showProtip"
283
+ v-clean-tooltip="{content: protip, triggers: ['hover', 'touch', 'focus'] }"
284
+ class="icon icon-info"
285
+ tabindex="0"
286
+ />
287
+ </h3>
327
288
  </slot>
328
289
  </div>
329
- <div
330
- v-for="(row, idx) in rows"
331
- :key="idx"
332
- :data-testid="`${componentTestid}-box${ idx }`"
333
- class="box"
334
- :class="{'hide-remove-is-view': isView}"
335
- role="group"
336
- >
337
- <slot
338
- name="columns"
339
- :queueUpdate="queueUpdate"
340
- :i="idx"
341
- :rows="rows"
342
- :row="row"
343
- :mode="mode"
344
- :isView="isView"
345
- >
346
- <div class="value">
290
+ </div>
291
+ <div style="width: 100%;" class="col">
292
+ <div>
293
+ <template v-if="rows.length">
294
+ <div
295
+ v-if="showHeader"
296
+ class="array-list-header-group"
297
+ role="group"
298
+ >
299
+ <slot name="column-headers">
300
+ <label class="value text-label mb-10">
301
+ {{ valueLabel }}
302
+ </label>
303
+ </slot>
304
+ </div>
305
+ <div
306
+ v-for="(row, idx) in rows"
307
+ :key="idx"
308
+ :data-testid="`${componentTestid}-box${ idx }`"
309
+ class="box"
310
+ :class="{'hide-remove-is-view': isView}"
311
+ role="group"
312
+ >
347
313
  <slot
348
- name="value"
314
+ name="columns"
315
+ :queueUpdate="queueUpdate"
316
+ :i="idx"
317
+ :rows="rows"
349
318
  :row="row"
350
319
  :mode="mode"
351
320
  :isView="isView"
352
- :queue-update="queueUpdate"
353
321
  >
354
- <TextAreaAutoGrow
355
- v-if="valueMultiline"
356
- ref="value"
357
- v-model:value="row.value"
358
- :data-testid="`${componentTestid}-textarea-${idx}`"
359
- :placeholder="valuePlaceholder"
360
- :mode="mode"
361
- :disabled="disabled"
362
- :aria-label="a11yLabel ? `${a11yLabel} ${t('generic.ariaLabel.genericRow', {index: idx+1})}` : undefined"
363
- @paste="onPaste(idx, $event)"
364
- @update:value="queueUpdate"
365
- />
366
- <LabeledInput
367
- v-else-if="rules.length > 0"
368
- ref="value"
369
- v-model:value="row.value"
370
- :data-testid="`${componentTestid}-labeled-input-${idx}`"
371
- :placeholder="valuePlaceholder"
372
- :disabled="isView || disabled"
373
- :rules="rules"
374
- :compact="false"
375
- :aria-label="a11yLabel ? `${a11yLabel} ${t('generic.ariaLabel.genericRow', {index: idx+1})}` : undefined"
376
- @paste="onPaste(idx, $event)"
377
- @update:value="queueUpdate"
378
- />
379
- <input
380
- v-else
381
- ref="value"
382
- v-model="row.value"
383
- :data-testid="`${componentTestid}-input-${idx}`"
384
- :placeholder="valuePlaceholder"
385
- :disabled="isView || disabled"
386
- :aria-label="a11yLabel ? `${a11yLabel} ${t('generic.ariaLabel.genericRow', {index: idx+1})}` : undefined"
387
- @paste="onPaste(idx, $event)"
388
- >
322
+ <div class="value">
323
+ <slot
324
+ name="value"
325
+ :row="row"
326
+ :mode="mode"
327
+ :isView="isView"
328
+ :queue-update="queueUpdate"
329
+ >
330
+ <TextAreaAutoGrow
331
+ v-if="valueMultiline"
332
+ ref="value"
333
+ v-model:value="row.value"
334
+ :data-testid="`${componentTestid}-textarea-${idx}`"
335
+ :placeholder="valuePlaceholder"
336
+ :mode="mode"
337
+ :disabled="disabled"
338
+ :aria-label="a11yLabel ? `${a11yLabel} ${t('generic.ariaLabel.genericRow', {index: idx+1})}` : undefined"
339
+ @paste="onPaste(idx, $event)"
340
+ @update:value="queueUpdate"
341
+ />
342
+ <LabeledInput
343
+ v-else-if="rules.length > 0"
344
+ ref="value"
345
+ v-model:value="row.value"
346
+ :data-testid="`${componentTestid}-labeled-input-${idx}`"
347
+ :placeholder="valuePlaceholder"
348
+ :disabled="isView || disabled"
349
+ :rules="rules"
350
+ :compact="false"
351
+ :aria-label="a11yLabel ? `${a11yLabel} ${t('generic.ariaLabel.genericRow', {index: idx+1})}` : undefined"
352
+ @paste="onPaste(idx, $event)"
353
+ @update:value="queueUpdate"
354
+ />
355
+ <input
356
+ v-else
357
+ ref="value"
358
+ v-model="row.value"
359
+ :data-testid="`${componentTestid}-input-${idx}`"
360
+ :placeholder="valuePlaceholder"
361
+ :disabled="isView || disabled"
362
+ :aria-label="a11yLabel ? `${a11yLabel} ${t('generic.ariaLabel.genericRow', {index: idx+1})}` : undefined"
363
+ @paste="onPaste(idx, $event)"
364
+ >
365
+ </slot>
366
+ </div>
389
367
  </slot>
368
+ <div
369
+ v-if="showRemove && !isView"
370
+ class="remove"
371
+ >
372
+ <slot
373
+ name="remove-button"
374
+ :remove="() => remove(row, idx)"
375
+ :i="idx"
376
+ :row="row"
377
+ >
378
+ <button
379
+ type="button"
380
+ :disabled="isView"
381
+ class="btn role-link"
382
+ :data-testid="`${componentTestid}-remove-item-${idx}`"
383
+ :aria-label="t('generic.ariaLabel.remove', {index: idx+1})"
384
+ role="button"
385
+ @click="remove(row, idx)"
386
+ >
387
+ {{ _removeLabel }}
388
+ </button>
389
+ </slot>
390
+ </div>
391
+ <slot
392
+ name="value-sub-row"
393
+ :row="row"
394
+ :mode="mode"
395
+ :isView="isView"
396
+ />
390
397
  </div>
391
- </slot>
398
+ </template>
399
+ <div v-else>
400
+ <slot name="empty">
401
+ <div
402
+ v-if="mode==='view'"
403
+ class="text-muted"
404
+ >
405
+ &mdash;
406
+ </div>
407
+ </slot>
408
+ </div>
392
409
  <div
393
- v-if="showRemove && !isView"
394
- class="remove"
410
+ v-if="showAdd && !isView"
411
+ class="footer"
395
412
  >
396
413
  <slot
397
- name="remove-button"
398
- :remove="() => remove(row, idx)"
399
- :i="idx"
400
- :row="row"
414
+ v-if="showAdd"
415
+ name="add"
416
+ :add="add"
401
417
  >
402
418
  <button
403
419
  type="button"
404
- :disabled="isView"
405
- class="btn role-link"
406
- :data-testid="`${componentTestid}-remove-item-${idx}`"
407
- :aria-label="t('generic.ariaLabel.remove', {index: idx+1})"
420
+ class="btn role-tertiary add"
421
+ :class="[addClass]"
422
+ :disabled="loading || disableAdd"
423
+ :data-testid="`${componentTestid}-button`"
424
+ :aria-label="_addLabel"
408
425
  role="button"
409
- @click="remove(row, idx)"
426
+ @click="add()"
410
427
  >
411
- {{ _removeLabel }}
428
+ <i
429
+ class="mr-5 icon"
430
+ :class="loading ? ['icon-lg', 'icon-spinner','icon-spin']: [addIcon]"
431
+ />
432
+ {{ _addLabel }}
412
433
  </button>
413
434
  </slot>
414
435
  </div>
415
- <slot
416
- name="value-sub-row"
417
- :row="row"
418
- :mode="mode"
419
- :isView="isView"
420
- />
421
436
  </div>
422
- </template>
423
- <div v-else>
424
- <slot name="empty">
425
- <div
426
- v-if="mode==='view'"
427
- class="text-muted"
428
- >
429
- &mdash;
430
- </div>
431
- </slot>
432
437
  </div>
433
438
  </div>
439
+
434
440
  </div>
435
441
  </template>
436
442
 
@@ -444,13 +450,15 @@ export default {
444
450
  }
445
451
 
446
452
  .box {
447
- display: grid;
448
- grid-template-columns: auto $array-list-remove-margin;
449
- align-items: center;
450
- margin-bottom: 10px;
453
+ // display: grid;
454
+ // grid-template-columns: auto $array-list-remove-margin;
455
+ // align-items: center;
456
+ // margin-bottom: 10px;
457
+ display: flex;
451
458
  .value {
452
- flex: 1;
459
+ // flex: 1;
453
460
  INPUT {
461
+ width: $input-width;
454
462
  height: $input-height;
455
463
  border: solid var(--border-width) var(--input-border);
456
464
  padding: 4px 11px;
@@ -462,9 +470,15 @@ export default {
462
470
  }
463
471
  .remove {
464
472
  text-align: right;
473
+ display: flex;
474
+ align-items: center;
475
+
476
+ button{
477
+ min-width: auto;
478
+ }
465
479
  }
466
480
  .footer {
467
- margin-bottom: 24px;
481
+ margin-bottom: 20px;
468
482
  .protip {
469
483
  float: right;
470
484
  padding: 5px 0;
@@ -481,4 +495,7 @@ export default {
481
495
  margin-bottom: 10px;
482
496
  }
483
497
 
498
+ H3{
499
+ width: 160px;
500
+ }
484
501
  </style>