dashboard-shell-shell 1.0.111 → 1.0.113

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 (180) hide show
  1. package/.DS_Store +0 -0
  2. package/assets/icons/demo.css +539 -0
  3. package/assets/icons/demo_index.html +1131 -0
  4. package/assets/icons/iconfont.css +200 -0
  5. package/assets/icons/iconfont.js +1 -0
  6. package/assets/icons/iconfont.json +296 -0
  7. package/assets/icons/iconfont.ttf +0 -0
  8. package/assets/icons/iconfont.woff +0 -0
  9. package/assets/icons/iconfont.woff2 +0 -0
  10. package/assets/images/API.svg +3 -0
  11. package/assets/images/login/password.svg +20 -0
  12. package/assets/images/login/user.svg +6 -0
  13. package/assets/images/login-bg.png +0 -0
  14. package/assets/images/login-left.png +0 -0
  15. package/assets/images/login-logo.svg +19 -0
  16. package/assets/images/logo.png +0 -0
  17. package/assets/images/pl/harvester.png +0 -0
  18. package/assets/images/promp-yellow.svg +5 -0
  19. package/assets/images/user.png +0 -0
  20. package/assets/styles/all.scss +63 -0
  21. package/assets/styles/app.scss +2 -0
  22. package/assets/styles/base/_basic.scss +8 -2
  23. package/assets/styles/base/_helpers.scss +4 -0
  24. package/assets/styles/base/_typography.scss +2 -1
  25. package/assets/styles/base/_variables.scss +10 -2
  26. package/assets/styles/global/_button.scss +37 -25
  27. package/assets/styles/global/_columns.scss +3 -1
  28. package/assets/styles/global/_form.scss +45 -13
  29. package/assets/styles/global/_labeled-input.scss +50 -25
  30. package/assets/styles/global/_layout.scss +9 -3
  31. package/assets/styles/global/_select.scss +20 -13
  32. package/assets/styles/global/_table.scss +1 -1
  33. package/assets/styles/global/_tooltip.scss +47 -6
  34. package/assets/styles/themes/_dark.scss +1 -0
  35. package/assets/styles/themes/_light.scss +59 -46
  36. package/assets/styles/themes/_suse.scss +1 -0
  37. package/assets/styles/vendor/vue-select.scss +18 -7
  38. package/assets/translations/en-us.yaml +93 -12
  39. package/assets/translations/zh-hans.yaml +278 -141
  40. package/components/ActionDropdown.vue +1 -1
  41. package/components/ActionDropdownShell.vue +71 -0
  42. package/components/ActionMenu.vue +2 -2
  43. package/components/ActionMenuShell.vue +1 -0
  44. package/components/AppModal.vue +78 -6
  45. package/components/AssignTo.vue +25 -11
  46. package/components/AsyncButton.vue +24 -7
  47. package/components/BannerGraphic.vue +1 -0
  48. package/components/ButtonDropdown.vue +26 -4
  49. package/components/ButtonGroup.vue +4 -0
  50. package/components/ButtonMultiAction.vue +1 -0
  51. package/components/CommunityLinks.vue +3 -3
  52. package/components/ConsumptionGauge.vue +24 -5
  53. package/components/CopyToClipboardText.vue +2 -1
  54. package/components/CruResource.vue +12 -7
  55. package/components/CruResourceFooter.vue +2 -2
  56. package/components/DashboardOptions.vue +21 -15
  57. package/components/DetailText.vue +5 -0
  58. package/components/DisableAuthProviderModal.vue +1 -0
  59. package/components/DotState.vue +84 -0
  60. package/components/ExplorerMembers.vue +1 -1
  61. package/components/ExplorerProjectsNamespaces.vue +56 -14
  62. package/components/FixedBanner.vue +19 -12
  63. package/components/GlobalRoleBindings.vue +5 -1
  64. package/components/GrafanaDashboard.vue +4 -4
  65. package/components/GrowlManager.vue +4 -1
  66. package/components/HardwareResourceGauge.vue +39 -3
  67. package/components/InfoBox.vue +3 -3
  68. package/components/InputOrDisplay.vue +28 -2
  69. package/components/LabelValue.vue +16 -1
  70. package/components/LandingPagePreference.vue +5 -3
  71. package/components/LocaleSelector.vue +39 -93
  72. package/components/ModalManager.vue +55 -0
  73. package/components/ModalWithCard.vue +2 -0
  74. package/components/MoveModal.vue +1 -0
  75. package/components/PromptChangePassword.vue +1 -1
  76. package/components/PromptModal.vue +15 -2
  77. package/components/PromptRemove.vue +28 -8
  78. package/components/PromptRestore.vue +1 -0
  79. package/components/ResourceCancelModal.vue +1 -0
  80. package/components/ResourceDetail/Masthead.vue +188 -43
  81. package/components/ResourceDetail/__tests__/Masthead.test.ts +5 -1
  82. package/components/ResourceDetail/index.vue +49 -14
  83. package/components/ResourceList/Masthead.vue +80 -18
  84. package/components/ResourceTable.vue +60 -19
  85. package/components/SideNav.vue +32 -12
  86. package/components/SlideInPanelManager.vue +126 -0
  87. package/components/SortableTable/THead.vue +34 -5
  88. package/components/SortableTable/actions.js +1 -1
  89. package/components/SortableTable/index.vue +649 -142
  90. package/components/SortableTable/paging.js +36 -28
  91. package/components/SortableTable/selection.js +0 -11
  92. package/components/StatusBadge.vue +77 -0
  93. package/components/Tabbed/Tab.vue +3 -3
  94. package/components/Tabbed/index.vue +44 -26
  95. package/components/Wizard.vue +2 -2
  96. package/components/__tests__/AsyncButton.test.ts +2 -2
  97. package/components/__tests__/FixedBanner.test.ts +3 -3
  98. package/components/__tests__/ModalManager.spec.ts +176 -0
  99. package/components/__tests__/SlideInPanelManager.spec.ts +166 -0
  100. package/components/auth/Principal.vue +10 -3
  101. package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
  102. package/components/form/ArrayList.vue +123 -85
  103. package/components/form/ArrayListGrouped.vue +10 -2
  104. package/components/form/Command.vue +6 -15
  105. package/components/form/EnvVars.vue +16 -8
  106. package/components/form/Footer.vue +8 -5
  107. package/components/form/HealthCheck.vue +3 -3
  108. package/components/form/HookOption.vue +11 -16
  109. package/components/form/KeyValue.vue +16 -7
  110. package/components/form/LabeledSelect.vue +59 -76
  111. package/components/form/LifecycleHooks.vue +3 -3
  112. package/components/form/MatchExpressions.vue +35 -12
  113. package/components/form/NameNsDescription.vue +147 -115
  114. package/components/form/Networking.vue +20 -12
  115. package/components/form/NodeAffinity.vue +31 -23
  116. package/components/form/NodeScheduling.vue +13 -3
  117. package/components/form/Password.vue +11 -5
  118. package/components/form/PodAffinity.vue +43 -44
  119. package/components/form/Probe.vue +68 -66
  120. package/components/form/ResourceQuota/Project.vue +5 -1
  121. package/components/form/ResourceSelector.vue +7 -9
  122. package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +6 -3
  123. package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +12 -1
  124. package/components/form/SSHKnownHosts/index.vue +16 -2
  125. package/components/form/Security.vue +54 -56
  126. package/components/form/Select.vue +41 -7
  127. package/components/form/ShellInput.vue +5 -1
  128. package/components/form/Tolerations.vue +5 -1
  129. package/components/form/UnitInput.vue +2 -2
  130. package/components/form/ValueFromResource.vue +134 -121
  131. package/components/form/WorkloadPorts.vue +18 -18
  132. package/components/form/__tests__/ArrayList.test.ts +5 -2
  133. package/components/form/__tests__/MatchExpressions.test.ts +12 -12
  134. package/components/form/__tests__/NameNsDescription.test.ts +115 -14
  135. package/components/form/__tests__/Probe.test.ts +12 -8
  136. package/components/form/__tests__/SSHKnownHosts.test.ts +11 -0
  137. package/components/form/__tests__/Select.test.ts +37 -0
  138. package/components/form/__tests__/UnitInput.test.ts +4 -5
  139. package/components/formatter/BadgeStateFormatter.vue +8 -5
  140. package/components/formatter/InternalExternalIP.vue +2 -0
  141. package/components/formatter/SecretData.vue +20 -7
  142. package/components/nav/Favorite.vue +5 -1
  143. package/components/nav/Group.vue +60 -27
  144. package/components/nav/Header.vue +39 -13
  145. package/components/nav/Jump.vue +7 -0
  146. package/components/nav/NamespaceFilter.vue +14 -8
  147. package/components/nav/Pinned.vue +1 -1
  148. package/components/nav/TopLevelMenu.vue +5 -17
  149. package/components/nav/Type.vue +32 -35
  150. package/components/nav/__tests__/TopLevelMenu.test.ts +0 -40
  151. package/components/templates/blank.vue +4 -1
  152. package/components/templates/default.vue +8 -0
  153. package/components/templates/home.vue +10 -1
  154. package/components/templates/plain.vue +10 -1
  155. package/package.json +1 -1
  156. package/rancher-components/Banner/Banner.vue +6 -4
  157. package/rancher-components/Card/Card.vue +6 -4
  158. package/rancher-components/Form/Checkbox/Checkbox.vue +20 -1
  159. package/rancher-components/Form/LabeledInput/LabeledInput.vue +46 -5
  160. package/rancher-components/Form/Radio/RadioButton.vue +32 -8
  161. package/rancher-components/Form/Radio/RadioGroup.vue +31 -24
  162. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +17 -0
  163. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +8 -3
  164. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +15 -3
  165. package/rancher-components/RcButton/RcButton.vue +1 -0
  166. package/rancher-components/RcButton/types.ts +1 -0
  167. package/rancher-components/RcDropdown/RcDropdown.vue +54 -15
  168. package/rancher-components/RcDropdown/RcDropdownItem.vue +5 -4
  169. package/rancher-components/RcDropdown/RcDropdownMenu.vue +11 -7
  170. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +12 -2
  171. package/rancher-components/RcDropdown/useDropdownCollection.ts +8 -0
  172. package/rancher-components/RcDropdown/useDropdownContext.ts +9 -3
  173. package/rancher-components/StringList/StringList.vue +1 -1
  174. package/store/type-map.js +29 -2
  175. package/utils/error.js +30 -8
  176. package/utils/errorTranslate.json +916 -0
  177. package/vue.config.js +1 -1
  178. package/components/formatter/ExtensionCache.vue +0 -74
  179. package/components/formatter/Port.vue +0 -24
  180. package/components/formatter/SecretType.vue +0 -41
@@ -29,6 +29,10 @@ export default {
29
29
  },
30
30
 
31
31
  data() {
32
+ return { rules: [] };
33
+ },
34
+
35
+ created() {
32
36
  const rules = [];
33
37
 
34
38
  // on creation in agent configuration, the backend "eats"
@@ -49,7 +53,7 @@ export default {
49
53
  });
50
54
  }
51
55
 
52
- return { rules };
56
+ this.rules = rules;
53
57
  },
54
58
 
55
59
  computed: {
@@ -206,7 +206,7 @@ export default {
206
206
  }
207
207
 
208
208
  if (this.outputModifier) {
209
- out = out === null ? null : `${ inputValue }${ this.unit }`;
209
+ out = out === null ? null : `${ parseInt(inputValue) }${ this.unit }`;
210
210
  } else if ( this.outputAs === 'string' ) {
211
211
  out = out === null ? '' : `${ inputValue }`;
212
212
  } else if (out) {
@@ -235,7 +235,7 @@ export default {
235
235
  :required="required"
236
236
  :placeholder="placeholder"
237
237
  :hide-arrows="hideArrows"
238
- @change="update($event.target.value)"
238
+ @update:value="update"
239
239
  @blur="update($event.target.value)"
240
240
  >
241
241
  <template #suffix>
@@ -4,6 +4,7 @@ import { get } from '@shell/utils/object';
4
4
  import { _VIEW } from '@shell/config/query-params';
5
5
  import LabeledSelect from '@shell/components/form/LabeledSelect';
6
6
  import { LabeledInput } from '@components/Form/LabeledInput';
7
+ import { ref, watch } from 'vue';
7
8
 
8
9
  export default {
9
10
  emits: ['update:value', 'remove'],
@@ -44,84 +45,164 @@ export default {
44
45
  },
45
46
 
46
47
  data() {
47
- const typeOpts = [
48
- { value: 'simple', label: 'Key/Value Pair' },
49
- { value: 'resourceFieldRef', label: 'Resource' },
50
- { value: 'configMapKeyRef', label: 'ConfigMap Key' },
51
- { value: 'secretKeyRef', label: 'Secret key' },
52
- { value: 'fieldRef', label: 'Pod Field' },
53
- { value: 'secretRef', label: 'Secret' },
54
- { value: 'configMapRef', label: 'ConfigMap' },
55
- ];
56
-
57
- const resourceKeyOpts = ['limits.cpu', 'limits.ephemeral-storage', 'limits.memory', 'requests.cpu', 'requests.ephemeral-storage', 'requests.memory'];
58
- let type;
59
-
60
- if (this.value.secretRef) {
61
- type = 'secretRef';
62
- } else if (this.value.configMapRef) {
63
- type = 'configMapRef';
64
- } else if (this.value.value) {
65
- type = 'simple';
66
- } else if (this.value.valueFrom) {
67
- type = Object.keys((this.value.valueFrom))[0] || 'simple';
48
+ return {
49
+ typeOpts: [
50
+ { value: 'simple', label: 'Key/Value Pair' },
51
+ { value: 'resourceFieldRef', label: 'Resource' },
52
+ { value: 'configMapKeyRef', label: 'ConfigMap Key' },
53
+ { value: 'secretKeyRef', label: 'Secret key' },
54
+ { value: 'fieldRef', label: 'Pod Field' },
55
+ { value: 'secretRef', label: 'Secret' },
56
+ { value: 'configMapRef', label: 'ConfigMap' },
57
+ ],
58
+ secrets: this.allSecrets,
59
+ resourceKeyOpts: ['limits.cpu', 'limits.ephemeral-storage', 'limits.memory', 'requests.cpu', 'requests.ephemeral-storage', 'requests.memory'],
60
+ };
61
+ },
62
+
63
+ setup(props, { emit }) {
64
+ const type = ref(null);
65
+
66
+ if (props.value.secretRef) {
67
+ type.value = 'secretRef';
68
+ } else if (props.value.configMapRef) {
69
+ type.value = 'configMapRef';
70
+ } else if (props.value.value) {
71
+ type.value = 'simple';
72
+ } else if (props.value.valueFrom) {
73
+ type.value = Object.keys((props.value.valueFrom))[0] || 'simple';
68
74
  }
69
75
 
70
- let refName;
71
- let name;
72
- let fieldPath;
73
- let referenced;
74
- let key;
75
- let valStr;
76
- const keys = [];
76
+ const refName = ref('');
77
+ const name = ref('');
78
+ const fieldPath = ref('');
79
+ const referenced = ref(null);
80
+ const key = ref(null);
81
+ const valStr = ref('');
82
+ const keys = ref([]);
77
83
 
78
- switch (type) {
84
+ switch (type.value) {
79
85
  case 'resourceFieldRef':
80
- name = this.value.name;
81
- refName = this.value.valueFrom[type].containerName;
82
- key = this.value.valueFrom[type].resource || '';
86
+ name.value = props.value.name;
87
+ refName.value = props.value.valueFrom[type.value].containerName;
88
+ key.value = props.value.valueFrom[type.value].resource || '';
83
89
  break;
84
90
  case 'configMapKeyRef':
85
- name = this.value.name;
86
- key = this.value.valueFrom[type].key || '';
87
- refName = this.value.valueFrom[type].name;
88
- referenced = this.allConfigMaps.filter((resource) => {
89
- return resource.metadata.name === refName;
91
+ name.value = props.value.name;
92
+ key.value = props.value.valueFrom[type.value].key || '';
93
+ refName.value = props.value.valueFrom[type.value].name;
94
+ referenced.value = props.allConfigMaps.filter((resource) => {
95
+ return resource.metadata.name === refName.value;
90
96
  })[0];
91
- if (referenced && referenced.data) {
92
- keys.push(...Object.keys(referenced.data));
97
+ if (referenced.value && referenced.value.data) {
98
+ keys.value.push(...Object.keys(referenced.value.data));
93
99
  }
94
100
  break;
95
101
  case 'secretRef':
96
102
  case 'configMapRef':
97
- name = this.value.prefix;
98
- refName = this.value[type].name;
103
+ name.value = props.value.prefix;
104
+ refName.value = props.value[type.value].name;
99
105
  break;
100
106
  case 'secretKeyRef':
101
- name = this.value.name;
102
- key = this.value.valueFrom[type].key || '';
103
- refName = this.value.valueFrom[type].name;
104
- referenced = this.allSecrets.filter((resource) => {
105
- return resource.metadata.name === refName;
107
+ name.value = props.value.name;
108
+ key.value = props.value.valueFrom[type.value].key || '';
109
+ refName.value = props.value.valueFrom[type.value].name;
110
+ referenced.value = props.allSecrets.filter((resource) => {
111
+ return resource.metadata.name === refName.value;
106
112
  })[0];
107
- if (referenced && referenced.data) {
108
- keys.push(...Object.keys(referenced.data));
113
+ if (referenced.value && referenced.value.data) {
114
+ keys.value.push(...Object.keys(referenced.value.data));
109
115
  }
110
116
  break;
111
117
  case 'fieldRef':
112
- fieldPath = get(this.value.valueFrom, `${ type }.fieldPath`) || '';
113
- name = this.value.name;
118
+ fieldPath.value = get(props.value.valueFrom, `${ type.value }.fieldPath`) || '';
119
+ name.value = props.value.name;
114
120
  break;
115
121
  default:
116
- name = this.value.name;
117
- valStr = this.value.value;
122
+ name.value = props.value.name;
123
+ valStr.value = props.value.value;
118
124
  break;
119
125
  }
120
126
 
127
+ referenced.value = refName.value;
128
+
129
+ const updateRow = () => {
130
+ if (!name.value?.length && !refName.value?.length) {
131
+ if (type.value !== 'fieldRef') {
132
+ emit('update:value', null);
133
+
134
+ return;
135
+ }
136
+ }
137
+ let out = { name: name.value || refName.value };
138
+
139
+ switch (type.value) {
140
+ case 'configMapKeyRef':
141
+ case 'secretKeyRef':
142
+ out.valueFrom = {
143
+ [type.value]: {
144
+ key: key.value, name: refName.value, optional: false
145
+ }
146
+ };
147
+ break;
148
+ case 'resourceFieldRef':
149
+ out.valueFrom = {
150
+ [type.value]: {
151
+ containerName: refName.value, divisor: 1, resource: key.value
152
+ }
153
+ };
154
+ break;
155
+ case 'fieldRef':
156
+ if (!fieldPath.value || !fieldPath.value.length) {
157
+ out = null; break;
158
+ }
159
+ out.valueFrom = { [type.value]: { apiVersion: 'v1', fieldPath: fieldPath.value } };
160
+ break;
161
+ case 'simple':
162
+ out.value = valStr.value;
163
+ break;
164
+ default:
165
+ delete out.name;
166
+ out.prefix = name.value;
167
+ out[type.value] = { name: refName.value, optional: false };
168
+ }
169
+ emit('update:value', out);
170
+ };
171
+
172
+ watch(type, () => {
173
+ referenced.value = null;
174
+ key.value = '';
175
+ refName.value = '';
176
+ keys.value = [];
177
+ key.value = '';
178
+ valStr.value = '';
179
+ fieldPath.value = '';
180
+ });
181
+
182
+ watch(referenced, (neu, old) => {
183
+ if (neu) {
184
+ if ((neu.type === SECRET || neu.type === CONFIG_MAP) && neu.data) {
185
+ keys.value = Object.keys(neu.data);
186
+ }
187
+ refName.value = neu?.metadata?.name;
188
+ }
189
+ updateRow();
190
+ });
191
+
121
192
  return {
122
- typeOpts, type, refName, referenced: refName, secrets: this.allSecrets, keys, key, fieldPath, name, resourceKeyOpts, valStr
193
+ type,
194
+ refName,
195
+ referenced,
196
+ keys,
197
+ key,
198
+ fieldPath,
199
+ name,
200
+ valStr,
201
+ updateRow,
202
+ get,
123
203
  };
124
204
  },
205
+
125
206
  computed: {
126
207
  isView() {
127
208
  return this.mode === _VIEW;
@@ -189,74 +270,6 @@ export default {
189
270
  return ['resourceFieldRef', 'configMapKeyRef', 'secretKeyRef'].includes(this.type);
190
271
  },
191
272
  },
192
-
193
- watch: {
194
- type() {
195
- this.referenced = null;
196
- this.key = '';
197
- this.refName = '';
198
- this.keys = [];
199
- this.key = '';
200
- this.valStr = '';
201
- this.fieldPath = '';
202
- },
203
-
204
- referenced(neu, old) {
205
- if (neu) {
206
- if ((neu.type === SECRET || neu.type === CONFIG_MAP) && neu.data) {
207
- this.keys = Object.keys(neu.data);
208
- }
209
- this.refName = neu?.metadata?.name;
210
- }
211
- this.updateRow();
212
- },
213
- },
214
-
215
- methods: {
216
- updateRow() {
217
- if (!this.name?.length && !this.refName?.length) {
218
- if (this.type !== 'fieldRef') {
219
- this.$emit('update:value', null);
220
-
221
- return;
222
- }
223
- }
224
- let out = { name: this.name || this.refName };
225
-
226
- switch (this.type) {
227
- case 'configMapKeyRef':
228
- case 'secretKeyRef':
229
- out.valueFrom = {
230
- [this.type]: {
231
- key: this.key, name: this.refName, optional: false
232
- }
233
- };
234
- break;
235
- case 'resourceFieldRef':
236
- out.valueFrom = {
237
- [this.type]: {
238
- containerName: this.refName, divisor: 1, resource: this.key
239
- }
240
- };
241
- break;
242
- case 'fieldRef':
243
- if (!this.fieldPath || !this.fieldPath.length) {
244
- out = null; break;
245
- }
246
- out.valueFrom = { [this.type]: { apiVersion: 'v1', fieldPath: this.fieldPath } };
247
- break;
248
- case 'simple':
249
- out.value = this.valStr;
250
- break;
251
- default:
252
- delete out.name;
253
- out.prefix = this.name;
254
- out[this.type] = { name: this.refName, optional: false };
255
- }
256
- this.$emit('update:value', out);
257
- },
258
- get
259
- }
260
273
  };
261
274
  </script>
262
275
 
@@ -44,25 +44,9 @@ export default {
44
44
  },
45
45
 
46
46
  data() {
47
- const rows = clone(this.value || []).map((row) => {
48
- row._showHost = false;
49
- row._serviceType = row._serviceType || '';
50
- row._name = row.name ? `${ row.name }` : `${ row.containerPort }${ row.protocol.toLowerCase() }${ row.hostPort || row._listeningPort || '' }`;
51
- if (row.hostPort || row.hostIP) {
52
- row._showHost = true;
53
- }
54
-
55
- row._ipam = '';
56
-
57
- return row;
58
- });
59
-
60
- // show host port column if existing port data has any host ports defined
61
- const showHostPorts = !!rows.some((row) => !!row.hostPort);
62
-
63
47
  return {
64
- rows,
65
- showHostPorts,
48
+ rows: [],
49
+ showHostPorts: false,
66
50
  workloadPortOptions: ['TCP', 'UDP']
67
51
  };
68
52
  },
@@ -168,6 +152,22 @@ export default {
168
152
  },
169
153
 
170
154
  created() {
155
+ const rows = clone(this.value || []).map((row) => {
156
+ row._showHost = false;
157
+ row._serviceType = row._serviceType || '';
158
+ row._name = row.name ? `${ row.name }` : `${ row.containerPort }${ row.protocol.toLowerCase() }${ row.hostPort || row._listeningPort || '' }`;
159
+ if (row.hostPort || row.hostIP) {
160
+ row._showHost = true;
161
+ }
162
+
163
+ row._ipam = '';
164
+
165
+ return row;
166
+ });
167
+
168
+ this.rows = rows;
169
+ // show host port column if existing port data has any host ports defined
170
+ this.showHostPorts = !!rows.some((row) => !!row.hostPort);
171
171
  this.queueUpdate = debounce(this.update, 500);
172
172
  this.rows.map((row) => {
173
173
  this.setServiceType(row);
@@ -4,6 +4,8 @@ import { _EDIT, _VIEW } from '@shell/config/query-params';
4
4
  import { ExtendedVue, Vue } from 'vue/types/vue';
5
5
  import { DefaultProps } from 'vue/types/options';
6
6
 
7
+ jest.mock('lodash/debounce', () => jest.fn((fn) => fn));
8
+
7
9
  describe('the ArrayList', () => {
8
10
  it('is empty', () => {
9
11
  const wrapper = mount(ArrayList, {
@@ -56,12 +58,13 @@ describe('the ArrayList', () => {
56
58
  });
57
59
 
58
60
  jest.useFakeTimers();
59
- await (wrapper.get('[data-testid="remove-item-1"]').element as HTMLElement).click();
61
+ await (wrapper.get('[data-testid="array-list-remove-item-1"]').element as HTMLElement).click();
60
62
  jest.advanceTimersByTime(50);
61
63
  jest.useRealTimers();
62
64
 
63
- expect(wrapper.find('[data-testid="remove-item-2"]').exists()).toBe(false);
65
+ expect(wrapper.find('[data-testid="array-list-remove-item-2"]').exists()).toBe(false);
64
66
  expect((wrapper.emitted('remove')![0][0] as any).row.value).toStrictEqual('string 1');
67
+ expect(wrapper.vm.rows).toStrictEqual([{ value: 'string 0' }, { value: 'string 2' }]);
65
68
  expect(wrapper.emitted('update:value')![0][0]).toStrictEqual(['string 0', 'string 2']);
66
69
  });
67
70
 
@@ -6,9 +6,9 @@ import { nextTick } from 'vue';
6
6
  describe('component: MatchExpressions', () => {
7
7
  it('should display all the inputs', () => {
8
8
  const wrapper = mount(MatchExpressions, {
9
- props: { mode: _CREATE },
10
- data: () => ({
11
- rules: [
9
+ props: {
10
+ mode: _CREATE,
11
+ value: [
12
12
  {
13
13
  id: '123',
14
14
  key: '123',
@@ -16,7 +16,7 @@ describe('component: MatchExpressions', () => {
16
16
  values: '123'
17
17
  }
18
18
  ]
19
- })
19
+ },
20
20
  });
21
21
 
22
22
  const inputWraps = wrapper.findAll('[data-testid^=input-match-expression-]');
@@ -29,9 +29,9 @@ describe('component: MatchExpressions', () => {
29
29
  'values',
30
30
  ])('should emit an update on %p input', async(field) => {
31
31
  const wrapper = mount(MatchExpressions, {
32
- props: { mode: _CREATE },
33
- data: () => ({
34
- rules: [
32
+ props: {
33
+ mode: _CREATE,
34
+ value: [
35
35
  {
36
36
  id: '123',
37
37
  key: '123',
@@ -39,7 +39,7 @@ describe('component: MatchExpressions', () => {
39
39
  values: '123'
40
40
  }
41
41
  ]
42
- })
42
+ },
43
43
  });
44
44
  const input = wrapper.find(`[data-testid="input-match-expression-${ field }-0"]`).find('input');
45
45
  const newValue = 123;
@@ -54,9 +54,9 @@ describe('component: MatchExpressions', () => {
54
54
  'operator',
55
55
  ])('should emit an update on %p selection change', async(field) => {
56
56
  const wrapper = mount(MatchExpressions, {
57
- props: { mode: _CREATE },
58
- data: () => ({
59
- rules: [
57
+ props: {
58
+ mode: _CREATE,
59
+ value: [
60
60
  {
61
61
  id: '123',
62
62
  key: '123',
@@ -64,7 +64,7 @@ describe('component: MatchExpressions', () => {
64
64
  values: '123'
65
65
  }
66
66
  ]
67
- })
67
+ },
68
68
  });
69
69
 
70
70
  const select = wrapper.find(`[data-testid="input-match-expression-${ field }-0"]`);
@@ -1,10 +1,18 @@
1
1
  import { mount } from '@vue/test-utils';
2
2
  import NameNsDescription from '@shell/components/form/NameNsDescription.vue';
3
+ import { createStore } from 'vuex';
3
4
 
4
5
  describe('component: NameNsDescription', () => {
5
6
  // Accessing to computed value due code complexity
6
7
  it('should map namespaces to options', () => {
7
8
  const namespaceName = 'test';
9
+ const store = createStore({
10
+ getters: {
11
+ allowedNamespaces: () => () => ({ [namespaceName]: true }),
12
+ currentStore: () => () => 'cluster',
13
+ 'cluster/schemaFor': () => jest.fn()
14
+ }
15
+ });
8
16
  const result = [
9
17
  {
10
18
  label: namespaceName,
@@ -13,20 +21,21 @@ describe('component: NameNsDescription', () => {
13
21
  ];
14
22
  const wrapper = mount(NameNsDescription, {
15
23
  props: {
16
- value: {},
24
+ value: {
25
+ setAnnotation: jest.fn(),
26
+ metadata: {}
27
+ },
17
28
  mode: 'create',
18
29
  cluster: {},
19
30
  },
20
31
  global: {
21
- mocks: {
32
+ provide: { store },
33
+ mocks: {
22
34
  $store: {
23
35
  dispatch: jest.fn(),
24
36
  getters: {
25
- namespaces: jest.fn(),
26
- allowedNamespaces: () => ({ [namespaceName]: true }),
27
- currentStore: () => 'cluster',
28
- 'cluster/schemaFor': jest.fn(),
29
- 'i18n/t': jest.fn(),
37
+ namespaces: jest.fn(),
38
+ 'i18n/t': jest.fn(),
30
39
  },
31
40
  },
32
41
  },
@@ -38,27 +47,35 @@ describe('component: NameNsDescription', () => {
38
47
 
39
48
  it('should emit in case of new namespace', () => {
40
49
  const namespaceName = 'test';
50
+ const store = createStore({
51
+ getters: {
52
+ allowedNamespaces: () => () => ({ [namespaceName]: true }),
53
+ currentStore: () => () => 'cluster',
54
+ 'cluster/schemaFor': () => jest.fn()
55
+ }
56
+ });
41
57
  const newNamespaceName = 'bananas';
42
58
  const wrapper = mount(NameNsDescription, {
43
59
  props: {
44
- value: { metadata: {} },
45
- mode: 'create',
60
+ value: {
61
+ setAnnotation: jest.fn(),
62
+ metadata: {}
63
+ },
64
+ mode: 'create',
46
65
  },
47
66
  global: {
48
- mocks: {
67
+ provide: { store },
68
+ mocks: {
49
69
  $store: {
50
70
  dispatch: jest.fn(),
51
71
  getters: {
52
72
  namespaces: jest.fn(),
53
- allowedNamespaces: () => ({ [namespaceName]: true }),
54
73
  'customizations/getPreviewCluster': {
55
74
  ready: true,
56
75
  isLocal: false,
57
76
  badge: {},
58
77
  },
59
- currentStore: () => 'cluster',
60
- 'cluster/schemaFor': jest.fn(),
61
- 'i18n/t': jest.fn(),
78
+ 'i18n/t': jest.fn(),
62
79
  },
63
80
  },
64
81
  },
@@ -69,4 +86,88 @@ describe('component: NameNsDescription', () => {
69
86
 
70
87
  expect(wrapper.emitted().isNamespaceNew?.[0][0]).toBe(true);
71
88
  });
89
+
90
+ it('renders the name input with the expected value', () => {
91
+ const namespaceName = 'test';
92
+ const store = createStore({
93
+ getters: {
94
+ allowedNamespaces: () => () => ({ [namespaceName]: true }),
95
+ currentStore: () => () => 'cluster',
96
+ 'cluster/schemaFor': () => jest.fn()
97
+ }
98
+ });
99
+ const wrapper = mount(NameNsDescription, {
100
+ props: {
101
+ value: {
102
+ setAnnotation: jest.fn(),
103
+ metadata: { name: 'Default' }
104
+ },
105
+ mode: 'create',
106
+ },
107
+ global: {
108
+ provide: { store },
109
+ mocks: {
110
+ $store: {
111
+ dispatch: jest.fn(),
112
+ getters: {
113
+ namespaces: jest.fn(),
114
+ 'customizations/getPreviewCluster': {
115
+ ready: true,
116
+ isLocal: false,
117
+ badge: {},
118
+ },
119
+ 'i18n/t': jest.fn(),
120
+ },
121
+ },
122
+ },
123
+ },
124
+ });
125
+
126
+ const nameInput = wrapper.find('[data-testid="NameNsDescriptionNameInput"]');
127
+
128
+ expect(nameInput.element.value).toBe('Default');
129
+ });
130
+
131
+ it('sets the name using the nameKey prop', () => {
132
+ const namespaceName = 'test';
133
+ const store = createStore({
134
+ getters: {
135
+ allowedNamespaces: () => () => ({ [namespaceName]: true }),
136
+ currentStore: () => () => 'cluster',
137
+ 'cluster/schemaFor': () => jest.fn()
138
+ }
139
+ });
140
+ const wrapper = mount(NameNsDescription, {
141
+ props: {
142
+ value: {
143
+ setAnnotation: jest.fn(),
144
+ metadata: {},
145
+ spec: { displayName: 'Default' }
146
+ },
147
+ mode: 'create',
148
+ nameKey: 'spec.displayName'
149
+ },
150
+ global: {
151
+ provide: { store },
152
+ mocks: {
153
+ $store: {
154
+ dispatch: jest.fn(),
155
+ getters: {
156
+ namespaces: jest.fn(),
157
+ 'customizations/getPreviewCluster': {
158
+ ready: true,
159
+ isLocal: false,
160
+ badge: {},
161
+ },
162
+ 'i18n/t': jest.fn(),
163
+ },
164
+ },
165
+ },
166
+ },
167
+ });
168
+
169
+ const nameInput = wrapper.find('[data-testid="NameNsDescriptionNameInput"]');
170
+
171
+ expect(nameInput.element.value).toBe('Default');
172
+ });
72
173
  });