@rancher/shell 3.0.8-rc.1 → 3.0.8-rc.10
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/brand/suse/banner.svg +1 -0
- package/assets/brand/suse/dark/banner.svg +1 -0
- package/assets/brand/suse/dark/login-landscape.svg +1 -0
- package/assets/brand/suse/dark/rancher-logo.svg +1 -1
- package/assets/brand/suse/favicon.png +0 -0
- package/assets/brand/suse/login-landscape.svg +1 -0
- package/assets/brand/suse/metadata.json +11 -1
- package/assets/brand/suse/rancher-logo.svg +1 -1
- package/assets/fonts/suse/suse-v2-latin-300.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-300.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-600.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-600.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-700.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-700.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-800.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-800.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-regular.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-regular.woff2 +0 -0
- package/assets/images/content/README.md +5 -0
- package/assets/images/content/cloud-native.svg +84 -0
- package/assets/images/content/dark/cloud-native.svg +21 -0
- package/assets/images/content/dark/shield.svg +59 -0
- package/assets/images/content/dark/suse.svg +10 -0
- package/assets/images/content/shield.svg +59 -0
- package/assets/images/content/suse.svg +10 -0
- package/assets/styles/base/_typography.scss +1 -0
- package/assets/styles/fonts/_fontstack.scss +53 -1
- package/assets/styles/global/_cards.scss +0 -3
- package/assets/styles/global/_layout.scss +21 -35
- package/assets/styles/themes/_dark.scss +1 -1
- package/assets/styles/themes/_light.scss +1 -1
- package/assets/styles/themes/_modern.scss +11 -3
- package/assets/styles/themes/_suse.scss +116 -24
- package/assets/translations/en-us.yaml +94 -10
- package/components/AutoscalerCard.vue +113 -0
- package/components/AutoscalerTab.vue +94 -0
- package/components/BackLink.vue +8 -0
- package/components/BannerGraphic.vue +36 -21
- package/components/BrandImage.vue +17 -6
- package/components/ClusterIconMenu.vue +1 -1
- package/components/ClusterProviderIcon.vue +1 -1
- package/components/Cron/CronExpressionEditor.vue +1 -1
- package/components/Cron/CronExpressionEditorModal.vue +1 -1
- package/components/Drawer/Chrome.vue +2 -6
- package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +4 -9
- package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +3 -8
- package/components/Drawer/ResourceDetailDrawer/composables.ts +3 -4
- package/components/Drawer/ResourceDetailDrawer/index.vue +4 -9
- package/components/Drawer/ResourceDetailDrawer/types.ts +17 -0
- package/components/Drawer/types.ts +3 -0
- package/components/DynamicContent/DynamicContentBanner.vue +102 -0
- package/components/DynamicContent/DynamicContentCloseButton.vue +42 -0
- package/components/DynamicContent/DynamicContentIcon.vue +132 -0
- package/components/DynamicContent/DynamicContentPanel.vue +112 -0
- package/components/DynamicContent/content.ts +78 -0
- package/components/EmberPage.vue +1 -1
- package/components/IconOrSvg.vue +2 -2
- package/components/PaginatedResourceTable.vue +2 -6
- package/components/PopoverCard.vue +192 -0
- package/components/Questions/__tests__/index.test.ts +159 -0
- package/components/Resource/Detail/CopyToClipboard.vue +4 -1
- package/components/Resource/Detail/FetchLoader/composables.ts +18 -4
- package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +1 -1
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +4 -0
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +1 -1
- package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
- package/components/Resource/Detail/Metadata/composables.ts +9 -9
- package/components/Resource/Detail/Metadata/index.vue +3 -3
- package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +2 -19
- package/components/Resource/Detail/ResourcePopover/__tests__/ResourcePopoverCard.test.ts +0 -29
- package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +132 -150
- package/components/Resource/Detail/ResourcePopover/index.vue +54 -159
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +0 -2
- package/components/Resource/Detail/TitleBar/composables.ts +2 -1
- package/components/Resource/Detail/TitleBar/index.vue +10 -6
- package/components/Resource/Detail/composables.ts +12 -0
- package/components/ResourceDetail/Masthead/latest.vue +29 -0
- package/components/ResourceDetail/index.vue +4 -1
- package/components/ResourceList/Masthead.vue +1 -1
- package/components/SortableTable/index.vue +1 -0
- package/components/Tabbed/__tests__/index.test.ts +86 -0
- package/components/{nav/WindowManager → Window}/ContainerLogs.vue +1 -1
- package/components/{nav/WindowManager → Window}/ContainerLogsActions.vue +1 -0
- package/components/{nav/WindowManager → Window}/__tests__/ContainerLogs.test.ts +1 -1
- package/components/{nav/WindowManager → Window}/__tests__/ContainerShell.test.ts +2 -2
- package/components/__tests__/AutoscalerCard.test.ts +154 -0
- package/components/__tests__/AutoscalerTab.test.ts +125 -0
- package/components/__tests__/PopoverCard.test.ts +204 -0
- package/components/auth/SelectPrincipal.vue +24 -6
- package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
- package/components/formatter/Autoscaler.vue +97 -0
- package/components/formatter/InternalExternalIP.vue +198 -24
- package/components/formatter/__tests__/Autoscaler.test.ts +156 -0
- package/components/formatter/__tests__/InternalExternalIP.test.ts +133 -0
- package/components/google/util/__tests__/formatter.test.ts +47 -0
- package/components/google/util/formatter.ts +5 -2
- package/components/nav/Group.vue +12 -3
- package/components/nav/Header.vue +36 -16
- package/components/nav/NamespaceFilter.vue +13 -1
- package/components/nav/NotificationCenter/index.vue +2 -1
- package/components/nav/TopLevelMenu.helper.ts +16 -6
- package/components/nav/TopLevelMenu.vue +4 -2
- package/components/{DraggableZone.vue → nav/WindowManager/PinArea.vue} +47 -80
- package/components/nav/WindowManager/composables/useComponentsMount.ts +70 -0
- package/components/nav/WindowManager/composables/useDimensionsHandler.ts +105 -0
- package/components/nav/WindowManager/composables/useDragHandler.ts +99 -0
- package/components/nav/WindowManager/composables/usePanelHandler.ts +72 -0
- package/components/nav/WindowManager/composables/usePanelsHandler.ts +14 -0
- package/components/nav/WindowManager/composables/useResizeHandler.ts +167 -0
- package/components/nav/WindowManager/composables/useTabsHandler.ts +51 -0
- package/components/nav/WindowManager/constants.ts +23 -0
- package/components/nav/WindowManager/index.vue +61 -575
- package/components/nav/WindowManager/panels/HorizontalPanel.vue +265 -0
- package/components/nav/WindowManager/panels/TabBodyContainer.vue +39 -0
- package/components/nav/WindowManager/panels/VerticalPanel.vue +308 -0
- package/components/templates/default.vue +4 -40
- package/components/templates/home.vue +31 -5
- package/components/templates/plain.vue +30 -4
- package/components/templates/standalone.vue +1 -1
- package/composables/useI18n.ts +10 -1
- package/composables/useInterval.ts +15 -0
- package/config/__test__/uiplugins.test.ts +309 -0
- package/config/labels-annotations.js +9 -1
- package/config/product/explorer.js +3 -1
- package/config/product/manager.js +20 -9
- package/config/router/routes.js +10 -2
- package/config/settings.ts +2 -1
- package/config/store.js +4 -2
- package/config/table-headers.js +8 -0
- package/config/types.js +9 -0
- package/config/uiplugins.js +46 -2
- package/config/version.js +1 -1
- package/core/__test__/extension-manager-impl.test.js +236 -0
- package/core/extension-manager-impl.js +23 -6
- package/core/plugin-helpers.ts +2 -0
- package/core/types-provisioning.ts +4 -1
- package/detail/pod.vue +1 -0
- package/detail/provisioning.cattle.io.cluster.vue +13 -1
- package/dialog/DeveloperLoadExtensionDialog.vue +12 -3
- package/dialog/RollbackWorkloadDialog.vue +2 -5
- package/directives/ui-context.ts +103 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +2 -2
- package/edit/auth/__tests__/oidc.test.ts +26 -0
- package/edit/auth/github.vue +5 -0
- package/edit/auth/oidc.vue +5 -1
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
- package/edit/cloudcredential.vue +1 -1
- package/edit/configmap.vue +1 -0
- package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
- package/edit/fleet.cattle.io.gitrepo.vue +0 -10
- package/edit/fleet.cattle.io.helmop.vue +6 -6
- package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
- package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
- package/edit/logging-flow/index.vue +1 -0
- package/edit/logging.banzaicloud.io.output/index.vue +1 -0
- package/edit/management.cattle.io.fleetworkspace.vue +1 -1
- package/edit/management.cattle.io.project.vue +1 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
- package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
- package/edit/monitoring.coreos.com.route.vue +1 -1
- package/edit/namespace.vue +1 -0
- package/edit/networking.istio.io.destinationrule/index.vue +1 -0
- package/edit/networking.k8s.io.ingress/index.vue +1 -0
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
- package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
- package/edit/node.vue +1 -0
- package/edit/persistentvolume/index.vue +27 -22
- package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
- package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
- package/edit/persistentvolume/plugins/azureFile.vue +15 -14
- package/edit/persistentvolume/plugins/cephfs.vue +15 -14
- package/edit/persistentvolume/plugins/cinder.vue +15 -14
- package/edit/persistentvolume/plugins/csi.vue +18 -16
- package/edit/persistentvolume/plugins/fc.vue +13 -14
- package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
- package/edit/persistentvolume/plugins/flocker.vue +1 -3
- package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
- package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
- package/edit/persistentvolume/plugins/hostPath.vue +40 -39
- package/edit/persistentvolume/plugins/iscsi.vue +13 -14
- package/edit/persistentvolume/plugins/local.vue +1 -3
- package/edit/persistentvolume/plugins/longhorn.vue +23 -22
- package/edit/persistentvolume/plugins/nfs.vue +15 -14
- package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
- package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
- package/edit/persistentvolume/plugins/quobyte.vue +15 -14
- package/edit/persistentvolume/plugins/rbd.vue +15 -14
- package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
- package/edit/persistentvolume/plugins/storageos.vue +15 -14
- package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
- package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +32 -5
- package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +35 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +155 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +25 -15
- package/edit/provisioning.cattle.io.cluster/rke2.vue +42 -8
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +107 -5
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +92 -4
- package/edit/secret/index.vue +1 -1
- package/edit/service.vue +9 -4
- package/edit/serviceaccount.vue +1 -0
- package/edit/storage.k8s.io.storageclass/index.vue +1 -0
- package/edit/workload/index.vue +2 -1
- package/edit/workload/mixins/workload.js +1 -1
- package/initialize/App.vue +4 -4
- package/initialize/install-directives.js +2 -0
- package/initialize/install-plugins.js +19 -2
- package/list/provisioning.cattle.io.cluster.vue +15 -2
- package/machine-config/amazonec2.vue +42 -135
- package/machine-config/components/EC2Networking.vue +490 -0
- package/machine-config/components/__tests__/EC2Networking.test.ts +148 -0
- package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +294 -0
- package/machine-config/digitalocean.vue +11 -0
- package/machine-config/google.vue +1 -1
- package/mixins/__tests__/brand.spec.ts +2 -2
- package/mixins/__tests__/chart.test.ts +21 -0
- package/mixins/brand.js +1 -7
- package/mixins/chart.js +7 -1
- package/mixins/create-edit-view/index.js +5 -0
- package/models/__tests__/chart.test.ts +33 -4
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +112 -5
- package/models/chart.js +25 -13
- package/models/cluster/node.js +13 -6
- package/models/cluster.x-k8s.io.machine.js +10 -20
- package/models/cluster.x-k8s.io.machinedeployment.js +5 -1
- package/models/management.cattle.io.cluster.js +21 -3
- package/models/management.cattle.io.kontainerdriver.js +1 -0
- package/models/provisioning.cattle.io.cluster.js +249 -33
- package/package.json +6 -5
- package/pages/auth/login.vue +38 -2
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
- package/pages/c/_cluster/apps/charts/chart.vue +33 -15
- package/pages/c/_cluster/apps/charts/index.vue +11 -13
- package/pages/c/_cluster/apps/charts/install.vue +1 -1
- package/pages/c/_cluster/explorer/index.vue +8 -6
- package/pages/c/_cluster/manager/hostedprovider/index.vue +220 -0
- package/pages/c/_cluster/settings/brand.vue +1 -1
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
- package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
- package/pages/c/_cluster/uiplugins/index.vue +126 -184
- package/pages/home.vue +14 -4
- package/pkg/dynamic-importer.lib.js +4 -0
- package/plugins/dashboard-client-init.js +3 -0
- package/plugins/dashboard-store/getters.js +18 -1
- package/plugins/dashboard-store/resource-class.js +4 -4
- package/plugins/dynamic-content.js +13 -0
- package/plugins/i18n.js +8 -0
- package/plugins/steve/__tests__/steve-pagination-utils.test.ts +333 -0
- package/plugins/steve/steve-pagination-utils.ts +39 -20
- package/plugins/steve/subscribe.js +17 -9
- package/plugins/subscribe-events.ts +4 -2
- package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -34
- package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
- package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
- package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
- package/rancher-components/Pill/types.ts +0 -1
- package/rancher-components/RcDropdown/RcDropdownItem.vue +1 -0
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +5 -1
- package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
- package/rancher-components/RcIcon/RcIcon.vue +46 -0
- package/rancher-components/RcIcon/index.ts +1 -0
- package/rancher-components/RcIcon/types.ts +160 -0
- package/rancher-components/utils/status.test.ts +67 -0
- package/rancher-components/utils/status.ts +77 -0
- package/scripts/typegen.sh +1 -0
- package/store/action-menu.js +8 -0
- package/store/auth.js +3 -3
- package/store/catalog.js +6 -0
- package/store/features.js +1 -0
- package/store/index.js +36 -17
- package/store/notifications.ts +51 -4
- package/store/plugins.js +7 -3
- package/store/prefs.js +6 -6
- package/store/type-map.js +3 -3
- package/store/ui-context.ts +86 -0
- package/store/wm.ts +244 -0
- package/types/notifications/index.ts +27 -3
- package/types/shell/index.d.ts +79 -4
- package/types/store/__tests__/pagination.types.spec.ts +137 -0
- package/types/store/pagination.types.ts +157 -9
- package/types/store/subscribe-events.types.ts +8 -1
- package/types/store/subscribe.types.ts +1 -0
- package/types/window-manager.ts +24 -0
- package/utils/__tests__/object.test.ts +19 -0
- package/utils/__tests__/provider.test.ts +98 -0
- package/utils/__tests__/selector-typed.test.ts +263 -0
- package/utils/__tests__/version.test.ts +19 -1
- package/utils/autoscaler-utils.ts +7 -0
- package/utils/back-off.ts +3 -3
- package/utils/brand.ts +29 -0
- package/utils/chart.js +18 -0
- package/utils/color.js +1 -1
- package/utils/dynamic-content/__tests__/announcement.test.ts +498 -0
- package/utils/dynamic-content/__tests__/info.test.ts +21 -9
- package/utils/dynamic-content/announcement.ts +142 -0
- package/utils/dynamic-content/example.json +40 -0
- package/utils/dynamic-content/index.ts +6 -2
- package/utils/dynamic-content/info.ts +44 -2
- package/utils/dynamic-content/new-release.ts +1 -1
- package/utils/dynamic-content/notification-handler.ts +48 -0
- package/utils/dynamic-content/types.d.ts +53 -1
- package/utils/dynamic-importer.js +2 -2
- package/utils/favicon.js +4 -4
- package/utils/object.js +20 -2
- package/utils/pagination-wrapper.ts +12 -8
- package/utils/provider.ts +14 -0
- package/utils/scroll.js +7 -0
- package/utils/selector-typed.ts +6 -2
- package/utils/settings.ts +15 -0
- package/utils/validators/machine-pool.ts +13 -3
- package/utils/version.js +15 -0
- package/assets/images/icons/document.svg +0 -3
- package/plugins/nuxt-client-init.js +0 -3
- package/store/wm.js +0 -95
- /package/components/{nav/WindowManager → Window}/ChartReadme.vue +0 -0
- /package/components/{nav/WindowManager → Window}/ContainerShell.vue +0 -0
- /package/components/{nav/WindowManager → Window}/KubectlShell.vue +0 -0
- /package/components/{nav/WindowManager → Window}/MachineSsh.vue +0 -0
- /package/components/{nav/WindowManager → Window}/Window.vue +0 -0
package/store/index.js
CHANGED
|
@@ -263,7 +263,7 @@ export const state = () => {
|
|
|
263
263
|
$route: markRaw({}),
|
|
264
264
|
$plugin: markRaw({}),
|
|
265
265
|
showWorkspaceSwitcher: true,
|
|
266
|
-
|
|
266
|
+
localCluster: null,
|
|
267
267
|
};
|
|
268
268
|
};
|
|
269
269
|
|
|
@@ -272,10 +272,20 @@ export const getters = {
|
|
|
272
272
|
return state.clusterReady === true;
|
|
273
273
|
},
|
|
274
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Cache of the mgmt cluster fetched at start up
|
|
277
|
+
*
|
|
278
|
+
* We cannot rely on the store to cache this as the store may contain a page without the local cluster
|
|
279
|
+
*/
|
|
280
|
+
localCluster(state) {
|
|
281
|
+
return state.localCluster;
|
|
282
|
+
},
|
|
283
|
+
|
|
275
284
|
isMultiCluster(state, getters) {
|
|
276
|
-
const
|
|
285
|
+
const clusterCount = getters['management/all'](COUNT)?.[0]?.counts?.[MANAGEMENT.CLUSTER]?.summary?.count || 0;
|
|
286
|
+
const localCluster = getters['localCluster'];
|
|
277
287
|
|
|
278
|
-
if (
|
|
288
|
+
if (clusterCount === 1 && !!localCluster) {
|
|
279
289
|
return false;
|
|
280
290
|
} else {
|
|
281
291
|
return true;
|
|
@@ -592,10 +602,9 @@ export const getters = {
|
|
|
592
602
|
},
|
|
593
603
|
|
|
594
604
|
isStandaloneHarvester(state, getters) {
|
|
595
|
-
const
|
|
596
|
-
const cluster = clusters.find((c) => c.id === 'local') || {};
|
|
605
|
+
const localCluster = getters['localCluster'];
|
|
597
606
|
|
|
598
|
-
return getters['isSingleProduct'] &&
|
|
607
|
+
return getters['isSingleProduct'] && localCluster?.isHarvester && !getters['isRancherInHarvester'];
|
|
599
608
|
},
|
|
600
609
|
|
|
601
610
|
showTopLevelMenu(getters) {
|
|
@@ -640,9 +649,10 @@ export const mutations = {
|
|
|
640
649
|
clearPageActionHandler(state) {
|
|
641
650
|
state.pageActionHandler = null;
|
|
642
651
|
},
|
|
643
|
-
managementChanged(state, { ready, isRancher }) {
|
|
652
|
+
managementChanged(state, { ready, isRancher, localCluster }) {
|
|
644
653
|
state.managementReady = ready;
|
|
645
654
|
state.isRancher = isRancher;
|
|
655
|
+
state.localCluster = localCluster;
|
|
646
656
|
},
|
|
647
657
|
clusterReady(state, ready) {
|
|
648
658
|
state.clusterReady = ready;
|
|
@@ -846,11 +856,21 @@ export const actions = {
|
|
|
846
856
|
|
|
847
857
|
res = await allHash(promises);
|
|
848
858
|
|
|
859
|
+
let localCluster = null;
|
|
860
|
+
|
|
849
861
|
if (!res[MANAGEMENT.SETTING] || !paginateClusters({ rootGetters, state })) {
|
|
850
862
|
// This introduces a synchronous request, however we need settings to determine if SSP is enabled
|
|
851
|
-
|
|
852
|
-
res[MANAGEMENT.CLUSTER] = await dispatch('management/findAll', { type: MANAGEMENT.CLUSTER, opt: { watch: false } });
|
|
863
|
+
await dispatch('management/findAll', { type: MANAGEMENT.CLUSTER, opt: { watch: false } });
|
|
853
864
|
toWatch.push(MANAGEMENT.CLUSTER);
|
|
865
|
+
|
|
866
|
+
localCluster = getters['management/byId'](MANAGEMENT.CLUSTER, 'local');
|
|
867
|
+
} else {
|
|
868
|
+
try {
|
|
869
|
+
localCluster = await dispatch('management/find', {
|
|
870
|
+
type: MANAGEMENT.CLUSTER, id: 'local', opt: { watch: false }
|
|
871
|
+
});
|
|
872
|
+
} catch (e) { // we don't care about errors, specifically 404s
|
|
873
|
+
}
|
|
854
874
|
}
|
|
855
875
|
|
|
856
876
|
// See comment above. Now that we have feature flags we can watch resources
|
|
@@ -858,11 +878,7 @@ export const actions = {
|
|
|
858
878
|
dispatch('management/watch', { type });
|
|
859
879
|
});
|
|
860
880
|
|
|
861
|
-
const isMultiCluster = getters['isMultiCluster'];
|
|
862
|
-
|
|
863
881
|
// If the local cluster is a Harvester cluster and 'rancher-manager-support' is true, it means that the embedded Rancher is being used.
|
|
864
|
-
const localCluster = res[MANAGEMENT.CLUSTER]?.find((c) => c.id === 'local');
|
|
865
|
-
|
|
866
882
|
if (localCluster?.isHarvester) {
|
|
867
883
|
const harvesterSetting = await dispatch('cluster/findAll', { type: HCI.SETTING, opt: { url: `/v1/harvester/${ HCI.SETTING }s` } });
|
|
868
884
|
const rancherManagerSupport = harvesterSetting.find((setting) => setting.id === 'rancher-manager-support');
|
|
@@ -904,6 +920,7 @@ export const actions = {
|
|
|
904
920
|
commit('managementChanged', {
|
|
905
921
|
ready: true,
|
|
906
922
|
isRancher,
|
|
923
|
+
localCluster
|
|
907
924
|
});
|
|
908
925
|
|
|
909
926
|
if ( res[FLEET.WORKSPACE] ) {
|
|
@@ -914,6 +931,8 @@ export const actions = {
|
|
|
914
931
|
});
|
|
915
932
|
}
|
|
916
933
|
|
|
934
|
+
const isMultiCluster = getters['isMultiCluster'];
|
|
935
|
+
|
|
917
936
|
console.log(`Done loading management; isRancher=${ isRancher }; isMultiCluster=${ isMultiCluster }`); // eslint-disable-line no-console
|
|
918
937
|
},
|
|
919
938
|
|
|
@@ -1232,10 +1251,10 @@ export const actions = {
|
|
|
1232
1251
|
}
|
|
1233
1252
|
},
|
|
1234
1253
|
|
|
1235
|
-
|
|
1236
|
-
commit('setRouter',
|
|
1237
|
-
commit('setRoute',
|
|
1238
|
-
commit('setPlugin',
|
|
1254
|
+
dashboardClientInit({ dispatch, commit, rootState }, context) {
|
|
1255
|
+
commit('setRouter', context.app.router);
|
|
1256
|
+
commit('setRoute', context.route);
|
|
1257
|
+
commit('setPlugin', context.app.$plugin);
|
|
1239
1258
|
|
|
1240
1259
|
dispatch('management/rehydrateSubscribe');
|
|
1241
1260
|
dispatch('cluster/rehydrateSubscribe');
|
package/store/notifications.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { md5 } from '@shell/utils/crypto';
|
|
2
2
|
import { randomStr } from '@shell/utils/string';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
EncryptedNotification,
|
|
5
|
+
Notification,
|
|
6
|
+
NotificationLevel,
|
|
7
|
+
NotificationHandlerExtensionName,
|
|
8
|
+
StoredNotification
|
|
9
|
+
} from '@shell/types/notifications';
|
|
4
10
|
import { encrypt, decrypt, deriveKey } from '@shell/utils/crypto/encryption';
|
|
5
11
|
|
|
6
12
|
/**
|
|
@@ -65,6 +71,9 @@ async function saveEncryptedNotification(getters: any, notification: Notificatio
|
|
|
65
71
|
level: notification.level,
|
|
66
72
|
primaryAction: notification.primaryAction,
|
|
67
73
|
secondaryAction: notification.secondaryAction,
|
|
74
|
+
preference: notification.preference,
|
|
75
|
+
handlerName: notification.handlerName,
|
|
76
|
+
data: notification.data,
|
|
68
77
|
};
|
|
69
78
|
|
|
70
79
|
const localStorageKey = getters['localStorageKey'];
|
|
@@ -108,15 +117,23 @@ export const getters = {
|
|
|
108
117
|
return state.notifications;
|
|
109
118
|
},
|
|
110
119
|
|
|
120
|
+
visible: (state: NotificationsStore) => {
|
|
121
|
+
return state.notifications.filter((n) => n.level !== NotificationLevel.Hidden);
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
hidden: (state: NotificationsStore) => {
|
|
125
|
+
return state.notifications.filter((n) => n.level === NotificationLevel.Hidden);
|
|
126
|
+
},
|
|
127
|
+
|
|
111
128
|
item: (state: NotificationsStore) => {
|
|
112
129
|
return (id: string) => {
|
|
113
130
|
return state.notifications.find((i) => i.id === id);
|
|
114
131
|
};
|
|
115
132
|
},
|
|
116
133
|
|
|
117
|
-
// Count of unread notifications
|
|
134
|
+
// Count of unread notifications - only considers visible notifications
|
|
118
135
|
unreadCount: (state: NotificationsStore) => {
|
|
119
|
-
return state.notifications.filter((n) => !n.read).length;
|
|
136
|
+
return state.notifications.filter((n) => !n.read && n.level !== NotificationLevel.Hidden).length;
|
|
120
137
|
},
|
|
121
138
|
|
|
122
139
|
/**
|
|
@@ -192,9 +209,10 @@ export const mutations = {
|
|
|
192
209
|
syncIndex(state);
|
|
193
210
|
},
|
|
194
211
|
|
|
212
|
+
// Only mark visible notifications as read via mark all
|
|
195
213
|
markAllRead(state: NotificationsStore) {
|
|
196
214
|
state.notifications.forEach((notification) => {
|
|
197
|
-
if (!notification.read) {
|
|
215
|
+
if (!notification.read && notification.level !== NotificationLevel.Hidden) {
|
|
198
216
|
notification.read = true;
|
|
199
217
|
}
|
|
200
218
|
});
|
|
@@ -252,6 +270,20 @@ export const mutations = {
|
|
|
252
270
|
},
|
|
253
271
|
};
|
|
254
272
|
|
|
273
|
+
async function callNotifyHandler({ $extension }: any, notification: Notification, read: boolean) {
|
|
274
|
+
if (notification?.handlerName) {
|
|
275
|
+
const handler = $extension.getDynamic(NotificationHandlerExtensionName, notification.handlerName);
|
|
276
|
+
|
|
277
|
+
if (handler) {
|
|
278
|
+
try {
|
|
279
|
+
await handler.onReadUpdated(notification, read);
|
|
280
|
+
} catch (e) {
|
|
281
|
+
console.error('Error invoking notification handler', e); // eslint-disable-line no-console
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
255
287
|
export const actions = {
|
|
256
288
|
async add( { commit, dispatch, getters }: any, notification: Notification) {
|
|
257
289
|
// We encrypt the notification on add - this is the only time we will encrypt it
|
|
@@ -295,6 +327,10 @@ export const actions = {
|
|
|
295
327
|
if (notification?.preference) {
|
|
296
328
|
await dispatch('prefs/set', notification.preference, { root: true });
|
|
297
329
|
}
|
|
330
|
+
|
|
331
|
+
if (notification?.handlerName) {
|
|
332
|
+
await callNotifyHandler({ $extension: (this as any).$extension }, notification, true);
|
|
333
|
+
}
|
|
298
334
|
},
|
|
299
335
|
|
|
300
336
|
async markUnread({ commit, dispatch, getters }: any, id: string) {
|
|
@@ -309,6 +345,10 @@ export const actions = {
|
|
|
309
345
|
value: notification.preference.unsetValue || '',
|
|
310
346
|
}, { root: true });
|
|
311
347
|
}
|
|
348
|
+
|
|
349
|
+
if (notification?.handlerName) {
|
|
350
|
+
await callNotifyHandler({ $extension: (this as any).$extension }, notification, false);
|
|
351
|
+
}
|
|
312
352
|
},
|
|
313
353
|
|
|
314
354
|
async markAllRead({ commit, dispatch, getters }: any) {
|
|
@@ -321,6 +361,13 @@ export const actions = {
|
|
|
321
361
|
for (let i = 0; i < withPreference.length; i++) {
|
|
322
362
|
await dispatch('prefs/set', withPreference[i].preference, { root: true });
|
|
323
363
|
}
|
|
364
|
+
|
|
365
|
+
// For all notifications that have a handler, call the handler
|
|
366
|
+
const withHandler = getters.all.filter((n: Notification) => !!n.handlerName);
|
|
367
|
+
|
|
368
|
+
for (let i = 0; i < withHandler.length; i++) {
|
|
369
|
+
await callNotifyHandler({ $extension: (this as any).$extension }, withHandler[i], true);
|
|
370
|
+
}
|
|
324
371
|
},
|
|
325
372
|
|
|
326
373
|
remove({ commit, getters }: any, id: string) {
|
package/store/plugins.js
CHANGED
|
@@ -43,7 +43,6 @@ export const rke1Supports = [
|
|
|
43
43
|
// Map a credential driver name to a component name
|
|
44
44
|
// e.g. ec2 and eks both use the 'aws' driver to share the same pool of creds.
|
|
45
45
|
const driverMap = {
|
|
46
|
-
aks: 'azure',
|
|
47
46
|
amazonec2: 'aws',
|
|
48
47
|
amazoneks: 'aws',
|
|
49
48
|
amazonelasticcontainerservice: 'aws',
|
|
@@ -62,6 +61,9 @@ const driverToFieldMap = {
|
|
|
62
61
|
aws: 'amazonec2',
|
|
63
62
|
gcp: 'google',
|
|
64
63
|
oracle: 'oci',
|
|
64
|
+
aks: 'azure',
|
|
65
|
+
eks: 'amazonec2',
|
|
66
|
+
gke: 'google'
|
|
65
67
|
};
|
|
66
68
|
|
|
67
69
|
// Machine driver fields that are probably a credential field
|
|
@@ -107,8 +109,10 @@ const driverToCloudProviderMap = {
|
|
|
107
109
|
linode: '', // Show restricted options
|
|
108
110
|
vmwarevsphere: 'rancher-vsphere',
|
|
109
111
|
ovhcloudpubliccloud: '',
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
aks: 'azure',
|
|
113
|
+
eks: 'aws',
|
|
114
|
+
gke: 'google',
|
|
115
|
+
custom: undefined // Show all options
|
|
112
116
|
};
|
|
113
117
|
|
|
114
118
|
// Dynamically loaded drivers can call this eventually to register their options
|
package/store/prefs.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SETTING } from '@shell/config/settings';
|
|
2
2
|
import { MANAGEMENT, STEVE } from '@shell/config/types';
|
|
3
3
|
import { clone } from '@shell/utils/object';
|
|
4
|
+
import { getBrandMeta } from '@shell/utils/brand';
|
|
4
5
|
|
|
5
6
|
const definitions = {};
|
|
6
7
|
/**
|
|
@@ -119,6 +120,7 @@ export const SCALE_POOL_PROMPT = create('scale-pool-prompt', null, { parseJSON }
|
|
|
119
120
|
export const READ_NEW_RELEASE = create('read-new-release', '', { parseJSON });
|
|
120
121
|
export const READ_SUPPORT_NOTICE = create('read-support-notice', '', { parseJSON });
|
|
121
122
|
export const READ_UPCOMING_SUPPORT_NOTICE = create('read-upcoming-support-notice', '', { parseJSON });
|
|
123
|
+
export const READ_ANNOUNCEMENTS = create('read-announcements', '', { parseJSON });
|
|
122
124
|
|
|
123
125
|
// --------------------
|
|
124
126
|
|
|
@@ -521,16 +523,14 @@ export const actions = {
|
|
|
521
523
|
setBrandStyle({ rootState, rootGetters }, dark = false) {
|
|
522
524
|
if (rootState.managementReady) {
|
|
523
525
|
try {
|
|
524
|
-
const brandSetting = rootGetters['management/
|
|
526
|
+
const brandSetting = rootGetters['management/brand'];
|
|
525
527
|
|
|
526
|
-
if (brandSetting
|
|
527
|
-
const
|
|
528
|
-
|
|
529
|
-
const brandMeta = require(`~shell/assets/brand/${ brand }/metadata.json`);
|
|
528
|
+
if (brandSetting !== '') {
|
|
529
|
+
const brandMeta = getBrandMeta(brandSetting);
|
|
530
530
|
const hasStylesheet = brandMeta.hasStylesheet === 'true';
|
|
531
531
|
|
|
532
532
|
if (hasStylesheet) {
|
|
533
|
-
document.body.classList.add(
|
|
533
|
+
document.body.classList.add(brandMeta);
|
|
534
534
|
} else {
|
|
535
535
|
// TODO option apply color at runtime
|
|
536
536
|
}
|
package/store/type-map.js
CHANGED
|
@@ -1895,7 +1895,7 @@ function ifHave(getters, option) {
|
|
|
1895
1895
|
case IF_HAVE.NOT_V1_ISTIO: {
|
|
1896
1896
|
return !isV1Istio(getters);
|
|
1897
1897
|
}
|
|
1898
|
-
case IF_HAVE.MULTI_CLUSTER: {
|
|
1898
|
+
case IF_HAVE.MULTI_CLUSTER: { // Used by harvester extension
|
|
1899
1899
|
return getters.isMultiCluster;
|
|
1900
1900
|
}
|
|
1901
1901
|
case IF_HAVE.NEUVECTOR_NAMESPACE: {
|
|
@@ -1904,10 +1904,10 @@ function ifHave(getters, option) {
|
|
|
1904
1904
|
case IF_HAVE.ADMIN: {
|
|
1905
1905
|
return isAdminUser(getters);
|
|
1906
1906
|
}
|
|
1907
|
-
case IF_HAVE.MCM_DISABLED: {
|
|
1907
|
+
case IF_HAVE.MCM_DISABLED: { // There's a general MCM ff, this is conflating it with a harvester concept
|
|
1908
1908
|
return !getters['isRancherInHarvester'];
|
|
1909
1909
|
}
|
|
1910
|
-
case IF_HAVE.NOT_STANDALONE_HARVESTER: {
|
|
1910
|
+
case IF_HAVE.NOT_STANDALONE_HARVESTER: { // Not used by harvester extension...
|
|
1911
1911
|
return !getters['isStandaloneHarvester'];
|
|
1912
1912
|
}
|
|
1913
1913
|
default:
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
interface Context {
|
|
2
|
+
tag: string;
|
|
3
|
+
value: any;
|
|
4
|
+
hookId?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
icon?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface Element {
|
|
10
|
+
id: number;
|
|
11
|
+
context: Context
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface State {
|
|
15
|
+
idCounter: number;
|
|
16
|
+
elements: Record<string, Element>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const state = function(): State {
|
|
20
|
+
return {
|
|
21
|
+
idCounter: 0,
|
|
22
|
+
elements: {}
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const getters = {
|
|
27
|
+
all: (state: State) => {
|
|
28
|
+
return Object.values(state.elements)
|
|
29
|
+
.map((e) => e.context)
|
|
30
|
+
.sort((a, b) => (a.tag || '').localeCompare(b.tag || '') || 0);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const mutations = {
|
|
35
|
+
add(state: State, element: Element) {
|
|
36
|
+
state.elements[element.id] = element;
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
update(state: State, element: Element) {
|
|
40
|
+
const existingElement = state.elements[element.id];
|
|
41
|
+
|
|
42
|
+
if (existingElement) {
|
|
43
|
+
existingElement.context = element.context;
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
remove(state: State, element: Element) {
|
|
48
|
+
delete state.elements[element.id];
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
let id = null;
|
|
53
|
+
|
|
54
|
+
export const actions = {
|
|
55
|
+
add({ commit, state }: { commit: Function, state: State }, context: Context) {
|
|
56
|
+
if (context?.value === undefined || !context?.tag) {
|
|
57
|
+
throw new Error(`[ui-context] context {{${ JSON.stringify(context) }}} is not valid`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
id = `ctx-${ state.idCounter++ }`;
|
|
61
|
+
|
|
62
|
+
commit('add', { id, context });
|
|
63
|
+
|
|
64
|
+
return id;
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
update({ commit, state }: { commit: Function, state: State }, element: Element) {
|
|
68
|
+
const old = state.elements[element.id];
|
|
69
|
+
|
|
70
|
+
if (!old) {
|
|
71
|
+
throw new Error(`[ui-context] element with id {{${ element.id }}} not found`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
commit('update', element);
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
remove({ commit, state }: { commit: Function, state: State }, id: number) {
|
|
78
|
+
const element = state.elements[id];
|
|
79
|
+
|
|
80
|
+
if (!element) {
|
|
81
|
+
throw new Error(`[ui-context] element with id {{${ id }}} not found`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
commit('remove', element);
|
|
85
|
+
}
|
|
86
|
+
};
|
package/store/wm.ts
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { STORAGE_KEY } from '@shell/components/nav/WindowManager/constants';
|
|
2
|
+
import { Layout, Position, Tab } from '@shell/types/window-manager';
|
|
3
|
+
import { addObject, removeObject } from '@shell/utils/array';
|
|
4
|
+
import { BOTTOM, LEFT, RIGHT } from '@shell/utils/position';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This module defines the Vuex store for the window manager, managing tabs, their positions,
|
|
8
|
+
* active states, panel dimensions, and user preferences.
|
|
9
|
+
*
|
|
10
|
+
* The store can be used to add, switch, and close tabs, as well as manage panel dimensions and locked positions.
|
|
11
|
+
* The store can be accessed also by Rancher extensions to integrate to handle the window manager.
|
|
12
|
+
*/
|
|
13
|
+
export interface State {
|
|
14
|
+
tabs: Array<Tab>;
|
|
15
|
+
active: Record<Position | string, string>;
|
|
16
|
+
open: Record<Position | string, boolean>;
|
|
17
|
+
panelHeight: Record<Position | string, number | null>;
|
|
18
|
+
panelWidth: Record<Position | string, number | null>;
|
|
19
|
+
userPin: Position | string | null;
|
|
20
|
+
lockedPositions: Position[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function moveTabByReference(tabs: Tab[], fromPosition: Position | undefined, toPosition: Position, tabId: string) {
|
|
24
|
+
const idx = tabs.findIndex((t) => t.id === tabId && t.position === fromPosition);
|
|
25
|
+
|
|
26
|
+
if (idx === -1) return;
|
|
27
|
+
const [tab] = tabs.splice(idx, 1);
|
|
28
|
+
|
|
29
|
+
tab.position = toPosition;
|
|
30
|
+
|
|
31
|
+
tabs.push(tab);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const state = function() {
|
|
35
|
+
return {
|
|
36
|
+
tabs: [],
|
|
37
|
+
active: {},
|
|
38
|
+
open: {},
|
|
39
|
+
panelHeight: { [BOTTOM]: window.localStorage.getItem(STORAGE_KEY[BOTTOM]) },
|
|
40
|
+
panelWidth: {
|
|
41
|
+
[LEFT]: window.localStorage.getItem(STORAGE_KEY[LEFT]),
|
|
42
|
+
[RIGHT]: window.localStorage.getItem(STORAGE_KEY[RIGHT]),
|
|
43
|
+
},
|
|
44
|
+
userPin: null,
|
|
45
|
+
lockedPositions: [],
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const getters = {
|
|
50
|
+
byId: (state: State) => (id: string) => state.tabs.find((x) => x.id === id),
|
|
51
|
+
tabs: (state: State) => state.tabs,
|
|
52
|
+
isOpen: (state: State) => (position: string) => state.open[position],
|
|
53
|
+
panelWidth: (state: State) => state.panelWidth,
|
|
54
|
+
panelHeight: (state: State) => state.panelHeight,
|
|
55
|
+
userPin: (state: State) => state.userPin,
|
|
56
|
+
lockedPositions: (state: State) => state.lockedPositions,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const mutations = {
|
|
60
|
+
/**
|
|
61
|
+
* Adds a new tab to the window manager.
|
|
62
|
+
*
|
|
63
|
+
* Usage:
|
|
64
|
+
*
|
|
65
|
+
* store.dispatch('wm/open', {
|
|
66
|
+
* id: PRODUCT_NAME,
|
|
67
|
+
* extensionId: PRODUCT_NAME,
|
|
68
|
+
* label: 'Label',
|
|
69
|
+
* component: 'LabelComponent',
|
|
70
|
+
* position: 'bottom',
|
|
71
|
+
* layouts: [
|
|
72
|
+
* Layout.default,
|
|
73
|
+
* Layout.home
|
|
74
|
+
* ],
|
|
75
|
+
* showHeader: false,
|
|
76
|
+
* }, { root: true });
|
|
77
|
+
*
|
|
78
|
+
* This will add a new tab with the specified properties to the window manager and set it as active.
|
|
79
|
+
*/
|
|
80
|
+
addTab(state: State, tab: Tab) {
|
|
81
|
+
const existing = state.tabs.find((x) => x.id === tab.id);
|
|
82
|
+
|
|
83
|
+
if (tab.position === undefined || tab.position as string === 'undefined') {
|
|
84
|
+
tab.position = (window.localStorage.getItem(STORAGE_KEY['pin']) || BOTTOM) as Position;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!existing) {
|
|
88
|
+
if (state.lockedPositions.includes(BOTTOM)) {
|
|
89
|
+
tab.position = BOTTOM;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (tab.layouts === undefined) {
|
|
93
|
+
tab.layouts = [Layout.default];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (tab.showHeader === undefined) {
|
|
97
|
+
tab.showHeader = true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
addObject(state.tabs, tab);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
state.active[tab.position] = tab.id;
|
|
104
|
+
state.open = { ...state.open, [tab.position]: true };
|
|
105
|
+
|
|
106
|
+
state.userPin = tab.position;
|
|
107
|
+
window.localStorage.setItem(STORAGE_KEY['pin'], tab.position);
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Switches a tab to a different position within the window manager.
|
|
112
|
+
*
|
|
113
|
+
* Usage:
|
|
114
|
+
* store.commit('wm/switchTab', { tabId: 'tab1', targetPosition: LEFT });
|
|
115
|
+
*
|
|
116
|
+
* This will move the tab with ID 'tab1' to the LEFT position and update the active tab accordingly.
|
|
117
|
+
*/
|
|
118
|
+
switchTab(state: State, { tabId, targetPosition }: { tabId: string, targetPosition: Position }) {
|
|
119
|
+
const current = { ...(state.tabs.find((x) => x.id === tabId) || {}) };
|
|
120
|
+
|
|
121
|
+
if (current) {
|
|
122
|
+
moveTabByReference(state.tabs, current.position, targetPosition, tabId);
|
|
123
|
+
|
|
124
|
+
state.active[targetPosition] = tabId;
|
|
125
|
+
state.open = { ...state.open, [targetPosition]: true };
|
|
126
|
+
|
|
127
|
+
if (current.position !== targetPosition) {
|
|
128
|
+
const oldPositionTabs = state.tabs.filter((t) => t.position === current.position);
|
|
129
|
+
|
|
130
|
+
if (current.position) {
|
|
131
|
+
state.active[current.position] = oldPositionTabs[0]?.id || '';
|
|
132
|
+
state.open[current.position] = oldPositionTabs.length > 0;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
state.userPin = targetPosition;
|
|
138
|
+
window.localStorage.setItem(STORAGE_KEY['pin'], targetPosition);
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
closeTab(state: State, { id }: { id: string }) {
|
|
142
|
+
const tab = state.tabs.find((x) => x.id === id);
|
|
143
|
+
|
|
144
|
+
if ( !tab ) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let idx = state.tabs.indexOf(tab);
|
|
149
|
+
|
|
150
|
+
removeObject(state.tabs, tab);
|
|
151
|
+
if ( idx >= state.tabs.length ) {
|
|
152
|
+
idx = state.tabs.length - 1;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if ( idx >= 0 ) {
|
|
156
|
+
state.active[tab.position] = state.tabs[idx].id;
|
|
157
|
+
} else {
|
|
158
|
+
state.open[tab.position] = false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const oldPositionTabs = state.tabs.filter((t) => t.position === tab.position);
|
|
162
|
+
|
|
163
|
+
if (tab.position) {
|
|
164
|
+
state.active[tab.position] = oldPositionTabs[0]?.id || '';
|
|
165
|
+
state.open[tab.position] = oldPositionTabs.length > 0;
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
removeTab(state: State, tab: Tab) {
|
|
170
|
+
removeObject(state.tabs, tab);
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
setOpen(state: State, { position, open }: { position: string, open: boolean }) {
|
|
174
|
+
state.open = { ...state.open, [position]: open };
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
setActive(state: State, { position, id }: { position: string, id: string }) {
|
|
178
|
+
state.active[position] = id;
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
setPanelHeight(state: State, { position, height }: { position: string, height: number | null }) {
|
|
182
|
+
state.panelHeight[position] = height;
|
|
183
|
+
window.localStorage.setItem(STORAGE_KEY[BOTTOM], `${ height }`);
|
|
184
|
+
|
|
185
|
+
for (const tab of state.tabs) {
|
|
186
|
+
if (tab.position === position) {
|
|
187
|
+
tab.containerHeight = height;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
setPanelWidth(state: State, { position, width }: { position: Position, width: number | null }) {
|
|
193
|
+
state.panelWidth[position] = width;
|
|
194
|
+
window.localStorage.setItem(STORAGE_KEY[position as keyof typeof STORAGE_KEY], `${ width }`);
|
|
195
|
+
|
|
196
|
+
for (const tab of state.tabs) {
|
|
197
|
+
if (tab.position === position) {
|
|
198
|
+
tab.containerWidth = width;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Sets the user's preferred pin position for tabs in the window manager.
|
|
205
|
+
*
|
|
206
|
+
* Usage:
|
|
207
|
+
* store.commit('wm/setUserPin', LEFT);
|
|
208
|
+
*
|
|
209
|
+
* This will set the user's preferred pin position to LEFT and store it in local storage.
|
|
210
|
+
*/
|
|
211
|
+
setUserPin(state: State, pin: string) {
|
|
212
|
+
state.userPin = pin;
|
|
213
|
+
window.localStorage.setItem(STORAGE_KEY['pin'], pin);
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Sets the locked positions for tabs in the window manager.
|
|
218
|
+
*
|
|
219
|
+
* Usage:
|
|
220
|
+
* store.commit('wm/setLockedPositions', [LEFT, RIGHT]);
|
|
221
|
+
*
|
|
222
|
+
* This will lock tabs to the specified positions, preventing them from being moved elsewhere.
|
|
223
|
+
*/
|
|
224
|
+
setLockedPositions(state: State, positions: Position[]) {
|
|
225
|
+
state.lockedPositions = positions;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
export const actions = {
|
|
230
|
+
close({ commit }: { state: State, getters: any, commit: any }, id: string) {
|
|
231
|
+
if ( !id ) {
|
|
232
|
+
throw new Error('[wm] id is not provided');
|
|
233
|
+
}
|
|
234
|
+
commit('closeTab', { id });
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
open({ commit }: { commit: any }, tab: Tab) {
|
|
238
|
+
if ( !tab.id ) {
|
|
239
|
+
throw new Error('[wm] id is not provided');
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
commit('addTab', tab);
|
|
243
|
+
}
|
|
244
|
+
};
|