@rancher/shell 3.0.11 → 3.0.12-rc.2
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.
- package/assets/images/providers/entraid-black.svg +4 -0
- package/assets/images/providers/entraid.svg +9 -0
- package/assets/images/vendor/entraid.svg +9 -0
- package/assets/styles/app.scss +0 -1
- package/assets/styles/base/_mixins.scss +31 -0
- package/assets/styles/base/_variables.scss +2 -0
- package/assets/styles/themes/_modern.scss +6 -5
- package/assets/translations/en-us.yaml +24 -21
- package/assets/translations/zh-hans.yaml +4 -11
- package/chart/__tests__/S3.test.ts +10 -3
- package/components/CountBox.vue +20 -0
- package/components/CreateDriver.vue +0 -12
- package/components/DetailText.vue +12 -3
- package/components/EmptyProductPage.vue +76 -0
- package/components/Resource/Detail/CopyToClipboard.vue +1 -2
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +9 -3
- package/components/Resource/Detail/TitleBar/__tests__/__snapshots__/index.test.ts.snap +31 -0
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +45 -1
- package/components/Resource/Detail/TitleBar/index.vue +1 -1
- package/components/Resource/Detail/ViewOptions/__tests__/__snapshots__/index.test.ts.snap +9 -0
- package/components/Resource/Detail/ViewOptions/__tests__/index.test.ts +62 -0
- package/components/Resource/Detail/ViewOptions/index.vue +2 -1
- package/components/ResourceList/Masthead.vue +25 -2
- package/components/SelectIconGrid.vue +5 -0
- package/components/SideNav.vue +13 -0
- package/components/__tests__/CountBox.test.ts +72 -0
- package/components/__tests__/DetailText.test.ts +113 -0
- package/components/__tests__/PromptModal.test.ts +2 -0
- package/components/fleet/FleetClusterTargets/index.vue +18 -1
- package/components/fleet/FleetClusters.vue +1 -0
- package/components/fleet/__tests__/FleetClusters.test.ts +71 -0
- package/components/form/InputWithSelect.vue +18 -10
- package/components/form/KeyValue.vue +17 -1
- package/components/form/LabeledSelect.vue +82 -24
- package/components/form/NodeScheduling.vue +17 -3
- package/components/form/PrivateRegistry.vue +69 -0
- package/components/form/Select.vue +73 -56
- package/components/form/ServiceNameSelect.vue +13 -11
- package/components/form/__tests__/KeyValue.test.ts +66 -0
- package/components/form/__tests__/NodeScheduling.test.ts +9 -0
- package/components/form/__tests__/PrivateRegistry.test.ts +133 -0
- package/components/form/labeled-select-utils/useLabeledSelectPagination.ts +138 -0
- package/components/formatter/WorkloadHealthScale.vue +3 -1
- package/components/nav/Group.vue +33 -9
- package/components/nav/Header.vue +56 -10
- package/components/nav/NotificationCenter/Notification.vue +4 -1
- package/components/nav/NotificationCenter/NotificationHeader.vue +20 -8
- package/components/nav/NotificationCenter/__tests__/NotificationHeader.test.ts +80 -0
- package/components/nav/TopLevelMenu.vue +15 -1
- package/components/nav/Type.vue +8 -7
- package/components/nav/WindowManager/index.vue +2 -1
- package/components/nav/WorkspaceSwitcher.vue +13 -0
- package/components/nav/__tests__/Group.test.ts +67 -0
- package/components/nav/__tests__/Header.test.ts +235 -0
- package/components/nav/__tests__/Type.test.ts +20 -3
- package/components/templates/default.vue +34 -4
- package/components/templates/home.vue +12 -25
- package/components/templates/plain.vue +13 -26
- package/composables/useLabeledFormElement.ts +10 -2
- package/composables/useLabeledSelect.ts +60 -0
- package/composables/useUserRetentionValidation.ts +1 -49
- package/config/cookies.js +0 -1
- package/config/labels-annotations.js +1 -0
- package/config/pagination-table-headers.js +8 -1
- package/config/product/apps.js +2 -1
- package/config/product/auth.js +1 -0
- package/config/product/backup.js +1 -0
- package/config/product/compliance.js +1 -1
- package/config/product/explorer.js +25 -6
- package/config/product/fleet.js +1 -0
- package/config/product/gatekeeper.js +1 -0
- package/config/product/istio.js +1 -0
- package/config/product/logging.js +1 -0
- package/config/product/longhorn.js +2 -1
- package/config/product/manager.js +1 -0
- package/config/product/monitoring.js +1 -0
- package/config/product/navlinks.js +1 -0
- package/config/product/neuvector.js +2 -1
- package/config/product/settings.js +1 -0
- package/config/product/uiplugins.js +1 -0
- package/config/query-params.js +1 -0
- package/config/router/routes.js +0 -8
- package/core/__tests__/plugin-products-helpers.test.ts +454 -0
- package/core/__tests__/plugin-products.test.ts +3810 -0
- package/core/extension-manager-impl.js +30 -1
- package/core/plugin-products-base.ts +392 -0
- package/core/plugin-products-extending.ts +44 -0
- package/core/plugin-products-helpers.ts +263 -0
- package/core/plugin-products-top-level.ts +66 -0
- package/core/plugin-products-type-guards.ts +33 -0
- package/core/plugin-products.ts +50 -0
- package/core/plugin-types.ts +237 -0
- package/core/plugin.ts +45 -10
- package/core/productDebugger.js +48 -0
- package/core/types.ts +97 -11
- package/detail/__tests__/__snapshots__/fleet.cattle.io.bundle.test.ts.snap +52 -0
- package/detail/__tests__/fleet.cattle.io.bundle.test.ts +171 -0
- package/detail/__tests__/management.cattle.io.fleetworkspace.test.ts +128 -0
- package/detail/fleet.cattle.io.bundle.vue +21 -34
- package/detail/management.cattle.io.fleetworkspace.vue +49 -0
- package/dialog/ExtensionCatalogInstallDialog.vue +1 -1
- package/dialog/InstallExtensionDialog.vue +6 -27
- package/dialog/UninstallExistingExtensionDialog.vue +141 -0
- package/dialog/UninstallExtensionDialog.vue +4 -26
- package/dialog/__tests__/UninstallExistingExtensionDialog.test.ts +114 -0
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +9 -0
- package/edit/__tests__/kontainerDriver.test.ts +0 -13
- package/edit/__tests__/nodeDriver.test.ts +5 -11
- package/edit/__tests__/resources.cattle.io.restore.test.ts +9 -0
- package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
- package/edit/auth/__tests__/oidc.test.ts +54 -0
- package/edit/auth/azuread.vue +1 -1
- package/edit/auth/oidc.vue +8 -0
- package/edit/kontainerDriver.vue +1 -2
- package/edit/nodeDriver.vue +0 -2
- package/edit/provisioning.cattle.io.cluster/AgentEnv.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/AgentEnv.test.ts +25 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Ingress.test.ts +176 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +70 -99
- package/edit/provisioning.cattle.io.cluster/rke2.vue +4 -1
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +6 -0
- package/edit/provisioning.cattle.io.cluster/tabs/Ingress.vue +7 -2
- package/initialize/App.vue +29 -2
- package/initialize/install-plugins.js +0 -2
- package/list/__tests__/management.cattle.io.feature.test.ts +105 -0
- package/list/catalog.cattle.io.app.vue +25 -5
- package/list/management.cattle.io.feature.vue +1 -1
- package/list/management.cattle.io.fleetworkspace.vue +8 -0
- package/list/provisioning.cattle.io.cluster.vue +0 -1
- package/list/workload.vue +11 -4
- package/machine-config/amazonec2.vue +1 -0
- package/mixins/chart.js +40 -9
- package/mixins/resource-fetch.js +12 -3
- package/models/__tests__/catalog.cattle.io.app.test.ts +15 -1
- package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +84 -0
- package/models/__tests__/chart.test.ts +99 -6
- package/models/__tests__/management.cattle.io.feature.test.ts +131 -0
- package/models/__tests__/monitoring.coreos.com.alertmanagerconfig.test.ts +98 -0
- package/models/catalog.cattle.io.app.js +21 -17
- package/models/catalog.cattle.io.clusterrepo.js +39 -11
- package/models/chart.js +33 -19
- package/models/fleet-application.js +1 -1
- package/models/fleet.cattle.io.bundle.js +1 -1
- package/models/kontainerdriver.js +11 -0
- package/models/management.cattle.io.authconfig.js +5 -1
- package/models/management.cattle.io.cluster.js +0 -53
- package/models/management.cattle.io.feature.js +3 -3
- package/models/management.cattle.io.kontainerdriver.js +1 -26
- package/models/monitoring.coreos.com.alertmanagerconfig.js +31 -17
- package/models/nodedriver.js +7 -0
- package/models/pod.js +18 -0
- package/models/workload.js +20 -2
- package/package.json +13 -13
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +0 -1
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +189 -0
- package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +55 -0
- package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +53 -0
- package/pages/c/_cluster/apps/charts/chart.vue +217 -33
- package/pages/c/_cluster/apps/charts/index.vue +2 -2
- package/pages/c/_cluster/apps/charts/install.vue +8 -3
- package/pages/c/_cluster/auth/user.retention/index.vue +55 -22
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -7
- package/pages/c/_cluster/settings/brand.vue +4 -4
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +39 -2
- package/pages/c/_cluster/uiplugins/__tests__/PluginInfoPanel.test.ts +61 -0
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +246 -23
- package/pages/c/_cluster/uiplugins/index.vue +166 -62
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +1 -0
- package/plugins/dashboard-store/actions.js +3 -2
- package/plugins/dashboard-store/resource-class.js +62 -6
- package/plugins/plugin.js +16 -0
- package/plugins/steve/steve-pagination-utils.ts +7 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +205 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +82 -4
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +1 -1
- package/scripts/test-plugins-build.sh +5 -2
- package/scripts/typegen.sh +13 -1
- package/server/server-middleware.js +2 -2
- package/static/humans.txt +1 -0
- package/static/robots.txt +34 -0
- package/static/welcome-cow.svg +18 -0
- package/store/__tests__/catalog.test.ts +161 -11
- package/store/__tests__/type-map.test.ts +84 -24
- package/store/auth.js +0 -3
- package/store/catalog.js +60 -8
- package/store/type-map.js +42 -3
- package/tsconfig.paths.json +1 -0
- package/types/resources/pod.ts +18 -0
- package/types/shell/index.d.ts +8539 -2938
- package/types/store/dashboard-store.types.ts +5 -0
- package/types/store/pagination.types.ts +6 -0
- package/utils/__tests__/git.test.ts +270 -0
- package/utils/__tests__/inactivity.test.ts +316 -0
- package/utils/__tests__/object.test.ts +77 -0
- package/utils/__tests__/time.test.ts +14 -1
- package/utils/__tests__/url.test.ts +246 -0
- package/utils/axios.js +1 -4
- package/utils/dynamic-importer.js +3 -2
- package/utils/object.js +33 -2
- package/utils/pagination-utils.ts +1 -1
- package/utils/time.ts +5 -0
- package/utils/uiplugins.ts +12 -16
- package/utils/validators/__tests__/private-registry.test.ts +76 -0
- package/utils/validators/private-registry.ts +28 -0
- package/vue.config.js +0 -9
- package/assets/images/providers/azuread-black.svg +0 -22
- package/assets/images/providers/azuread.svg +0 -25
- package/assets/images/vendor/azuread.svg +0 -18
- package/assets/styles/fonts/_dots.scss +0 -18
- package/components/EmberPage.vue +0 -622
- package/components/EmberPageView.vue +0 -39
- package/components/form/labeled-select-utils/labeled-select-pagination.ts +0 -116
- package/mixins/labeled-form-element.ts +0 -225
- package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -28
- package/pages/c/_cluster/manager/pages/_page.vue +0 -22
- package/pages/c/_cluster/mcapps/pages/_page.vue +0 -22
- package/plugins/ember-cookie.js +0 -17
- package/utils/ember-page.js +0 -30
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineComponent, nextTick } from 'vue';
|
|
2
|
+
import { mount, flushPromises } from '@vue/test-utils';
|
|
3
|
+
import { useForm } from 'vee-validate';
|
|
2
4
|
import { LabeledInput } from './index';
|
|
3
5
|
|
|
4
6
|
describe('component: LabeledInput', () => {
|
|
@@ -105,4 +107,206 @@ describe('component: LabeledInput', () => {
|
|
|
105
107
|
expect(mainInput.attributes('aria-label')).toBeUndefined();
|
|
106
108
|
expect(wrapper.find('label').text()).toBe(label);
|
|
107
109
|
});
|
|
110
|
+
|
|
111
|
+
describe('vee-validate integration', () => {
|
|
112
|
+
const i18nMock = { $store: { getters: { 'i18n/t': jest.fn() } } };
|
|
113
|
+
|
|
114
|
+
it('without name prop: existing rules-based validation message is shown after blur', async() => {
|
|
115
|
+
const errorMessage = 'This field cannot be empty';
|
|
116
|
+
const notEmptyRule = (v: string) => (!v ? errorMessage : undefined);
|
|
117
|
+
|
|
118
|
+
const wrapper = mount(LabeledInput, {
|
|
119
|
+
propsData: {
|
|
120
|
+
rules: [notEmptyRule],
|
|
121
|
+
value: '',
|
|
122
|
+
},
|
|
123
|
+
mocks: i18nMock
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
await wrapper.find('input').trigger('blur');
|
|
127
|
+
await nextTick();
|
|
128
|
+
|
|
129
|
+
expect(wrapper.vm.validationMessage).toBe(errorMessage);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('without name prop: error CSS class is not applied automatically', async() => {
|
|
133
|
+
const notEmptyRule = (v: string) => (!v ? 'Error' : undefined);
|
|
134
|
+
|
|
135
|
+
const wrapper = mount(LabeledInput, {
|
|
136
|
+
propsData: {
|
|
137
|
+
rules: [notEmptyRule],
|
|
138
|
+
value: '',
|
|
139
|
+
},
|
|
140
|
+
mocks: i18nMock
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
await wrapper.find('input').trigger('blur');
|
|
144
|
+
await nextTick();
|
|
145
|
+
|
|
146
|
+
expect(wrapper.find('.labeled-input').classes()).not.toContain('error');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('with name prop: name attribute is set on the input element', () => {
|
|
150
|
+
const wrapper = mount(LabeledInput, {
|
|
151
|
+
propsData: { name: 'myField' },
|
|
152
|
+
mocks: i18nMock
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
expect(wrapper.find('input').attributes('name')).toStrictEqual('myField');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('with name prop: existing rules run through vee-validate and show error message after blur', async() => {
|
|
159
|
+
const errorMessage = 'Field cannot be empty';
|
|
160
|
+
const notEmptyRule = (v: string) => (!v ? errorMessage : undefined);
|
|
161
|
+
|
|
162
|
+
const wrapper = mount(LabeledInput, {
|
|
163
|
+
propsData: {
|
|
164
|
+
name: 'testField',
|
|
165
|
+
rules: [notEmptyRule],
|
|
166
|
+
value: '',
|
|
167
|
+
},
|
|
168
|
+
mocks: i18nMock
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
await wrapper.find('input').trigger('blur');
|
|
172
|
+
await flushPromises();
|
|
173
|
+
|
|
174
|
+
expect(wrapper.vm.validationMessage).toStrictEqual(errorMessage);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('with name prop: no error class when validation passes', async() => {
|
|
178
|
+
const notEmptyRule = (v: string) => (!v ? 'Error' : undefined);
|
|
179
|
+
|
|
180
|
+
const wrapper = mount(LabeledInput, {
|
|
181
|
+
propsData: {
|
|
182
|
+
name: 'testField',
|
|
183
|
+
rules: [notEmptyRule],
|
|
184
|
+
value: 'valid value',
|
|
185
|
+
},
|
|
186
|
+
mocks: i18nMock
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
await wrapper.find('input').trigger('blur');
|
|
190
|
+
await flushPromises();
|
|
191
|
+
|
|
192
|
+
expect(wrapper.find('.labeled-input').classes()).not.toContain('error');
|
|
193
|
+
expect(wrapper.vm.validationMessage).toBeUndefined();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('with name prop: form-level validation schema error is shown when the form validates', async() => {
|
|
197
|
+
const errorMessage = 'Username is required';
|
|
198
|
+
let triggerFormValidation!: () => Promise<unknown>;
|
|
199
|
+
|
|
200
|
+
const TestWrapper = defineComponent({
|
|
201
|
+
components: { LabeledInput },
|
|
202
|
+
setup() {
|
|
203
|
+
const { validate } = useForm({
|
|
204
|
+
validationSchema: { username: (v: string) => (!v ? errorMessage : true) },
|
|
205
|
+
initialValues: { username: '' }
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
triggerFormValidation = validate;
|
|
209
|
+
|
|
210
|
+
return {};
|
|
211
|
+
},
|
|
212
|
+
template: '<LabeledInput name="username" value="" />'
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const wrapper = mount(TestWrapper, { global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } } });
|
|
216
|
+
|
|
217
|
+
await triggerFormValidation();
|
|
218
|
+
await flushPromises();
|
|
219
|
+
|
|
220
|
+
const labeledInput = wrapper.findComponent(LabeledInput);
|
|
221
|
+
|
|
222
|
+
expect(labeledInput.vm.validationMessage).toStrictEqual(errorMessage);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('without name prop: error clears when a previously invalid value becomes valid', async() => {
|
|
226
|
+
const errorMessage = 'This field cannot be empty';
|
|
227
|
+
const notEmptyRule = (v: string) => (!v ? errorMessage : undefined);
|
|
228
|
+
|
|
229
|
+
const wrapper = mount(LabeledInput, {
|
|
230
|
+
propsData: {
|
|
231
|
+
rules: [notEmptyRule],
|
|
232
|
+
value: '',
|
|
233
|
+
},
|
|
234
|
+
mocks: i18nMock
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
await wrapper.find('input').trigger('blur');
|
|
238
|
+
await nextTick();
|
|
239
|
+
|
|
240
|
+
expect(wrapper.vm.validationMessage).toBe(errorMessage);
|
|
241
|
+
|
|
242
|
+
await wrapper.setProps({ value: 'valid value' });
|
|
243
|
+
await nextTick();
|
|
244
|
+
|
|
245
|
+
expect(wrapper.vm.validationMessage).toBeUndefined();
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('with name prop: error clears when a previously invalid value becomes valid', async() => {
|
|
249
|
+
const errorMessage = 'Field cannot be empty';
|
|
250
|
+
const notEmptyRule = (v: string) => (!v ? errorMessage : undefined);
|
|
251
|
+
|
|
252
|
+
const wrapper = mount(LabeledInput, {
|
|
253
|
+
propsData: {
|
|
254
|
+
name: 'testField',
|
|
255
|
+
rules: [notEmptyRule],
|
|
256
|
+
value: '',
|
|
257
|
+
},
|
|
258
|
+
mocks: i18nMock
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
await wrapper.find('input').trigger('blur');
|
|
262
|
+
await flushPromises();
|
|
263
|
+
|
|
264
|
+
expect(wrapper.vm.validationMessage).toStrictEqual(errorMessage);
|
|
265
|
+
|
|
266
|
+
await wrapper.setProps({ value: 'valid value' });
|
|
267
|
+
await flushPromises();
|
|
268
|
+
|
|
269
|
+
expect(wrapper.vm.validationMessage).toBeUndefined();
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
describe('with both name and rules provided', () => {
|
|
273
|
+
it('shows the error message exactly once when invalid (not duplicated across both validation paths)', async() => {
|
|
274
|
+
const errorMessage = 'Field cannot be empty';
|
|
275
|
+
const notEmptyRule = (v: string) => (!v ? errorMessage : undefined);
|
|
276
|
+
|
|
277
|
+
const wrapper = mount(LabeledInput, {
|
|
278
|
+
propsData: {
|
|
279
|
+
name: 'testField',
|
|
280
|
+
rules: [notEmptyRule],
|
|
281
|
+
value: '',
|
|
282
|
+
},
|
|
283
|
+
mocks: i18nMock
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
await wrapper.find('input').trigger('blur');
|
|
287
|
+
await flushPromises();
|
|
288
|
+
|
|
289
|
+
expect(wrapper.vm.validationMessage).toStrictEqual(errorMessage);
|
|
290
|
+
expect(wrapper.vm.validationMessage).not.toContain(`${ errorMessage }, ${ errorMessage }`);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it('shows no error when the value satisfies the rules', async() => {
|
|
294
|
+
const notEmptyRule = (v: string) => (!v ? 'Field cannot be empty' : undefined);
|
|
295
|
+
|
|
296
|
+
const wrapper = mount(LabeledInput, {
|
|
297
|
+
propsData: {
|
|
298
|
+
name: 'testField',
|
|
299
|
+
rules: [notEmptyRule],
|
|
300
|
+
value: 'valid value',
|
|
301
|
+
},
|
|
302
|
+
mocks: i18nMock
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
await wrapper.find('input').trigger('blur');
|
|
306
|
+
await flushPromises();
|
|
307
|
+
|
|
308
|
+
expect(wrapper.vm.validationMessage).toBeUndefined();
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
});
|
|
108
312
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { defineComponent, inject } from 'vue';
|
|
2
|
+
import { defineComponent, inject, computed, watch } from 'vue';
|
|
3
|
+
import { useField } from 'vee-validate';
|
|
3
4
|
import TextAreaAutoGrow from '@components/Form/TextArea/TextAreaAutoGrow.vue';
|
|
4
5
|
import LabeledTooltip from '@components/LabeledTooltip/LabeledTooltip.vue';
|
|
5
6
|
import { escapeHtml, generateRandomAlphaString } from '@shell/utils/string';
|
|
@@ -114,6 +115,15 @@ export default defineComponent({
|
|
|
114
115
|
ariaLabel: {
|
|
115
116
|
type: String,
|
|
116
117
|
default: ''
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The field name used for vee-validate integration. When provided, the
|
|
122
|
+
* component registers with a parent vee-validate form context
|
|
123
|
+
*/
|
|
124
|
+
name: {
|
|
125
|
+
type: String,
|
|
126
|
+
default: null
|
|
117
127
|
}
|
|
118
128
|
},
|
|
119
129
|
|
|
@@ -132,15 +142,72 @@ export default defineComponent({
|
|
|
132
142
|
|
|
133
143
|
const onInput = inject('onInput', provideProps.onInput);
|
|
134
144
|
|
|
145
|
+
// Stable fallback name so useField is always called unconditionally.
|
|
146
|
+
// When no name prop is given the field won't match any form-schema path.
|
|
147
|
+
const standaloneFieldId = `__field__${ generateRandomAlphaString(12) }`;
|
|
148
|
+
const veeFieldName = computed(() => props.name || standaloneFieldId);
|
|
149
|
+
|
|
150
|
+
// Pass existing rules to vee-validate so field-level validation still runs
|
|
151
|
+
const veeValidator = (value: unknown): boolean | string => {
|
|
152
|
+
// Return true when name is absent to avoid duplicating
|
|
153
|
+
// useLabeledFormElement validation
|
|
154
|
+
if (!props.name) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
for (const rule of props.rules as Array<(v: unknown) => string | undefined>) {
|
|
158
|
+
const msg = rule(value);
|
|
159
|
+
|
|
160
|
+
if (msg) {
|
|
161
|
+
return msg;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return true;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const {
|
|
169
|
+
errorMessage: veeError,
|
|
170
|
+
handleBlur: veeHandleBlur,
|
|
171
|
+
validate: veeValidate,
|
|
172
|
+
value: veeValue,
|
|
173
|
+
} = useField<string | number | Record<string, unknown>>(
|
|
174
|
+
veeFieldName,
|
|
175
|
+
veeValidator,
|
|
176
|
+
{
|
|
177
|
+
initialValue: props.value as string | number,
|
|
178
|
+
validateOnValueUpdate: true,
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
// Keep vee-validate's internal value in sync with the controlled prop value.
|
|
183
|
+
watch(() => props.value, (v) => {
|
|
184
|
+
if (veeValue.value !== v) {
|
|
185
|
+
veeValue.value = v as string | number;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const effectiveValidationMessage = computed(() => {
|
|
190
|
+
if (props.name && veeError.value) {
|
|
191
|
+
return veeError.value;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return validationMessage.value;
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
const effectiveStatus = computed(() => props.status);
|
|
198
|
+
|
|
135
199
|
return {
|
|
136
200
|
focused,
|
|
137
201
|
onFocusLabeled,
|
|
138
202
|
onBlurLabeled,
|
|
139
203
|
onInput,
|
|
140
204
|
isDisabled,
|
|
141
|
-
validationMessage,
|
|
205
|
+
validationMessage: effectiveValidationMessage,
|
|
142
206
|
requiredField,
|
|
143
207
|
isCompact,
|
|
208
|
+
veeHandleBlur,
|
|
209
|
+
veeValidate,
|
|
210
|
+
effectiveStatus,
|
|
144
211
|
};
|
|
145
212
|
},
|
|
146
213
|
|
|
@@ -339,6 +406,11 @@ export default defineComponent({
|
|
|
339
406
|
onBlur(event: string | FocusEvent): void {
|
|
340
407
|
this.$emit('blur', event);
|
|
341
408
|
this.onBlurLabeled();
|
|
409
|
+
// Mark the field as touched in vee-validate without relying on its
|
|
410
|
+
// 'validated-only' guard, then run validation unconditionally so
|
|
411
|
+
// errors surface on the first blur (matching useLabeledFormElement behavior).
|
|
412
|
+
this.veeHandleBlur(event instanceof FocusEvent ? event : undefined, false);
|
|
413
|
+
this.veeValidate();
|
|
342
414
|
},
|
|
343
415
|
|
|
344
416
|
escapeHtml
|
|
@@ -353,7 +425,7 @@ export default defineComponent({
|
|
|
353
425
|
focused,
|
|
354
426
|
[mode]: true,
|
|
355
427
|
disabled: isDisabled,
|
|
356
|
-
[
|
|
428
|
+
[effectiveStatus]: effectiveStatus,
|
|
357
429
|
suffix: hasSuffix,
|
|
358
430
|
'has-clean-tooltip': hasTooltip,
|
|
359
431
|
'compact-input': isCompact,
|
|
@@ -389,13 +461,14 @@ export default defineComponent({
|
|
|
389
461
|
ref="value"
|
|
390
462
|
v-bind="$attrs"
|
|
391
463
|
v-stripped-aria-label="!hasLabel && ariaLabel ? ariaLabel : undefined"
|
|
464
|
+
:name="name || undefined"
|
|
392
465
|
:maxlength="_maxlength"
|
|
393
466
|
:disabled="isDisabled"
|
|
394
467
|
:aria-disabled="isDisabled"
|
|
395
468
|
:value="value || ''"
|
|
396
469
|
:placeholder="_placeholder"
|
|
397
470
|
autocapitalize="off"
|
|
398
|
-
:class="{
|
|
471
|
+
:class="{ 'multiline-password': type === 'multiline-password' }"
|
|
399
472
|
:aria-describedby="ariaDescribedBy"
|
|
400
473
|
:aria-required="requiredField"
|
|
401
474
|
@update:value="onInput"
|
|
@@ -410,6 +483,7 @@ export default defineComponent({
|
|
|
410
483
|
:role="type === 'number' ? undefined : 'textbox'"
|
|
411
484
|
:class="{ 'no-label': !hasLabel }"
|
|
412
485
|
v-bind="$attrs"
|
|
486
|
+
:name="name || undefined"
|
|
413
487
|
:maxlength="_maxlength"
|
|
414
488
|
:disabled="isDisabled"
|
|
415
489
|
:aria-disabled="isDisabled"
|
|
@@ -464,6 +538,10 @@ export default defineComponent({
|
|
|
464
538
|
</div>
|
|
465
539
|
</template>
|
|
466
540
|
<style scoped lang="scss">
|
|
541
|
+
.multiline-password:not(:focus) {
|
|
542
|
+
-webkit-text-security: disc;
|
|
543
|
+
}
|
|
544
|
+
|
|
467
545
|
.labeled-input.view {
|
|
468
546
|
input {
|
|
469
547
|
text-overflow: ellipsis;
|
|
@@ -236,10 +236,13 @@ function clone_repo_test_extension_build() {
|
|
|
236
236
|
# Here we just add the extension that we want to include as a check (all our official extensions should be included here)
|
|
237
237
|
# Don't forget to add the unit tests exception to clone_repo_test_extension_build function if a new extension has those
|
|
238
238
|
# TODO: ISSUE #16858 - Reenable the tests as packages migrate to node version 24
|
|
239
|
-
|
|
239
|
+
clone_repo_test_extension_build "rancher" "kubewarden-ui" "kubewarden"
|
|
240
240
|
# clone_repo_test_extension_build "rancher" "elemental-ui" "elemental"
|
|
241
241
|
clone_repo_test_extension_build "neuvector" "manager-ext" "neuvector-ui-ext"
|
|
242
242
|
# clone_repo_test_extension_build "StackVista" "rancher-extension-stackstate" "observability"
|
|
243
|
-
|
|
243
|
+
clone_repo_test_extension_build "harvester" "harvester-ui-extension" "harvester"
|
|
244
|
+
clone_repo_test_extension_build "rancher" "ali-ui" "ali"
|
|
245
|
+
clone_repo_test_extension_build "rancher" "virtual-clusters-ui" "virtual-clusters"
|
|
246
|
+
# clone_repo_test_extension_build "rancher" "rancher-ai-ui" "rancher-ai-ui"
|
|
244
247
|
|
|
245
248
|
echo "All done"
|
package/scripts/typegen.sh
CHANGED
|
@@ -22,11 +22,13 @@ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/table-headers.js --declara
|
|
|
22
22
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/types.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
|
|
23
23
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/labels-annotations.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
|
|
24
24
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/version.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
|
|
25
|
+
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/product/*.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config/product > /dev/null
|
|
25
26
|
|
|
26
27
|
# # store
|
|
27
28
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/features.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
|
|
28
|
-
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/prefs.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
|
|
29
29
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/plugins.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
|
|
30
|
+
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/prefs.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
|
|
31
|
+
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/store-types.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
|
|
30
32
|
|
|
31
33
|
# # plugins
|
|
32
34
|
${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/i18n.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/ > /dev/null
|
|
@@ -93,6 +95,16 @@ function processDir() {
|
|
|
93
95
|
echo "declare module '${module}' {" >> ${INDEX}
|
|
94
96
|
cat $entry >> ${INDEX}
|
|
95
97
|
echo -e "}" >> ${INDEX}
|
|
98
|
+
|
|
99
|
+
# Also generate a module declaration with .js extension for JS source files
|
|
100
|
+
# TypeScript imports use .js extensions for JS files
|
|
101
|
+
if [ "${name}" != "index" ]; then
|
|
102
|
+
local moduleWithJs=${basePkg}/${name}.js
|
|
103
|
+
echo -e "\n// ${moduleWithJs}\n" >> ${INDEX}
|
|
104
|
+
echo "declare module '${moduleWithJs}' {" >> ${INDEX}
|
|
105
|
+
cat $entry >> ${INDEX}
|
|
106
|
+
echo -e "}" >> ${INDEX}
|
|
107
|
+
fi
|
|
96
108
|
fi
|
|
97
109
|
fi
|
|
98
110
|
done
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module.exports = function(req, res, next) {
|
|
2
|
-
// We do this redirect so that /verify-auth can work with both standalone
|
|
3
|
-
//
|
|
2
|
+
// We do this redirect so that /verify-auth can work with both standalone
|
|
3
|
+
// and hosted configurations.
|
|
4
4
|
if (req.url.includes('/verify-auth') || req.url.includes('/verify-auth-azure')) {
|
|
5
5
|
res.writeHead(301, { Location: req.url.replace(/verify-auth(-azure)?/, 'auth/verify') });
|
|
6
6
|
res.end();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This product was created by the inspirational people at Rancher by SUSE.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# ::::::::::::::::::::::::::::::;;;;;;;:::::::::::::::::::;:::::::::::::::::::
|
|
2
|
+
# ::::::::::::::::::::::;+xxxxxxxxxxxxxxxxxxxx+;:::::::::+xxx+::::::::::::::::
|
|
3
|
+
# :::::::::::::::::;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;::::+xxxxxxx+::::::::::::
|
|
4
|
+
# ::::::::::::::+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;+xxxxxxxxxxx+::::::::
|
|
5
|
+
# :::::::::::+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;::;++;:::::
|
|
6
|
+
# :::::::::+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx+::::::;+;::::
|
|
7
|
+
# :::::::;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::::;++:++::::
|
|
8
|
+
# ::::::+xxxxxxxxxx++xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx+::::;:;xx::::
|
|
9
|
+
# :::::+xxxxxx+;:::::::::;;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx+;;;+xxx;:::
|
|
10
|
+
# ::::;xxxxx+:::::::::::::::;+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx+;;+xxxxxxxx;:::
|
|
11
|
+
# ::::xxxxx;::::;+xxxxxx++::::;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx++++++++;::::
|
|
12
|
+
# ::::xxxx+::::;xxx+;;;+xxx;::::xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx+;;::::::
|
|
13
|
+
# ::::xxxx+::::+xx;:::::;+xx;::::xxxxxxxxxxxxxxxxxxxxxxx;:::;;;;;;;:::::::::::
|
|
14
|
+
# ::::xxxxx;:::+xx+::::::;xxx;::::xxxxxx;:::::::;;+xxxxx;:::::::::::::::::::::
|
|
15
|
+
# ::::;xxxx+;:::;++::::::;xxx;::::;xxxxx+;:::::::::;+xxxx;::::::::::::::::::::
|
|
16
|
+
# :::::+xxxx+;::::::::::;xxxx;:::::;+xxxxxx+;:::::::;+xxxxx+;:::::::::::::::::
|
|
17
|
+
# ::::::;xxxxx++;;:::;;+xxxx;:::::::::::::::::::::::::::::::::::::::::::::::::
|
|
18
|
+
# :::::::;+xxxxxxxxxxxxxxxx;::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
19
|
+
# :::::::::;++xxxxxxxxxx++::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
20
|
+
# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
21
|
+
# ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
22
|
+
# ::::::::;;;;;::::::::::;;:::::::::;;:::::::::;;;;;::::::::::::;;;;;;;;;:::::
|
|
23
|
+
# :::::+X&&$$$$&$+::::::x&$+:::::::X&X;:::::;X$&$$$$&$x;::::::x&&$$$$$$$$x::::
|
|
24
|
+
# ::::x&$X;::::x$&X:::::x&$+:::::::X&X;::::+$&$;::::+$$X;::::;&$;:::::::::::::
|
|
25
|
+
# :::;$&X;::::::::::::::x&$+:::::::X&X;::::X&$;::::::::::::::+&$::::::::::::::
|
|
26
|
+
# ::::x&&$X;;:::::::::::x&$+:::::::X&X;::::+$&&X+;:::::::::::+&$;:::::::::::::
|
|
27
|
+
# :::::;X$&&&&&&$;::::::x&$+:::::::X&X;::::::x$&&&&&&$+::::::+&&&&&&&&&&+:::::
|
|
28
|
+
# :::::::::::;x$&&$:::::x&$+:::::::X&X;::::::::::::+$&&$+::::+&$::::::::::::::
|
|
29
|
+
# :::::;::::::::X$&;::::+$$x:::::::$&X;:::::;::::::::x$$+::::+&$::::::::::::::
|
|
30
|
+
# :::;$&$X;:::;X$&$:::::;X&$X;:::x$&$+::::;X&$X;:::;x$&$+::::;&$x;;;;;;;;:::::
|
|
31
|
+
# :::::+X&&&&&&&X;::::::::+X$&&&&&$x;:::::::;X$&&&&&&$+:::::::;$&&&&&&&&&x::::
|
|
32
|
+
# :::::::::;;;::::::::::::::::;;:::::::::::::::::;;::::::::::::::::::::::::::;
|
|
33
|
+
User-Agent: *
|
|
34
|
+
Disallow: /
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
+
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
4
|
+
viewBox="0 0 305.3 143.2" style="enable-background:new 0 0 305.3 143.2;" xml:space="preserve">
|
|
5
|
+
<style type="text/css">
|
|
6
|
+
.st0{fill:#0876A9;}
|
|
7
|
+
</style>
|
|
8
|
+
<g>
|
|
9
|
+
<path class="st0" d="M305.2,31.5l-3.3-19.9C300.8,5.2,298.3,0,296.4,0c-2,0-3.6,5.3-3.6,11.8v5.2c0,6.5-5.3,11.8-11.8,11.8h-5.2
|
|
10
|
+
c-0.4,0-0.7,0-1.1,0V43c0.4,0,0.7,0,1.1,0h19.5C301.8,43.1,306.2,37.8,305.2,31.5"/>
|
|
11
|
+
<path class="st0" d="M258.3,14.6h-31.7c-0.3,0-0.5,0-0.8,0h-32.5c-0.4,0-0.8,0-1.1,0.1v-3c0-6.5-1.6-11.8-3.6-11.8
|
|
12
|
+
s-4.5,5.2-5.5,11.6l-3.3,19.9c-1.1,6.4,3.4,11.6,9.8,11.6h19.5c2,0,3.9-0.3,5.6-0.9c-0.6,3.3-3.5,5.9-7,5.9h-27.4
|
|
13
|
+
c-4.4,0-7.8-4-7.1-8.4L176,23c0.7-4.4-2.6-8.4-7.1-8.4H32.5c-2.9,0-5.4,1.7-6.5,4.2L0.3,58c-0.4,0.7-0.4,1.5,0.1,2.1l5,5.9
|
|
14
|
+
c0.6,0.7,1.7,0.8,2.5,0.2l17.5-13.8v83.6c0,4,3.2,7.2,7.2,7.2h38.7c4,0,7.2-3.2,7.2-7.2V107c0-4,3.2-7.2,7.2-7.2h96.7
|
|
15
|
+
c4,0,7.2,3.2,7.2,7.2v29.1c0,4,3.2,7.2,7.2,7.2h38.7c4,0,7.2-3.2,7.2-7.2v-31.3h-20.6c-6.5,0-11.8-5.3-11.8-11.8V72.9
|
|
16
|
+
c0-3.8,1.9-7.2,4.7-9.4v24c0,6.5,5.3,11.8,11.8,11.8h31.7c6.5,0,11.8-5.3,11.8-11.8V26.4C270.1,19.9,264.8,14.6,258.3,14.6"/>
|
|
17
|
+
</g>
|
|
18
|
+
</svg>
|