@rancher/shell 3.0.2-rc.5 → 3.0.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/nutanix.svg +12 -1
- package/assets/styles/base/_basic.scss +2 -1
- package/assets/styles/base/_helpers.scss +4 -0
- package/assets/styles/base/_variables.scss +2 -0
- package/assets/styles/global/_labeled-input.scss +5 -13
- package/assets/styles/global/_layout.scss +4 -1
- package/assets/styles/global/_select.scss +5 -0
- package/assets/styles/themes/_dark.scss +1 -3
- package/assets/styles/themes/_light.scss +5 -1
- package/assets/translations/en-us.yaml +130 -23
- package/assets/translations/zh-hans.yaml +0 -3
- package/cloud-credential/azure.vue +1 -1
- package/components/ActionMenuShell.vue +105 -0
- package/components/AppModal.vue +2 -2
- package/components/AsyncButton.vue +2 -0
- package/components/ButtonGroup.vue +9 -2
- package/components/ClusterBadge.vue +1 -0
- package/components/ClusterIconMenu.vue +3 -0
- package/components/ClusterProviderIcon.vue +14 -1
- package/components/CodeMirror.vue +96 -5
- package/components/Collapse.vue +16 -3
- package/components/CruResource.vue +9 -0
- package/components/CruResourceFooter.vue +1 -1
- package/components/ExplorerMembers.vue +2 -1
- package/components/FixedBanner.vue +19 -12
- package/components/Import.vue +14 -1
- package/components/LandingPagePreference.vue +4 -2
- package/components/PodSecurityAdmission.vue +8 -6
- package/components/PromptChangePassword.vue +1 -0
- package/components/PromptRemove.vue +23 -21
- package/components/ResourceDetail/Masthead.vue +30 -11
- package/components/ResourceDetail/__tests__/Masthead.test.ts +61 -0
- package/components/ResourceDetail/index.vue +6 -0
- package/components/ResourceTable.vue +6 -1
- package/components/ResourceYaml.vue +1 -0
- package/components/Setting.vue +115 -0
- package/components/SortableTable/THead.vue +2 -0
- package/components/SortableTable/index.vue +7 -12
- package/components/StatusBadge.vue +71 -0
- package/components/Tabbed/index.vue +16 -15
- package/components/Wizard.vue +108 -104
- package/components/YamlEditor.vue +12 -2
- package/components/__tests__/Collapse.test.ts +2 -2
- package/components/__tests__/FixedBanner.test.ts +3 -3
- package/components/auth/Principal.vue +29 -17
- package/components/auth/__tests__/Principal.test.ts +40 -0
- package/components/auth/login/ldap.vue +7 -0
- package/components/fleet/FleetBundles.vue +1 -1
- package/components/fleet/FleetRepos.vue +1 -1
- package/components/fleet/FleetResources.vue +0 -2
- package/components/fleet/FleetSummary.vue +60 -65
- package/components/fleet/ForceDirectedTreeChart/index.vue +5 -1
- package/components/fleet/__tests__/FleetSummary.test.ts +49 -9
- package/components/form/ArrayList.vue +6 -2
- package/components/form/ColorInput.vue +1 -0
- package/components/form/KeyValue.vue +11 -12
- package/components/form/LabeledSelect.vue +15 -3
- package/components/form/Labels.vue +8 -1
- package/components/form/Members/MembershipEditor.vue +230 -222
- package/components/form/Members/__tests__/MembershipEditor.test.ts +62 -0
- package/components/form/Password.vue +3 -0
- package/components/form/ProjectMemberEditor.vue +6 -3
- package/components/form/ResourceTabs/index.vue +15 -13
- package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +5 -4
- package/components/form/SchedulingCustomization.vue +85 -0
- package/components/form/Select.vue +3 -2
- package/components/form/SelectOrCreateAuthSecret.vue +2 -1
- package/components/form/UnitInput.vue +3 -4
- package/components/form/__tests__/ArrayList.test.ts +9 -6
- package/components/form/__tests__/LabeledSelect.test.ts +37 -0
- package/components/form/__tests__/SelectOrCreateAuthSecret.test.ts +34 -0
- package/components/form/__tests__/UnitInput.test.ts +4 -5
- package/components/formatter/LiveDate.vue +3 -1
- package/components/formatter/ServiceType.vue +12 -4
- package/components/formatter/WorkloadHealthScale.vue +2 -1
- package/components/nav/Header.vue +35 -2
- package/components/nav/HeaderPageActionMenu.vue +11 -40
- package/components/nav/Jump.vue +8 -2
- package/components/nav/NamespaceFilter.vue +5 -4
- package/components/nav/Pinned.vue +1 -1
- package/components/nav/TopLevelMenu.helper.ts +5 -5
- package/components/nav/TopLevelMenu.vue +1 -12
- package/components/nav/WindowManager/ContainerLogs.vue +96 -58
- package/components/nav/WindowManager/ContainerShell.vue +99 -18
- package/components/nav/WindowManager/index.vue +74 -6
- package/components/nav/__tests__/TopLevelMenu.test.ts +0 -40
- package/components/templates/default.vue +2 -47
- package/config/features.js +1 -0
- package/config/labels-annotations.js +11 -1
- package/config/router/navigation-guards/index.js +2 -1
- package/config/router/navigation-guards/record-last-route.js +24 -0
- package/config/settings.ts +66 -98
- package/config/version.js +1 -1
- package/core/types-provisioning.ts +7 -0
- package/detail/fleet.cattle.io.bundle.vue +7 -0
- package/detail/fleet.cattle.io.cluster.vue +0 -3
- package/detail/fleet.cattle.io.gitrepo.vue +8 -15
- package/detail/provisioning.cattle.io.cluster.vue +8 -2
- package/dialog/DeactivateDriverDialog.vue +5 -5
- package/dialog/GitRepoForceUpdateDialog.vue +132 -0
- package/directives/strip-html-aria-label.js +19 -0
- package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +87 -0
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +217 -37
- package/edit/auth/__tests__/oidc.test.ts +60 -12
- package/edit/auth/ldap/__tests__/config.test.ts +40 -0
- package/edit/auth/ldap/config.vue +67 -89
- package/edit/auth/oidc.vue +16 -2
- package/edit/catalog.cattle.io.clusterrepo.vue +12 -8
- package/edit/cis.cattle.io.clusterscan.vue +13 -1
- package/edit/fleet.cattle.io.gitrepo.vue +198 -72
- package/edit/logging-flow/Match.vue +0 -21
- package/edit/management.cattle.io.project.vue +1 -1
- package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +10 -3
- package/edit/monitoring.coreos.com.prometheusrule/RecordingRule.vue +5 -1
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +5 -2
- package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +8 -1
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +2 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +0 -2
- package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +55 -15
- package/edit/provisioning.cattle.io.cluster/index.vue +28 -30
- package/edit/provisioning.cattle.io.cluster/rke2.vue +64 -13
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +37 -2
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +3 -2
- package/edit/resources.cattle.io.backup.vue +150 -15
- package/edit/secret/__tests__/ssh.test.ts +79 -0
- package/edit/secret/ssh.vue +7 -1
- package/edit/service.vue +0 -3
- package/edit/workload/Job.vue +8 -8
- package/edit/workload/__tests__/Job.test.ts +0 -1
- package/edit/workload/index.vue +3 -1
- package/initialize/install-directives.js +2 -0
- package/initialize/install-plugins.js +6 -1
- package/list/catalog.cattle.io.app.vue +21 -4
- package/list/fleet.cattle.io.bundle.vue +1 -1
- package/list/management.cattle.io.setting.vue +34 -132
- package/list/provisioning.cattle.io.cluster.vue +11 -3
- package/machine-config/vmwarevsphere.vue +15 -8
- package/mixins/__tests__/auth-config.test.ts +74 -0
- package/mixins/__tests__/chart.test.ts +5 -4
- package/mixins/__tests__/create-edit-view.test.ts +38 -0
- package/mixins/auth-config.js +8 -0
- package/mixins/chart.js +2 -2
- package/mixins/create-edit-view/impl.js +4 -1
- package/mixins/vue-select-overrides.js +10 -0
- package/models/__tests__/catalog.cattle.io.app.test.ts +148 -0
- package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +157 -0
- package/models/__tests__/secret.test.ts +56 -13
- package/models/catalog.cattle.io.app.js +112 -37
- package/models/cluster.js +11 -0
- package/models/fleet.cattle.io.bundle.js +40 -2
- package/models/fleet.cattle.io.gitrepo.js +169 -109
- package/models/management.cattle.io.fleetworkspace.js +4 -0
- package/models/management.cattle.io.kontainerdriver.js +7 -0
- package/models/nodedriver.js +4 -1
- package/models/provisioning.cattle.io.cluster.js +24 -0
- package/models/secret.js +1 -1
- package/package.json +5 -5
- package/pages/auth/login.vue +5 -11
- package/pages/auth/verify.vue +11 -1
- package/pages/c/_cluster/apps/charts/index.vue +6 -4
- package/pages/c/_cluster/apps/charts/install.vue +1 -1
- package/pages/c/_cluster/explorer/ConfigBadge.vue +3 -5
- package/pages/c/_cluster/explorer/EventsTable.vue +3 -2
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +9 -9
- package/pages/c/_cluster/explorer/index.vue +33 -35
- package/pages/c/_cluster/explorer/tools/index.vue +3 -3
- package/pages/c/_cluster/fleet/index.vue +0 -5
- package/pages/c/_cluster/legacy/project/index.vue +1 -1
- package/pages/c/_cluster/settings/performance.vue +52 -53
- package/pages/c/_cluster/uiplugins/index.vue +19 -22
- package/pages/home.vue +17 -12
- package/pages/prefs.vue +5 -1
- package/plugins/shortkey.js +10 -1
- package/plugins/steve/steve-pagination-utils.ts +58 -8
- package/promptRemove/management.cattle.io.fleetworkspace.vue +98 -0
- package/promptRemove/management.cattle.io.globalrole.vue +1 -1
- package/promptRemove/management.cattle.io.project.vue +2 -8
- package/promptRemove/management.cattle.io.roletemplate.vue +1 -1
- package/promptRemove/mixin/roleDeletionCheck.js +1 -7
- package/promptRemove/pod.vue +7 -28
- package/rancher-components/Card/Card.vue +9 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +42 -6
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +30 -3
- package/rancher-components/Form/Radio/RadioButton.vue +18 -3
- package/rancher-components/Form/Radio/RadioGroup.vue +39 -5
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +13 -1
- package/rancher-components/RcButton/RcButton.test.ts +97 -0
- package/rancher-components/RcButton/RcButton.vue +14 -9
- package/rancher-components/RcDropdown/RcDropdown.vue +3 -1
- package/rancher-components/RcDropdown/RcDropdownItem.vue +8 -2
- package/rancher-components/RcDropdown/RcDropdownMenu.vue +66 -0
- package/rancher-components/RcDropdown/index.ts +1 -0
- package/rancher-components/RcDropdown/types.ts +27 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +5 -2
- package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +2 -2
- package/scripts/typegen.sh +1 -0
- package/store/__tests__/auth.test.ts +120 -0
- package/store/action-menu.js +13 -3
- package/store/auth.js +14 -9
- package/store/aws.js +9 -2
- package/store/catalog.js +14 -7
- package/store/features.js +1 -0
- package/store/prefs.js +9 -28
- package/store/type-map.utils.ts +4 -0
- package/types/resources/settings.d.ts +27 -20
- package/types/shell/index.d.ts +18 -12
- package/utils/__tests__/array.test.ts +13 -1
- package/utils/__tests__/string.test.ts +80 -1
- package/utils/array.ts +13 -0
- package/utils/auth.js +4 -0
- package/utils/banners.js +0 -45
- package/utils/cluster.js +1 -1
- package/{edit/monitoring.coreos.com.prometheusrule → utils}/duration.js +5 -3
- package/utils/object.js +0 -3
- package/utils/pagination-utils.ts +15 -2
- package/utils/string.js +31 -7
- package/utils/validators/formRules/__tests__/index.test.ts +27 -0
- package/utils/validators/formRules/index.ts +16 -0
- package/edit/provisioning.cattle.io.cluster/import.vue +0 -198
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ActionFindPageArgs } from '@shell/types/store/dashboard-store.types';
|
|
2
2
|
import { PaginationParam, PaginationFilterField, PaginationParamProjectOrNamespace, PaginationParamFilter } from '@shell/types/store/pagination.types';
|
|
3
3
|
import { NAMESPACE_FILTER_ALL_SYSTEM, NAMESPACE_FILTER_ALL_USER, NAMESPACE_FILTER_P_FULL_PREFIX } from '@shell/utils/namespace-filter';
|
|
4
|
-
import
|
|
4
|
+
import ModelNamespace from '@shell/models/namespace';
|
|
5
5
|
import { uniq } from '@shell/utils/array';
|
|
6
6
|
import {
|
|
7
7
|
CAPI,
|
|
@@ -12,10 +12,21 @@ import {
|
|
|
12
12
|
SERVICE,
|
|
13
13
|
INGRESS,
|
|
14
14
|
WORKLOAD_TYPES,
|
|
15
|
-
HPA
|
|
15
|
+
HPA,
|
|
16
|
+
SECRET
|
|
16
17
|
} from '@shell/config/types';
|
|
17
|
-
import { CAPI as
|
|
18
|
+
import { CAPI as CAPI_LAB_AND_ANO, CATTLE_PUBLIC_ENDPOINTS } from '@shell/config/labels-annotations';
|
|
18
19
|
import { Schema } from '@shell/plugins/steve/schema';
|
|
20
|
+
import { PaginationSettingsStore } from '@shell/types/resources/settings';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* This is a workaround for a ts build issue found in check-plugins-build.
|
|
24
|
+
*
|
|
25
|
+
* The build would error on <ns>.name, it somehow doesn't know about the steve model's properties (they are included in typegen)
|
|
26
|
+
*/
|
|
27
|
+
interface Namespace extends ModelNamespace {
|
|
28
|
+
name: string;
|
|
29
|
+
}
|
|
19
30
|
|
|
20
31
|
class NamespaceProjectFilters {
|
|
21
32
|
/**
|
|
@@ -141,8 +152,8 @@ class StevePaginationUtils extends NamespaceProjectFilters {
|
|
|
141
152
|
{ field: 'spec.internal' },
|
|
142
153
|
{ field: 'spec.displayName' },
|
|
143
154
|
{ field: `status.provider` },
|
|
144
|
-
{ field: `metadata.labels
|
|
145
|
-
|
|
155
|
+
{ field: `metadata.labels["${ CAPI_LAB_AND_ANO.PROVIDER }]` },
|
|
156
|
+
{ field: `status.connected` },
|
|
146
157
|
],
|
|
147
158
|
[CONFIG_MAP]: [
|
|
148
159
|
{ field: 'metadata.labels[harvesterhci.io/cloud-init-template]' }
|
|
@@ -171,9 +182,10 @@ class StevePaginationUtils extends NamespaceProjectFilters {
|
|
|
171
182
|
{ field: 'status.releaseName' },
|
|
172
183
|
],
|
|
173
184
|
[CAPI.RANCHER_CLUSTER]: [
|
|
174
|
-
{ field: `metadata.labels
|
|
185
|
+
{ field: `metadata.labels[${ CAPI_LAB_AND_ANO.PROVIDER }]` },
|
|
175
186
|
{ field: `status.provider` },
|
|
176
187
|
{ field: 'status.clusterName' },
|
|
188
|
+
{ field: `metadata.annotations[${ CAPI_LAB_AND_ANO.HUMAN_NAME }]` }
|
|
177
189
|
],
|
|
178
190
|
[SERVICE]: [
|
|
179
191
|
{ field: 'spec.type' },
|
|
@@ -433,9 +445,14 @@ class StevePaginationUtils extends NamespaceProjectFilters {
|
|
|
433
445
|
this.validateField(validateFields, schema, field.field);
|
|
434
446
|
|
|
435
447
|
const value = encodeURIComponent(field.value);
|
|
436
|
-
const exactPartial = field.exact ? `'${ value }'` : value;
|
|
437
448
|
|
|
438
|
-
|
|
449
|
+
// = exact match (equals + exact)
|
|
450
|
+
// ~ partial match (equals + !exact)
|
|
451
|
+
// != not exact match (!equals + exact)
|
|
452
|
+
// !~ not partial match (!equals + !exact)
|
|
453
|
+
const operator = `${ field.equals ? '' : '!' }${ field.exact ? '=' : '~' }`;
|
|
454
|
+
|
|
455
|
+
return `${ this.convertArrayPath(field.field) }${ operator }${ value }`;
|
|
439
456
|
}
|
|
440
457
|
|
|
441
458
|
return field.value;
|
|
@@ -460,4 +477,37 @@ class StevePaginationUtils extends NamespaceProjectFilters {
|
|
|
460
477
|
}
|
|
461
478
|
}
|
|
462
479
|
|
|
480
|
+
export const PAGINATION_SETTINGS_STORE_DEFAULTS: PaginationSettingsStore = {
|
|
481
|
+
cluster: {
|
|
482
|
+
resources: {
|
|
483
|
+
enableAll: false,
|
|
484
|
+
enableSome: {
|
|
485
|
+
// if a resource list is shown by a custom resource list component or has specific list headers then it's not generically shown
|
|
486
|
+
// and must be included here.
|
|
487
|
+
enabled: [
|
|
488
|
+
NODE, EVENT,
|
|
489
|
+
WORKLOAD_TYPES.CRON_JOB, WORKLOAD_TYPES.DAEMON_SET, WORKLOAD_TYPES.DEPLOYMENT, WORKLOAD_TYPES.JOB, WORKLOAD_TYPES.STATEFUL_SET, POD,
|
|
490
|
+
CATALOG.APP, CATALOG.CLUSTER_REPO, CATALOG.OPERATION,
|
|
491
|
+
HPA, INGRESS, SERVICE,
|
|
492
|
+
PV, CONFIG_MAP, STORAGE_CLASS, PVC, SECRET,
|
|
493
|
+
WORKLOAD_TYPES.REPLICA_SET, WORKLOAD_TYPES.REPLICATION_CONTROLLER
|
|
494
|
+
],
|
|
495
|
+
generic: true,
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
management: {
|
|
500
|
+
resources: {
|
|
501
|
+
enableAll: false,
|
|
502
|
+
enableSome: {
|
|
503
|
+
enabled: [
|
|
504
|
+
{ resource: CAPI.RANCHER_CLUSTER, context: ['home', 'side-bar'] },
|
|
505
|
+
{ resource: MANAGEMENT.CLUSTER, context: ['side-bar'] },
|
|
506
|
+
],
|
|
507
|
+
generic: false,
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
|
|
463
513
|
export default new StevePaginationUtils();
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { exceptionToErrorsArray } from '@shell/utils/error';
|
|
3
|
+
import { resourceNames } from '@shell/utils/string';
|
|
4
|
+
import { Banner } from '@components/Banner';
|
|
5
|
+
import { mapGetters, mapState } from 'vuex';
|
|
6
|
+
import { getVendor } from '@shell/config/private-label';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
name: 'PromptRemoveFleetWorkspacesDialog',
|
|
10
|
+
|
|
11
|
+
emits: ['errors'],
|
|
12
|
+
|
|
13
|
+
components: { Banner },
|
|
14
|
+
|
|
15
|
+
props: {
|
|
16
|
+
value: {
|
|
17
|
+
type: Array,
|
|
18
|
+
default: () => {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
names: {
|
|
24
|
+
type: Array,
|
|
25
|
+
default: () => {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
type: {
|
|
31
|
+
type: String,
|
|
32
|
+
required: true
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
close: {
|
|
36
|
+
type: Function,
|
|
37
|
+
required: true
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
data() {
|
|
42
|
+
return {
|
|
43
|
+
vendor: getVendor(),
|
|
44
|
+
errors: []
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
computed: {
|
|
49
|
+
...mapState('action-menu', ['toRemove']),
|
|
50
|
+
...mapGetters({ t: 'i18n/t' }),
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
methods: {
|
|
54
|
+
resourceNames,
|
|
55
|
+
async remove(buttonDone) {
|
|
56
|
+
try {
|
|
57
|
+
await Promise.all(this.value.map((resource) => resource.remove()));
|
|
58
|
+
|
|
59
|
+
this.close(buttonDone);
|
|
60
|
+
} catch (err) {
|
|
61
|
+
this.errors = exceptionToErrorsArray(err);
|
|
62
|
+
buttonDone(false);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
<template>
|
|
71
|
+
<div class="mt-10">
|
|
72
|
+
<div class="mb-10">
|
|
73
|
+
{{ t('promptRemove.attemptingToRemove', { type }) }} <span
|
|
74
|
+
v-clean-html="resourceNames(names, t)"
|
|
75
|
+
class="description"
|
|
76
|
+
/>
|
|
77
|
+
</div>
|
|
78
|
+
<Banner
|
|
79
|
+
color="warning"
|
|
80
|
+
class="warning"
|
|
81
|
+
>
|
|
82
|
+
<span v-clean-html="t('fleet.workspaces.remove.warning', {}, true)" />
|
|
83
|
+
</Banner>
|
|
84
|
+
<Banner
|
|
85
|
+
v-for="(error, i) in errors"
|
|
86
|
+
:key="i"
|
|
87
|
+
class=""
|
|
88
|
+
color="error"
|
|
89
|
+
:label="error"
|
|
90
|
+
/>
|
|
91
|
+
</div>
|
|
92
|
+
</template>
|
|
93
|
+
|
|
94
|
+
<style lang='scss' scoped>
|
|
95
|
+
.description {
|
|
96
|
+
font-weight: 600;
|
|
97
|
+
}
|
|
98
|
+
</style>
|
|
@@ -21,7 +21,7 @@ export default {
|
|
|
21
21
|
|
|
22
22
|
<template>
|
|
23
23
|
<div>
|
|
24
|
-
{{ t('promptRemove.attemptingToRemove', { type }) }} <span v-clean-html="resourceNames(names,
|
|
24
|
+
{{ t('promptRemove.attemptingToRemove', { type }) }} <span v-clean-html="resourceNames(names, t)" />
|
|
25
25
|
<div
|
|
26
26
|
v-if="info"
|
|
27
27
|
class="text info mb-10 mt-20"
|
|
@@ -58,12 +58,6 @@ export default {
|
|
|
58
58
|
return [];
|
|
59
59
|
},
|
|
60
60
|
|
|
61
|
-
plusMore() {
|
|
62
|
-
const remaining = this.filteredNamespaces.length > 5 ? this.filteredNamespaces.length - 5 : 0;
|
|
63
|
-
|
|
64
|
-
return this.t('promptRemove.andOthers', { count: remaining });
|
|
65
|
-
},
|
|
66
|
-
|
|
67
61
|
displayName() {
|
|
68
62
|
return this.currentProject?.spec?.displayName;
|
|
69
63
|
},
|
|
@@ -100,7 +94,7 @@ export default {
|
|
|
100
94
|
<template v-if="!canSeeProjectlessNamespaces">
|
|
101
95
|
<span class="delete-warning"> {{ t('promptRemove.willDeleteAssociatedNamespaces') }}</span> <br>
|
|
102
96
|
<div
|
|
103
|
-
v-clean-html="resourceNames(names,
|
|
97
|
+
v-clean-html="resourceNames(names, t)"
|
|
104
98
|
class="mt-10"
|
|
105
99
|
/>
|
|
106
100
|
</template>
|
|
@@ -114,7 +108,7 @@ export default {
|
|
|
114
108
|
:label="t('promptRemove.deleteAssociatedNamespaces')"
|
|
115
109
|
/>
|
|
116
110
|
<div class="mt-10 ml-20">
|
|
117
|
-
<span v-clean-html="resourceNames(names,
|
|
111
|
+
<span v-clean-html="resourceNames(names, t)" />
|
|
118
112
|
</div>
|
|
119
113
|
</div>
|
|
120
114
|
</div>
|
|
@@ -17,13 +17,7 @@ export default {
|
|
|
17
17
|
...mapGetters({ t: 'i18n/t' }),
|
|
18
18
|
|
|
19
19
|
names() {
|
|
20
|
-
return this.toRemove.map((obj) => obj.nameDisplay)
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
plusMore() {
|
|
24
|
-
const remaining = this.toRemove.length - this.names.length;
|
|
25
|
-
|
|
26
|
-
return this.t('promptRemove.andOthers', { count: remaining });
|
|
20
|
+
return this.toRemove.map((obj) => obj.nameDisplay);
|
|
27
21
|
},
|
|
28
22
|
},
|
|
29
23
|
watch: {
|
package/promptRemove/pod.vue
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import { resourceNames } from '@shell/utils/string';
|
|
2
3
|
import { Banner } from '@components/Banner';
|
|
3
4
|
import Checkbox from '@components/Form/Checkbox/Checkbox.vue';
|
|
4
5
|
import { mapGetters, mapState } from 'vuex';
|
|
@@ -55,31 +56,10 @@ export default {
|
|
|
55
56
|
computed: {
|
|
56
57
|
...mapState('action-menu', ['toRemove']),
|
|
57
58
|
...mapGetters({ t: 'i18n/t' }),
|
|
58
|
-
|
|
59
|
-
plusMore() {
|
|
60
|
-
const count = this.names.length - this.names.length;
|
|
61
|
-
|
|
62
|
-
return this.t('promptRemove.andOthers', { count });
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
podNames() {
|
|
66
|
-
return this.names.reduce((res, name, i) => {
|
|
67
|
-
if (i >= 5) {
|
|
68
|
-
return res;
|
|
69
|
-
}
|
|
70
|
-
res += `<b>${ name }</b>`;
|
|
71
|
-
if (i === this.names.length - 1) {
|
|
72
|
-
res += this.plusMore;
|
|
73
|
-
} else {
|
|
74
|
-
res += i === this.toRemove.length - 2 ? ' and ' : ', ';
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return res;
|
|
78
|
-
}, '');
|
|
79
|
-
},
|
|
80
59
|
},
|
|
81
60
|
|
|
82
61
|
methods: {
|
|
62
|
+
resourceNames,
|
|
83
63
|
async remove(confirm) {
|
|
84
64
|
let goTo;
|
|
85
65
|
|
|
@@ -118,8 +98,8 @@ export default {
|
|
|
118
98
|
<div class="mt-10">
|
|
119
99
|
<div class="mb-30">
|
|
120
100
|
{{ t('promptRemove.attemptingToRemove', { type }) }} <span
|
|
121
|
-
v-clean-html="
|
|
122
|
-
class="
|
|
101
|
+
v-clean-html="resourceNames(names, t)"
|
|
102
|
+
class="body"
|
|
123
103
|
/>
|
|
124
104
|
</div>
|
|
125
105
|
<div class="mb-30">
|
|
@@ -143,11 +123,10 @@ export default {
|
|
|
143
123
|
</template>
|
|
144
124
|
|
|
145
125
|
<style lang='scss' scoped>
|
|
126
|
+
.body {
|
|
127
|
+
font-weight: 600;
|
|
128
|
+
}
|
|
146
129
|
.actions {
|
|
147
130
|
text-align: right;
|
|
148
131
|
}
|
|
149
|
-
|
|
150
|
-
.machine-name {
|
|
151
|
-
font-weight: 600;
|
|
152
|
-
}
|
|
153
132
|
</style>
|
|
@@ -59,7 +59,15 @@ export default defineComponent({
|
|
|
59
59
|
},
|
|
60
60
|
setup(props) {
|
|
61
61
|
if (props.triggerFocusTrap) {
|
|
62
|
-
useBasicSetupFocusTrap('#focus-trap-card-container-element'
|
|
62
|
+
useBasicSetupFocusTrap('#focus-trap-card-container-element', {
|
|
63
|
+
// needs to be false because of import YAML modal from header
|
|
64
|
+
// where the YAML editor itself is a focus trap
|
|
65
|
+
// and we can't have it superseed the "escape key" to blur that UI element
|
|
66
|
+
// In this case the focus trap moves the focus out of the modal
|
|
67
|
+
// correctly once it closes because of the "onBeforeUnmount" trigger
|
|
68
|
+
escapeDeactivates: false,
|
|
69
|
+
allowOutsideClick: true,
|
|
70
|
+
});
|
|
63
71
|
}
|
|
64
72
|
}
|
|
65
73
|
});
|
|
@@ -3,6 +3,7 @@ import { PropType, defineComponent } from 'vue';
|
|
|
3
3
|
import { _EDIT, _VIEW } from '@shell/config/query-params';
|
|
4
4
|
import { addObject, removeObject } from '@shell/utils/array';
|
|
5
5
|
import cloneDeep from 'lodash/cloneDeep';
|
|
6
|
+
import { generateRandomAlphaString } from '@shell/utils/string';
|
|
6
7
|
|
|
7
8
|
export default defineComponent({
|
|
8
9
|
name: 'Checkbox',
|
|
@@ -37,7 +38,7 @@ export default defineComponent({
|
|
|
37
38
|
*/
|
|
38
39
|
id: {
|
|
39
40
|
type: String,
|
|
40
|
-
default:
|
|
41
|
+
default: generateRandomAlphaString(12)
|
|
41
42
|
},
|
|
42
43
|
|
|
43
44
|
/**
|
|
@@ -113,7 +114,16 @@ export default defineComponent({
|
|
|
113
114
|
primary: {
|
|
114
115
|
type: Boolean,
|
|
115
116
|
default: false
|
|
116
|
-
}
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Use this for usage of checkboxes that don't present a label.
|
|
121
|
+
* Used for cases such as table checkboxes (group or row)
|
|
122
|
+
*/
|
|
123
|
+
alternateLabel: {
|
|
124
|
+
type: String,
|
|
125
|
+
default: undefined
|
|
126
|
+
},
|
|
117
127
|
},
|
|
118
128
|
|
|
119
129
|
emits: ['update:value'],
|
|
@@ -143,6 +153,18 @@ export default defineComponent({
|
|
|
143
153
|
hasTooltip(): boolean {
|
|
144
154
|
return !!this.tooltip || !!this.tooltipKey;
|
|
145
155
|
},
|
|
156
|
+
|
|
157
|
+
replacementLabel(): string | undefined {
|
|
158
|
+
if (!this.label && !this.labelKey && this.alternateLabel) {
|
|
159
|
+
return this.alternateLabel;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return undefined;
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
idForLabel():string {
|
|
166
|
+
return `${ this.id }-label`;
|
|
167
|
+
}
|
|
146
168
|
},
|
|
147
169
|
|
|
148
170
|
methods: {
|
|
@@ -228,17 +250,16 @@ export default defineComponent({
|
|
|
228
250
|
<label
|
|
229
251
|
class="checkbox-container"
|
|
230
252
|
:class="{ 'disabled': isDisabled}"
|
|
231
|
-
:for="id"
|
|
232
253
|
@keydown.enter.prevent="clicked($event)"
|
|
233
254
|
@keydown.space.prevent="clicked($event)"
|
|
234
255
|
@click="clicked($event)"
|
|
235
256
|
>
|
|
236
257
|
<input
|
|
258
|
+
:id="id"
|
|
237
259
|
:checked="isChecked"
|
|
238
260
|
:value="valueWhenTrue"
|
|
239
261
|
type="checkbox"
|
|
240
262
|
tabindex="-1"
|
|
241
|
-
:name="id"
|
|
242
263
|
@click.stop.prevent
|
|
243
264
|
@keyup.enter.stop.prevent
|
|
244
265
|
>
|
|
@@ -246,8 +267,9 @@ export default defineComponent({
|
|
|
246
267
|
class="checkbox-custom"
|
|
247
268
|
:class="{indeterminate: indeterminate}"
|
|
248
269
|
:tabindex="isDisabled ? -1 : 0"
|
|
249
|
-
:aria-label="
|
|
270
|
+
:aria-label="replacementLabel"
|
|
250
271
|
:aria-checked="!!value"
|
|
272
|
+
:aria-labelledby="labelKey || label ? idForLabel : undefined"
|
|
251
273
|
role="checkbox"
|
|
252
274
|
/>
|
|
253
275
|
<span
|
|
@@ -258,19 +280,25 @@ export default defineComponent({
|
|
|
258
280
|
<slot name="label">
|
|
259
281
|
<t
|
|
260
282
|
v-if="labelKey"
|
|
283
|
+
:id="idForLabel"
|
|
261
284
|
:k="labelKey"
|
|
262
285
|
:raw="true"
|
|
263
286
|
/>
|
|
264
|
-
<
|
|
287
|
+
<span
|
|
288
|
+
v-else-if="label"
|
|
289
|
+
:id="idForLabel"
|
|
290
|
+
>{{ label }}</span>
|
|
265
291
|
<i
|
|
266
292
|
v-if="tooltipKey"
|
|
267
293
|
v-clean-tooltip="{content: t(tooltipKey), triggers: ['hover', 'touch', 'focus']}"
|
|
294
|
+
v-stripped-aria-label="t(tooltipKey)"
|
|
268
295
|
class="checkbox-info icon icon-info icon-lg"
|
|
269
296
|
:tabindex="isDisabled ? -1 : 0"
|
|
270
297
|
/>
|
|
271
298
|
<i
|
|
272
299
|
v-else-if="tooltip"
|
|
273
300
|
v-clean-tooltip="{content: tooltip, triggers: ['hover', 'touch', 'focus']}"
|
|
301
|
+
v-stripped-aria-label="tooltip"
|
|
274
302
|
class="checkbox-info icon icon-info icon-lg"
|
|
275
303
|
:tabindex="isDisabled ? -1 : 0"
|
|
276
304
|
/>
|
|
@@ -289,6 +317,9 @@ export default defineComponent({
|
|
|
289
317
|
{{ description }}
|
|
290
318
|
</template>
|
|
291
319
|
</div>
|
|
320
|
+
<div class="checkbox-outer-container-extra">
|
|
321
|
+
<slot name="extra" />
|
|
322
|
+
</div>
|
|
292
323
|
</div>
|
|
293
324
|
</template>
|
|
294
325
|
|
|
@@ -305,6 +336,11 @@ $fontColor: var(--input-label);
|
|
|
305
336
|
margin-top: 5px;
|
|
306
337
|
opacity: 0.8;
|
|
307
338
|
}
|
|
339
|
+
&-extra {
|
|
340
|
+
font-size: 14px;
|
|
341
|
+
margin-left: 19px;
|
|
342
|
+
margin-top: 5px;
|
|
343
|
+
}
|
|
308
344
|
}
|
|
309
345
|
|
|
310
346
|
// NOTE: SortableTable depends on the names of this class, do not arbitrarily change.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { defineComponent, inject } from 'vue';
|
|
3
3
|
import TextAreaAutoGrow from '@components/Form/TextArea/TextAreaAutoGrow.vue';
|
|
4
4
|
import LabeledTooltip from '@components/LabeledTooltip/LabeledTooltip.vue';
|
|
5
|
-
import { escapeHtml } from '@shell/utils/string';
|
|
5
|
+
import { escapeHtml, generateRandomAlphaString } from '@shell/utils/string';
|
|
6
6
|
import cronstrue from 'cronstrue';
|
|
7
7
|
import { isValidCron } from 'cron-validator';
|
|
8
8
|
import { debounce } from 'lodash';
|
|
@@ -105,6 +105,15 @@ export default defineComponent({
|
|
|
105
105
|
class: {
|
|
106
106
|
type: String,
|
|
107
107
|
default: ''
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Optionally use this to comply with a11y IF there's no label
|
|
112
|
+
* associated with the input
|
|
113
|
+
*/
|
|
114
|
+
ariaLabel: {
|
|
115
|
+
type: String,
|
|
116
|
+
default: ''
|
|
108
117
|
}
|
|
109
118
|
},
|
|
110
119
|
|
|
@@ -139,6 +148,7 @@ export default defineComponent({
|
|
|
139
148
|
return {
|
|
140
149
|
updated: false,
|
|
141
150
|
validationErrors: '',
|
|
151
|
+
inputId: `input-${ generateRandomAlphaString(12) }`
|
|
142
152
|
};
|
|
143
153
|
},
|
|
144
154
|
|
|
@@ -240,6 +250,14 @@ export default defineComponent({
|
|
|
240
250
|
}
|
|
241
251
|
},
|
|
242
252
|
|
|
253
|
+
mounted() {
|
|
254
|
+
const id = this.$attrs?.id as string | undefined;
|
|
255
|
+
|
|
256
|
+
if (id) {
|
|
257
|
+
this.inputId = id;
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
|
|
243
261
|
created() {
|
|
244
262
|
/**
|
|
245
263
|
* Determines if the Labeled Input @input event should be debounced.
|
|
@@ -330,7 +348,10 @@ export default defineComponent({
|
|
|
330
348
|
}"
|
|
331
349
|
>
|
|
332
350
|
<slot name="label">
|
|
333
|
-
<label
|
|
351
|
+
<label
|
|
352
|
+
v-if="hasLabel"
|
|
353
|
+
:for="inputId"
|
|
354
|
+
>
|
|
334
355
|
<t
|
|
335
356
|
v-if="labelKey"
|
|
336
357
|
:k="labelKey"
|
|
@@ -349,8 +370,10 @@ export default defineComponent({
|
|
|
349
370
|
<slot name="field">
|
|
350
371
|
<TextAreaAutoGrow
|
|
351
372
|
v-if="type === 'multiline' || type === 'multiline-password'"
|
|
373
|
+
:id="inputId"
|
|
352
374
|
ref="value"
|
|
353
375
|
v-bind="$attrs"
|
|
376
|
+
v-stripped-aria-label="!hasLabel && ariaLabel ? ariaLabel : undefined"
|
|
354
377
|
:maxlength="_maxlength"
|
|
355
378
|
:disabled="isDisabled"
|
|
356
379
|
:value="value || ''"
|
|
@@ -363,7 +386,9 @@ export default defineComponent({
|
|
|
363
386
|
/>
|
|
364
387
|
<input
|
|
365
388
|
v-else
|
|
389
|
+
:id="inputId"
|
|
366
390
|
ref="value"
|
|
391
|
+
v-stripped-aria-label="!hasLabel && ariaLabel ? ariaLabel : undefined"
|
|
367
392
|
role="textbox"
|
|
368
393
|
:class="{ 'no-label': !hasLabel }"
|
|
369
394
|
v-bind="$attrs"
|
|
@@ -383,12 +408,14 @@ export default defineComponent({
|
|
|
383
408
|
</slot>
|
|
384
409
|
|
|
385
410
|
<slot name="suffix" />
|
|
411
|
+
<!-- informational tooltip about field -->
|
|
386
412
|
<LabeledTooltip
|
|
387
|
-
v-if="hasTooltip
|
|
413
|
+
v-if="hasTooltip"
|
|
388
414
|
:hover="hoverTooltip"
|
|
389
415
|
:value="tooltipValue"
|
|
390
416
|
:status="status"
|
|
391
417
|
/>
|
|
418
|
+
<!-- validation tooltip -->
|
|
392
419
|
<LabeledTooltip
|
|
393
420
|
v-if="!!validationMessage"
|
|
394
421
|
:hover="hoverTooltip"
|
|
@@ -68,6 +68,14 @@ export default defineComponent({
|
|
|
68
68
|
description: {
|
|
69
69
|
type: String,
|
|
70
70
|
default: null
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Prevent focus when using radio in the context of a Radio group
|
|
75
|
+
*/
|
|
76
|
+
preventFocusOnRadioGroups: {
|
|
77
|
+
type: Boolean,
|
|
78
|
+
default: false
|
|
71
79
|
}
|
|
72
80
|
},
|
|
73
81
|
|
|
@@ -111,7 +119,7 @@ export default defineComponent({
|
|
|
111
119
|
watch: {
|
|
112
120
|
value(neu) {
|
|
113
121
|
this.isChecked = this.val === neu;
|
|
114
|
-
if (this.isChecked) {
|
|
122
|
+
if (this.isChecked && !this.preventFocusOnRadioGroups) {
|
|
115
123
|
(this.$refs.custom as HTMLElement).focus();
|
|
116
124
|
}
|
|
117
125
|
}
|
|
@@ -136,7 +144,11 @@ export default defineComponent({
|
|
|
136
144
|
|
|
137
145
|
<template>
|
|
138
146
|
<label
|
|
139
|
-
:class="{
|
|
147
|
+
:class="{
|
|
148
|
+
'disabled': isDisabled,
|
|
149
|
+
'radio-container': true,
|
|
150
|
+
'radio-button-checked': isChecked
|
|
151
|
+
}"
|
|
140
152
|
@keydown.enter="clicked($event)"
|
|
141
153
|
@keydown.space="clicked($event)"
|
|
142
154
|
@click.stop="clicked($event)"
|
|
@@ -146,6 +158,7 @@ export default defineComponent({
|
|
|
146
158
|
:disabled="isDisabled"
|
|
147
159
|
:name="name"
|
|
148
160
|
:value="''+val"
|
|
161
|
+
:data-testid="label"
|
|
149
162
|
:checked="isChecked"
|
|
150
163
|
type="radio"
|
|
151
164
|
:tabindex="-1"
|
|
@@ -154,7 +167,7 @@ export default defineComponent({
|
|
|
154
167
|
<span
|
|
155
168
|
ref="custom"
|
|
156
169
|
:class="[ isDisabled ? 'text-muted' : '', 'radio-custom']"
|
|
157
|
-
:tabindex="isDisabled ? -1 : 0"
|
|
170
|
+
:tabindex="isDisabled || preventFocusOnRadioGroups ? -1 : 0"
|
|
158
171
|
:aria-label="label"
|
|
159
172
|
:aria-checked="isChecked"
|
|
160
173
|
role="radio"
|
|
@@ -220,9 +233,11 @@ $fontColor: var(--input-label);
|
|
|
220
233
|
display: inline-flex;
|
|
221
234
|
align-items: flex-start;
|
|
222
235
|
margin: 0;
|
|
236
|
+
left: -4px;
|
|
223
237
|
user-select: none;
|
|
224
238
|
border-radius: var(--border-radius);
|
|
225
239
|
padding-bottom: 5px;
|
|
240
|
+
padding-left: 4px;
|
|
226
241
|
|
|
227
242
|
&,
|
|
228
243
|
.radio-label,
|