@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
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import Vue from 'vue';
|
|
2
2
|
import { addObject, addObjects, clear, removeObject } from '@shell/utils/array';
|
|
3
|
-
import { SCHEMA } from '@shell/config/types';
|
|
4
|
-
import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
|
|
3
|
+
import { SCHEMA, COUNT } from '@shell/config/types';
|
|
4
|
+
import { normalizeType, keyFieldFor } from '@shell/plugins/dashboard-store/normalize';
|
|
5
|
+
import { addSchemaIndexFields } from '@shell/plugins/steve/schema.utils';
|
|
5
6
|
import { classify } from '@shell/plugins/dashboard-store/classify';
|
|
6
7
|
import garbageCollect from '@shell/utils/gc/gc';
|
|
7
8
|
|
|
@@ -10,12 +11,13 @@ function registerType(state, type) {
|
|
|
10
11
|
|
|
11
12
|
if ( !cache ) {
|
|
12
13
|
cache = {
|
|
13
|
-
list:
|
|
14
|
-
haveAll:
|
|
15
|
-
haveSelector:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
list: [],
|
|
15
|
+
haveAll: false,
|
|
16
|
+
haveSelector: {},
|
|
17
|
+
haveNamespace: undefined, // If the cached list only contains resources for a namespace, this will contain the ns name
|
|
18
|
+
revision: 0, // The highest known resourceVersion from the server for this type
|
|
19
|
+
generation: 0, // Updated every time something is loaded for this type
|
|
20
|
+
loadCounter: 0, // Used to cancel incremental loads if the page changes during load
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
// Not enumerable so they don't get sent back to the client for SSR
|
|
@@ -31,6 +33,24 @@ function registerType(state, type) {
|
|
|
31
33
|
return cache;
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
export function replace(existing, data) {
|
|
37
|
+
for ( const k of Object.keys(existing) ) {
|
|
38
|
+
delete existing[k];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for ( const k of Object.keys(data) ) {
|
|
42
|
+
Vue.set(existing, k, data[k]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return existing;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function replaceResource(existing, data, getters) {
|
|
49
|
+
data = getters.cleanResource(existing, data);
|
|
50
|
+
|
|
51
|
+
return replace(existing, data);
|
|
52
|
+
}
|
|
53
|
+
|
|
34
54
|
export function load(state, { data, ctx, existing }) {
|
|
35
55
|
const { getters } = ctx;
|
|
36
56
|
let type = normalizeType(data.type);
|
|
@@ -40,8 +60,7 @@ export function load(state, { data, ctx, existing }) {
|
|
|
40
60
|
|
|
41
61
|
// Inject special fields for indexing schemas
|
|
42
62
|
if ( type === SCHEMA ) {
|
|
43
|
-
|
|
44
|
-
data._group = normalizeType(data.attributes?.group);
|
|
63
|
+
addSchemaIndexFields(data);
|
|
45
64
|
}
|
|
46
65
|
|
|
47
66
|
const id = data[keyField];
|
|
@@ -52,24 +71,10 @@ export function load(state, { data, ctx, existing }) {
|
|
|
52
71
|
|
|
53
72
|
let entry;
|
|
54
73
|
|
|
55
|
-
function replace(existing, data) {
|
|
56
|
-
data = getters.cleanResource(existing, data);
|
|
57
|
-
|
|
58
|
-
for ( const k of Object.keys(existing) ) {
|
|
59
|
-
delete existing[k];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
for ( const k of Object.keys(data) ) {
|
|
63
|
-
Vue.set(existing, k, data[k]);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return existing;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
74
|
if ( existing && !existing.id ) {
|
|
70
75
|
// A specific proxy instance to used was passed in (for create -> save),
|
|
71
76
|
// use it instead of making a new proxy
|
|
72
|
-
entry =
|
|
77
|
+
entry = replaceResource(existing, data, getters);
|
|
73
78
|
addObject(cache.list, entry);
|
|
74
79
|
cache.map.set(id, entry);
|
|
75
80
|
// console.log('### Mutation added from existing proxy', type, id);
|
|
@@ -78,7 +83,7 @@ export function load(state, { data, ctx, existing }) {
|
|
|
78
83
|
|
|
79
84
|
if ( entry ) {
|
|
80
85
|
// There's already an entry in the store, update it
|
|
81
|
-
|
|
86
|
+
replaceResource(entry, data, getters);
|
|
82
87
|
// console.log('### Mutation Updated', type, id);
|
|
83
88
|
} else {
|
|
84
89
|
// There's no entry, make a new proxy
|
|
@@ -115,6 +120,7 @@ export function forgetType(state, type) {
|
|
|
115
120
|
if ( cache ) {
|
|
116
121
|
cache.haveAll = false;
|
|
117
122
|
cache.haveSelector = {};
|
|
123
|
+
cache.haveNamespace = undefined;
|
|
118
124
|
cache.revision = 0;
|
|
119
125
|
cache.generation = 0;
|
|
120
126
|
clear(cache.list);
|
|
@@ -163,11 +169,99 @@ export function remove(state, obj, getters) {
|
|
|
163
169
|
}
|
|
164
170
|
}
|
|
165
171
|
|
|
172
|
+
export function batchChanges(state, { ctx, batch }) {
|
|
173
|
+
const batchTypes = Object.keys(batch);
|
|
174
|
+
const combinedBatch = {};
|
|
175
|
+
|
|
176
|
+
batchTypes.forEach((batchType) => {
|
|
177
|
+
combinedBatch[batchType] = batch[batchType];
|
|
178
|
+
const typeOption = ctx.rootGetters['type-map/optionsFor'](batchType);
|
|
179
|
+
|
|
180
|
+
if (typeOption?.alias?.length > 0) {
|
|
181
|
+
const alias = typeOption?.alias || [];
|
|
182
|
+
|
|
183
|
+
alias.forEach((aliasType) => {
|
|
184
|
+
combinedBatch[aliasType] = {};
|
|
185
|
+
for (const [key, value] of Object.entries(batch[batchType])) {
|
|
186
|
+
combinedBatch[aliasType][key] = {
|
|
187
|
+
...value,
|
|
188
|
+
type: aliasType
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const combinedBatchTypes = Object.keys(combinedBatch);
|
|
196
|
+
|
|
197
|
+
combinedBatchTypes.forEach((type) => {
|
|
198
|
+
const normalizedType = normalizeType(type === 'counts' ? COUNT : type);
|
|
199
|
+
const keyField = keyFieldFor(normalizedType);
|
|
200
|
+
const typeCache = registerType(state, normalizedType);
|
|
201
|
+
|
|
202
|
+
// making a map for every resource's location in the list is gonna ensure we only have to loop through the big list once.
|
|
203
|
+
const typeCacheIndexMap = {};
|
|
204
|
+
|
|
205
|
+
typeCache.list.forEach((resource, index) => {
|
|
206
|
+
typeCacheIndexMap[resource[keyField]] = index;
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const removeAtIndexes = [];
|
|
210
|
+
|
|
211
|
+
// looping through the batch, executing changes, deferring creates and removes since they change the array length
|
|
212
|
+
Object.keys(batch[normalizedType]).forEach((id) => {
|
|
213
|
+
const index = typeCacheIndexMap[id];
|
|
214
|
+
const resource = batch[normalizedType][id];
|
|
215
|
+
|
|
216
|
+
// an empty resource passed into batch changes is how we'll signal which ones to delete
|
|
217
|
+
if (Object.keys(resource).length === 0 && index !== undefined) {
|
|
218
|
+
typeCache.map.delete(id);
|
|
219
|
+
removeAtIndexes.push(index);
|
|
220
|
+
} else if (Object.keys(resource).length === 0) {
|
|
221
|
+
// No op. We're removing it... but we don't have it in the cache
|
|
222
|
+
} else {
|
|
223
|
+
if (normalizedType === SCHEMA) {
|
|
224
|
+
addSchemaIndexFields(resource);
|
|
225
|
+
}
|
|
226
|
+
const classyResource = classify(ctx, resource);
|
|
227
|
+
|
|
228
|
+
if (index === undefined) {
|
|
229
|
+
typeCache.list.push(classyResource);
|
|
230
|
+
typeCache.map.set(id, classyResource);
|
|
231
|
+
|
|
232
|
+
typeCacheIndexMap[classyResource[keyField]] = typeCache.list.length - 1;
|
|
233
|
+
} else {
|
|
234
|
+
replaceResource(typeCache.list[index], resource, ctx.getters);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// looping through the removeAtIndexes, making sure to offset by iteration so the array changing doesn't mess us up
|
|
240
|
+
removeAtIndexes.sort().forEach((cacheIndex, loopIndex) => {
|
|
241
|
+
typeCache.list.splice(cacheIndex - loopIndex, 1);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
const opts = ctx.rootGetters[`type-map/optionsFor`](type);
|
|
245
|
+
const limit = opts?.limit;
|
|
246
|
+
|
|
247
|
+
// If there is a limit to the number of resources we can store for this type then
|
|
248
|
+
// remove the first one to keep the list size to that limit
|
|
249
|
+
if (limit && typeCache.list.length > limit) {
|
|
250
|
+
const rm = typeCache.list.shift();
|
|
251
|
+
|
|
252
|
+
typeCache.map.delete(rm.id);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
typeCache.generation++;
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
166
259
|
export function loadAll(state, {
|
|
167
260
|
type,
|
|
168
261
|
data,
|
|
169
262
|
ctx,
|
|
170
|
-
skipHaveAll
|
|
263
|
+
skipHaveAll,
|
|
264
|
+
namespace
|
|
171
265
|
}) {
|
|
172
266
|
const { getters } = ctx;
|
|
173
267
|
|
|
@@ -199,7 +293,8 @@ export function loadAll(state, {
|
|
|
199
293
|
|
|
200
294
|
// Allow requester to skip setting that everything has loaded
|
|
201
295
|
if (!skipHaveAll) {
|
|
202
|
-
cache.
|
|
296
|
+
cache.haveNamespace = namespace;
|
|
297
|
+
cache.haveAll = !namespace;
|
|
203
298
|
}
|
|
204
299
|
|
|
205
300
|
return proxies;
|
|
@@ -238,6 +333,11 @@ export default {
|
|
|
238
333
|
|
|
239
334
|
loadAll,
|
|
240
335
|
|
|
336
|
+
/**
|
|
337
|
+
* Handles changes (add, update, remove) to multiple resources for multiple types
|
|
338
|
+
*/
|
|
339
|
+
batchChanges,
|
|
340
|
+
|
|
241
341
|
loadMerge(state, { type, data: allLatest, ctx }) {
|
|
242
342
|
const { commit, getters } = ctx;
|
|
243
343
|
// const allLatest = await dispatch('findAll', { type, opt: { force: true, load, _NONE } });
|
|
@@ -288,6 +388,12 @@ export default {
|
|
|
288
388
|
cache.haveAll = true;
|
|
289
389
|
},
|
|
290
390
|
|
|
391
|
+
setHaveNamespace(state, { type, namespace }) {
|
|
392
|
+
const cache = registerType(state, type);
|
|
393
|
+
|
|
394
|
+
cache.haveNamespace = namespace;
|
|
395
|
+
},
|
|
396
|
+
|
|
291
397
|
loadedAll(state, { type }) {
|
|
292
398
|
const cache = registerType(state, type);
|
|
293
399
|
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
validateLength,
|
|
26
26
|
} from '@shell/utils/validators';
|
|
27
27
|
import formRulesGenerator from '@shell/utils/validators/formRules/index';
|
|
28
|
+
import { waitFor } from '@shell/utils/async';
|
|
28
29
|
import jsyaml from 'js-yaml';
|
|
29
30
|
import compact from 'lodash/compact';
|
|
30
31
|
import forIn from 'lodash/forIn';
|
|
@@ -36,6 +37,9 @@ import Vue from 'vue';
|
|
|
36
37
|
|
|
37
38
|
import { normalizeType } from './normalize';
|
|
38
39
|
|
|
40
|
+
import { ExtensionPoint, ActionLocation } from '@shell/core/types';
|
|
41
|
+
import { getApplicableExtensionEnhancements } from '@shell/core/plugin-helpers';
|
|
42
|
+
|
|
39
43
|
const STRING_LIKE_TYPES = [
|
|
40
44
|
'string',
|
|
41
45
|
'date',
|
|
@@ -752,41 +756,7 @@ export default class Resource {
|
|
|
752
756
|
// ------------------------------------------------------------------
|
|
753
757
|
|
|
754
758
|
waitForTestFn(fn, msg, timeoutMs, intervalMs) {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
if ( !timeoutMs ) {
|
|
758
|
-
timeoutMs = DEFAULT_WAIT_TMIMEOUT;
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
if ( !intervalMs ) {
|
|
762
|
-
intervalMs = DEFAULT_WAIT_INTERVAL;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
return new Promise((resolve, reject) => {
|
|
766
|
-
// Do a first check immediately
|
|
767
|
-
if ( fn.apply(this) ) {
|
|
768
|
-
console.log('Wait for', msg, 'done immediately'); // eslint-disable-line no-console
|
|
769
|
-
resolve(this);
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
const timeout = setTimeout(() => {
|
|
773
|
-
console.log('Wait for', msg, 'timed out'); // eslint-disable-line no-console
|
|
774
|
-
clearInterval(interval);
|
|
775
|
-
clearTimeout(timeout);
|
|
776
|
-
reject(new Error(`Failed waiting for: ${ msg }`));
|
|
777
|
-
}, timeoutMs);
|
|
778
|
-
|
|
779
|
-
const interval = setInterval(() => {
|
|
780
|
-
if ( fn.apply(this) ) {
|
|
781
|
-
console.log('Wait for', msg, 'done'); // eslint-disable-line no-console
|
|
782
|
-
clearInterval(interval);
|
|
783
|
-
clearTimeout(timeout);
|
|
784
|
-
resolve(this);
|
|
785
|
-
} else {
|
|
786
|
-
console.log('Wait for', msg, 'not done yet'); // eslint-disable-line no-console
|
|
787
|
-
}
|
|
788
|
-
}, intervalMs);
|
|
789
|
-
});
|
|
759
|
+
return waitFor(() => fn.apply(this), msg, timeoutMs || DEFAULT_WAIT_TMIMEOUT, intervalMs || DEFAULT_WAIT_INTERVAL, true);
|
|
790
760
|
}
|
|
791
761
|
|
|
792
762
|
waitForState(state, timeout, interval) {
|
|
@@ -798,19 +768,19 @@ export default class Resource {
|
|
|
798
768
|
waitForTransition() {
|
|
799
769
|
return this.waitForTestFn(() => {
|
|
800
770
|
return !this.transitioning;
|
|
801
|
-
}, 'transition completion');
|
|
771
|
+
}, 'transition completion', undefined, undefined);
|
|
802
772
|
}
|
|
803
773
|
|
|
804
774
|
waitForAction(name) {
|
|
805
775
|
return this.waitForTestFn(() => {
|
|
806
776
|
return this.hasAction(name);
|
|
807
|
-
}, `action=${ name }
|
|
777
|
+
}, `action=${ name }`, undefined, undefined);
|
|
808
778
|
}
|
|
809
779
|
|
|
810
780
|
waitForLink(name) {
|
|
811
781
|
return this.waitForTestFn(() => {
|
|
812
782
|
return this.hasLink(name);
|
|
813
|
-
}, `link=${ name }
|
|
783
|
+
}, `link=${ name }`, undefined, undefined);
|
|
814
784
|
}
|
|
815
785
|
|
|
816
786
|
hasCondition(condition) {
|
|
@@ -884,7 +854,11 @@ export default class Resource {
|
|
|
884
854
|
|
|
885
855
|
// You can add custom actions by overriding your own availableActions (and probably reading super._availableActions)
|
|
886
856
|
get _availableActions() {
|
|
887
|
-
|
|
857
|
+
// get menu actions available by plugins configuration
|
|
858
|
+
const currentRoute = this.currentRouter().app._route;
|
|
859
|
+
const extensionMenuActions = getApplicableExtensionEnhancements(this.$rootState, ExtensionPoint.ACTION, ActionLocation.TABLE, currentRoute, this);
|
|
860
|
+
|
|
861
|
+
let all = [
|
|
888
862
|
{ divider: true },
|
|
889
863
|
{
|
|
890
864
|
action: this.canUpdate ? 'goToEdit' : 'goToViewConfig',
|
|
@@ -932,6 +906,13 @@ export default class Resource {
|
|
|
932
906
|
},
|
|
933
907
|
];
|
|
934
908
|
|
|
909
|
+
// Extension actions get added to the end, so add a divider if there are any
|
|
910
|
+
if (extensionMenuActions.length) {
|
|
911
|
+
// Add a divider first
|
|
912
|
+
all.push({ divider: true });
|
|
913
|
+
all = all.concat(extensionMenuActions);
|
|
914
|
+
}
|
|
915
|
+
|
|
935
916
|
return all;
|
|
936
917
|
}
|
|
937
918
|
|
|
@@ -1075,9 +1056,16 @@ export default class Resource {
|
|
|
1075
1056
|
return this._save(...arguments);
|
|
1076
1057
|
}
|
|
1077
1058
|
|
|
1059
|
+
/**
|
|
1060
|
+
* Allow to handle the response of the save request
|
|
1061
|
+
* @param {*} res Full request response
|
|
1062
|
+
*/
|
|
1063
|
+
processSaveResponse(res) { }
|
|
1064
|
+
|
|
1078
1065
|
async _save(opt = {}) {
|
|
1079
1066
|
delete this.__rehydrate;
|
|
1080
1067
|
delete this.__clone;
|
|
1068
|
+
|
|
1081
1069
|
const forNew = !this.id;
|
|
1082
1070
|
|
|
1083
1071
|
const errors = await this.validationErrors(this, opt.ignoreFields);
|
|
@@ -1151,6 +1139,9 @@ export default class Resource {
|
|
|
1151
1139
|
try {
|
|
1152
1140
|
const res = await this.$dispatch('request', { opt, type: this.type } );
|
|
1153
1141
|
|
|
1142
|
+
// Allow to process response independently from the related models
|
|
1143
|
+
this.processSaveResponse(res);
|
|
1144
|
+
|
|
1154
1145
|
// Steve sometimes returns Table responses instead of the resource you just saved.. ignore
|
|
1155
1146
|
if ( res && res.kind !== 'Table') {
|
|
1156
1147
|
await this.$dispatch('load', { data: res, existing: (forNew ? this : undefined ) });
|
|
@@ -1323,8 +1314,9 @@ export default class Resource {
|
|
|
1323
1314
|
|
|
1324
1315
|
async download() {
|
|
1325
1316
|
const value = await this.followLink('view', { headers: { accept: 'application/yaml' } });
|
|
1317
|
+
const data = await this.$dispatch('cleanForDownload', value.data);
|
|
1326
1318
|
|
|
1327
|
-
downloadFile(`${ this.nameDisplay }.yaml`,
|
|
1319
|
+
downloadFile(`${ this.nameDisplay }.yaml`, data, 'application/yaml');
|
|
1328
1320
|
}
|
|
1329
1321
|
|
|
1330
1322
|
async downloadBulk(items) {
|
|
@@ -1343,8 +1335,11 @@ export default class Resource {
|
|
|
1343
1335
|
}
|
|
1344
1336
|
|
|
1345
1337
|
await eachLimit(items, 10, (item, idx) => {
|
|
1346
|
-
return item.followLink('view', { headers: { accept: 'application/yaml' } } ).then((data) => {
|
|
1347
|
-
|
|
1338
|
+
return item.followLink('view', { headers: { accept: 'application/yaml' } } ).then(async(data) => {
|
|
1339
|
+
const yaml = data.data || data;
|
|
1340
|
+
const cleanedYaml = await this.$dispatch('cleanForDownload', yaml);
|
|
1341
|
+
|
|
1342
|
+
files[`resources/${ names[idx] }`] = cleanedYaml;
|
|
1348
1343
|
});
|
|
1349
1344
|
});
|
|
1350
1345
|
|
package/plugins/steve/actions.js
CHANGED
|
@@ -7,6 +7,7 @@ import { streamJson, streamingSupported } from '@shell/utils/stream';
|
|
|
7
7
|
import isObject from 'lodash/isObject';
|
|
8
8
|
import { classify } from '@shell/plugins/dashboard-store/classify';
|
|
9
9
|
import { NAMESPACE } from '@shell/config/types';
|
|
10
|
+
import jsyaml from 'js-yaml';
|
|
10
11
|
|
|
11
12
|
export default {
|
|
12
13
|
|
|
@@ -323,6 +324,35 @@ export default {
|
|
|
323
324
|
|
|
324
325
|
return resource;
|
|
325
326
|
},
|
|
327
|
+
|
|
328
|
+
// remove fields added by steve before showing/downloading yamls
|
|
329
|
+
cleanForDownload(ctx, yaml) {
|
|
330
|
+
if (!yaml) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const rootKeys = [
|
|
334
|
+
'id',
|
|
335
|
+
'links',
|
|
336
|
+
'type',
|
|
337
|
+
'actions'
|
|
338
|
+
];
|
|
339
|
+
const metadataKeys = [
|
|
340
|
+
'fields',
|
|
341
|
+
'relationships',
|
|
342
|
+
'state',
|
|
343
|
+
];
|
|
344
|
+
const conditionKeys = [
|
|
345
|
+
'error',
|
|
346
|
+
'transitioning',
|
|
347
|
+
];
|
|
348
|
+
const obj = jsyaml.load(yaml);
|
|
349
|
+
|
|
350
|
+
dropKeys(obj, rootKeys);
|
|
351
|
+
dropKeys(obj?.metadata, metadataKeys);
|
|
352
|
+
(obj?.status?.conditions || []).forEach(condition => dropKeys(condition, conditionKeys));
|
|
353
|
+
|
|
354
|
+
return jsyaml.dump(obj);
|
|
355
|
+
}
|
|
326
356
|
};
|
|
327
357
|
|
|
328
358
|
const diffRootKeys = [
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { SCHEMA, COUNT } from '@shell/config/types';
|
|
2
|
+
import { keyFieldFor, normalizeType } from '@shell/plugins/dashboard-store/normalize';
|
|
3
|
+
import { addSchemaIndexFields } from '@shell/plugins/steve/schema.utils';
|
|
4
|
+
import { hashObj } from '@shell/utils/crypto/browserHashUtils';
|
|
5
|
+
|
|
6
|
+
export default class ResourceCache {
|
|
7
|
+
resources = {};
|
|
8
|
+
type;
|
|
9
|
+
keyField;
|
|
10
|
+
constructor(type) {
|
|
11
|
+
this.type = normalizeType(type === 'counts' ? COUNT : type);
|
|
12
|
+
this.keyField = keyFieldFor(this.type);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
load(collection = []) {
|
|
16
|
+
// console.time('startSchemaLoads!!!');
|
|
17
|
+
for (let i = 0; i < collection.length; i++) {
|
|
18
|
+
const resource = collection[i];
|
|
19
|
+
|
|
20
|
+
if ( this.type === SCHEMA ) {
|
|
21
|
+
addSchemaIndexFields(resource);
|
|
22
|
+
}
|
|
23
|
+
const id = resource[this.keyField];
|
|
24
|
+
|
|
25
|
+
// Store the hash instead of the whole object. This means longer load time be reduces memory footprint
|
|
26
|
+
// Perf Note: 3.328125 ms to load ~2500 schemas as objects into cache
|
|
27
|
+
// Perf Note: 67.450927734375 ms to load ~2500 schemas as hashes into cache
|
|
28
|
+
this.resources[id] = hashObj(resource);
|
|
29
|
+
}
|
|
30
|
+
// console.timeEnd('startSchemaLoads!!!');
|
|
31
|
+
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
change(resource, callback) {
|
|
36
|
+
if ( this.type === SCHEMA ) {
|
|
37
|
+
addSchemaIndexFields(resource);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const existingResourceHash = this.resources[resource[this.keyField]] || {};
|
|
41
|
+
const newResourceHash = hashObj(resource);
|
|
42
|
+
|
|
43
|
+
if (existingResourceHash !== newResourceHash) {
|
|
44
|
+
this.resources[resource[this.keyField]] = resource;
|
|
45
|
+
callback();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
create(resource, callback) {
|
|
50
|
+
// ToDo: the logic for create is identical to change in these caches but the worker doesn't know that
|
|
51
|
+
this.change(resource, callback);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
remove(id, callback) {
|
|
55
|
+
if (this.resources[id]) {
|
|
56
|
+
delete this.resources[id];
|
|
57
|
+
callback();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
package/plugins/steve/getters.js
CHANGED
|
@@ -6,6 +6,8 @@ import { NAMESPACE, SCHEMA, COUNT, UI } from '@shell/config/types';
|
|
|
6
6
|
import SteveModel from './steve-class';
|
|
7
7
|
import HybridModel, { cleanHybridResources } from './hybrid-class';
|
|
8
8
|
import NormanModel from './norman-class';
|
|
9
|
+
import { urlFor } from '@shell/plugins/dashboard-store/getters';
|
|
10
|
+
import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
|
|
9
11
|
|
|
10
12
|
export const STEVE_MODEL_TYPES = {
|
|
11
13
|
NORMAN: 'norman',
|
|
@@ -67,6 +69,20 @@ export default {
|
|
|
67
69
|
return url;
|
|
68
70
|
},
|
|
69
71
|
|
|
72
|
+
urlFor: (state, getters) => (type, id, opt) => {
|
|
73
|
+
let url = urlFor(state, getters)(type, id, opt);
|
|
74
|
+
|
|
75
|
+
if (opt.namespaced) {
|
|
76
|
+
const parts = url.split('/');
|
|
77
|
+
|
|
78
|
+
url = `${ parts.join('/') }/${ opt.namespaced }`;
|
|
79
|
+
|
|
80
|
+
return url;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return url;
|
|
84
|
+
},
|
|
85
|
+
|
|
70
86
|
defaultModel: state => (obj) => {
|
|
71
87
|
const which = state.config.modelBaseClass || STEVE_MODEL_TYPES.BY_TYPE.STEVE;
|
|
72
88
|
|
|
@@ -106,6 +122,21 @@ export default {
|
|
|
106
122
|
},
|
|
107
123
|
|
|
108
124
|
cleanResource: () => (existing, data) => {
|
|
125
|
+
/**
|
|
126
|
+
* Resource counts are contained within a single 'count' resource with a 'counts' field that is a map of resource types
|
|
127
|
+
* When counts are updated through the websocket, only the resources that changed are sent so we can't load the new 'count' resource into the store as we would another resource
|
|
128
|
+
*/
|
|
129
|
+
if (data?.type === COUNT && existing) {
|
|
130
|
+
data.counts = { ...existing.counts, ...data.counts };
|
|
131
|
+
|
|
132
|
+
return data;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// If the existing model has a cleanResource method, use it
|
|
136
|
+
if (existing?.cleanResource && typeof existing.cleanResource === 'function') {
|
|
137
|
+
return existing.cleanResource(data);
|
|
138
|
+
}
|
|
139
|
+
|
|
109
140
|
const typeSuperClass = Object.getPrototypeOf(Object.getPrototypeOf(existing))?.constructor;
|
|
110
141
|
|
|
111
142
|
return typeSuperClass === HybridModel ? cleanHybridResources(data) : data;
|
|
@@ -120,6 +151,18 @@ export default {
|
|
|
120
151
|
|
|
121
152
|
gcIgnoreTypes: () => {
|
|
122
153
|
return GC_IGNORE_TYPES;
|
|
123
|
-
}
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
currentGeneration: state => (type) => {
|
|
157
|
+
type = normalizeType(type);
|
|
158
|
+
|
|
159
|
+
const cache = state.types[type];
|
|
160
|
+
|
|
161
|
+
if ( !cache ) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return cache.generation;
|
|
166
|
+
},
|
|
124
167
|
|
|
125
168
|
};
|