@rancher/shell 0.3.0 → 0.3.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/styles/global/_button.scss +5 -1
- package/assets/styles/global/_columns.scss +4 -0
- package/assets/styles/global/_gauges.scss +1 -1
- package/assets/styles/global/_layout.scss +5 -2
- package/assets/styles/global/_select.scss +1 -4
- package/assets/styles/themes/_dark.scss +5 -4
- package/assets/styles/themes/_light.scss +4 -3
- package/assets/styles/themes/_suse.scss +1 -1
- package/assets/styles/vendor/vue-select.scss +4 -3
- package/assets/translations/en-us.yaml +673 -73
- package/assets/translations/zh-hans.yaml +720 -207
- package/chart/monitoring/steps/uninstall-v1.vue +2 -2
- package/cloud-credential/azure.vue +23 -0
- package/cloud-credential/harvester.vue +25 -62
- package/cloud-credential/pnap.vue +80 -0
- package/components/.DS_Store +0 -0
- package/components/ActionMenu.vue +28 -7
- package/components/AdvancedSection.vue +9 -2
- package/components/Alert.vue +2 -2
- package/components/ButtonDropdown.vue +0 -2
- package/components/ButtonGroup.vue +1 -0
- package/components/CollapsibleCard.vue +0 -1
- package/components/CruResource.vue +41 -4
- package/components/DetailTop.vue +72 -4
- package/components/DisableAuthProviderModal.vue +106 -0
- package/{rancher-components/components/Utils/DraggableZone → components}/DraggableZone.vue +0 -0
- package/components/ExplorerMembers.vue +253 -30
- package/components/ExplorerProjectsNamespaces.vue +77 -33
- package/components/ExtensionPanel.vue +42 -0
- package/components/GrowlManager.vue +3 -3
- package/components/IconOrSvg.vue +178 -0
- package/components/LogItem.vue +69 -0
- package/components/PodSecurityAdmission.vue +302 -0
- package/components/PromptModal.vue +1 -0
- package/components/ResourceDetail/Masthead.vue +69 -4
- package/components/ResourceDetail/index.vue +12 -5
- package/components/ResourceList/Masthead.vue +11 -1
- package/components/ResourceList/ResourceLoadingIndicator.vue +12 -2
- package/components/ResourceList/index.vue +66 -12
- package/components/ResourceList/resource-list.config.js +7 -0
- package/components/ResourceTable.vue +33 -6
- package/components/SimpleBox.vue +1 -1
- package/components/SortableTable/THead.vue +21 -14
- package/components/SortableTable/filtering.js +1 -1
- package/components/SortableTable/index.vue +21 -10
- package/components/SortableTable/selection.js +15 -3
- package/components/Tabbed/Tab.vue +1 -1
- package/components/Tabbed/index.vue +20 -15
- package/components/__tests__/.DS_Store +0 -0
- package/components/__tests__/AsyncButton.test.ts +140 -0
- package/components/__tests__/BackLink.test.ts +33 -0
- package/components/__tests__/ButtonGroup.test.ts +124 -0
- package/components/__tests__/ClusterBadge.test.ts +32 -0
- package/components/__tests__/CollapsibleCard.test.ts +64 -0
- package/components/__tests__/ConsumptionGauge.test.ts +88 -0
- package/components/__tests__/CruResource.test.ts +3 -2
- package/components/__tests__/FixedBanner.test.ts +129 -0
- package/components/__tests__/GrowlManager.test.ts +147 -0
- package/components/__tests__/NamespaceFilter.test.ts +33 -25
- package/components/__tests__/PercentageBar.test.ts +32 -0
- package/components/__tests__/PodSecurityAdmission.test.ts +398 -0
- package/components/auth/AuthBanner.vue +20 -10
- package/components/auth/RoleDetailEdit.vue +26 -17
- package/components/auth/SelectPrincipal.vue +36 -5
- package/components/form/ArrayList.vue +3 -35
- package/components/form/ArrayListGrouped.vue +13 -4
- package/components/form/ArrayListSelect.vue +5 -5
- package/components/form/Error.vue +8 -0
- package/components/form/KeyValue.vue +39 -7
- package/components/form/LabeledSelect.vue +5 -2
- package/components/form/Labels.vue +46 -16
- package/components/form/Members/ClusterPermissionsEditor.vue +17 -17
- package/components/form/Members/MembershipEditor.vue +12 -12
- package/components/form/NameNsDescription.vue +1 -1
- package/components/form/NodeScheduling.vue +1 -1
- package/components/form/Probe.vue +3 -3
- package/components/form/ResourceQuota/Project.vue +6 -6
- package/components/form/ResourceTabs/index.vue +24 -6
- package/components/form/Security.vue +7 -6
- package/components/form/Select.vue +3 -2
- package/components/form/SelectOrCreateAuthSecret.vue +22 -29
- package/components/form/ServicePorts.vue +8 -0
- package/components/form/WorkloadPorts.vue +7 -1
- package/components/form/__tests__/ArrayList.test.ts +74 -0
- package/components/form/__tests__/ArrayListGrouped.test.ts +6 -4
- package/components/formatter/Checked.vue +1 -1
- package/components/formatter/ClusterLink.vue +5 -0
- package/components/formatter/IconIsDefault.vue +2 -2
- package/components/formatter/InternalExternalIP.vue +11 -8
- package/components/formatter/LiveDuration.vue +78 -0
- package/components/formatter/WorkloadHealthScale.vue +5 -3
- package/components/nav/Header.vue +74 -7
- package/components/nav/NamespaceFilter.vue +146 -63
- package/components/nav/TopLevelMenu.vue +22 -19
- package/components/nav/WindowManager/ContainerLogs.vue +83 -126
- package/components/nav/WindowManager/ContainerShell.vue +9 -7
- package/components/nav/WindowManager/Window.vue +2 -0
- package/components/nav/WindowManager/index.vue +10 -0
- package/config/elemental-types.js +9 -0
- package/config/features.js +2 -0
- package/config/home-links.js +4 -1
- package/config/pod-security-admission.ts +82 -0
- package/config/product/apps.js +1 -1
- package/config/product/auth.js +6 -5
- package/config/product/backup.js +1 -1
- package/config/product/explorer.js +6 -6
- package/config/product/fleet.js +1 -1
- package/config/product/manager.js +6 -2
- package/config/query-params.js +1 -0
- package/config/secret.js +0 -1
- package/config/settings.ts +26 -9
- package/config/table-headers.js +22 -11
- package/config/types.js +4 -1
- package/config/uiplugins.js +3 -3
- package/content/docs/zh-hans/getting-started.md +113 -137
- package/content/docs/zh-hans/whats-new.md +8 -46
- package/core/plugin-helpers.js +171 -0
- package/core/plugin.ts +61 -1
- package/core/plugins.js +33 -0
- package/core/types.ts +128 -2
- package/creators/pkg/package-lock.json +37 -0
- package/creators/pkg/package.json +1 -1
- package/detail/catalog.cattle.io.app.vue +1 -1
- package/detail/pod.vue +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +35 -9
- package/detail/service.vue +2 -9
- package/detail/workload/index.vue +0 -1
- package/dialog/AddClusterMemberDialog.vue +22 -28
- package/dialog/AddProjectMemberDialog.vue +53 -9
- package/dialog/DiagnosticTimingsDialog.vue +8 -7
- package/dialog/DrainNode.vue +44 -48
- package/dialog/ForceMachineRemoveDialog.vue +5 -7
- package/dialog/GenericPrompt.vue +15 -20
- package/dialog/RollbackWorkloadDialog.vue +15 -46
- package/dialog/RotateCertificatesDialog.vue +5 -7
- package/dialog/RotateEncryptionKeyDialog.vue +5 -9
- package/dialog/SaveAsRKETemplateDialog.vue +5 -13
- package/dialog/ScaleMachineDownDialog.vue +1 -1
- package/dialog/ScalePoolDownDialog.vue +121 -0
- package/edit/__tests__/management.cattle.io.setting.test.ts +3 -3
- package/edit/auth/azuread.vue +16 -16
- package/edit/auth/github.vue +8 -0
- package/edit/auth/googleoauth.vue +10 -1
- package/edit/auth/ldap/index.vue +10 -0
- package/edit/auth/oidc.vue +10 -0
- package/edit/auth/saml.vue +10 -0
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -1
- package/edit/catalog.cattle.io.clusterrepo.vue +3 -0
- package/edit/cloudcredential.vue +3 -7
- package/edit/logging-flow/Match.vue +39 -8
- package/edit/logging-flow/index.vue +27 -4
- package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +107 -0
- package/edit/management.cattle.io.project.vue +8 -1
- package/edit/management.cattle.io.setting.vue +5 -2
- package/edit/management.cattle.io.user.vue +7 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +36 -8
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/email.vue +2 -2
- package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +14 -6
- package/edit/namespace.vue +18 -4
- package/edit/networking.k8s.io.ingress/Certificate.vue +1 -0
- package/edit/networking.k8s.io.ingress/IngressClass.vue +8 -6
- package/edit/networking.k8s.io.ingress/RulePath.vue +12 -6
- package/edit/networking.k8s.io.ingress/index.vue +8 -6
- package/edit/persistentvolume/index.vue +30 -27
- package/edit/persistentvolume/plugins/cephfs.vue +29 -29
- package/edit/persistentvolume/plugins/csi.vue +102 -62
- package/edit/persistentvolume/plugins/fc.vue +19 -19
- package/edit/persistentvolume/plugins/iscsi.vue +45 -45
- package/edit/persistentvolume/plugins/rbd.vue +39 -39
- package/edit/persistentvolumeclaim.vue +78 -75
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -7
- package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +10 -1
- package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +87 -27
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -6
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +96 -0
- package/edit/provisioning.cattle.io.cluster/import.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +29 -6
- package/edit/provisioning.cattle.io.cluster/rke2.vue +445 -154
- package/edit/secret/index.vue +3 -7
- package/edit/service.vue +3 -1
- package/edit/storage.k8s.io.storageclass/index.vue +100 -16
- package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +114 -0
- package/edit/workload/__tests__/index.test.ts +98 -0
- package/edit/workload/index.vue +58 -8
- package/edit/workload/mixins/workload.js +107 -70
- package/edit/workload/storage/ContainerMountPaths.vue +0 -10
- package/edit/workload/storage/emptyDir.vue +88 -0
- package/edit/workload/storage/ephemeralVolume/index.vue +1 -1
- package/edit/workload/storage/index.vue +8 -0
- package/edit/workload/storage/persistentVolumeClaim/index.vue +1 -1
- package/layouts/default.vue +57 -44
- package/list/__tests__/workload.test.ts +5 -2
- package/list/catalog.cattle.io.app.vue +1 -0
- package/list/cis.cattle.io.clusterscan.vue +1 -0
- package/list/fleet.cattle.io.bundle.vue +5 -6
- package/list/fleet.cattle.io.cluster.vue +6 -3
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +5 -6
- package/list/fleet.cattle.io.gitrepo.vue +4 -9
- package/list/helm.cattle.io.projecthelmchart.vue +1 -5
- package/list/logging.banzaicloud.io.clusterflow.vue +4 -1
- package/list/logging.banzaicloud.io.flow.vue +6 -5
- package/list/management.cattle.io.cluster.vue +1 -0
- package/list/management.cattle.io.feature.vue +3 -4
- package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +47 -0
- package/list/management.cattle.io.setting.vue +2 -2
- package/list/management.cattle.io.user.vue +4 -10
- package/list/monitoring.coreos.com.alertmanagerconfig.vue +2 -7
- package/list/node.vue +8 -5
- package/list/persistentvolume.vue +3 -3
- package/list/persistentvolumeclaim.vue +3 -4
- package/list/provisioning.cattle.io.cluster.vue +18 -19
- package/list/service.vue +6 -14
- package/list/workload.vue +43 -38
- package/machine-config/azure.vue +429 -60
- package/machine-config/pnap.vue +288 -0
- package/mixins/auth-config.js +1 -3
- package/mixins/browser-tab-visibility.js +8 -14
- package/mixins/chart.js +1 -1
- package/mixins/create-edit-view/impl.js +4 -0
- package/mixins/create-edit-view/index.js +4 -2
- package/mixins/resource-fetch-namespaced.js +98 -0
- package/mixins/resource-fetch.js +79 -45
- package/mixins/resource-manager.js +1 -23
- package/models/apps.controllerrevision.js +7 -0
- package/models/apps.daemonset.js +18 -0
- package/models/apps.deployment.js +44 -0
- package/models/apps.replicaset.js +7 -0
- package/models/apps.statefulset.js +18 -0
- package/models/batch.job.js +7 -14
- package/models/cluster/node.js +10 -2
- package/models/cluster.x-k8s.io.machine.js +26 -4
- package/models/cluster.x-k8s.io.machinedeployment.js +12 -2
- package/models/event.js +7 -0
- package/models/logging.banzaicloud.io.flow.js +4 -0
- package/models/management.cattle.io.cluster.js +1 -1
- package/models/management.cattle.io.clusterroletemplatebinding.js +1 -1
- package/models/management.cattle.io.globalrole.js +2 -2
- package/models/management.cattle.io.node.js +37 -2
- package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +4 -0
- package/models/management.cattle.io.project.js +30 -11
- package/models/management.cattle.io.setting.js +1 -1
- package/models/management.cattle.io.user.js +37 -1
- package/models/namespace.js +42 -5
- package/models/persistentvolume.js +14 -2
- package/models/pod.js +15 -0
- package/models/projectroletemplatebinding.js +7 -0
- package/models/provisioning.cattle.io.cluster.js +61 -10
- package/models/rke-machine.cattle.io.pnapmachinetemplate.js +15 -0
- package/models/service.js +14 -13
- package/models/storage.k8s.io.storageclass.js +33 -18
- package/models/workload.js +38 -7
- package/nuxt.config.js +27 -17
- package/package.json +7 -7
- package/pages/about.vue +14 -2
- package/pages/c/_cluster/apps/charts/index.vue +21 -3
- package/pages/c/_cluster/apps/charts/install.vue +59 -22
- package/pages/c/_cluster/auth/config/_id.vue +6 -0
- package/pages/c/_cluster/auth/config/index.vue +8 -6
- package/pages/c/_cluster/auth/group.principal/assign-edit.vue +1 -1
- package/pages/c/_cluster/auth/roles/index.vue +1 -1
- package/pages/c/_cluster/explorer/index.vue +51 -6
- package/pages/c/_cluster/longhorn/index.vue +1 -1
- package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +15 -4
- package/pages/c/_cluster/monitoring/index.vue +1 -1
- package/pages/c/_cluster/neuvector/index.vue +1 -1
- package/pages/c/_cluster/settings/performance.vue +48 -2
- package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +2 -0
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +3 -0
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +42 -2
- package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +2 -0
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +1 -0
- package/pages/c/_cluster/uiplugins/UninstallDialog.vue +2 -0
- package/pages/c/_cluster/uiplugins/index.vue +42 -3
- package/pages/diagnostic.vue +5 -4
- package/pages/home.vue +105 -30
- package/pages/prefs.vue +23 -12
- package/pages/rio/mesh.vue +1 -1
- package/pkg/dynamic-importer.lib.js +8 -0
- package/pkg/vue.config.js +4 -0
- package/plugins/dashboard-store/__tests__/mutations.spec.js +406 -0
- package/plugins/dashboard-store/actions.js +32 -25
- package/plugins/dashboard-store/getters.js +50 -33
- package/plugins/dashboard-store/mutations.js +134 -28
- package/plugins/dashboard-store/resource-class.js +37 -42
- package/plugins/steve/actions.js +30 -0
- package/plugins/steve/caches/resourceCache.js +60 -0
- package/plugins/steve/getters.js +44 -1
- package/plugins/steve/mutations.js +97 -36
- package/plugins/steve/resourceWatcher.js +277 -0
- package/plugins/steve/schema.utils.js +25 -0
- package/plugins/steve/subscribe.js +288 -115
- package/plugins/steve/worker/index.js +17 -0
- package/plugins/steve/worker/web-worker.advanced.js +302 -0
- package/plugins/steve/{web-worker.steve-sub-worker.js → worker/web-worker.basic.js} +3 -44
- package/rancher-components/Card/Card.vue +3 -3
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +1 -0
- package/rancher-components/StringList/StringList.test.ts +45 -420
- package/rancher-components/StringList/StringList.vue +1 -10
- package/rancher-components/components/Banner/Banner.test.ts +44 -0
- package/rancher-components/components/Banner/Banner.vue +130 -61
- package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +13 -22
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +8 -6
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +9 -9
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -1
- package/rancher-components/components/StringList/StringList.test.ts +7 -7
- package/rancher-components/components/StringList/StringList.vue +21 -15
- package/scripts/test-plugins-build.sh +8 -0
- package/static/loading-indicator.html +1 -1
- package/store/action-menu.js +4 -3
- package/store/index.js +54 -3
- package/store/plugins.js +0 -17
- package/store/pnap.js +128 -0
- package/store/prefs.js +4 -2
- package/store/type-map.js +81 -13
- package/types/pod-security-admission.ts +36 -0
- package/types/shell/index.d.ts +497 -396
- package/utils/__tests__/object.test.ts +17 -1
- package/utils/__tests__/pod-security-admission.test.ts +61 -0
- package/utils/async.ts +36 -0
- package/utils/color.js +45 -0
- package/utils/crypto/browserHashUtils.js +18 -0
- package/utils/dynamic-importer.js +8 -0
- package/utils/install-redirect.js +1 -1
- package/utils/object.js +24 -0
- package/utils/pod-security-admission.ts +39 -0
- package/utils/socket.js +61 -24
- package/utils/string.js +2 -0
- package/utils/svg-filter.js +301 -0
- package/utils/time.js +49 -0
- package/utils/validators/cidr.js +4 -0
- package/utils/validators/formRules/__tests__/index.test.ts +23 -3
- package/utils/validators/formRules/index.ts +14 -0
- package/config/product/harvester-manager.js +0 -162
- package/edit/harvesterhci.io.management.cluster.vue +0 -153
- package/list/harvesterhci.io.management.cluster.vue +0 -241
- package/machine-config/harvester.vue +0 -693
- package/models/harvesterhci.io.management.cluster.js +0 -228
- package/pages/c/_cluster/harvesterManager/index.vue +0 -24
- package/rancher-components/Card/Card.test.ts +0 -39
- package/rancher-components/Utils/DraggableZone/DraggableZone.vue +0 -181
- package/rancher-components/Utils/DraggableZone/index.ts +0 -1
- package/rancher-components/components/Utils/DraggableZone/index.ts +0 -1
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import PodSecurityAdmission from '@shell/components/PodSecurityAdmission.vue';
|
|
3
|
+
|
|
4
|
+
describe('component: PodSecurityAdmission', () => {
|
|
5
|
+
it.each([
|
|
6
|
+
['updateLabels', {
|
|
7
|
+
audit: 'privileged',
|
|
8
|
+
'audit-version': 'latest',
|
|
9
|
+
enforce: 'privileged',
|
|
10
|
+
'enforce-version': 'latest',
|
|
11
|
+
warn: 'privileged',
|
|
12
|
+
'warn-version': 'latest',
|
|
13
|
+
}],
|
|
14
|
+
['updateExemptions', {
|
|
15
|
+
namespaces: [], runtimeClasses: [], usernames: []
|
|
16
|
+
}]
|
|
17
|
+
])('should emit %p and exemptions on creation if labels always active', (emission, value) => {
|
|
18
|
+
const wrapper = mount(PodSecurityAdmission, { propsData: { mode: 'create', labelsAlwaysActive: true } });
|
|
19
|
+
|
|
20
|
+
expect(wrapper.emitted(emission)![0][0]).toStrictEqual(value);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('handling labels', () => {
|
|
24
|
+
it.each([
|
|
25
|
+
['true', 'active'],
|
|
26
|
+
['', 'level'],
|
|
27
|
+
['', 'version'],
|
|
28
|
+
])('should display default value %p for input %p', (value, inputId) => {
|
|
29
|
+
const wrapper = mount(PodSecurityAdmission, { propsData: { mode: 'edit' } });
|
|
30
|
+
|
|
31
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaControl-0-${ inputId }"]`).find('input').element as HTMLInputElement;
|
|
32
|
+
|
|
33
|
+
expect(input.value).toStrictEqual(value);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe.each([
|
|
37
|
+
'pod-security.kubernetes.io/',
|
|
38
|
+
''
|
|
39
|
+
])('given prefix %p', (prefix) => {
|
|
40
|
+
it('should map labels to the form control', () => {
|
|
41
|
+
const labels = {
|
|
42
|
+
[`${ prefix }enforce`]: 'baseline',
|
|
43
|
+
[`${ prefix }enforce-version`]: '123'
|
|
44
|
+
};
|
|
45
|
+
const psaControls = {
|
|
46
|
+
audit: {
|
|
47
|
+
active: false,
|
|
48
|
+
level: 'privileged',
|
|
49
|
+
version: ''
|
|
50
|
+
},
|
|
51
|
+
enforce: {
|
|
52
|
+
active: true,
|
|
53
|
+
level: 'baseline',
|
|
54
|
+
version: '123'
|
|
55
|
+
},
|
|
56
|
+
warn: {
|
|
57
|
+
active: false,
|
|
58
|
+
level: 'privileged',
|
|
59
|
+
version: ''
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
64
|
+
propsData: {
|
|
65
|
+
mode: 'edit',
|
|
66
|
+
labels,
|
|
67
|
+
labelsPrefix: prefix
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
expect(wrapper.vm.psaControls).toStrictEqual(psaControls);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it.each([
|
|
75
|
+
// ['true', 'active'],
|
|
76
|
+
// ['baseline', 'level'],
|
|
77
|
+
['123', 'version'],
|
|
78
|
+
])('should map labels to the form, with value %p for input %p', (value, inputId) => {
|
|
79
|
+
const labels = {
|
|
80
|
+
[`${ prefix }enforce`]: 'baseline',
|
|
81
|
+
[`${ prefix }enforce-version`]: '123'
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
85
|
+
propsData: {
|
|
86
|
+
mode: 'edit',
|
|
87
|
+
labels,
|
|
88
|
+
labelsPrefix: prefix
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaControl-0-${ inputId }"]`).find('input').element as HTMLInputElement;
|
|
93
|
+
|
|
94
|
+
expect(input.value).toStrictEqual(value);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it.each([
|
|
98
|
+
// ['true', 'active'],
|
|
99
|
+
// ['privileged', 'level'],
|
|
100
|
+
['', 'version'],
|
|
101
|
+
])('should map labels to the form, using default values if none, with value %p for input %p', (value, inputId) => {
|
|
102
|
+
const labels = {
|
|
103
|
+
[`${ prefix }enforce`]: '',
|
|
104
|
+
[`${ prefix }enforce-version`]: ''
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
108
|
+
propsData: {
|
|
109
|
+
mode: 'edit',
|
|
110
|
+
labels,
|
|
111
|
+
labelsPrefix: prefix
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaControl-0-${ inputId }"]`).find('input').element as HTMLInputElement;
|
|
116
|
+
|
|
117
|
+
expect(input.value).toStrictEqual(value);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('changing input values', () => {
|
|
121
|
+
it('should add labels if active', () => {
|
|
122
|
+
const version = '123';
|
|
123
|
+
const newLabels = {
|
|
124
|
+
[`${ prefix }enforce`]: 'privileged',
|
|
125
|
+
[`${ prefix }enforce-version`]: version
|
|
126
|
+
};
|
|
127
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
128
|
+
propsData: {
|
|
129
|
+
mode: 'edit',
|
|
130
|
+
labels: {},
|
|
131
|
+
labelsPrefix: prefix
|
|
132
|
+
},
|
|
133
|
+
// Unable to toggle the checkbox, so we enforce the data
|
|
134
|
+
data: () => ({
|
|
135
|
+
psaControls: {
|
|
136
|
+
enforce: {
|
|
137
|
+
active: true,
|
|
138
|
+
level: '',
|
|
139
|
+
version: ''
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}),
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Unable to toggle the checkbox, so we use the input
|
|
146
|
+
wrapper.find(`[data-testid="pod-security-admission--psaControl-0-version"]`).find('input').setValue(version);
|
|
147
|
+
|
|
148
|
+
expect(wrapper.emitted('updateLabels')![0][0]).toStrictEqual(newLabels);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should remove other labels if not active', () => {
|
|
152
|
+
const labels = {
|
|
153
|
+
[`${ prefix }audit`]: 'privileged',
|
|
154
|
+
[`${ prefix }audit-version`]: 'latest'
|
|
155
|
+
};
|
|
156
|
+
const newLabels = {
|
|
157
|
+
[`${ prefix }enforce`]: 'privileged',
|
|
158
|
+
[`${ prefix }enforce-version`]: 'latest',
|
|
159
|
+
};
|
|
160
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
161
|
+
propsData: {
|
|
162
|
+
mode: 'edit',
|
|
163
|
+
labels,
|
|
164
|
+
labelsPrefix: prefix
|
|
165
|
+
},
|
|
166
|
+
// Unable to toggle the checkbox, so we enforce the data
|
|
167
|
+
data: () => ({
|
|
168
|
+
psaControls: {
|
|
169
|
+
enforce: {
|
|
170
|
+
active: true,
|
|
171
|
+
level: '',
|
|
172
|
+
version: ''
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}),
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Unable to toggle the checkbox, so we enforce the data
|
|
179
|
+
wrapper.setData({
|
|
180
|
+
psaControls: {
|
|
181
|
+
audit: {
|
|
182
|
+
active: false,
|
|
183
|
+
level: '',
|
|
184
|
+
version: ''
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// Unable to toggle the checkbox, so we use the input
|
|
190
|
+
wrapper.find(`[data-testid="pod-security-admission--psaControl-0-version"]`).find('input').setValue('');
|
|
191
|
+
|
|
192
|
+
expect(wrapper.emitted('updateLabels')![0][0]).toStrictEqual(newLabels);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should assign default version and level if missing', () => {
|
|
196
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
197
|
+
propsData: {
|
|
198
|
+
mode: 'edit',
|
|
199
|
+
labels: {},
|
|
200
|
+
labelsPrefix: prefix
|
|
201
|
+
},
|
|
202
|
+
// Unable to toggle the checkbox, so we enforce the data
|
|
203
|
+
data: () => ({
|
|
204
|
+
psaControls: {
|
|
205
|
+
enforce: {
|
|
206
|
+
active: true,
|
|
207
|
+
level: '',
|
|
208
|
+
version: ''
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}),
|
|
212
|
+
});
|
|
213
|
+
const newLabels = {
|
|
214
|
+
[`${ prefix }enforce`]: 'privileged',
|
|
215
|
+
[`${ prefix }enforce-version`]: 'latest'
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// Unable to toggle the checkbox, so we use the input
|
|
219
|
+
wrapper.find(`[data-testid="pod-security-admission--psaControl-0-version"]`).find('input').setValue('');
|
|
220
|
+
|
|
221
|
+
expect(wrapper.emitted('updateLabels')![0][0]).toStrictEqual(newLabels);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
describe.each(['level', 'version'])('should keep always %p enabled', (inputId) => {
|
|
227
|
+
it('given labelsAlwaysActive true and no labels', () => {
|
|
228
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
229
|
+
propsData: {
|
|
230
|
+
mode: 'edit',
|
|
231
|
+
labelsAlwaysActive: true,
|
|
232
|
+
labels: {}
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaControl-0-${ inputId }"]`).find('input').element as HTMLInputElement;
|
|
237
|
+
|
|
238
|
+
expect(input.disabled).toBe(false);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('given existing values', () => {
|
|
242
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
243
|
+
propsData: {
|
|
244
|
+
mode: 'edit',
|
|
245
|
+
labels: {
|
|
246
|
+
[`enforce`]: 'baseline',
|
|
247
|
+
[`enforce-version`]: '123'
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaControl-0-${ inputId }"]`).find('input').element as HTMLInputElement;
|
|
253
|
+
|
|
254
|
+
expect(input.disabled).toBe(false);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
describe.each(['level', 'version'])('should keep always %p disabled', (inputId) => {
|
|
259
|
+
it('given labelsAlwaysActive false and no labels', () => {
|
|
260
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
261
|
+
propsData: {
|
|
262
|
+
mode: 'edit',
|
|
263
|
+
labelsAlwaysActive: false,
|
|
264
|
+
labels: {}
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaControl-0-${ inputId }"]`).find('input').element as HTMLInputElement;
|
|
269
|
+
|
|
270
|
+
expect(input.disabled).toBe(true);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it('given disabled active status', () => {
|
|
274
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
275
|
+
propsData: { mode: 'edit' },
|
|
276
|
+
data: () => ({
|
|
277
|
+
psaControls: {
|
|
278
|
+
enforce: {
|
|
279
|
+
active: false,
|
|
280
|
+
level: '',
|
|
281
|
+
version: ''
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}),
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaControl-0-${ inputId }"]`).find('input').element as HTMLInputElement;
|
|
288
|
+
|
|
289
|
+
expect(input.disabled).toBe(true);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('given view mode and provided labels', () => {
|
|
293
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
294
|
+
propsData: {
|
|
295
|
+
mode: 'view',
|
|
296
|
+
labels: {
|
|
297
|
+
[`enforce`]: 'baseline',
|
|
298
|
+
[`enforce-version`]: '123'
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaControl-0-${ inputId }"]`).find('input').element as HTMLInputElement;
|
|
304
|
+
|
|
305
|
+
expect(input.disabled).toBe(true);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it.each([
|
|
310
|
+
[true, false],
|
|
311
|
+
])('should display the checkbox %p', (value) => {
|
|
312
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
313
|
+
propsData: {
|
|
314
|
+
mode: 'edit',
|
|
315
|
+
labelsAlwaysActive: value
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaControl-0-active"]`).element as HTMLInputElement;
|
|
320
|
+
|
|
321
|
+
expect(!input).toBe(value);
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
describe('handling exemptions', () => {
|
|
326
|
+
it.each([
|
|
327
|
+
[['namespace1', 'namespace2'], 'namespace1,namespace2'],
|
|
328
|
+
])('should map %p to the form control as %p', (exemption, control) => {
|
|
329
|
+
const exemptions = { namespaces: exemption };
|
|
330
|
+
const result = {
|
|
331
|
+
namespaces: {
|
|
332
|
+
active: true,
|
|
333
|
+
value: control
|
|
334
|
+
},
|
|
335
|
+
runtimeClasses: {
|
|
336
|
+
active: false,
|
|
337
|
+
value: ''
|
|
338
|
+
},
|
|
339
|
+
usernames: {
|
|
340
|
+
active: false,
|
|
341
|
+
value: ''
|
|
342
|
+
},
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
346
|
+
propsData: {
|
|
347
|
+
mode: 'edit',
|
|
348
|
+
exemptions,
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
expect(wrapper.vm.psaExemptionsControls).toStrictEqual(result);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it.each([
|
|
356
|
+
// ['true', 'active'],
|
|
357
|
+
['username', 'value'],
|
|
358
|
+
])('should map to the form, with value %p for input %p', (value, inputId) => {
|
|
359
|
+
const exemptions = { usernames: [value] };
|
|
360
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
361
|
+
propsData: {
|
|
362
|
+
mode: 'edit',
|
|
363
|
+
exemptions
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaExemptionsControl-0-${ inputId }"]`).find('input').element as HTMLInputElement;
|
|
368
|
+
|
|
369
|
+
expect(input.value).toStrictEqual(value);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
describe('changing input values', () => {
|
|
373
|
+
it.each([
|
|
374
|
+
['username1', ['username1']],
|
|
375
|
+
['username1, username2', ['username1', 'username2']],
|
|
376
|
+
['username1,username2', ['username1', 'username2']],
|
|
377
|
+
])('should emit exemption input value %p as %p', (value, exemption) => {
|
|
378
|
+
const exemptions = {
|
|
379
|
+
usernames: exemption,
|
|
380
|
+
namespaces: [],
|
|
381
|
+
runtimeClasses: []
|
|
382
|
+
};
|
|
383
|
+
const wrapper = mount(PodSecurityAdmission, {
|
|
384
|
+
propsData: {
|
|
385
|
+
mode: 'edit',
|
|
386
|
+
exemptions
|
|
387
|
+
},
|
|
388
|
+
});
|
|
389
|
+
// Unable to toggle the checkbox, so we use the input
|
|
390
|
+
const input = wrapper.find(`[data-testid="pod-security-admission--psaExemptionsControl-0-value"]`).find('input');
|
|
391
|
+
|
|
392
|
+
input.setValue(value);
|
|
393
|
+
|
|
394
|
+
expect(wrapper.emitted('updateExemptions')![0][0]).toStrictEqual(exemptions);
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
<script>
|
|
3
3
|
import { Banner } from '@components/Banner';
|
|
4
|
-
import
|
|
4
|
+
import DisableAuthProviderModal from '@shell/components/DisableAuthProviderModal';
|
|
5
5
|
|
|
6
6
|
export default {
|
|
7
7
|
components: {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
Banner,
|
|
9
|
+
DisableAuthProviderModal
|
|
10
10
|
},
|
|
11
11
|
|
|
12
12
|
props: {
|
|
@@ -32,6 +32,12 @@ export default {
|
|
|
32
32
|
return Object.entries(this.table);
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
|
+
|
|
36
|
+
methods: {
|
|
37
|
+
showDisableModal() {
|
|
38
|
+
this.$refs.disableAuthProviderModal.show();
|
|
39
|
+
}
|
|
40
|
+
},
|
|
35
41
|
};
|
|
36
42
|
</script>
|
|
37
43
|
|
|
@@ -52,13 +58,13 @@ export default {
|
|
|
52
58
|
>
|
|
53
59
|
{{ t('action.edit') }}
|
|
54
60
|
</button>
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
<button
|
|
62
|
+
type="button"
|
|
63
|
+
class="ml-10 btn-sm role-primary bg-error"
|
|
64
|
+
@click="showDisableModal"
|
|
65
|
+
>
|
|
66
|
+
{{ t('generic.disable') }}
|
|
67
|
+
</button>
|
|
62
68
|
</Banner>
|
|
63
69
|
|
|
64
70
|
<table
|
|
@@ -67,6 +73,10 @@ export default {
|
|
|
67
73
|
>
|
|
68
74
|
<slot name="rows" />
|
|
69
75
|
</table>
|
|
76
|
+
<DisableAuthProviderModal
|
|
77
|
+
ref="disableAuthProviderModal"
|
|
78
|
+
@disable="disable"
|
|
79
|
+
/>
|
|
70
80
|
</div>
|
|
71
81
|
</template>
|
|
72
82
|
|
|
@@ -380,28 +380,27 @@ export default {
|
|
|
380
380
|
// - resourceNames
|
|
381
381
|
// - resources
|
|
382
382
|
// - verbs
|
|
383
|
-
const value = event.label ? event.label : event;
|
|
384
383
|
|
|
385
384
|
switch (key) {
|
|
386
385
|
case 'apiGroups':
|
|
387
386
|
|
|
388
|
-
if (
|
|
389
|
-
this.$set(rule, 'apiGroups', [
|
|
387
|
+
if (event || (event === '')) {
|
|
388
|
+
this.$set(rule, 'apiGroups', [event]);
|
|
390
389
|
}
|
|
391
390
|
|
|
392
391
|
break;
|
|
393
392
|
|
|
394
393
|
case 'verbs':
|
|
395
394
|
|
|
396
|
-
if (
|
|
397
|
-
this.$set(rule, 'verbs', [
|
|
395
|
+
if (event) {
|
|
396
|
+
this.$set(rule, 'verbs', [event]);
|
|
398
397
|
} else {
|
|
399
398
|
this.$set(rule, 'verbs', []);
|
|
400
399
|
}
|
|
401
400
|
break;
|
|
402
401
|
|
|
403
402
|
case 'resources':
|
|
404
|
-
if (event
|
|
403
|
+
if (event?.resourceName) {
|
|
405
404
|
// If we are updating the resources defined in a rule,
|
|
406
405
|
// the event will be an object with the
|
|
407
406
|
// properties apiGroupValue and resourceName.
|
|
@@ -409,7 +408,7 @@ export default {
|
|
|
409
408
|
// Automatically fill in the API group of the
|
|
410
409
|
// selected resource.
|
|
411
410
|
this.$set(rule, 'apiGroups', [event.apiGroupValue]);
|
|
412
|
-
} else if (event
|
|
411
|
+
} else if (event?.label) {
|
|
413
412
|
// When the user creates a new resource name in the resource
|
|
414
413
|
// field instead of selecting an existing one,
|
|
415
414
|
// we have to treat that differently because the incoming event
|
|
@@ -424,8 +423,8 @@ export default {
|
|
|
424
423
|
break;
|
|
425
424
|
|
|
426
425
|
case 'nonResourceURLs':
|
|
427
|
-
if (
|
|
428
|
-
this.$set(rule, 'nonResourceURLs', [
|
|
426
|
+
if (event) {
|
|
427
|
+
this.$set(rule, 'nonResourceURLs', [event]);
|
|
429
428
|
} else {
|
|
430
429
|
this.$set(rule, 'nonResourceURLs', []);
|
|
431
430
|
}
|
|
@@ -447,6 +446,21 @@ export default {
|
|
|
447
446
|
this.done();
|
|
448
447
|
},
|
|
449
448
|
async actuallySave(url) {
|
|
449
|
+
// Go through all of the grules and replace double quote apiGroups
|
|
450
|
+
// k8S documentation shows using empty rules as "" - we change this to empty string when used
|
|
451
|
+
this.value.rules?.forEach((rule) => {
|
|
452
|
+
if (rule.apiGroups) {
|
|
453
|
+
rule.apiGroups = rule.apiGroups.map((group) => {
|
|
454
|
+
// If the group is two double quotes ("") replace if with empty string
|
|
455
|
+
if (group.trim() === '\"\"') {
|
|
456
|
+
group = '';
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return group;
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
|
|
450
464
|
if ( this.isCreate ) {
|
|
451
465
|
url = url || this.schema.linkFor('collection');
|
|
452
466
|
await this.value.save({ url, redirectUnauthorized: false });
|
|
@@ -623,12 +637,7 @@ export default {
|
|
|
623
637
|
</span>
|
|
624
638
|
</div>
|
|
625
639
|
<div :class="ruleClass">
|
|
626
|
-
<span class="text-label">{{ t('rbac.roletemplate.tabs.grantResources.tableHeaders.apiGroups') }}
|
|
627
|
-
<span
|
|
628
|
-
v-if="isNamespaced"
|
|
629
|
-
class="required"
|
|
630
|
-
>*</span>
|
|
631
|
-
</span>
|
|
640
|
+
<span class="text-label">{{ t('rbac.roletemplate.tabs.grantResources.tableHeaders.apiGroups') }}</span>
|
|
632
641
|
</div>
|
|
633
642
|
<div
|
|
634
643
|
v-if="!isNamespaced"
|
|
@@ -670,7 +679,7 @@ export default {
|
|
|
670
679
|
:value="getRule('apiGroups', props.row.value)"
|
|
671
680
|
:disabled="isBuiltin"
|
|
672
681
|
:mode="mode"
|
|
673
|
-
@input="setRule('apiGroups', props.row.value, $event)"
|
|
682
|
+
@input="setRule('apiGroups', props.row.value, $event.target.value)"
|
|
674
683
|
>
|
|
675
684
|
</div>
|
|
676
685
|
<div
|
|
@@ -681,7 +690,7 @@ export default {
|
|
|
681
690
|
:value="getRule('nonResourceURLs', props.row.value)"
|
|
682
691
|
:disabled="isBuiltin"
|
|
683
692
|
:mode="mode"
|
|
684
|
-
@input="setRule('nonResourceURLs', props.row.value, $event)"
|
|
693
|
+
@input="setRule('nonResourceURLs', props.row.value, $event.target.value)"
|
|
685
694
|
>
|
|
686
695
|
</div>
|
|
687
696
|
</div>
|
|
@@ -40,7 +40,7 @@ export default {
|
|
|
40
40
|
project: {
|
|
41
41
|
type: Boolean,
|
|
42
42
|
default: false
|
|
43
|
-
}
|
|
43
|
+
}
|
|
44
44
|
},
|
|
45
45
|
|
|
46
46
|
async fetch() {
|
|
@@ -54,10 +54,11 @@ export default {
|
|
|
54
54
|
|
|
55
55
|
data() {
|
|
56
56
|
return {
|
|
57
|
-
principals:
|
|
58
|
-
searchStr:
|
|
59
|
-
options:
|
|
60
|
-
newValue:
|
|
57
|
+
principals: null,
|
|
58
|
+
searchStr: '',
|
|
59
|
+
options: [],
|
|
60
|
+
newValue: '',
|
|
61
|
+
tooltipContent: null,
|
|
61
62
|
};
|
|
62
63
|
},
|
|
63
64
|
|
|
@@ -94,6 +95,24 @@ export default {
|
|
|
94
95
|
},
|
|
95
96
|
|
|
96
97
|
methods: {
|
|
98
|
+
setTooltipContent() {
|
|
99
|
+
if (!this.retainSelection) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (this.principals) {
|
|
103
|
+
const selected = this.principals.find(p => p.id === this.newValue);
|
|
104
|
+
|
|
105
|
+
this.tooltipContent = selected?.name;
|
|
106
|
+
} else {
|
|
107
|
+
this.tooltipContent = null;
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
resetTooltipContent() {
|
|
111
|
+
if (!this.retainSelection) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
this.tooltipContent = null;
|
|
115
|
+
},
|
|
97
116
|
add(id) {
|
|
98
117
|
if (!id) {
|
|
99
118
|
// Ignore attempts to select an invalid principal
|
|
@@ -156,6 +175,11 @@ export default {
|
|
|
156
175
|
<LabeledSelect
|
|
157
176
|
ref="labeled-select"
|
|
158
177
|
v-model="newValue"
|
|
178
|
+
v-tooltip="{
|
|
179
|
+
content: tooltipContent,
|
|
180
|
+
placement: 'bottom',
|
|
181
|
+
classes: ['select-principal-tooltip']
|
|
182
|
+
}"
|
|
159
183
|
:mode="mode"
|
|
160
184
|
:label="label"
|
|
161
185
|
:placeholder="placeholder"
|
|
@@ -166,6 +190,8 @@ export default {
|
|
|
166
190
|
:class="{'retain-selection': retainSelection}"
|
|
167
191
|
@input="add"
|
|
168
192
|
@search="onSearch"
|
|
193
|
+
@on-open="resetTooltipContent()"
|
|
194
|
+
@on-close="setTooltipContent()"
|
|
169
195
|
>
|
|
170
196
|
<template v-slot:no-options="{ searching }">
|
|
171
197
|
<template v-if="searching">
|
|
@@ -226,4 +252,9 @@ export default {
|
|
|
226
252
|
text-overflow: ellipsis;
|
|
227
253
|
}
|
|
228
254
|
}
|
|
255
|
+
|
|
256
|
+
.select-principal-tooltip {
|
|
257
|
+
max-width: 580px;
|
|
258
|
+
word-wrap: break-word;
|
|
259
|
+
}
|
|
229
260
|
</style>
|