@rancher/shell 3.0.5-rc.3 → 3.0.5-rc.5
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/icons/document.svg +3 -0
- package/assets/images/vendor/cognito.svg +1 -0
- package/assets/styles/app.scss +1 -0
- package/assets/styles/base/_basic.scss +10 -0
- package/assets/styles/base/_spacing.scss +29 -0
- package/assets/styles/global/_layout.scss +1 -1
- package/assets/styles/themes/_dark.scss +25 -0
- package/assets/styles/themes/_light.scss +65 -0
- package/assets/translations/en-us.yaml +322 -24
- package/assets/translations/zh-hans.yaml +8 -5
- package/components/Certificates.vue +5 -0
- package/components/FilterPanel.vue +156 -0
- package/components/{fleet/ForceDirectedTreeChart/index.vue → ForceDirectedTreeChart.vue} +47 -41
- package/components/IconOrSvg.vue +14 -35
- package/components/PromptRemove.vue +5 -1
- package/components/Resource/Detail/Card/PodsCard/Bubble.vue +13 -0
- package/components/Resource/Detail/Card/PodsCard/composable.ts +30 -0
- package/components/Resource/Detail/Card/PodsCard/index.vue +118 -0
- package/components/Resource/Detail/Card/ResourceUsageCard/composable.ts +51 -0
- package/components/Resource/Detail/Card/ResourceUsageCard/index.vue +79 -0
- package/components/Resource/Detail/Card/Scaler.vue +89 -0
- package/components/Resource/Detail/Card/StateCard/composables.ts +112 -0
- package/components/Resource/Detail/Card/StateCard/index.vue +39 -0
- package/components/Resource/Detail/Card/VerticalGap.vue +11 -0
- package/components/Resource/Detail/Card/__tests__/Card.test.ts +36 -0
- package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +84 -0
- package/components/Resource/Detail/Card/__tests__/ResourceUsageCard.test.ts +72 -0
- package/components/Resource/Detail/Card/__tests__/Scaler.test.ts +87 -0
- package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +53 -0
- package/components/Resource/Detail/Card/__tests__/VerticalGap.test.ts +14 -0
- package/components/Resource/Detail/Card/__tests__/index.test.ts +36 -0
- package/components/Resource/Detail/Card/index.vue +56 -0
- package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +19 -0
- package/components/Resource/Detail/Metadata/Annotations/composable.ts +12 -0
- package/components/Resource/Detail/Metadata/Annotations/index.vue +26 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +103 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +281 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +111 -0
- package/components/Resource/Detail/Metadata/KeyValue.vue +130 -0
- package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +18 -0
- package/components/Resource/Detail/Metadata/Labels/composable.ts +12 -0
- package/components/Resource/Detail/Metadata/Labels/index.vue +27 -0
- package/components/Resource/Detail/Metadata/Rectangle.vue +32 -0
- package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +107 -0
- package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +24 -0
- package/components/Resource/Detail/Metadata/__tests__/index.test.ts +91 -0
- package/components/Resource/Detail/Metadata/composables.ts +29 -0
- package/components/Resource/Detail/Metadata/index.vue +66 -0
- package/components/Resource/Detail/Page.vue +22 -0
- package/components/Resource/Detail/PercentageBar.vue +40 -0
- package/components/Resource/Detail/ResourceRow.vue +119 -0
- package/components/Resource/Detail/SpacedRow.vue +14 -0
- package/components/Resource/Detail/StatusBar.vue +59 -0
- package/components/Resource/Detail/StatusRow.vue +61 -0
- package/components/Resource/Detail/TitleBar/Title.vue +13 -0
- package/components/Resource/Detail/TitleBar/Top.vue +14 -0
- package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +17 -0
- package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +17 -0
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +142 -0
- package/components/Resource/Detail/TitleBar/composable.ts +31 -0
- package/components/Resource/Detail/TitleBar/index.vue +124 -0
- package/components/Resource/Detail/Top/index.vue +34 -0
- package/components/Resource/Detail/__tests__/Page.test.ts +32 -0
- package/components/ResourceDetail/__tests__/index.test.ts +114 -0
- package/components/ResourceDetail/index.vue +64 -562
- package/components/ResourceDetail/legacy.vue +545 -0
- package/components/ResourceTable.vue +41 -7
- package/components/SlideInPanelManager.vue +76 -8
- package/components/SortableTable/index.vue +13 -2
- package/components/SortableTable/selection.js +21 -8
- package/components/StatusBadge.vue +6 -4
- package/components/SubtleLink.vue +25 -0
- package/components/Wizard.vue +12 -1
- package/components/YamlEditor.vue +1 -1
- package/components/__tests__/FilterPanel.test.ts +81 -0
- package/components/auth/AuthBanner.vue +2 -3
- package/components/auth/RoleDetailEdit.vue +45 -3
- package/components/auth/login/oidc.vue +6 -1
- package/components/fleet/FleetApplications.vue +181 -0
- package/components/fleet/FleetHelmOps.vue +115 -0
- package/components/fleet/FleetIntro.vue +58 -28
- package/components/fleet/FleetNoWorkspaces.vue +5 -1
- package/components/fleet/FleetOCIStorageSecret.vue +171 -0
- package/components/fleet/FleetRepos.vue +38 -76
- package/components/fleet/FleetResources.vue +50 -22
- package/components/fleet/FleetSummary.vue +26 -51
- package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +213 -0
- package/components/fleet/__tests__/FleetSummary.test.ts +39 -39
- package/components/fleet/dashboard/Empty.vue +73 -0
- package/components/fleet/dashboard/ResourceCard.vue +183 -0
- package/components/fleet/dashboard/ResourceCardSummary.vue +199 -0
- package/components/fleet/dashboard/ResourceDetails.vue +196 -0
- package/components/fleet/dashboard/ResourcePanel.vue +376 -0
- package/components/form/ArrayList.vue +6 -0
- package/components/form/SimpleSecretSelector.vue +8 -2
- package/components/form/ValueFromResource.vue +31 -19
- package/components/formatter/FleetApplicationClustersReady.vue +77 -0
- package/components/formatter/FleetApplicationSource.vue +71 -0
- package/components/formatter/FleetSummaryGraph.vue +7 -0
- package/components/nav/Header.vue +8 -7
- package/components/nav/TopLevelMenu.helper.ts +55 -34
- package/components/nav/TopLevelMenu.vue +11 -0
- package/components/nav/Type.vue +4 -1
- package/composables/useI18n.ts +12 -11
- package/config/labels-annotations.js +14 -11
- package/config/product/auth.js +1 -0
- package/config/product/fleet.js +70 -17
- package/config/query-params.js +3 -1
- package/config/roles.ts +1 -0
- package/config/router/routes.js +20 -2
- package/config/secret.ts +15 -0
- package/config/settings.ts +3 -2
- package/config/table-headers.js +52 -22
- package/config/types.js +2 -0
- package/core/plugin-helpers.ts +3 -2
- package/detail/fleet.cattle.io.cluster.vue +28 -15
- package/detail/fleet.cattle.io.gitrepo.vue +10 -1
- package/detail/fleet.cattle.io.helmop.vue +157 -0
- package/dialog/HelmOpForceUpdateDialog.vue +132 -0
- package/dialog/RedeployWorkloadDialog.vue +164 -0
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +56 -67
- package/edit/auth/oidc.vue +159 -93
- package/edit/fleet.cattle.io.gitrepo.vue +26 -33
- package/edit/fleet.cattle.io.helmop.vue +997 -0
- package/edit/management.cattle.io.fleetworkspace.vue +43 -10
- package/list/fleet.cattle.io.gitrepo.vue +1 -1
- package/list/fleet.cattle.io.helmop.vue +108 -0
- package/list/namespace.vue +5 -2
- package/mixins/auth-config.js +8 -1
- package/mixins/preset.js +100 -0
- package/mixins/resource-fetch-api-pagination.js +2 -0
- package/mixins/resource-fetch.js +1 -1
- package/mixins/resource-table-watch.js +45 -0
- package/models/__tests__/chart.test.ts +273 -0
- package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
- package/models/chart.js +144 -2
- package/models/fleet-application.js +385 -0
- package/models/fleet.cattle.io.bundle.js +9 -8
- package/models/fleet.cattle.io.gitrepo.js +41 -365
- package/models/fleet.cattle.io.helmop.js +228 -0
- package/models/management.cattle.io.authconfig.js +1 -0
- package/models/management.cattle.io.fleetworkspace.js +12 -0
- package/models/workload.js +14 -18
- package/package.json +2 -1
- package/pages/auth/verify.vue +13 -1
- package/pages/c/_cluster/apps/charts/AddRepoLink.vue +37 -0
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +80 -0
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +54 -0
- package/pages/c/_cluster/apps/charts/StatusLabel.vue +33 -0
- package/pages/c/_cluster/apps/charts/index.vue +302 -484
- package/pages/c/_cluster/explorer/EventsTable.vue +1 -1
- package/pages/c/_cluster/fleet/__tests__/index.test.ts +426 -0
- package/pages/c/_cluster/fleet/application/_resource/_id.vue +14 -0
- package/pages/c/_cluster/fleet/application/_resource/create.vue +14 -0
- package/pages/c/_cluster/fleet/application/create.vue +340 -0
- package/pages/c/_cluster/fleet/application/index.vue +139 -0
- package/pages/c/_cluster/fleet/graph/config.js +277 -0
- package/pages/c/_cluster/fleet/index.vue +772 -330
- package/pages/explorer/resource/detail/configmap.vue +19 -0
- package/plugins/dashboard-store/actions.js +31 -9
- package/plugins/dashboard-store/getters.js +34 -21
- package/plugins/dashboard-store/mutations.js +51 -7
- package/plugins/dashboard-store/resource-class.js +14 -2
- package/plugins/steve/__tests__/subscribe.spec.ts +66 -1
- package/plugins/steve/actions.js +3 -0
- package/plugins/steve/steve-pagination-utils.ts +14 -13
- package/plugins/steve/subscribe.js +229 -42
- package/rancher-components/BadgeState/BadgeState.vue +3 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +2 -2
- package/rancher-components/RcItemCard/RcItemCard.test.ts +189 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +425 -0
- package/rancher-components/RcItemCard/RcItemCardAction.vue +24 -0
- package/rancher-components/RcItemCard/index.ts +2 -0
- package/store/auth.js +1 -0
- package/store/catalog.js +62 -24
- package/store/index.js +33 -14
- package/store/slideInPanel.ts +6 -0
- package/store/type-map.js +1 -0
- package/types/fleet.d.ts +35 -0
- package/types/resources/settings.d.ts +19 -1
- package/types/shell/index.d.ts +339 -272
- package/types/store/dashboard-store.types.ts +17 -3
- package/types/store/pagination.types.ts +6 -1
- package/types/store/subscribe.types.ts +50 -0
- package/utils/auth.js +32 -3
- package/utils/fleet-types.ts +0 -0
- package/utils/fleet.ts +200 -1
- package/utils/pagination-utils.ts +26 -1
- package/utils/pagination-wrapper.ts +132 -50
- package/utils/settings.ts +4 -1
- package/utils/style.ts +39 -0
- package/utils/validators/formRules/__tests__/index.test.ts +36 -3
- package/utils/validators/formRules/index.ts +10 -3
- package/utils/window.js +11 -7
- package/components/__tests__/ApplicationCard.test.ts +0 -27
- package/components/cards/ApplicationCard.vue +0 -145
- package/components/fleet/ForceDirectedTreeChart/chartIcons.js +0 -17
- package/config/secret.js +0 -14
- package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +0 -249
- /package/{components/form/SSHKnownHosts → dialog}/__tests__/KnownHostsEditDialog.test.ts +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import DetailPage from '@shell/components/Resource/Detail/Page.vue';
|
|
3
|
+
import { CONFIG_MAP } from '@shell/config/types';
|
|
4
|
+
import { useStore } from 'vuex';
|
|
5
|
+
|
|
6
|
+
const store = useStore();
|
|
7
|
+
const configMaps = await store.dispatch('cluster/findAll', { type: CONFIG_MAP });
|
|
8
|
+
|
|
9
|
+
</script>
|
|
10
|
+
<template>
|
|
11
|
+
<DetailPage>
|
|
12
|
+
<template #top-area>
|
|
13
|
+
ConfigMap
|
|
14
|
+
</template>
|
|
15
|
+
<template #middle-area>
|
|
16
|
+
{{ configMaps }}
|
|
17
|
+
</template>
|
|
18
|
+
</DetailPage>
|
|
19
|
+
</template>
|
|
@@ -9,6 +9,7 @@ import garbageCollect from '@shell/utils/gc/gc';
|
|
|
9
9
|
import { addSchemaIndexFields } from '@shell/plugins/steve/schema.utils';
|
|
10
10
|
import { addParam, parse } from '@shell/utils/url';
|
|
11
11
|
import { conditionalDepaginate } from '@shell/store/type-map.utils';
|
|
12
|
+
import { STEVE_WATCH_MODE } from '@shell/types/store/subscribe.types';
|
|
12
13
|
import { FilterArgs } from '@shell/types/store/pagination.types';
|
|
13
14
|
import { isLabelSelectorEmpty, labelSelectorToSelector } from '@shell/utils/selector-typed';
|
|
14
15
|
|
|
@@ -183,7 +184,6 @@ export default {
|
|
|
183
184
|
|
|
184
185
|
opt = opt || {};
|
|
185
186
|
type = getters.normalizeType(type);
|
|
186
|
-
|
|
187
187
|
if ( !getters.typeRegistered(type) ) {
|
|
188
188
|
commit('registerType', type);
|
|
189
189
|
}
|
|
@@ -426,8 +426,20 @@ export default {
|
|
|
426
426
|
commit('registerType', type);
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
+
// of type @STEVE_WATCH_PARAMS
|
|
430
|
+
const watchArgs = {
|
|
431
|
+
type,
|
|
432
|
+
namespace: opt.watchNamespace || opt.namespaced, // it could be either apparently
|
|
433
|
+
force: opt.forceWatch === true,
|
|
434
|
+
mode: STEVE_WATCH_MODE.RESOURCE_CHANGES,
|
|
435
|
+
};
|
|
436
|
+
|
|
429
437
|
// No need to request the resources if we have them already
|
|
430
438
|
if (!opt.transient && !opt.force && getters['havePaginatedPage'](type, opt)) {
|
|
439
|
+
if (opt.watch !== false ) {
|
|
440
|
+
dispatch('watch', watchArgs);
|
|
441
|
+
}
|
|
442
|
+
|
|
431
443
|
return findAllGetter(getters, type, opt);
|
|
432
444
|
}
|
|
433
445
|
|
|
@@ -451,11 +463,7 @@ export default {
|
|
|
451
463
|
return Promise.reject(e);
|
|
452
464
|
}
|
|
453
465
|
|
|
454
|
-
|
|
455
|
-
type,
|
|
456
|
-
all: true,
|
|
457
|
-
});
|
|
458
|
-
|
|
466
|
+
// Of type @StorePagination
|
|
459
467
|
const pagination = opt.pagination ? {
|
|
460
468
|
request: {
|
|
461
469
|
namespace: opt.namespaced,
|
|
@@ -472,11 +480,16 @@ export default {
|
|
|
472
480
|
commit('loadPage', {
|
|
473
481
|
ctx,
|
|
474
482
|
type,
|
|
475
|
-
data:
|
|
483
|
+
data: out.data,
|
|
476
484
|
pagination,
|
|
485
|
+
revision: out.revision,
|
|
477
486
|
});
|
|
478
487
|
}
|
|
479
488
|
|
|
489
|
+
if ( !opt.transient && opt.watch !== false ) {
|
|
490
|
+
dispatch('watch', watchArgs);
|
|
491
|
+
}
|
|
492
|
+
|
|
480
493
|
if (opt.hasManualRefresh) {
|
|
481
494
|
dispatch('resource-fetch/updateManualRefreshIsLoading', false, { root: true });
|
|
482
495
|
}
|
|
@@ -671,7 +684,15 @@ export default {
|
|
|
671
684
|
return out;
|
|
672
685
|
},
|
|
673
686
|
|
|
674
|
-
|
|
687
|
+
/**
|
|
688
|
+
* Add or update the given resource in the store
|
|
689
|
+
*
|
|
690
|
+
* invalidatePageCache
|
|
691
|
+
* - if something calls `load` then the cache no longer has a page so we invalidate it
|
|
692
|
+
* - however on resource create or remove this can lead to lists showing nothing... before the new page is fetched
|
|
693
|
+
* - for those cases avoid invaliding the page cache
|
|
694
|
+
*/
|
|
695
|
+
load(ctx, { data, existing, invalidatePageCache }) {
|
|
675
696
|
const { getters, commit } = ctx;
|
|
676
697
|
|
|
677
698
|
let type = normalizeType(data.type);
|
|
@@ -704,7 +725,8 @@ export default {
|
|
|
704
725
|
commit('load', {
|
|
705
726
|
ctx,
|
|
706
727
|
data,
|
|
707
|
-
existing
|
|
728
|
+
existing,
|
|
729
|
+
invalidatePageCache // Avoid havePage invalidation
|
|
708
730
|
});
|
|
709
731
|
|
|
710
732
|
if ( type === SCHEMA ) {
|
|
@@ -50,6 +50,33 @@ export const urlFor = (state, getters) => (type, id, opt) => {
|
|
|
50
50
|
return url;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
+
function resourceCount(rootGetters, getters, typeObj) {
|
|
54
|
+
let _typeObj = typeObj;
|
|
55
|
+
const { name: type, count } = _typeObj;
|
|
56
|
+
|
|
57
|
+
if (!type) {
|
|
58
|
+
throw new Error(`Resource type required to calc count: ${ JSON.stringify(typeObj) }`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!count) {
|
|
62
|
+
const schema = getters.schemaFor(type);
|
|
63
|
+
const counts = getters.all(COUNT)?.[0]?.counts || {};
|
|
64
|
+
const count = counts[type];
|
|
65
|
+
|
|
66
|
+
// This object aligns with `Type.vue` `type`
|
|
67
|
+
_typeObj = {
|
|
68
|
+
count: count ? count.summary.count || 0 : null,
|
|
69
|
+
byNamespace: count ? count.namespaces : {},
|
|
70
|
+
revision: count ? count.revision : null,
|
|
71
|
+
namespaced: schema?.attributes?.namespaced
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const namespaces = _typeObj?.namespaced && !rootGetters.isAllNamespaces ? Object.keys(rootGetters.activeNamespaceCache || {}) : [];
|
|
76
|
+
|
|
77
|
+
return matchingCounts(_typeObj, namespaces.length ? namespaces : null);
|
|
78
|
+
}
|
|
79
|
+
|
|
53
80
|
/**
|
|
54
81
|
* Find the number of resources given
|
|
55
82
|
* - if the type is namespaced
|
|
@@ -374,6 +401,9 @@ export default {
|
|
|
374
401
|
return state.types[type]?.haveNamespace || null;
|
|
375
402
|
},
|
|
376
403
|
|
|
404
|
+
/**
|
|
405
|
+
* Returns (type: string ) => StorePagination
|
|
406
|
+
*/
|
|
377
407
|
havePage: (state, getters) => (type) => {
|
|
378
408
|
type = getters.normalizeType(type);
|
|
379
409
|
|
|
@@ -455,30 +485,13 @@ export default {
|
|
|
455
485
|
*
|
|
456
486
|
*/
|
|
457
487
|
count: (state, getters, rootState, rootGetters) => (typeObj) => {
|
|
458
|
-
|
|
459
|
-
const { name: type, count } = _typeObj;
|
|
488
|
+
const subTypes = rootGetters['type-map/optionsFor'](typeObj.name).subTypes || [];
|
|
460
489
|
|
|
461
|
-
if (
|
|
462
|
-
|
|
490
|
+
if (subTypes.length) {
|
|
491
|
+
return subTypes.reduce((acc, type) => acc + resourceCount(rootGetters, getters, { name: type }), 0);
|
|
463
492
|
}
|
|
464
493
|
|
|
465
|
-
|
|
466
|
-
const schema = getters.schemaFor(type);
|
|
467
|
-
const counts = getters.all(COUNT)?.[0]?.counts || {};
|
|
468
|
-
const count = counts[type];
|
|
469
|
-
|
|
470
|
-
// This object aligns with `Type.vue` `type`
|
|
471
|
-
_typeObj = {
|
|
472
|
-
count: count ? count.summary.count || 0 : null,
|
|
473
|
-
byNamespace: count ? count.namespaces : {},
|
|
474
|
-
revision: count ? count.revision : null,
|
|
475
|
-
namespaced: schema?.attributes?.namespaced
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
const namespaces = _typeObj?.namespaced && !rootGetters.isAllNamespaces ? Object.keys(rootGetters.activeNamespaceCache || {}) : [];
|
|
480
|
-
|
|
481
|
-
return matchingCounts(_typeObj, namespaces.length ? namespaces : null);
|
|
494
|
+
return resourceCount(rootGetters, getters, typeObj);
|
|
482
495
|
},
|
|
483
496
|
|
|
484
497
|
generation: (state, getters) => (type) => {
|
|
@@ -86,8 +86,16 @@ export function createLoadArgs(ctx, dataType) {
|
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Add or update the given resource in the store
|
|
91
|
+
*
|
|
92
|
+
* invalidatePageCache
|
|
93
|
+
* - if something calls `load` then the cache no longer has a page so we invalidate it
|
|
94
|
+
* - however on resource create or remove this can lead to lists showing nothing... before the new page is fetched
|
|
95
|
+
* - for those cases avoid invaliding the page cache
|
|
96
|
+
*/
|
|
89
97
|
export function load(state, {
|
|
90
|
-
data, ctx, existing, cachedArgs
|
|
98
|
+
data, ctx, existing, cachedArgs, invalidatePageCache = true,
|
|
91
99
|
}) {
|
|
92
100
|
const { getters } = ctx;
|
|
93
101
|
// Optimisation. This can run once per resource loaded.., so pass in from parent
|
|
@@ -130,8 +138,12 @@ export function load(state, {
|
|
|
130
138
|
}
|
|
131
139
|
} else {
|
|
132
140
|
if (inMap) {
|
|
141
|
+
// In theory cached `entry` should match provided `existing`, so changes merged from `data` into `entry` should be reflected in `existing`.
|
|
142
|
+
// However.. there's a disconnect happening somewhere so merge data into `existing` before merging into `entry`
|
|
143
|
+
const latestEntry = existing && entry !== existing ? replaceResource(existing, data, getters) : data;
|
|
144
|
+
|
|
133
145
|
// There's already an entry in the store, so merge changes into it. The list entry is a reference to the map (and vice versa)
|
|
134
|
-
entry = replaceResource(entry,
|
|
146
|
+
entry = replaceResource(entry, latestEntry, getters);
|
|
135
147
|
} else {
|
|
136
148
|
// There's no entry, make a new proxy
|
|
137
149
|
entry = reactive(classify(ctx, data));
|
|
@@ -164,7 +176,8 @@ export function load(state, {
|
|
|
164
176
|
}
|
|
165
177
|
}
|
|
166
178
|
|
|
167
|
-
|
|
179
|
+
// see `invalidatePageCache` description above
|
|
180
|
+
cache.havePage = invalidatePageCache ? false : cache.havePage;
|
|
168
181
|
|
|
169
182
|
return entry;
|
|
170
183
|
}
|
|
@@ -476,29 +489,60 @@ export default {
|
|
|
476
489
|
data,
|
|
477
490
|
ctx,
|
|
478
491
|
pagination,
|
|
492
|
+
revision
|
|
479
493
|
}) {
|
|
480
494
|
if (!data) {
|
|
481
495
|
return;
|
|
482
496
|
}
|
|
497
|
+
// We loop over data three times in this mutator, which is bad
|
|
498
|
+
// However we're only dealing with pageSize worth of data and splitting out into three loops improves legibility
|
|
483
499
|
|
|
484
500
|
const keyField = ctx.getters.keyFieldForType(type);
|
|
485
|
-
|
|
501
|
+
|
|
502
|
+
// Why don't we just replace the map? Because we
|
|
503
|
+
// 1. nav to list, subscribe to changes
|
|
504
|
+
// 2. nav to resource in list
|
|
505
|
+
// 3. update to page comes over
|
|
506
|
+
// 4. need to update the reference the detail list uses
|
|
507
|
+
const proxiesMap = {};
|
|
508
|
+
const proxies = reactive(data.map((x) => {
|
|
509
|
+
proxiesMap[x[keyField]] = true;
|
|
510
|
+
|
|
511
|
+
return classify(ctx, x);
|
|
512
|
+
}));
|
|
486
513
|
const cache = registerType(state, type);
|
|
487
514
|
|
|
488
|
-
clear(cache.list);
|
|
489
|
-
cache.map.clear();
|
|
490
515
|
cache.generation++;
|
|
491
516
|
|
|
517
|
+
// Update list
|
|
518
|
+
clear(cache.list);
|
|
492
519
|
addObjects(cache.list, proxies);
|
|
493
520
|
|
|
521
|
+
// Update Map (remove stale)
|
|
522
|
+
cache.map.forEach((value, key) => {
|
|
523
|
+
if (!proxiesMap[value[keyField]]) {
|
|
524
|
+
cache.map.delete(key);
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// Update Map (update existing / add latest)
|
|
494
529
|
for ( let i = 0 ; i < proxies.length ; i++ ) {
|
|
495
|
-
|
|
530
|
+
// This could probably be merged with the first loop above
|
|
531
|
+
const existing = cache.map.get(proxies[i][keyField]);
|
|
532
|
+
const latest = proxies[i];
|
|
533
|
+
|
|
534
|
+
if (existing) {
|
|
535
|
+
replaceResource(existing, latest, ctx.getters);
|
|
536
|
+
} else {
|
|
537
|
+
cache.map.set(latest[keyField], latest);
|
|
538
|
+
}
|
|
496
539
|
}
|
|
497
540
|
|
|
498
541
|
// havePage is of type `StorePagination`
|
|
499
542
|
cache.havePage = pagination;
|
|
500
543
|
cache.haveNamespace = undefined;
|
|
501
544
|
cache.haveAll = undefined;
|
|
545
|
+
cache.revision = revision;
|
|
502
546
|
|
|
503
547
|
return proxies;
|
|
504
548
|
},
|
|
@@ -1180,7 +1180,8 @@ export default class Resource {
|
|
|
1180
1180
|
}
|
|
1181
1181
|
|
|
1182
1182
|
// @TODO remove this once the API maps steve _type <-> k8s type in both directions
|
|
1183
|
-
// Completely disconnect the object we're going to
|
|
1183
|
+
// `JSON.parse(JSON.stringify` - Completely disconnect the object we're going to send and `this`. This ensures that properties
|
|
1184
|
+
// removed from opt.data before sending (as part of cleanForSave) are not stripped from where they're still needed (`this`)
|
|
1184
1185
|
opt.data = this.toSave() || JSON.parse(JSON.stringify(this));
|
|
1185
1186
|
|
|
1186
1187
|
if (opt.data._type) {
|
|
@@ -1248,7 +1249,18 @@ export default class Resource {
|
|
|
1248
1249
|
|
|
1249
1250
|
const res = await this.$dispatch('request', { opt, type: this.type } );
|
|
1250
1251
|
|
|
1251
|
-
|
|
1252
|
+
// In theory...
|
|
1253
|
+
// 200 - resource could have finalizer (could hang around, keep resource to show deleting state)
|
|
1254
|
+
// 204 - resource should be gone gone (so remove immediately)
|
|
1255
|
+
// However...
|
|
1256
|
+
// 200 - this is the only status code returned
|
|
1257
|
+
if ( res?._status === 200 ) {
|
|
1258
|
+
// Show state (probably terminating) immediately, don't wait for resource.change or debounced resource.changes update
|
|
1259
|
+
// It would be neater to only do this in the debounced resource.changes world, but there's no neat / complete way to do this (paginationUtils will cause dep issues if imported)
|
|
1260
|
+
await this.$dispatch('load', {
|
|
1261
|
+
data: res, existing: this, invalidatePageCache: false
|
|
1262
|
+
});
|
|
1263
|
+
} else if ( res?._status === 204 ) {
|
|
1252
1264
|
// If there's no body, assume the resource was immediately deleted
|
|
1253
1265
|
// and drop it from the store as if a remove event happened.
|
|
1254
1266
|
await this.$dispatch('ws.resource.remove', { data: this });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { actions } from '../subscribe';
|
|
1
|
+
import { actions, getters } from '../subscribe';
|
|
2
2
|
|
|
3
3
|
describe('steve: subscribe', () => {
|
|
4
4
|
describe('actions', () => {
|
|
@@ -106,4 +106,69 @@ describe('steve: subscribe', () => {
|
|
|
106
106
|
});
|
|
107
107
|
});
|
|
108
108
|
});
|
|
109
|
+
|
|
110
|
+
describe('getters', () => {
|
|
111
|
+
describe('nextResourceVersion', () => {
|
|
112
|
+
const myType = 'myType';
|
|
113
|
+
const myId = `myId`;
|
|
114
|
+
|
|
115
|
+
type Revision = string | number | null | undefined
|
|
116
|
+
|
|
117
|
+
const createState = (revision?: Revision, cachedList?: any[] ) => {
|
|
118
|
+
const typeState: any = {};
|
|
119
|
+
|
|
120
|
+
if (revision !== undefined) {
|
|
121
|
+
typeState.revision = revision;
|
|
122
|
+
}
|
|
123
|
+
if (cachedList !== undefined) {
|
|
124
|
+
typeState.list = cachedList;
|
|
125
|
+
} else {
|
|
126
|
+
typeState.list = [];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return { types: { [myType.toLocaleLowerCase()]: typeState } };
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const createGetters = (revision?: Revision) => {
|
|
133
|
+
return {
|
|
134
|
+
byId: (type: any, id: any) => {
|
|
135
|
+
expect(type).toBe(myType.toLowerCase());
|
|
136
|
+
expect(id).toBe(myId);
|
|
137
|
+
|
|
138
|
+
return { metadata: { resourceVersion: revision } };
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
it.each([
|
|
144
|
+
['Is String, Return String', createGetters('abc'), myId, 'abc'],
|
|
145
|
+
// This catches old parseInt errors
|
|
146
|
+
['Is String, Return String (integer prefix)', createGetters('123-abc'), myId, '123-abc'],
|
|
147
|
+
// This catches old parseInt errors
|
|
148
|
+
['Is String, Return String (integer postfix)', createGetters('abc-123'), myId, 'abc-123'],
|
|
149
|
+
['Is 0, Return Null', createGetters(0), myId, null],
|
|
150
|
+
['Is Number, Return Number', createGetters(123), myId, 123],
|
|
151
|
+
['Is Missing (null), Return Null', createGetters(null), myId, null],
|
|
152
|
+
['Is Missing (undefined), Return Null', createGetters(undefined), myId, null],
|
|
153
|
+
])('test revision from a single resource - %s', (_, storeGetters, id, expected) => {
|
|
154
|
+
expect(getters.nextResourceVersion(createState(), storeGetters)(myType, id)).toBe(expected);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const createResource = (revision: Revision) => ({ metadata: { resourceVersion: revision } });
|
|
158
|
+
|
|
159
|
+
it.each([
|
|
160
|
+
['Is String, Return String', createState('abc'), 'abc'],
|
|
161
|
+
['Is String, Return String (integer prefix)', createState('123-abc'), '123-abc'],
|
|
162
|
+
['Is String, Return String (integer postfix)', createState('abc-123'), 'abc-123'],
|
|
163
|
+
['Is 0, Return Null (nothing in cache)', createState(0), null],
|
|
164
|
+
['Is 0, Return Number (numbers in cache)', createState(0, [createResource(1), createResource(2), createResource(3)]), 3],
|
|
165
|
+
['Is 0, Return Number (numbers and strings in cache)', createState(0, [createResource(1), createResource('abc-2'), createResource('3-abc')]), 1],
|
|
166
|
+
['Is 0, Return Null (only strings in cache)', createState(0, [createResource('abc'), createResource('abc-2'), createResource('3-abc')]), null],
|
|
167
|
+
['Is missing (undefined), Return Null ', createState(undefined), null],
|
|
168
|
+
['Is missing (null), Return Null', createState(null), null],
|
|
169
|
+
])('test revision from a collection - %s', (_, state, expected) => {
|
|
170
|
+
expect(getters.nextResourceVersion(state, {})(myType)).toBe(expected);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
});
|
|
109
174
|
});
|
package/plugins/steve/actions.js
CHANGED
|
@@ -58,6 +58,9 @@ export default {
|
|
|
58
58
|
waiting = state.deferredRequests[key];
|
|
59
59
|
|
|
60
60
|
if ( waiting ) {
|
|
61
|
+
// A matching request has already been made and is currently waiting to complete
|
|
62
|
+
// Avoid making another request, just wait for the original one to complete
|
|
63
|
+
// and return the result of the first call (see `waiting` being processed far below)
|
|
61
64
|
const later = deferred();
|
|
62
65
|
|
|
63
66
|
waiting.push(later);
|
|
@@ -649,7 +649,7 @@ export const PAGINATION_SETTINGS_STORE_DEFAULTS: PaginationSettingsStore = {
|
|
|
649
649
|
enabled: [
|
|
650
650
|
NODE, EVENT,
|
|
651
651
|
WORKLOAD_TYPES.CRON_JOB, WORKLOAD_TYPES.DAEMON_SET, WORKLOAD_TYPES.DEPLOYMENT, WORKLOAD_TYPES.JOB, WORKLOAD_TYPES.STATEFUL_SET, POD,
|
|
652
|
-
CATALOG.APP, CATALOG.
|
|
652
|
+
CATALOG.APP, CATALOG.OPERATION,
|
|
653
653
|
HPA, INGRESS, SERVICE,
|
|
654
654
|
PV, CONFIG_MAP, STORAGE_CLASS, PVC, SECRET,
|
|
655
655
|
WORKLOAD_TYPES.REPLICA_SET, WORKLOAD_TYPES.REPLICATION_CONTROLLER
|
|
@@ -658,18 +658,19 @@ export const PAGINATION_SETTINGS_STORE_DEFAULTS: PaginationSettingsStore = {
|
|
|
658
658
|
}
|
|
659
659
|
}
|
|
660
660
|
},
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
661
|
+
// Disabled due to https://github.com/rancher/dashboard/issues/14493
|
|
662
|
+
// management: {
|
|
663
|
+
// resources: {
|
|
664
|
+
// enableAll: false,
|
|
665
|
+
// enableSome: {
|
|
666
|
+
// enabled: [
|
|
667
|
+
// { resource: CAPI.RANCHER_CLUSTER, context: ['home', 'side-bar'] },
|
|
668
|
+
// { resource: MANAGEMENT.CLUSTER, context: ['side-bar'] },
|
|
669
|
+
// ],
|
|
670
|
+
// generic: false,
|
|
671
|
+
// }
|
|
672
|
+
// }
|
|
673
|
+
// }
|
|
673
674
|
};
|
|
674
675
|
|
|
675
676
|
export default new StevePaginationUtils();
|