@rancher/shell 3.0.4 → 3.0.5-rc.1

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 (122) hide show
  1. package/assets/styles/base/_basic.scss +6 -0
  2. package/assets/styles/global/_button.scss +1 -0
  3. package/assets/translations/en-us.yaml +37 -3
  4. package/cloud-credential/aws.vue +2 -0
  5. package/components/AssignTo.vue +25 -11
  6. package/components/AsyncButton.vue +24 -7
  7. package/components/BannerGraphic.vue +1 -0
  8. package/components/CommunityLinks.vue +3 -3
  9. package/components/CopyToClipboardText.vue +2 -1
  10. package/components/DetailText.vue +5 -0
  11. package/components/DisableAuthProviderModal.vue +1 -0
  12. package/components/ExplorerMembers.vue +1 -1
  13. package/components/ExplorerProjectsNamespaces.vue +56 -14
  14. package/components/LandingPagePreference.vue +5 -3
  15. package/components/LocaleSelector.vue +38 -94
  16. package/components/ModalWithCard.vue +1 -0
  17. package/components/MoveModal.vue +1 -0
  18. package/components/PromptRemove.vue +1 -0
  19. package/components/PromptRestore.vue +1 -0
  20. package/components/ResourceCancelModal.vue +1 -0
  21. package/components/SortableTable/index.vue +10 -11
  22. package/components/__tests__/AsyncButton.test.ts +2 -2
  23. package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
  24. package/components/form/ArrayList.vue +66 -54
  25. package/components/form/Command.vue +6 -15
  26. package/components/form/EnvVars.vue +15 -8
  27. package/components/form/HealthCheck.vue +3 -3
  28. package/components/form/HookOption.vue +11 -16
  29. package/components/form/LabeledSelect.vue +2 -1
  30. package/components/form/LifecycleHooks.vue +3 -3
  31. package/components/form/MatchExpressions.vue +10 -7
  32. package/components/form/NameNsDescription.vue +123 -103
  33. package/components/form/Networking.vue +20 -12
  34. package/components/form/NodeAffinity.vue +31 -23
  35. package/components/form/NodeScheduling.vue +13 -3
  36. package/components/form/PodAffinity.vue +43 -43
  37. package/components/form/Probe.vue +67 -66
  38. package/components/form/ResourceQuota/Project.vue +5 -1
  39. package/components/form/ResourceSelector.vue +7 -9
  40. package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +6 -3
  41. package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +12 -1
  42. package/components/form/SSHKnownHosts/index.vue +16 -2
  43. package/components/form/Security.vue +54 -56
  44. package/components/form/Select.vue +31 -6
  45. package/components/form/ShellInput.vue +5 -1
  46. package/components/form/Tolerations.vue +5 -1
  47. package/components/form/ValueFromResource.vue +134 -121
  48. package/components/form/WorkloadPorts.vue +18 -18
  49. package/components/form/__tests__/ArrayList.test.ts +3 -0
  50. package/components/form/__tests__/MatchExpressions.test.ts +12 -12
  51. package/components/form/__tests__/NameNsDescription.test.ts +115 -14
  52. package/components/form/__tests__/Probe.test.ts +12 -8
  53. package/components/form/__tests__/SSHKnownHosts.test.ts +11 -0
  54. package/components/form/__tests__/Select.test.ts +37 -0
  55. package/components/formatter/InternalExternalIP.vue +2 -0
  56. package/components/formatter/SecretData.vue +20 -7
  57. package/components/nav/Group.vue +15 -1
  58. package/components/nav/Header.vue +1 -0
  59. package/components/nav/Type.vue +12 -1
  60. package/components/templates/blank.vue +4 -1
  61. package/components/templates/default.vue +2 -0
  62. package/components/templates/home.vue +4 -1
  63. package/components/templates/plain.vue +4 -1
  64. package/composables/useRuntimeFlag.ts +29 -0
  65. package/config/router/routes.js +20 -13
  66. package/core/types.ts +5 -0
  67. package/dialog/AddCustomBadgeDialog.vue +1 -0
  68. package/dialog/DeactivateDriverDialog.vue +1 -0
  69. package/dialog/ForceMachineRemoveDialog.vue +4 -1
  70. package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +16 -3
  71. package/edit/auth/__tests__/oidc.test.ts +152 -109
  72. package/edit/auth/azuread.vue +1 -0
  73. package/edit/auth/googleoauth.vue +4 -0
  74. package/edit/auth/oidc.vue +37 -4
  75. package/edit/cloudcredential.vue +1 -0
  76. package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +40 -9
  77. package/edit/networking.k8s.io.ingress/IngressClass.vue +7 -3
  78. package/edit/networking.k8s.io.ingress/__tests__/IngressClass.test.ts +58 -0
  79. package/edit/persistentvolume/__tests__/persistentvolume.test.ts +14 -2
  80. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +1 -0
  81. package/edit/provisioning.cattle.io.cluster/rke2.vue +25 -34
  82. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +6 -1
  83. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +29 -1
  84. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +2 -2
  85. package/edit/token.vue +2 -0
  86. package/edit/workload/index.vue +1 -0
  87. package/edit/workload/mixins/workload.js +0 -2
  88. package/list/management.cattle.io.feature.vue +1 -0
  89. package/list/provisioning.cattle.io.cluster.vue +20 -12
  90. package/models/__tests__/namespace.test.ts +25 -1
  91. package/models/cloudcredential.js +5 -0
  92. package/models/kontainerdriver.js +6 -3
  93. package/models/management.cattle.io.node.js +3 -3
  94. package/models/namespace.js +4 -5
  95. package/models/nodedriver.js +6 -3
  96. package/models/workload.js +4 -1
  97. package/package.json +3 -3
  98. package/pages/account/index.vue +4 -1
  99. package/pages/auth/login.vue +11 -3
  100. package/pages/auth/logout.vue +4 -1
  101. package/pages/auth/setup.vue +1 -0
  102. package/pages/auth/verify.vue +4 -1
  103. package/pages/c/_cluster/apps/charts/chart.vue +1 -1
  104. package/pages/diagnostic.vue +47 -2
  105. package/pages/fail-whale.vue +6 -3
  106. package/pages/home.vue +24 -18
  107. package/pages/support/index.vue +4 -1
  108. package/rancher-components/Form/Radio/RadioGroup.vue +25 -23
  109. package/rancher-components/RcDropdown/RcDropdown.vue +3 -2
  110. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -0
  111. package/rancher-components/RcDropdown/useDropdownCollection.ts +8 -0
  112. package/rancher-components/RcDropdown/useDropdownContext.ts +9 -3
  113. package/scripts/extension/publish +1 -0
  114. package/server/har-file.js +25 -3
  115. package/store/features.js +2 -1
  116. package/store/type-map.js +4 -0
  117. package/types/shell/index.d.ts +8 -1
  118. package/utils/cluster.js +35 -0
  119. package/utils/validators/machine-pool.ts +20 -0
  120. package/components/formatter/ExtensionCache.vue +0 -74
  121. package/components/formatter/Port.vue +0 -24
  122. package/components/formatter/SecretType.vue +0 -41
@@ -1,11 +1,17 @@
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';
4
5
 
5
6
  export default {
6
7
  name: 'LocalSelector',
7
8
 
8
- components: { Select },
9
+ components: {
10
+ Select,
11
+ RcDropdown,
12
+ RcDropdownItem,
13
+ RcDropdownTrigger,
14
+ },
9
15
 
10
16
  props: {
11
17
  mode: {
@@ -65,71 +71,37 @@ export default {
65
71
  <template>
66
72
  <div>
67
73
  <div v-if="mode === 'login'">
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"
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')"
90
80
  >
91
- <a
92
- data-testid="locale-selector"
93
- class="locale-chooser"
81
+ {{ selectedLocaleLabel }}
82
+ <template
83
+ v-if="showIcon"
84
+ #after
94
85
  >
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
- :lang="name"
123
- @click.stop="switchLocale(name)"
124
- @keyup.enter.stop="switchLocale(name)"
125
- @keyup.space.stop="switchLocale(name)"
126
- >
127
- {{ label }}
128
- </li>
129
- </ul>
86
+ <i class="icon icon-fw icon-sort-down" />
130
87
  </template>
131
- </v-dropdown>
132
- </div>
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>
133
105
  </div>
134
106
  <div v-else>
135
107
  <Select
@@ -142,36 +114,8 @@ export default {
142
114
  </div>
143
115
  </template>
144
116
 
145
- <style lang="scss" scoped>
146
- .advanced {
147
- user-select: none;
148
- padding: 0 5px;
149
- line-height: 40px;
150
- font-size: 15px;
151
- font-weight: 500;
152
- }
153
- .content {
154
- background: var(--nav-active);
155
- padding: 10px;
156
- margin-top: 6px;
157
- border-radius: 4px;
158
- }
159
-
160
- .hand:focus-visible {
161
- @include focus-outline;
162
- outline-offset: 4px;
163
- }
164
-
165
- .locale-chooser {
166
- cursor: pointer;
167
-
168
- &:hover {
169
- text-decoration: none;
117
+ <style lang="scss">
118
+ .baseline {
119
+ align-items: baseline;
170
120
  }
171
- }
172
-
173
- .locale-login-container:focus-visible {
174
- @include focus-outline;
175
- outline-offset: 2px;
176
- }
177
121
  </style>
@@ -65,6 +65,7 @@ export default {
65
65
  v-bind="$attrs"
66
66
  class="modal"
67
67
  data-testid="mvc__card"
68
+ :trigger-focus-trap="true"
68
69
  @close="$emit('finish', $event)"
69
70
  >
70
71
  <Card
@@ -93,6 +93,7 @@ export default {
93
93
  :name="modalName"
94
94
  :width="440"
95
95
  height="auto"
96
+ :trigger-focus-trap="true"
96
97
  @close="close"
97
98
  >
98
99
  <Loading v-if="$fetchState.pending" />
@@ -339,6 +339,7 @@ export default {
339
339
  :width="400"
340
340
  height="auto"
341
341
  styles="max-height: 100vh;"
342
+ :trigger-focus-trap="true"
342
343
  @close="close"
343
344
  >
344
345
  <Card
@@ -213,6 +213,7 @@ export default {
213
213
  styles="background-color: var(--nav-bg); border-radius: var(--border-radius); max-height: 100vh;"
214
214
  height="auto"
215
215
  :scrollable="true"
216
+ :trigger-focus-trap="true"
216
217
  @close="close"
217
218
  >
218
219
  <Card
@@ -56,6 +56,7 @@ export default {
56
56
  name="cancel-modal"
57
57
  :width="440"
58
58
  height="auto"
59
+ :trigger-focus-trap="true"
59
60
  @close="cancelCancel"
60
61
  >
61
62
  <div class="header">
@@ -1,8 +1,7 @@
1
1
  <script>
2
- import { mapGetters } from 'vuex';
2
+ import { mapGetters, useStore } from 'vuex';
3
3
  import { defineAsyncComponent, ref, onMounted, onBeforeUnmount } from 'vue';
4
4
  import day from 'dayjs';
5
- import semver from 'semver';
6
5
  import isEmpty from 'lodash/isEmpty';
7
6
  import { dasherize, ucFirst } from '@shell/utils/string';
8
7
  import { get, clone } from '@shell/utils/object';
@@ -25,7 +24,7 @@ import { getParent } from '@shell/utils/dom';
25
24
  import { FORMATTERS } from '@shell/components/SortableTable/sortable-config';
26
25
  import ButtonMultiAction from '@shell/components/ButtonMultiAction.vue';
27
26
  import ActionMenu from '@shell/components/ActionMenuShell.vue';
28
- import { getVersionInfo } from '@shell/utils/version';
27
+ import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
29
28
 
30
29
  // Uncomment for table performance debugging
31
30
  // import tableDebug from './debug';
@@ -546,7 +545,13 @@ export default {
546
545
  table.value.removeEventListener('keyup', handleEnterKey);
547
546
  });
548
547
 
549
- return { table };
548
+ const store = useStore();
549
+ const { featureDropdownMenu } = useRuntimeFlag(store);
550
+
551
+ return {
552
+ table,
553
+ featureDropdownMenu,
554
+ };
550
555
  },
551
556
 
552
557
  created() {
@@ -768,12 +773,6 @@ export default {
768
773
 
769
774
  return rows;
770
775
  },
771
-
772
- featureDropdownMenu() {
773
- const { fullVersion } = getVersionInfo(this.$store);
774
-
775
- return semver.gte(semver.coerce(fullVersion).version, '2.11.0');
776
- }
777
776
  },
778
777
 
779
778
  methods: {
@@ -1457,9 +1456,9 @@ export default {
1457
1456
  :value="col.value"
1458
1457
  :row="row.row"
1459
1458
  :col="col.col"
1459
+ :get-custom-detail-link="getCustomDetailLink"
1460
1460
  v-bind="col.col.formatterOpts"
1461
1461
  :row-key="row.key"
1462
- :get-custom-detail-link="getCustomDetailLink"
1463
1462
  />
1464
1463
  <component
1465
1464
  :is="col.component"
@@ -42,7 +42,7 @@ describe('component: AsyncButton', () => {
42
42
  expect(span.text()).toBe('some-string');
43
43
  });
44
44
 
45
- it('click on async button should emit click with a proper state of waiting, disabled and spinning ::: CB true', () => {
45
+ it('click on async button should emit click with a proper state of waiting, appear disabled and spinning ::: CB true', () => {
46
46
  jest.useFakeTimers();
47
47
 
48
48
  const wrapper: VueWrapper<InstanceType<typeof AsyncButton>> = mount(AsyncButton, {
@@ -65,7 +65,7 @@ describe('component: AsyncButton', () => {
65
65
  expect(wrapper.emitted('click')).toHaveLength(1);
66
66
  expect(wrapper.vm.phase).toBe(ASYNC_BUTTON_STATES.WAITING);
67
67
  expect(wrapper.vm.isSpinning).toBe(true);
68
- expect(wrapper.vm.isDisabled).toBe(true);
68
+ expect(wrapper.vm.appearsDisabled).toBe(true);
69
69
  // testing cb function has been emitted
70
70
  expect(typeof wrapper.emitted('click')![0][0]).toBe('function');
71
71
 
@@ -51,8 +51,9 @@ describe('component: RoleDetailEdit', () => {
51
51
  const wrapper = mount(RoleDetailEdit, {
52
52
  props: {
53
53
  value: {
54
- rules: [{ verbs }],
55
- subtype: 'GLOBAL'
54
+ rules: [{ verbs }],
55
+ subtype: 'GLOBAL',
56
+ metadata: { name: 'global-role-with-inherited' },
56
57
  },
57
58
  },
58
59
 
@@ -1,4 +1,5 @@
1
1
  <script>
2
+ import { ref, watch, computed } from 'vue';
2
3
  import debounce from 'lodash/debounce';
3
4
  import { _EDIT, _VIEW } from '@shell/config/query-params';
4
5
  import { removeAt } from '@shell/utils/array';
@@ -99,21 +100,78 @@ export default {
99
100
  default: '',
100
101
  },
101
102
  },
102
- data() {
103
- const input = (Array.isArray(this.value) ? this.value : []).slice();
104
- const rows = [];
103
+
104
+ setup(props, { emit }) {
105
+ const input = (Array.isArray(props.value) ? props.value : []).slice();
106
+ const rows = ref([]);
105
107
 
106
108
  for ( const value of input ) {
107
- rows.push({ value });
109
+ rows.value.push({ value });
108
110
  }
109
- if ( !rows.length && this.initialEmptyRow ) {
110
- const value = this.defaultAddValue ? clone(this.defaultAddValue) : '';
111
+ if ( !rows.value.length && props.initialEmptyRow ) {
112
+ const value = props.defaultAddValue ? clone(props.defaultAddValue) : '';
111
113
 
112
- rows.push({ value });
114
+ rows.value.push({ value });
113
115
  }
114
116
 
115
- return { rows, lastUpdateWasFromValue: false };
117
+ const isView = computed(() => {
118
+ return props.mode === _VIEW;
119
+ });
120
+
121
+ /**
122
+ * Cleanup rows and emit input
123
+ */
124
+ const update = () => {
125
+ if ( isView.value ) {
126
+ return;
127
+ }
128
+ const out = [];
129
+
130
+ for ( const row of rows.value ) {
131
+ const trim = !props.valueMultiline && (typeof row.value === 'string');
132
+ const value = trim ? row.value.trim() : row.value;
133
+
134
+ if ( typeof value !== 'undefined' ) {
135
+ out.push(value);
136
+ }
137
+ }
138
+ emit('update:value', out);
139
+ };
140
+
141
+ const lastUpdateWasFromValue = ref(false);
142
+ const queueUpdate = debounce(update, 50);
143
+
144
+ watch(
145
+ rows,
146
+ () => {
147
+ // lastUpdateWasFromValue is used to break a cycle where when rows are updated
148
+ // this was called which then forced rows to updated again
149
+ if (!lastUpdateWasFromValue.value) {
150
+ queueUpdate();
151
+ }
152
+ lastUpdateWasFromValue.value = false;
153
+ },
154
+ { deep: true }
155
+ );
156
+
157
+ watch(
158
+ () => props.value,
159
+ () => {
160
+ lastUpdateWasFromValue.value = true;
161
+ rows.value = (props.value || []).map((v) => ({ value: v }));
162
+ },
163
+ { deep: true }
164
+ );
165
+
166
+ return {
167
+ rows,
168
+ lastUpdateWasFromValue,
169
+ queueUpdate,
170
+ isView,
171
+ update,
172
+ };
116
173
  },
174
+
117
175
  computed: {
118
176
  _addLabel() {
119
177
  return this.addLabel || this.t('generic.add');
@@ -121,10 +179,6 @@ export default {
121
179
  _removeLabel() {
122
180
  return this.removeLabel || this.t('generic.remove');
123
181
  },
124
-
125
- isView() {
126
- return this.mode === _VIEW;
127
- },
128
182
  showAdd() {
129
183
  return this.addAllowed;
130
184
  },
@@ -145,29 +199,7 @@ export default {
145
199
  return !this.valueMultiline && this.protip;
146
200
  }
147
201
  },
148
- watch: {
149
- value: {
150
- deep: true,
151
- handler() {
152
- this.lastUpdateWasFromValue = true;
153
- this.rows = (this.value || []).map((v) => ({ value: v }));
154
- }
155
- },
156
-
157
- rows: {
158
- deep: true,
159
- handler(newValue, oldValue) {
160
- // lastUpdateWasFromValue is used to break a cycle where when rows are updated
161
- // this was called which then forced rows to updated again
162
- if (!this.lastUpdateWasFromValue) {
163
- this.queueUpdate();
164
- }
165
- this.lastUpdateWasFromValue = false;
166
- }
167
- }
168
- },
169
202
  created() {
170
- this.queueUpdate = debounce(this.update, 50);
171
203
  },
172
204
  methods: {
173
205
  add() {
@@ -193,26 +225,6 @@ export default {
193
225
  this.queueUpdate();
194
226
  },
195
227
 
196
- /**
197
- * Cleanup rows and emit input
198
- */
199
- update() {
200
- if ( this.isView ) {
201
- return;
202
- }
203
- const out = [];
204
-
205
- for ( const row of this.rows ) {
206
- const trim = !this.valueMultiline && (typeof row.value === 'string');
207
- const value = trim ? row.value.trim() : row.value;
208
-
209
- if ( typeof value !== 'undefined' ) {
210
- out.push(value);
211
- }
212
- }
213
- this.$emit('update:value', out);
214
- },
215
-
216
228
  /**
217
229
  * Handle paste event, e.g. split multiple lines in rows
218
230
  */
@@ -43,23 +43,14 @@ export default {
43
43
  },
44
44
 
45
45
  data() {
46
- const {
47
- command,
48
- args,
49
- workingDir,
50
- stdin = false,
51
- stdinOnce = false,
52
- tty = false,
53
- } = this.value;
54
-
55
46
  return {
56
- args,
57
- command,
47
+ args: this.value.args,
48
+ command: this.value.command,
58
49
  commandOptions: ['No', 'Once', 'Yes'],
59
- stdin,
60
- stdinOnce,
61
- tty,
62
- workingDir,
50
+ stdin: this.value.stdin || false,
51
+ stdinOnce: this.value.stdin || false,
52
+ tty: this.value.tty || false,
53
+ workingDir: this.value.workingDir,
63
54
  };
64
55
  },
65
56
 
@@ -39,14 +39,10 @@ export default {
39
39
  },
40
40
 
41
41
  data() {
42
- const { env = [], envFrom = [] } = this.value;
43
-
44
- const allEnv = [...env, ...envFrom].map((row) => {
45
- return { value: row, id: randomStr(4) };
46
- });
47
-
48
42
  return {
49
- env, envFrom, allEnv
43
+ env: [],
44
+ envFrom: [],
45
+ allEnv: [],
50
46
  };
51
47
  },
52
48
 
@@ -63,7 +59,18 @@ export default {
63
59
  }
64
60
  }
65
61
  },
62
+
66
63
  created() {
64
+ const { env = [], envFrom = [] } = this.value;
65
+
66
+ const allEnv = [...env, ...envFrom].map((row) => {
67
+ return { value: row, id: randomStr(4) };
68
+ });
69
+
70
+ this.env = env;
71
+ this.envFrom = envFrom;
72
+ this.allEnv = allEnv;
73
+
67
74
  this.queueUpdate = debounce(this.update, 500);
68
75
  },
69
76
 
@@ -107,7 +114,7 @@ export default {
107
114
  <div :style="{'width':'100%'}">
108
115
  <div
109
116
  v-for="(row, i) in allEnv"
110
- :key="i"
117
+ :key="row.id"
111
118
  >
112
119
  <ValueFromResource
113
120
  v-model:value="row.value"
@@ -18,10 +18,10 @@ export default {
18
18
  },
19
19
 
20
20
  data() {
21
- const { readinessProbe, livenessProbe, startupProbe } = this.value;
22
-
23
21
  return {
24
- readinessProbe, livenessProbe, startupProbe
22
+ readinessProbe: this.value.readinessProbe,
23
+ livenessProbe: this.value.livenessProbe,
24
+ startupProbe: this.value.startupProbe,
25
25
  };
26
26
  },
27
27
 
@@ -28,23 +28,18 @@ export default {
28
28
  },
29
29
 
30
30
  data() {
31
- const selectHook = null;
32
-
33
- const defaultExec = { exec: { command: [] } };
34
- const defaultHttpGet = {
35
- httpGet: {
36
- host: '',
37
- path: '',
38
- port: null,
39
- scheme: '',
40
- httpHeaders: null
41
- }
42
- };
43
-
44
31
  return {
45
- selectHook,
46
- defaultExec,
47
- defaultHttpGet,
32
+ selectHook: null,
33
+ defaultExec: { exec: { command: [] } },
34
+ defaultHttpGet: {
35
+ httpGet: {
36
+ host: '',
37
+ path: '',
38
+ port: null,
39
+ scheme: '',
40
+ httpHeaders: null
41
+ }
42
+ },
48
43
  schemeOptions: ['HTTP', 'HTTPS']
49
44
  };
50
45
  },
@@ -296,6 +296,7 @@ export default {
296
296
  }
297
297
  ]"
298
298
  :tabindex="isView || disabled ? -1 : 0"
299
+ role="listbox"
299
300
  @click="focusSearch"
300
301
  @keydown.enter="focusSearch"
301
302
  @keydown.down.prevent="focusSearch"
@@ -344,7 +345,7 @@ export default {
344
345
  :modelValue="value != null && !loading ? value : ''"
345
346
  :dropdown-should-open="dropdownShouldOpen"
346
347
  :tabindex="-1"
347
- role="listbox"
348
+ role="listitem"
348
349
  @update:modelValue="$emit('selecting', $event); $emit('update:value', $event)"
349
350
  @search:blur="onBlur"
350
351
  @search:focus="onFocus"
@@ -24,10 +24,10 @@ export default {
24
24
  },
25
25
 
26
26
  data() {
27
- const { postStart, preStop } = this.value;
28
-
29
27
  return {
30
- postStart, preStop, hookOptions: ['postStart', 'preStop']
28
+ postStart: this.value.postStart,
29
+ preStop: this.value.preStop,
30
+ hookOptions: ['postStart', 'preStop']
31
31
  };
32
32
  },
33
33
 
@@ -70,6 +70,14 @@ export default {
70
70
  },
71
71
 
72
72
  data() {
73
+ return {
74
+ ops: [],
75
+ rules: [],
76
+ custom: []
77
+ };
78
+ },
79
+
80
+ created() {
73
81
  const t = this.$store.getters['i18n/t'];
74
82
 
75
83
  const podOptions = [
@@ -88,8 +96,6 @@ export default {
88
96
  { label: t('workload.scheduling.affinity.matchExpressions.greaterThan'), value: 'Gt' },
89
97
  ];
90
98
 
91
- const ops = this.type === NODE ? nodeOptions : podOptions;
92
-
93
99
  let rules;
94
100
 
95
101
  // special case for matchFields and matchExpressions
@@ -127,11 +133,8 @@ export default {
127
133
  rules.push(newRule);
128
134
  }
129
135
 
130
- return {
131
- ops,
132
- rules,
133
- custom: []
134
- };
136
+ this.rules = rules;
137
+ this.ops = this.type === NODE ? nodeOptions : podOptions;
135
138
  },
136
139
 
137
140
  computed: {