@rancher/shell 3.0.4 → 3.0.5-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/images/providers/sks.svg +1 -0
- package/assets/styles/base/_basic.scss +6 -0
- package/assets/styles/base/_helpers.scss +4 -0
- package/assets/styles/base/_variables.scss +1 -0
- package/assets/styles/global/_button.scss +1 -0
- package/assets/translations/en-us.yaml +65 -15
- package/assets/translations/zh-hans.yaml +4 -3
- package/chart/monitoring/index.vue +3 -1
- package/cloud-credential/aws.vue +2 -0
- package/components/ActionDropdownShell.vue +71 -0
- package/components/AppModal.vue +18 -4
- package/components/AsyncButton.vue +24 -7
- package/components/BannerGraphic.vue +1 -0
- package/components/CommunityLinks.vue +4 -59
- package/components/CopyToClipboardText.vue +2 -1
- package/components/CruResource.vue +6 -1
- package/components/DetailText.vue +5 -0
- package/components/ExplorerMembers.vue +1 -1
- package/components/ExplorerProjectsNamespaces.vue +68 -18
- package/components/GlobalRoleBindings.vue +5 -1
- package/components/GrowlManager.vue +1 -0
- package/components/LandingPagePreference.vue +7 -3
- package/components/LocaleSelector.vue +39 -95
- package/components/ModalManager.vue +55 -0
- package/components/ModalWithCard.vue +1 -0
- package/components/PromptModal.vue +47 -8
- package/components/PromptRemove.vue +1 -0
- package/components/PromptRestore.vue +1 -0
- package/components/ResourceCancelModal.vue +1 -0
- package/components/ResourceDetail/Masthead.vue +38 -12
- package/components/ResourceDetail/__tests__/Masthead.test.ts +5 -1
- package/components/ResourceDetail/index.vue +47 -12
- package/components/ResourceTable.vue +54 -19
- package/components/SideNav.vue +5 -1
- package/components/SlideInPanelManager.vue +126 -0
- package/components/SortableTable/THead.vue +5 -2
- package/components/SortableTable/actions.js +1 -1
- package/components/SortableTable/index.vue +64 -51
- package/components/SortableTable/paging.js +16 -19
- package/components/SortableTable/selection.js +0 -11
- package/components/Wizard.vue +2 -2
- package/components/__tests__/AsyncButton.test.ts +2 -2
- package/components/__tests__/ModalManager.spec.ts +176 -0
- package/components/__tests__/PromptModal.test.ts +148 -0
- package/components/__tests__/SlideInPanelManager.spec.ts +166 -0
- package/components/auth/AuthBanner.vue +13 -11
- package/components/auth/Principal.vue +1 -0
- package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
- package/components/auth/login/ldap.vue +1 -1
- package/components/fleet/FleetResources.vue +21 -6
- package/components/form/ArrayList.vue +76 -60
- package/components/form/BannerSettings.vue +17 -2
- package/components/form/ColorInput.vue +35 -6
- package/components/form/Command.vue +6 -15
- package/components/form/EnvVars.vue +16 -8
- package/components/form/HealthCheck.vue +3 -3
- package/components/form/HookOption.vue +11 -16
- package/components/form/LabeledSelect.vue +18 -22
- package/components/form/LifecycleHooks.vue +3 -3
- package/components/form/MatchExpressions.vue +14 -8
- package/components/form/NameNsDescription.vue +128 -104
- package/components/form/Networking.vue +20 -12
- package/components/form/NodeAffinity.vue +31 -23
- package/components/form/NodeScheduling.vue +13 -3
- package/components/form/NotificationSettings.vue +15 -1
- package/components/form/Password.vue +1 -0
- package/components/form/PodAffinity.vue +43 -43
- package/components/form/Probe.vue +68 -66
- package/components/form/ResourceQuota/Project.vue +5 -1
- package/components/form/ResourceSelector.vue +7 -9
- package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +16 -24
- package/components/form/SSHKnownHosts/index.vue +30 -13
- package/components/form/Security.vue +54 -56
- package/components/form/Select.vue +32 -21
- package/components/form/ShellInput.vue +5 -1
- package/components/form/Tolerations.vue +5 -1
- package/components/form/ValueFromResource.vue +134 -121
- package/components/form/WorkloadPorts.vue +18 -18
- package/components/form/__tests__/ArrayList.test.ts +5 -2
- package/components/form/__tests__/ColorInput.test.ts +35 -0
- package/components/form/__tests__/LabeledSelect.test.ts +40 -0
- package/components/form/__tests__/MatchExpressions.test.ts +12 -12
- package/components/form/__tests__/NameNsDescription.test.ts +115 -14
- package/components/form/__tests__/Probe.test.ts +12 -8
- package/components/form/__tests__/SSHKnownHosts.test.ts +22 -2
- package/components/form/__tests__/Select.test.ts +37 -0
- package/components/formatter/InternalExternalIP.vue +2 -0
- package/components/formatter/SecretData.vue +20 -7
- package/components/nav/Group.vue +27 -5
- package/components/nav/Header.vue +17 -43
- package/components/nav/NamespaceFilter.vue +134 -86
- package/components/nav/TopLevelMenu.vue +4 -5
- package/components/nav/Type.vue +12 -1
- package/components/nav/WindowManager/ContainerLogs.vue +87 -61
- package/components/nav/WindowManager/ContainerLogsActions.vue +76 -0
- package/components/templates/blank.vue +4 -1
- package/components/templates/default.vue +8 -3
- package/components/templates/home.vue +10 -1
- package/components/templates/plain.vue +10 -4
- package/composables/focusTrap.ts +12 -4
- package/composables/useRuntimeFlag.ts +29 -0
- package/config/router/routes.js +20 -13
- package/config/store.js +4 -0
- package/config/uiplugins.js +5 -1
- package/core/types.ts +12 -6
- package/detail/catalog.cattle.io.app.vue +6 -1
- package/detail/fleet.cattle.io.bundle.vue +70 -6
- package/detail/fleet.cattle.io.gitrepo.vue +1 -1
- package/detail/namespace.vue +0 -3
- package/detail/node.vue +17 -13
- package/detail/provisioning.cattle.io.cluster.vue +72 -6
- package/dialog/AddCustomBadgeDialog.vue +1 -1
- package/{pages/c/_cluster/uiplugins/AddExtensionRepos.vue → dialog/AddExtensionReposDialog.vue} +72 -42
- package/{components/AssignTo.vue → dialog/AssignToDialog.vue} +71 -80
- package/dialog/ChangePasswordDialog.vue +106 -0
- package/dialog/DeactivateDriverDialog.vue +1 -0
- package/{pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue → dialog/DeveloperLoadExtensionDialog.vue} +74 -71
- package/dialog/DisableAuthProviderDialog.vue +101 -0
- package/dialog/DrainNode.vue +1 -1
- package/{pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue → dialog/ExtensionCatalogInstallDialog.vue} +100 -88
- package/{pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue → dialog/ExtensionCatalogUninstallDialog.vue} +69 -57
- package/dialog/FeatureFlagListDialog.vue +288 -0
- package/dialog/ForceMachineRemoveDialog.vue +5 -2
- package/{components/Import.vue → dialog/ImportDialog.vue} +0 -5
- package/{pages/c/_cluster/uiplugins/InstallDialog.vue → dialog/InstallExtensionDialog.vue} +124 -106
- package/{components/form/SSHKnownHosts → dialog}/KnownHostsEditDialog.vue +52 -59
- package/dialog/MoveNamespaceDialog.vue +157 -0
- package/dialog/ScalePoolDownDialog.vue +1 -1
- package/{components/nav/Jump.vue → dialog/SearchDialog.vue} +34 -14
- package/{pages/c/_cluster/uiplugins/UninstallDialog.vue → dialog/UninstallExtensionDialog.vue} +67 -58
- package/dialog/WechatDialog.vue +57 -0
- package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +16 -3
- package/edit/auth/__tests__/oidc.test.ts +152 -109
- package/edit/auth/azuread.vue +2 -1
- package/edit/auth/github.vue +1 -1
- package/edit/auth/googleoauth.vue +5 -1
- package/edit/auth/ldap/index.vue +1 -1
- package/edit/auth/oidc.vue +38 -5
- package/edit/auth/saml.vue +1 -1
- package/edit/cloudcredential.vue +24 -9
- package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +40 -9
- package/edit/management.cattle.io.user.vue +28 -3
- package/edit/namespace.vue +1 -4
- package/edit/networking.k8s.io.ingress/IngressClass.vue +7 -3
- package/edit/networking.k8s.io.ingress/__tests__/IngressClass.test.ts +58 -0
- package/edit/persistentvolume/__tests__/persistentvolume.test.ts +14 -2
- package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +4 -1
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +26 -9
- package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +8 -8
- package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +26 -12
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +66 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/utils/rke2-test-data.ts +58 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +49 -41
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +6 -1
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +5 -3
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +33 -2
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +2 -2
- package/edit/token.vue +2 -0
- package/edit/workload/index.vue +1 -0
- package/edit/workload/mixins/workload.js +0 -2
- package/initialize/install-plugins.js +2 -1
- package/list/harvesterhci.io.management.cluster.vue +4 -1
- package/list/management.cattle.io.feature.vue +4 -287
- package/list/provisioning.cattle.io.cluster.vue +20 -12
- package/machine-config/azure.vue +16 -4
- package/mixins/vue-select-overrides.js +0 -4
- package/models/__tests__/namespace.test.ts +25 -1
- package/models/cloudcredential.js +5 -0
- package/models/fleet.cattle.io.cluster.js +8 -2
- package/models/fleet.cattle.io.gitrepo.js +8 -34
- package/models/kontainerdriver.js +6 -3
- package/models/management.cattle.io.feature.js +7 -1
- package/models/management.cattle.io.node.js +3 -3
- package/models/namespace.js +11 -6
- package/models/nodedriver.js +6 -3
- package/models/workload.js +4 -1
- package/package.json +3 -3
- package/pages/about.vue +13 -3
- package/pages/account/index.vue +16 -6
- package/pages/auth/login.vue +18 -7
- package/pages/auth/logout.vue +4 -1
- package/pages/auth/setup.vue +2 -0
- package/pages/auth/verify.vue +13 -8
- package/pages/c/_cluster/apps/charts/chart.vue +1 -1
- package/pages/c/_cluster/apps/charts/install.vue +26 -26
- package/pages/c/_cluster/auth/config/index.vue +10 -12
- package/pages/c/_cluster/explorer/EventsTable.vue +38 -33
- package/pages/c/_cluster/explorer/index.vue +17 -15
- package/pages/c/_cluster/istio/index.vue +2 -2
- package/pages/c/_cluster/longhorn/index.vue +1 -1
- package/pages/c/_cluster/monitoring/index.vue +1 -1
- package/pages/c/_cluster/monitoring/monitor/_namespace/_id.vue +4 -2
- package/pages/c/_cluster/monitoring/monitor/create.vue +4 -2
- package/pages/c/_cluster/monitoring/route-receiver/_id.vue +4 -2
- package/pages/c/_cluster/monitoring/route-receiver/create.vue +5 -2
- package/pages/c/_cluster/neuvector/index.vue +1 -1
- package/pages/c/_cluster/settings/banners.vue +4 -3
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +8 -10
- package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +4 -7
- package/pages/c/_cluster/uiplugins/index.vue +98 -55
- package/pages/diagnostic.vue +59 -11
- package/pages/fail-whale.vue +14 -8
- package/pages/home.vue +24 -18
- package/pages/prefs.vue +7 -6
- package/pages/support/index.vue +4 -1
- package/plugins/internal-api/index.ts +37 -0
- package/plugins/internal-api/shared/base-api.ts +13 -0
- package/plugins/internal-api/shell/shell.api.ts +108 -0
- package/plugins/steve/actions.js +0 -12
- package/public/index.html +1 -0
- package/rancher-components/Card/Card.vue +1 -1
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +59 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +27 -3
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +47 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +20 -2
- package/rancher-components/Form/Radio/RadioButton.test.ts +36 -1
- package/rancher-components/Form/Radio/RadioButton.vue +20 -4
- package/rancher-components/Form/Radio/RadioGroup.test.ts +60 -0
- package/rancher-components/Form/Radio/RadioGroup.vue +52 -10
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +17 -0
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +5 -0
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +10 -1
- package/rancher-components/RcButton/RcButton.vue +2 -1
- package/rancher-components/RcButton/types.ts +1 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +18 -6
- package/rancher-components/RcDropdown/RcDropdownItem.vue +3 -56
- package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +68 -0
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +92 -0
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -0
- package/rancher-components/RcDropdown/index.ts +2 -0
- package/rancher-components/RcDropdown/useDropdownCollection.ts +8 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +9 -3
- package/rancher-components/RcDropdown/useDropdownItem.ts +63 -0
- package/scripts/extension/bundle +20 -0
- package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +2 -1
- package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +2 -0
- package/scripts/extension/helmpatch +44 -31
- package/scripts/extension/publish +12 -12
- package/scripts/typegen.sh +2 -4
- package/server/har-file.js +25 -3
- package/store/action-menu.js +26 -56
- package/store/features.js +2 -1
- package/store/index.js +5 -0
- package/store/modal.ts +71 -0
- package/store/slideInPanel.ts +47 -0
- package/store/type-map.js +12 -1
- package/store/type-map.utils.ts +4 -4
- package/types/global-vue.d.ts +5 -0
- package/types/internal-api/shell/growl.d.ts +25 -0
- package/types/internal-api/shell/modal.d.ts +77 -0
- package/types/internal-api/shell/slideIn.d.ts +15 -0
- package/types/resources/fleet.d.ts +0 -14
- package/types/shell/index.d.ts +43 -24
- package/types/vue-shim.d.ts +4 -1
- package/utils/__mocks__/tabbable.js +13 -0
- package/utils/__tests__/object.test.ts +38 -4
- package/utils/cluster.js +35 -0
- package/utils/fleet.ts +15 -73
- package/utils/object.js +48 -5
- package/utils/validators/formRules/__tests__/index.test.ts +10 -1
- package/utils/validators/formRules/index.ts +27 -3
- package/utils/validators/machine-pool.ts +20 -0
- package/components/DisableAuthProviderModal.vue +0 -114
- package/components/MoveModal.vue +0 -166
- package/components/PromptChangePassword.vue +0 -123
- package/components/fleet/FleetBundleResources.vue +0 -86
- package/components/formatter/ExtensionCache.vue +0 -74
- package/components/formatter/Port.vue +0 -24
- package/components/formatter/SecretType.vue +0 -41
- package/types/vue-shim.d +0 -20
|
@@ -17,6 +17,7 @@ export const useDropdownContext = (emit: typeof rcDropdownEmits) => {
|
|
|
17
17
|
const {
|
|
18
18
|
dropdownItems,
|
|
19
19
|
firstDropdownItem,
|
|
20
|
+
lastDropdownItem,
|
|
20
21
|
dropdownContainer,
|
|
21
22
|
registerDropdownCollection,
|
|
22
23
|
} = useDropdownCollection();
|
|
@@ -70,7 +71,7 @@ export const useDropdownContext = (emit: typeof rcDropdownEmits) => {
|
|
|
70
71
|
/**
|
|
71
72
|
* Sets focus to the first dropdown item if a keydown event has occurred.
|
|
72
73
|
*/
|
|
73
|
-
const setFocus = () => {
|
|
74
|
+
const setFocus = (direction: 'down' | 'up') => {
|
|
74
75
|
nextTick(() => {
|
|
75
76
|
if (!didKeydown.value) {
|
|
76
77
|
dropdownContainer.value?.focus();
|
|
@@ -78,7 +79,12 @@ export const useDropdownContext = (emit: typeof rcDropdownEmits) => {
|
|
|
78
79
|
return;
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
if (direction === 'down') {
|
|
83
|
+
firstDropdownItem.value?.focus();
|
|
84
|
+
} else if (direction === 'up') {
|
|
85
|
+
lastDropdownItem.value?.focus();
|
|
86
|
+
}
|
|
87
|
+
|
|
82
88
|
didKeydown.value = false;
|
|
83
89
|
});
|
|
84
90
|
};
|
|
@@ -95,7 +101,7 @@ export const useDropdownContext = (emit: typeof rcDropdownEmits) => {
|
|
|
95
101
|
dropdownItems,
|
|
96
102
|
close: () => returnFocus(),
|
|
97
103
|
focusFirstElement: () => {
|
|
98
|
-
setFocus();
|
|
104
|
+
setFocus('down');
|
|
99
105
|
},
|
|
100
106
|
handleKeydown,
|
|
101
107
|
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { inject } from 'vue';
|
|
2
|
+
import { DropdownContext, defaultContext } from './types';
|
|
3
|
+
|
|
4
|
+
export const useDropdownItem = () => {
|
|
5
|
+
const { dropdownItems, close } = inject<DropdownContext>('dropdownContext') || defaultContext;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Handles keydown events to navigate between dropdown items.
|
|
9
|
+
* @param {KeyboardEvent} e - The keydown event.
|
|
10
|
+
*/
|
|
11
|
+
const handleKeydown = (e: KeyboardEvent) => {
|
|
12
|
+
const activeItem = document.activeElement;
|
|
13
|
+
|
|
14
|
+
const activeIndex = dropdownItems.value.indexOf(activeItem || new HTMLElement());
|
|
15
|
+
|
|
16
|
+
if (activeIndex < 0) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const shouldAdvance = e.key === 'ArrowDown';
|
|
21
|
+
|
|
22
|
+
const newIndex = findNewIndex(shouldAdvance, activeIndex, dropdownItems.value);
|
|
23
|
+
|
|
24
|
+
if (dropdownItems.value[newIndex] instanceof HTMLElement) {
|
|
25
|
+
dropdownItems.value[newIndex].focus();
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Finds the new index for the dropdown item based on the key pressed.
|
|
31
|
+
* @param shouldAdvance - Whether to advance to the next or previous item.
|
|
32
|
+
* @param activeIndex - Current active index.
|
|
33
|
+
* @param itemsArr - Array of dropdown items.
|
|
34
|
+
* @returns The new index.
|
|
35
|
+
*/
|
|
36
|
+
const findNewIndex = (shouldAdvance: boolean, activeIndex: number, itemsArr: Element[]) => {
|
|
37
|
+
const newIndex = shouldAdvance ? activeIndex + 1 : activeIndex - 1;
|
|
38
|
+
|
|
39
|
+
if (newIndex > itemsArr.length - 1) {
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (newIndex < 0) {
|
|
44
|
+
return itemsArr.length - 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return newIndex;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Handles keydown events to activate the dropdown item.
|
|
52
|
+
* @param e - The keydown event.
|
|
53
|
+
*/
|
|
54
|
+
const handleActivate = (e: KeyboardEvent) => {
|
|
55
|
+
if (e?.target instanceof HTMLElement) {
|
|
56
|
+
e?.target?.click();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
handleKeydown, close, handleActivate
|
|
62
|
+
};
|
|
63
|
+
};
|
package/scripts/extension/bundle
CHANGED
|
@@ -29,12 +29,32 @@ cp -R ${CHART_TEMPLATE}/* ${TMP}/container/
|
|
|
29
29
|
# Copy the plugin assets
|
|
30
30
|
mkdir -p ${TMP}/container/plugin
|
|
31
31
|
|
|
32
|
+
# Copy Helm charts and plugin assets
|
|
32
33
|
cp -R ${BASE_DIR}/assets/* ${TMP}/container/plugin
|
|
33
34
|
cp ${BASE_DIR}/package.json ${TMP}/container/plugin
|
|
34
35
|
cp ${BASE_DIR}/index.yaml ${TMP}/container/
|
|
35
36
|
cp ${BASE_DIR}/index.yaml ${TMP}/container/plugin
|
|
36
37
|
rm -f ${TMP}/container/plugin/report.html
|
|
37
38
|
|
|
39
|
+
# Add extension .tgz files with proper naming
|
|
40
|
+
echo -e "${CYAN}Copying extension archives...${RESET}"
|
|
41
|
+
for pkg_dir in ${BASE_DIR}/extensions/*/; do
|
|
42
|
+
pkg=$(basename "${pkg_dir}")
|
|
43
|
+
echo -e "Processing package: ${pkg}"
|
|
44
|
+
|
|
45
|
+
# Find all .tgz files in the package directory
|
|
46
|
+
for tgz_path in "${pkg_dir}"*.tgz; do
|
|
47
|
+
if [ -f "${tgz_path}" ]; then
|
|
48
|
+
# Extract version from filename
|
|
49
|
+
version=$(basename "${tgz_path}" .tgz)
|
|
50
|
+
compressed_package_name="${pkg}-${version}.tgz"
|
|
51
|
+
|
|
52
|
+
echo "Copying ${tgz_path} to ${TMP}/container/plugin/${compressed_package_name}"
|
|
53
|
+
cp "${tgz_path}" "${TMP}/container/plugin/${compressed_package_name}"
|
|
54
|
+
fi
|
|
55
|
+
done
|
|
56
|
+
done
|
|
57
|
+
|
|
38
58
|
# Generate files.txt for each pkg and move pkg files into relative plugin directories
|
|
39
59
|
for d in ${BASE_DIR}/dist-pkg/*; do
|
|
40
60
|
pkg=$(basename $d)
|
|
@@ -8,7 +8,8 @@ spec:
|
|
|
8
8
|
plugin:
|
|
9
9
|
name: {{ include "extension-server.fullname" . }}
|
|
10
10
|
version: {{ (semver (default .Chart.AppVersion .Values.plugin.versionOverride)).Original }}
|
|
11
|
-
endpoint:
|
|
11
|
+
endpoint: {{ .Values.plugin.endpoint | quote }}
|
|
12
|
+
compressedEndpoint: {{ .Values.plugin.compressedEndpoint | quote }}
|
|
12
13
|
noCache: {{ .Values.plugin.noCache }}
|
|
13
14
|
noAuth: {{ .Values.plugin.noAuth }}
|
|
14
15
|
metadata: {{ include "extension-server.pluginMetadata" . | indent 6 }}
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// Update Chart.yaml and values.yaml files
|
|
4
|
-
|
|
5
3
|
const fs = require('fs');
|
|
6
4
|
const path = require('path');
|
|
7
5
|
const yaml = require('js-yaml');
|
|
8
6
|
|
|
9
|
-
// TODO: Should already be in the template
|
|
10
|
-
// const UI_PLUGIN_ANNOTATION_NAME = 'catalog.cattle.io/ui-component';
|
|
11
|
-
// const UI_PLUGIN_ANNOTATION_VALUE = 'plugins';
|
|
12
|
-
|
|
13
7
|
console.log('Helm file update');
|
|
14
8
|
|
|
15
9
|
if (process.argv.length !== 4) {
|
|
@@ -17,12 +11,10 @@ if (process.argv.length !== 4) {
|
|
|
17
11
|
process.exit(1);
|
|
18
12
|
}
|
|
19
13
|
|
|
20
|
-
const
|
|
14
|
+
const chartFolder = process.argv[2];
|
|
21
15
|
const pkgFilePath = process.argv[3];
|
|
22
16
|
|
|
23
17
|
const pkgFile = JSON.parse(fs.readFileSync(pkgFilePath, 'utf8'));
|
|
24
|
-
|
|
25
|
-
const chartFolder = destFolder;
|
|
26
18
|
const chartFile = path.join(chartFolder, 'Chart.yaml');
|
|
27
19
|
const valuesFile = path.join(chartFolder, 'values.yaml');
|
|
28
20
|
|
|
@@ -32,36 +24,57 @@ if (!fs.existsSync(chartFolder)) {
|
|
|
32
24
|
}
|
|
33
25
|
|
|
34
26
|
// --------------------------------------------------------------------------------
|
|
35
|
-
// Chart.yaml
|
|
27
|
+
// Chart.yaml updates (annotations)
|
|
36
28
|
// --------------------------------------------------------------------------------
|
|
37
29
|
const chart = yaml.load(fs.readFileSync(chartFile, 'utf8'));
|
|
38
|
-
let
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
});
|
|
49
|
-
}
|
|
30
|
+
let chartUpdated = false;
|
|
31
|
+
|
|
32
|
+
if (pkgFile.rancher?.annotations) {
|
|
33
|
+
chart.annotations = chart.annotations || {};
|
|
34
|
+
Object.entries(pkgFile.rancher.annotations).forEach(([key, value]) => {
|
|
35
|
+
if (chart.annotations[key] !== value) {
|
|
36
|
+
chart.annotations[key] = value;
|
|
37
|
+
chartUpdated = true;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
50
40
|
}
|
|
51
41
|
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
fs.writeFileSync(chartFile, str, 'utf8');
|
|
42
|
+
if (chartUpdated) {
|
|
43
|
+
fs.writeFileSync(chartFile, yaml.dump(chart), 'utf8');
|
|
44
|
+
console.log('Updated Chart.yaml annotations');
|
|
57
45
|
}
|
|
58
46
|
|
|
59
47
|
// --------------------------------------------------------------------------------
|
|
60
|
-
// values.yaml
|
|
48
|
+
// values.yaml updates (endpoints)
|
|
61
49
|
// --------------------------------------------------------------------------------
|
|
62
|
-
|
|
63
50
|
const values = yaml.load(fs.readFileSync(valuesFile, 'utf8'));
|
|
64
51
|
|
|
65
|
-
|
|
52
|
+
// Get package metadata from package.json
|
|
53
|
+
const pkgName = pkgFile.name;
|
|
54
|
+
const pkgVersion = pkgFile.version;
|
|
55
|
+
const pkgFullName = `${ pkgName }-${ pkgVersion }`;
|
|
56
|
+
|
|
57
|
+
// Determine build type from environment
|
|
58
|
+
const isGitHubBuild = process.env.GITHUB_BUILD === 'true';
|
|
59
|
+
|
|
60
|
+
// Set endpoints based on build type
|
|
61
|
+
if (isGitHubBuild) {
|
|
62
|
+
const githubSource = process.env.GITHUB_SOURCE;
|
|
63
|
+
const githubBranch = process.env.GITHUB_BRANCH;
|
|
64
|
+
|
|
65
|
+
values.plugin.endpoint = `https://raw.githubusercontent.com/${ githubSource }/${ githubBranch }/extensions/${ pkgName }/${ pkgVersion }`;
|
|
66
|
+
} else {
|
|
67
|
+
const imagePrefix = process.env.IMAGE_PREFIX || '';
|
|
68
|
+
const baseExt = process.env.BASE_EXT;
|
|
69
|
+
|
|
70
|
+
values.plugin.endpoint = `http://${ imagePrefix }${ baseExt }-svc.cattle-ui-plugin-system:8080/plugin/${ pkgFullName }`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Always set compressedEndpoint as endpoint + .tgz
|
|
74
|
+
values.plugin.compressedEndpoint = `${ values.plugin.endpoint }.tgz`;
|
|
66
75
|
|
|
67
|
-
|
|
76
|
+
// Write updated values.yaml
|
|
77
|
+
fs.writeFileSync(valuesFile, yaml.dump(values, { quotingType: '"' }), 'utf8');
|
|
78
|
+
console.log('Updated values.yaml endpoints:');
|
|
79
|
+
console.log(`- endpoint: ${ values.plugin.endpoint }`);
|
|
80
|
+
console.log(`- compressedEndpoint: ${ values.plugin.compressedEndpoint }`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
+
# set -eo pipefail comment out for now because of a Harvester issue
|
|
2
3
|
|
|
3
4
|
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
|
4
5
|
BASE_DIR="$(pwd)"
|
|
@@ -330,6 +331,12 @@ if [ "${UPDATE_LATEST_PACAKGES}" = "true" ]; then
|
|
|
330
331
|
find plugin -type f | sort > files.txt
|
|
331
332
|
popd > /dev/null
|
|
332
333
|
|
|
334
|
+
# --------------------------------------------------------------------------------
|
|
335
|
+
# Package extensions into tgz for the compressedEndpoint
|
|
336
|
+
# --------------------------------------------------------------------------------
|
|
337
|
+
echo -e "${CYAN}Packaging extension into tgz${RESET}"
|
|
338
|
+
tar -czf ${BASE_DIR}/extensions/${pkg}/${PKG_VERSION}.tgz -C ${BASE_DIR}/extensions/${pkg} ${PKG_VERSION}
|
|
339
|
+
|
|
333
340
|
# --------------------------------------------------------------------------------
|
|
334
341
|
# Create the Helm chart
|
|
335
342
|
# --------------------------------------------------------------------------------
|
|
@@ -358,18 +365,11 @@ if [ "${UPDATE_LATEST_PACAKGES}" = "true" ]; then
|
|
|
358
365
|
cp ./pkg/${pkg}/README.md ${CHART_FOLDER}/README.md
|
|
359
366
|
fi
|
|
360
367
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
else
|
|
367
|
-
echo "Patching for container build"
|
|
368
|
-
ENDPOINT=http://${IMAGE_PREFIX}${BASE_EXT}-svc.cattle-ui-plugin-system:8080/plugin/${PKG_NAME}
|
|
369
|
-
fi
|
|
370
|
-
sed -i.bak -e 's@endpoint: .*@endpoint: '"${ENDPOINT}"'@g' cr.yaml
|
|
371
|
-
rm *.bak
|
|
372
|
-
popd > /dev/null
|
|
368
|
+
export GITHUB_BUILD
|
|
369
|
+
export IMAGE_PREFIX
|
|
370
|
+
export BASE_EXT
|
|
371
|
+
export GITHUB_SOURCE
|
|
372
|
+
export GITHUB_BRANCH
|
|
373
373
|
|
|
374
374
|
# Additional patches
|
|
375
375
|
${SCRIPT_DIR}/helmpatch ${CHART_FOLDER} "${BASE_DIR}/pkg/${pkg}/package.json"
|
package/scripts/typegen.sh
CHANGED
|
@@ -63,10 +63,8 @@ rm -rf ${INDEX}
|
|
|
63
63
|
echo "// Auto-generated type definitions for shell" > ${INDEX}
|
|
64
64
|
echo "// Do not modify this file as changes will get overwritten" >> ${INDEX}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
cat "$BASE_DIR/shell/types/vue-shim.d" >> ${INDEX}
|
|
69
|
-
fi
|
|
66
|
+
echo "/// <reference types=\"@rancher/shell/types/vue-shim\" />" >> ${INDEX}
|
|
67
|
+
echo "/// <reference types=\"@rancher/shell/types/global-vue\" />" >> ${INDEX}
|
|
70
68
|
|
|
71
69
|
function processDir() {
|
|
72
70
|
local dir=$1
|
package/server/har-file.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const querystring = require('querystring');
|
|
3
4
|
|
|
4
5
|
// When we receive a request to this URL we will reset the session to replay again from the HAR file
|
|
5
6
|
// This allows the user to refresh the browser and replay the HAR file again
|
|
6
7
|
const RESET_URL = '/api/v1/namespaces/cattle-ui-plugin-system/services/http:ui-plugin-operator:80/proxy/index.json';
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
+
const EXCLUDE_QS = 'exclude';
|
|
10
|
+
|
|
11
|
+
const LEGACY_UI_PLUGIN_INDEX = '/api/v1/namespaces/cattle-ui-plugin-system/services/http:ui-plugin-operator:80/proxy/index.json';
|
|
12
|
+
const NEW_UI_PLUGIN_INDEX = '/v1/uiplugins';
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
15
|
* Load the network requests/responses from the har file
|
|
@@ -113,10 +117,28 @@ function harProxy(responses, folder) {
|
|
|
113
117
|
const url = decodeURIComponent(req.originalUrl);
|
|
114
118
|
let playback = session[req.originalUrl];
|
|
115
119
|
|
|
120
|
+
// Handle case where HAR file was created with older UI Extension API that used the operator
|
|
121
|
+
if (!playback && req.originalUrl.includes(NEW_UI_PLUGIN_INDEX)) {
|
|
122
|
+
// Look for new URl for UI plugins
|
|
123
|
+
playback = session[LEGACY_UI_PLUGIN_INDEX];
|
|
124
|
+
}
|
|
125
|
+
|
|
116
126
|
// If it did not match, try without the metadata excludes query string that was adding in 2.8.0
|
|
117
127
|
// This might allow HAR captures with Rancher < 2.8.0 to be replayed on >= 2.8.0
|
|
118
|
-
if (!playback && req.originalUrl.
|
|
119
|
-
|
|
128
|
+
if (!playback && req.originalUrl.includes('?')) {
|
|
129
|
+
const urlParts = req.originalUrl.split('?');
|
|
130
|
+
|
|
131
|
+
if (urlParts.length > 1) {
|
|
132
|
+
const queryString = urlParts[1];
|
|
133
|
+
const qs = querystring.parse(queryString);
|
|
134
|
+
|
|
135
|
+
delete qs[EXCLUDE_QS];
|
|
136
|
+
|
|
137
|
+
const newQs = querystring.stringify(qs);
|
|
138
|
+
const newUrl = newQs.length ? `${ urlParts[0] }?${ newQs }` : urlParts[0];
|
|
139
|
+
|
|
140
|
+
playback = session[newUrl];
|
|
141
|
+
}
|
|
120
142
|
}
|
|
121
143
|
|
|
122
144
|
if (playback && playback[req.method] && playback[req.method].length) {
|
package/store/action-menu.js
CHANGED
|
@@ -2,31 +2,26 @@ import { filterBy, isArray } from '@shell/utils/array';
|
|
|
2
2
|
|
|
3
3
|
export const state = function() {
|
|
4
4
|
return {
|
|
5
|
-
show:
|
|
6
|
-
resources:
|
|
7
|
-
elem:
|
|
8
|
-
event:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
toRemove: [],
|
|
17
|
-
toRestore: [],
|
|
18
|
-
toAssign: [],
|
|
19
|
-
toUpdate: [],
|
|
20
|
-
modalData: {},
|
|
5
|
+
show: false,
|
|
6
|
+
resources: [],
|
|
7
|
+
elem: null,
|
|
8
|
+
event: null,
|
|
9
|
+
showPromptRemove: false,
|
|
10
|
+
showPromptRestore: false,
|
|
11
|
+
showModal: false,
|
|
12
|
+
performCallbackData: undefined,
|
|
13
|
+
toRemove: [],
|
|
14
|
+
toRestore: [],
|
|
15
|
+
modalData: {},
|
|
21
16
|
};
|
|
22
17
|
};
|
|
23
18
|
|
|
24
19
|
export const getters = {
|
|
25
|
-
showing:
|
|
26
|
-
elem:
|
|
27
|
-
event:
|
|
28
|
-
resources:
|
|
29
|
-
|
|
20
|
+
showing: (state) => state.show,
|
|
21
|
+
elem: (state) => state.elem,
|
|
22
|
+
event: (state) => state.event,
|
|
23
|
+
resources: (state) => state.resources,
|
|
24
|
+
performCallbackData: (state) => state.performCallbackData,
|
|
30
25
|
optionsArray(state) {
|
|
31
26
|
let selected = state.resources;
|
|
32
27
|
|
|
@@ -89,16 +84,6 @@ export const mutations = {
|
|
|
89
84
|
state.toRemove = resources;
|
|
90
85
|
},
|
|
91
86
|
|
|
92
|
-
togglePromptMove(state, resources) {
|
|
93
|
-
if (!resources) {
|
|
94
|
-
state.showPromptMove = false;
|
|
95
|
-
resources = [];
|
|
96
|
-
} else {
|
|
97
|
-
state.showPromptMove = !state.showPromptMove;
|
|
98
|
-
state.toMove = Array.isArray(resources) ? resources : [resources];
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
|
|
102
87
|
togglePromptRestore(state, resources) {
|
|
103
88
|
if (!resources) {
|
|
104
89
|
state.showPromptRestore = false;
|
|
@@ -112,35 +97,13 @@ export const mutations = {
|
|
|
112
97
|
state.toRestore = resources;
|
|
113
98
|
},
|
|
114
99
|
|
|
115
|
-
toggleAssignTo(state, resources) {
|
|
116
|
-
state.showAssignTo = !state.showAssignTo;
|
|
117
|
-
|
|
118
|
-
if (!isArray(resources)) {
|
|
119
|
-
resources = [resources];
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
state.toAssign = resources;
|
|
123
|
-
},
|
|
124
|
-
|
|
125
|
-
togglePromptUpdate(state, resources) {
|
|
126
|
-
if (!resources) {
|
|
127
|
-
// Clearing the resources also hides the prompt
|
|
128
|
-
state.showPromptUpdate = false;
|
|
129
|
-
} else {
|
|
130
|
-
state.showPromptUpdate = !state.showPromptUpdate;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (!isArray(resources)) {
|
|
134
|
-
resources = [resources];
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
state.toUpdate = resources;
|
|
138
|
-
},
|
|
139
|
-
|
|
140
100
|
togglePromptModal(state, data) {
|
|
141
101
|
if (!data) {
|
|
142
102
|
// Clearing the resources also hides the prompt
|
|
143
103
|
state.showModal = false;
|
|
104
|
+
} else if (data.performCallback) {
|
|
105
|
+
state.performCallbackData = data;
|
|
106
|
+
state.showModal = false;
|
|
144
107
|
} else {
|
|
145
108
|
state.showModal = true;
|
|
146
109
|
}
|
|
@@ -148,6 +111,10 @@ export const mutations = {
|
|
|
148
111
|
state.modalData = data;
|
|
149
112
|
},
|
|
150
113
|
|
|
114
|
+
clearCallbackData(state) {
|
|
115
|
+
state.performCallbackData = undefined;
|
|
116
|
+
},
|
|
117
|
+
|
|
151
118
|
SET_RESOURCE(state, resources) {
|
|
152
119
|
state.resources = !isArray(resources) ? [resources] : resources;
|
|
153
120
|
}
|
|
@@ -159,6 +126,9 @@ export const actions = {
|
|
|
159
126
|
},
|
|
160
127
|
setResource({ commit }, resource) {
|
|
161
128
|
commit('SET_RESOURCE', resource);
|
|
129
|
+
},
|
|
130
|
+
clearCallbackData({ commit }) {
|
|
131
|
+
commit('clearCallbackData');
|
|
162
132
|
}
|
|
163
133
|
};
|
|
164
134
|
|
package/store/features.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MANAGEMENT } from '@shell/config/types';
|
|
2
|
+
import { SCHEDULING_CUSTOMIZATION as SCHEDULING_CUSTOMIZATION_FEATURE } from '@shell/config/features';
|
|
2
3
|
|
|
3
4
|
const definitions = {};
|
|
4
5
|
|
|
@@ -36,7 +37,7 @@ export const FLEET_WORKSPACE_BACK = create('provisioningv2-fleet-workspace-back-
|
|
|
36
37
|
export const STEVE_CACHE = create('ui-sql-cache', false);
|
|
37
38
|
export const UIEXTENSION = create('uiextension', true);
|
|
38
39
|
export const PROVISIONING_PRE_BOOTSTRAP = create('provisioningprebootstrap', false);
|
|
39
|
-
export const SCHEDULING_CUSTOMIZATION = create(
|
|
40
|
+
export const SCHEDULING_CUSTOMIZATION = create(SCHEDULING_CUSTOMIZATION_FEATURE, false);
|
|
40
41
|
|
|
41
42
|
// Not currently used.. no point defining ones we don't use
|
|
42
43
|
// export const EMBEDDED_CLUSTER_API = create('embedded-cluster-api', true);
|
package/store/index.js
CHANGED
|
@@ -862,6 +862,11 @@ export const actions = {
|
|
|
862
862
|
const isRancherInHarvester = (rancherManagerSupport?.value || rancherManagerSupport?.default) === 'true';
|
|
863
863
|
|
|
864
864
|
commit('isRancherInHarvester', isRancherInHarvester);
|
|
865
|
+
|
|
866
|
+
if (getters['isSingleProduct']) {
|
|
867
|
+
console.log('Detect standalone harvester, subscribe Rancher socket'); // eslint-disable-line no-console
|
|
868
|
+
await dispatch('rancher/subscribe');
|
|
869
|
+
}
|
|
865
870
|
}
|
|
866
871
|
|
|
867
872
|
const pl = res.settings?.find((x) => x.id === 'ui-pl')?.value;
|
package/store/modal.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { markRaw, Component } from 'vue';
|
|
2
|
+
import { MutationTree, GetterTree, ActionTree } from 'vuex';
|
|
3
|
+
|
|
4
|
+
export interface ModalState {
|
|
5
|
+
isOpen: boolean;
|
|
6
|
+
component: Component | null;
|
|
7
|
+
componentProps: Record<string, any>;
|
|
8
|
+
resources: any[];
|
|
9
|
+
closeOnClickOutside: boolean;
|
|
10
|
+
modalWidth: string;
|
|
11
|
+
modalSticky: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const state = (): ModalState => ({
|
|
15
|
+
isOpen: false,
|
|
16
|
+
component: null,
|
|
17
|
+
componentProps: {},
|
|
18
|
+
resources: [],
|
|
19
|
+
closeOnClickOutside: false,
|
|
20
|
+
modalWidth: '600px',
|
|
21
|
+
modalSticky: false
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const getters: GetterTree<ModalState, any> = {
|
|
25
|
+
isOpen: (state) => state.isOpen,
|
|
26
|
+
component: (state) => state.component,
|
|
27
|
+
componentProps: (state) => state.componentProps,
|
|
28
|
+
resources: (state) => state.resources,
|
|
29
|
+
closeOnClickOutside: (state) => state.closeOnClickOutside,
|
|
30
|
+
modalWidth: (state) => state.modalWidth,
|
|
31
|
+
modalSticky: (state) => state.modalSticky,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const mutations: MutationTree<ModalState> = {
|
|
35
|
+
openModal(state, payload: {
|
|
36
|
+
component: Component;
|
|
37
|
+
componentProps?: Record<string, any>;
|
|
38
|
+
resources?: any[];
|
|
39
|
+
closeOnClickOutside?: boolean;
|
|
40
|
+
modalWidth?: string;
|
|
41
|
+
modalSticky?: boolean;
|
|
42
|
+
}) {
|
|
43
|
+
state.isOpen = true;
|
|
44
|
+
state.component = markRaw(payload.component);
|
|
45
|
+
state.componentProps = payload.componentProps || {};
|
|
46
|
+
state.resources = Array.isArray(payload.resources) ? payload.resources : (payload.resources ? [payload.resources] : []);
|
|
47
|
+
state.closeOnClickOutside = payload.closeOnClickOutside ?? false;
|
|
48
|
+
state.modalWidth = payload.modalWidth || '600px';
|
|
49
|
+
state.modalSticky = payload.modalSticky ?? false;
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
closeModal(state) {
|
|
53
|
+
state.isOpen = false;
|
|
54
|
+
state.component = null;
|
|
55
|
+
state.componentProps = {};
|
|
56
|
+
state.resources = [];
|
|
57
|
+
state.closeOnClickOutside = false;
|
|
58
|
+
state.modalWidth = '600px';
|
|
59
|
+
state.modalSticky = false;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const actions: ActionTree<ModalState, any> = {};
|
|
64
|
+
|
|
65
|
+
export default {
|
|
66
|
+
namespaced: true,
|
|
67
|
+
state,
|
|
68
|
+
getters,
|
|
69
|
+
mutations,
|
|
70
|
+
actions
|
|
71
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { markRaw, Component } from 'vue';
|
|
2
|
+
import { MutationTree, GetterTree, ActionTree } from 'vuex';
|
|
3
|
+
|
|
4
|
+
export interface SlideInPanelState {
|
|
5
|
+
isOpen: boolean;
|
|
6
|
+
component: Component | null;
|
|
7
|
+
componentProps: Record<string, any>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const state = (): SlideInPanelState => ({
|
|
11
|
+
isOpen: false,
|
|
12
|
+
component: null,
|
|
13
|
+
componentProps: {}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const getters: GetterTree<SlideInPanelState, any> = {
|
|
17
|
+
isOpen: (state) => state.isOpen,
|
|
18
|
+
component: (state) => state.component,
|
|
19
|
+
componentProps: (state) => state.componentProps
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const mutations: MutationTree<SlideInPanelState> = {
|
|
23
|
+
open(state, payload: { component: Component; componentProps?: Record<string, any> }) {
|
|
24
|
+
state.isOpen = true;
|
|
25
|
+
state.component = markRaw(payload.component);
|
|
26
|
+
state.componentProps = payload.componentProps || {};
|
|
27
|
+
},
|
|
28
|
+
close(state) {
|
|
29
|
+
state.isOpen = false;
|
|
30
|
+
|
|
31
|
+
// Delay clearing component/props for 500ms (same as transition duration)
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
state.component = null;
|
|
34
|
+
state.componentProps = {};
|
|
35
|
+
}, 500);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const actions: ActionTree<SlideInPanelState, any> = {};
|
|
40
|
+
|
|
41
|
+
export default {
|
|
42
|
+
namespaced: true,
|
|
43
|
+
state,
|
|
44
|
+
getters,
|
|
45
|
+
mutations,
|
|
46
|
+
actions
|
|
47
|
+
};
|