@rancher/shell 3.0.6 → 3.0.8-rc.1
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/pl/dark/rancher-logo.svg +131 -44
- package/assets/images/pl/rancher-logo.svg +120 -44
- package/assets/images/vendor/githubapp.svg +13 -0
- package/assets/styles/base/_basic.scss +2 -2
- package/assets/styles/base/_color-classic.scss +51 -0
- package/assets/styles/base/_color.scss +3 -3
- package/assets/styles/base/_mixins.scss +1 -1
- package/assets/styles/base/_typography.scss +1 -1
- package/assets/styles/base/_variables-classic.scss +47 -0
- package/assets/styles/global/_button.scss +49 -17
- package/assets/styles/global/_form.scss +1 -1
- package/assets/styles/themes/_dark.scss +4 -0
- package/assets/styles/themes/_light.scss +3 -69
- package/assets/styles/themes/_modern.scss +194 -50
- package/assets/styles/vendor/vue-select.scss +1 -2
- package/assets/translations/en-us.yaml +124 -32
- package/assets/translations/zh-hans.yaml +0 -4
- package/components/ClusterIconMenu.vue +1 -1
- package/components/ClusterProviderIcon.vue +1 -1
- package/components/CodeMirror.vue +1 -1
- package/components/IconOrSvg.vue +40 -29
- package/components/Inactivity.vue +222 -106
- package/components/InstallHelmCharts.vue +2 -2
- package/components/ResourceDetail/index.vue +2 -1
- package/components/SortableTable/index.vue +17 -2
- package/components/SortableTable/sorting.js +3 -1
- package/components/Tabbed/index.vue +5 -5
- package/components/fleet/FleetConfigMapSelector.vue +117 -0
- package/components/fleet/FleetSecretSelector.vue +127 -0
- package/components/fleet/__tests__/FleetConfigMapSelector.test.ts +125 -0
- package/components/fleet/__tests__/FleetSecretSelector.test.ts +82 -0
- package/components/form/FileImageSelector.vue +13 -4
- package/components/form/FileSelector.vue +11 -2
- package/components/form/ResourceLabeledSelect.vue +1 -0
- package/components/form/ResourceTabs/index.vue +37 -18
- package/components/form/SecretSelector.vue +6 -2
- package/components/form/__tests__/ResourceLabeledSelect.test.ts +90 -0
- package/components/nav/Group.vue +29 -9
- package/components/nav/Header.vue +7 -8
- package/components/nav/NamespaceFilter.vue +1 -1
- package/components/nav/TopLevelMenu.helper.ts +47 -20
- package/components/nav/TopLevelMenu.vue +44 -14
- package/components/nav/Type.vue +0 -5
- package/components/nav/__tests__/TopLevelMenu.test.ts +2 -0
- package/config/pagination-table-headers.js +10 -2
- package/config/product/auth.js +1 -0
- package/config/product/explorer.js +4 -3
- package/config/query-params.js +1 -0
- package/config/settings.ts +8 -1
- package/config/table-headers.js +9 -0
- package/config/types.js +2 -0
- package/core/plugin.ts +18 -6
- package/core/types.ts +8 -0
- package/detail/provisioning.cattle.io.cluster.vue +1 -0
- package/dialog/AddonConfigConfirmationDialog.vue +45 -1
- package/dialog/InstallExtensionDialog.vue +71 -45
- package/dialog/UninstallExtensionDialog.vue +2 -1
- package/dialog/__tests__/InstallExtensionDialog.test.ts +111 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +52 -11
- package/edit/auth/AuthProviderWarningBanners.vue +14 -1
- package/edit/auth/github-app-steps.vue +97 -0
- package/edit/auth/github-steps.vue +75 -0
- package/edit/auth/github.vue +94 -65
- package/edit/auth/oidc.vue +86 -16
- package/edit/fleet.cattle.io.helmop.vue +51 -2
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +15 -5
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +11 -9
- package/edit/provisioning.cattle.io.cluster/rke2.vue +56 -9
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +28 -2
- package/list/projectsecret.vue +1 -1
- package/machine-config/azure.vue +1 -1
- package/mixins/__tests__/chart.test.ts +1 -1
- package/mixins/chart.js +2 -2
- package/models/__tests__/chart.test.ts +17 -9
- package/models/__tests__/compliance.cattle.io.clusterscanprofile.spec.js +30 -0
- package/models/catalog.cattle.io.app.js +1 -1
- package/models/chart.js +3 -1
- package/models/compliance.cattle.io.clusterscanprofile.js +1 -1
- package/models/event.js +7 -0
- package/models/management.cattle.io.authconfig.js +1 -0
- package/models/provisioning.cattle.io.cluster.js +9 -0
- package/package.json +2 -2
- package/pages/auth/login.vue +5 -2
- package/pages/auth/verify.vue +1 -1
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +3 -2
- package/pages/c/_cluster/apps/charts/chart.vue +2 -2
- package/pages/c/_cluster/explorer/EventsTable.vue +92 -9
- package/pages/c/_cluster/explorer/tools/index.vue +3 -3
- package/pages/c/_cluster/settings/performance.vue +13 -26
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +159 -62
- package/pages/c/_cluster/uiplugins/__tests__/PluginInfoPanel.test.ts +102 -0
- package/pages/c/_cluster/uiplugins/__tests__/{index.spec.ts → index.test.ts} +121 -55
- package/pages/c/_cluster/uiplugins/index.vue +110 -94
- package/pages/home.vue +313 -12
- package/plugins/__tests__/subscribe.events.test.ts +194 -0
- package/plugins/axios.js +2 -1
- package/plugins/dashboard-store/actions.js +4 -1
- package/plugins/dashboard-store/getters.js +1 -1
- package/plugins/dashboard-store/resource-class.js +20 -5
- package/plugins/steve/__tests__/subscribe.spec.ts +27 -24
- package/plugins/steve/index.js +18 -10
- package/plugins/steve/mutations.js +2 -2
- package/plugins/steve/resourceWatcher.js +2 -2
- package/plugins/steve/steve-pagination-utils.ts +12 -9
- package/plugins/steve/subscribe.js +113 -85
- package/plugins/subscribe-events.ts +211 -0
- package/rancher-components/BadgeState/BadgeState.vue +8 -6
- package/rancher-components/Banner/Banner.vue +2 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +3 -3
- package/rancher-components/Form/Radio/RadioButton.vue +3 -3
- package/scripts/extension/publish +1 -1
- package/store/auth.js +8 -3
- package/store/aws.js +8 -6
- package/store/features.js +1 -0
- package/store/index.js +21 -25
- package/store/prefs.js +6 -0
- package/types/extension-manager.ts +8 -1
- package/types/kube/kube-api.ts +2 -1
- package/types/rancher/index.d.ts +1 -0
- package/types/resources/settings.d.ts +52 -23
- package/types/shell/index.d.ts +412 -336
- package/types/store/subscribe-events.types.ts +70 -0
- package/types/store/subscribe.types.ts +6 -22
- package/utils/__tests__/cluster.test.ts +379 -1
- package/utils/cluster.js +157 -3
- package/utils/dynamic-content/__tests__/config.test.ts +187 -0
- package/utils/dynamic-content/__tests__/index.test.ts +390 -0
- package/utils/dynamic-content/__tests__/info.test.ts +263 -0
- package/utils/dynamic-content/__tests__/new-release.test.ts +216 -0
- package/utils/dynamic-content/__tests__/support-notice.test.ts +262 -0
- package/utils/dynamic-content/__tests__/util.test.ts +235 -0
- package/utils/dynamic-content/config.ts +55 -0
- package/utils/dynamic-content/index.ts +273 -0
- package/utils/dynamic-content/info.ts +219 -0
- package/utils/dynamic-content/new-release.ts +126 -0
- package/utils/dynamic-content/support-notice.ts +169 -0
- package/utils/dynamic-content/types.d.ts +101 -0
- package/utils/dynamic-content/util.ts +122 -0
- package/utils/inactivity.ts +104 -0
- package/utils/pagination-utils.ts +105 -31
- package/utils/pagination-wrapper.ts +6 -8
- package/utils/release-notes.ts +1 -1
- package/utils/sort.js +5 -0
- package/utils/unit-tests/pagination-utils.spec.ts +283 -0
- package/utils/validators/formRules/__tests__/index.test.ts +7 -0
- package/utils/validators/formRules/index.ts +2 -2
|
@@ -2,10 +2,9 @@ import paginationUtils from '@shell/utils/pagination-utils';
|
|
|
2
2
|
import { PaginationArgs, PaginationResourceContext } from '@shell/types/store/pagination.types';
|
|
3
3
|
import { VuexStore } from '@shell/types/store/vuex';
|
|
4
4
|
import { ActionFindPageArgs, ActionFindPageTransientResult } from '@shell/types/store/dashboard-store.types';
|
|
5
|
-
import {
|
|
6
|
-
STEVE_WATCH_EVENT_LISTENER_CALLBACK, STEVE_UNWATCH_EVENT_PARAMS, STEVE_WATCH_EVENT, STEVE_WATCH_EVENT_PARAMS, STEVE_WATCH_EVENT_PARAMS_COMMON, STEVE_WATCH_MODE
|
|
7
|
-
} from '@shell/types/store/subscribe.types';
|
|
5
|
+
import { STEVE_WATCH_EVENT_TYPES, STEVE_WATCH_MODE } from '@shell/types/store/subscribe.types';
|
|
8
6
|
import { Reactive, reactive } from 'vue';
|
|
7
|
+
import { STEVE_UNWATCH_EVENT_PARAMS, STEVE_WATCH_EVENT_LISTENER_CALLBACK, STEVE_WATCH_EVENT_PARAMS, STEVE_WATCH_EVENT_PARAMS_COMMON } from '@shell/types/store/subscribe-events.types';
|
|
9
8
|
|
|
10
9
|
interface Args {
|
|
11
10
|
$store: VuexStore,
|
|
@@ -70,7 +69,7 @@ class PaginationWrapper<T extends object> {
|
|
|
70
69
|
this.classify = formatResponse?.classify || false;
|
|
71
70
|
this.reactive = formatResponse?.reactive || false;
|
|
72
71
|
|
|
73
|
-
this.isEnabled = paginationUtils.isEnabled({ rootGetters: $store.getters }, enabledFor);
|
|
72
|
+
this.isEnabled = paginationUtils.isEnabled({ rootGetters: $store.getters, $plugin: this.$store.$plugin }, enabledFor);
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
async request(args: {
|
|
@@ -92,7 +91,7 @@ class PaginationWrapper<T extends object> {
|
|
|
92
91
|
// Watch
|
|
93
92
|
if (this.onChange && !this.steveWatchParams) {
|
|
94
93
|
this.steveWatchParams = {
|
|
95
|
-
event:
|
|
94
|
+
event: STEVE_WATCH_EVENT_TYPES.CHANGES,
|
|
96
95
|
id: this.id,
|
|
97
96
|
params: {
|
|
98
97
|
type: this.enabledFor.resource?.id as string,
|
|
@@ -126,7 +125,7 @@ class PaginationWrapper<T extends object> {
|
|
|
126
125
|
}
|
|
127
126
|
const watchParams: STEVE_WATCH_EVENT_PARAMS = {
|
|
128
127
|
...this.steveWatchParams,
|
|
129
|
-
callback: this.onChange as STEVE_WATCH_EVENT_LISTENER_CALLBACK, // we must have
|
|
128
|
+
callback: this.onChange as STEVE_WATCH_EVENT_LISTENER_CALLBACK, // we must have onChange by now
|
|
130
129
|
};
|
|
131
130
|
|
|
132
131
|
await this.$store.dispatch(`${ this.enabledFor.store }/watchEvent`, watchParams);
|
|
@@ -134,8 +133,7 @@ class PaginationWrapper<T extends object> {
|
|
|
134
133
|
|
|
135
134
|
private async unWatch() {
|
|
136
135
|
if (!this.steveWatchParams) {
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
// We're unwatching before we've made the initial request
|
|
139
137
|
return;
|
|
140
138
|
}
|
|
141
139
|
|
package/utils/release-notes.ts
CHANGED
|
@@ -20,7 +20,7 @@ export async function addReleaseNotesNotification(dispatch: any, getters: any) {
|
|
|
20
20
|
if (notification.id === id) {
|
|
21
21
|
found = true;
|
|
22
22
|
} else {
|
|
23
|
-
await dispatch('notifications/
|
|
23
|
+
await dispatch('notifications/remove', notification.id);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
}
|
package/utils/sort.js
CHANGED
|
@@ -169,6 +169,11 @@ export function compare(a, b) {
|
|
|
169
169
|
return 0;
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Should the logic of this sort field be flipped?
|
|
174
|
+
*
|
|
175
|
+
* For instance show descending but sort by ascending
|
|
176
|
+
*/
|
|
172
177
|
export function parseField(str) {
|
|
173
178
|
const parts = str.split(/:/);
|
|
174
179
|
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { STEVE_CACHE } from '@shell/store/features';
|
|
2
|
+
import { SETTING } from '@shell/config/settings';
|
|
3
|
+
import { EXT_IDS } from '@shell/core/plugin';
|
|
4
|
+
import { PaginationResourceContext } from '@shell/types/store/pagination.types';
|
|
5
|
+
import { PaginationSettings, PaginationSettingsStore } from '@shell/types/resources/settings';
|
|
6
|
+
import paginationUtils from '@shell/utils/pagination-utils';
|
|
7
|
+
|
|
8
|
+
describe('pagination-utils', () => {
|
|
9
|
+
describe('isEnabledInStore', () => {
|
|
10
|
+
const mockRootGetters = {
|
|
11
|
+
'type-map/configuredHeaders': jest.fn(),
|
|
12
|
+
'type-map/configuredPaginationHeaders': jest.fn(),
|
|
13
|
+
'type-map/hasCustomList': jest.fn(),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
jest.resetAllMocks();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should return false if no store settings are provided', () => {
|
|
21
|
+
const result = paginationUtils.isEnabledInStore({
|
|
22
|
+
ctx: { rootGetters: mockRootGetters },
|
|
23
|
+
storeSettings: undefined as unknown as PaginationSettingsStore,
|
|
24
|
+
enabledFor: { store: 'cluster' }
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
expect(result).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should return true if no specific resource is being checked', () => {
|
|
31
|
+
const storeSettings: PaginationSettingsStore = { resources: {} };
|
|
32
|
+
const result = paginationUtils.isEnabledInStore({
|
|
33
|
+
ctx: { rootGetters: mockRootGetters },
|
|
34
|
+
storeSettings,
|
|
35
|
+
enabledFor: { store: 'cluster' }
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
expect(result).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should return true if enableAll is true for the store', () => {
|
|
42
|
+
const storeSettings: PaginationSettingsStore = { resources: { enableAll: true } };
|
|
43
|
+
const result = paginationUtils.isEnabledInStore({
|
|
44
|
+
ctx: { rootGetters: mockRootGetters },
|
|
45
|
+
storeSettings,
|
|
46
|
+
enabledFor: { store: 'cluster', resource: { id: 'pod' } }
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
expect(result).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should return false if a resource is checked but has no id', () => {
|
|
53
|
+
const storeSettings: PaginationSettingsStore = { resources: {} };
|
|
54
|
+
const result = paginationUtils.isEnabledInStore({
|
|
55
|
+
ctx: { rootGetters: mockRootGetters },
|
|
56
|
+
storeSettings,
|
|
57
|
+
enabledFor: { store: 'cluster', resource: { id: undefined as unknown as string } }
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(result).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should return true for a generic resource when generic is enabled', () => {
|
|
64
|
+
mockRootGetters['type-map/configuredHeaders'].mockReturnValue(false);
|
|
65
|
+
mockRootGetters['type-map/configuredPaginationHeaders'].mockReturnValue(false);
|
|
66
|
+
mockRootGetters['type-map/hasCustomList'].mockReturnValue(false);
|
|
67
|
+
|
|
68
|
+
const storeSettings: PaginationSettingsStore = { resources: { enableSome: { generic: true } } };
|
|
69
|
+
const result = paginationUtils.isEnabledInStore({
|
|
70
|
+
ctx: { rootGetters: mockRootGetters },
|
|
71
|
+
storeSettings,
|
|
72
|
+
enabledFor: { store: 'cluster', resource: { id: 'pod' } }
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
expect(result).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should return false for a non-generic resource when only generic is enabled', () => {
|
|
79
|
+
mockRootGetters['type-map/hasCustomList'].mockReturnValue(true);
|
|
80
|
+
|
|
81
|
+
const storeSettings: PaginationSettingsStore = { resources: { enableSome: { generic: true } } };
|
|
82
|
+
const result = paginationUtils.isEnabledInStore({
|
|
83
|
+
ctx: { rootGetters: mockRootGetters },
|
|
84
|
+
storeSettings,
|
|
85
|
+
enabledFor: { store: 'cluster', resource: { id: 'pod' } }
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
expect(result).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should return true if resource id is in enabled list as a string', () => {
|
|
92
|
+
const storeSettings: PaginationSettingsStore = { resources: { enableSome: { enabled: ['pod'] } } };
|
|
93
|
+
const result = paginationUtils.isEnabledInStore({
|
|
94
|
+
ctx: { rootGetters: mockRootGetters },
|
|
95
|
+
storeSettings,
|
|
96
|
+
enabledFor: { store: 'cluster', resource: { id: 'pod' } }
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
expect(result).toBe(true);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should return true if resource id is in enabled list as an object without context', () => {
|
|
103
|
+
const storeSettings: PaginationSettingsStore = { resources: { enableSome: { enabled: [{ resource: 'pod' }] } } };
|
|
104
|
+
const result = paginationUtils.isEnabledInStore({
|
|
105
|
+
ctx: { rootGetters: mockRootGetters },
|
|
106
|
+
storeSettings,
|
|
107
|
+
enabledFor: { store: 'cluster', resource: { id: 'pod' } }
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
expect(result).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should return false if resource id is in enabled list as an object with empty context', () => {
|
|
114
|
+
const storeSettings: PaginationSettingsStore = { resources: { enableSome: { enabled: [{ resource: 'pod', context: [] }] } } };
|
|
115
|
+
const result = paginationUtils.isEnabledInStore({
|
|
116
|
+
ctx: { rootGetters: mockRootGetters },
|
|
117
|
+
storeSettings,
|
|
118
|
+
enabledFor: { store: 'cluster', resource: { id: 'pod' } }
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
expect(result).toBe(false);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should return true if resource id and context match an enabled setting', () => {
|
|
125
|
+
const storeSettings: PaginationSettingsStore = { resources: { enableSome: { enabled: [{ resource: 'pod', context: ['list'] }] } } };
|
|
126
|
+
const result = paginationUtils.isEnabledInStore({
|
|
127
|
+
ctx: { rootGetters: mockRootGetters },
|
|
128
|
+
storeSettings,
|
|
129
|
+
enabledFor: { store: 'cluster', resource: { id: 'pod', context: 'list' } }
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
expect(result).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should return false if resource context does not match enabled setting', () => {
|
|
136
|
+
const storeSettings: PaginationSettingsStore = { resources: { enableSome: { enabled: [{ resource: 'pod', context: ['detail'] }] } } };
|
|
137
|
+
const result = paginationUtils.isEnabledInStore({
|
|
138
|
+
ctx: { rootGetters: mockRootGetters },
|
|
139
|
+
storeSettings,
|
|
140
|
+
enabledFor: { store: 'cluster', resource: { id: 'pod', context: 'list' } }
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
expect(result).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe('isEnabled', () => {
|
|
148
|
+
let mockRootGetters: any;
|
|
149
|
+
let mockPlugin: any;
|
|
150
|
+
let enabledFor: PaginationResourceContext;
|
|
151
|
+
|
|
152
|
+
beforeEach(() => {
|
|
153
|
+
enabledFor = { store: 'cluster', resource: { id: 'pod' } };
|
|
154
|
+
mockPlugin = { getAll: jest.fn().mockReturnValue({}) };
|
|
155
|
+
mockRootGetters = {
|
|
156
|
+
'features/get': jest.fn(),
|
|
157
|
+
'management/byId': jest.fn(),
|
|
158
|
+
'type-map/configuredHeaders': jest.fn().mockReturnValue(false),
|
|
159
|
+
'type-map/configuredPaginationHeaders': jest.fn().mockReturnValue(false),
|
|
160
|
+
'type-map/hasCustomList': jest.fn().mockReturnValue(false),
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should return false if steve cache is disabled', () => {
|
|
165
|
+
mockRootGetters['features/get'].mockImplementation((feature: string) => feature === STEVE_CACHE ? false : undefined);
|
|
166
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $plugin: mockPlugin }, enabledFor);
|
|
167
|
+
|
|
168
|
+
expect(result).toBe(false);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should return false if pagination settings are not defined', () => {
|
|
172
|
+
jest.spyOn(paginationUtils, 'getSettings').mockReturnValue(undefined);
|
|
173
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $plugin: mockPlugin }, enabledFor);
|
|
174
|
+
|
|
175
|
+
expect(result).toBe(false);
|
|
176
|
+
|
|
177
|
+
jest.clearAllMocks();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should return false if enabledFor is not provided', () => {
|
|
181
|
+
mockRootGetters['features/get'].mockReturnValue(true);
|
|
182
|
+
const settings: PaginationSettings = { useDefaultStores: true };
|
|
183
|
+
|
|
184
|
+
mockRootGetters['management/byId'].mockImplementation((type: string, id: string) => {
|
|
185
|
+
if (type === 'management.cattle.io.setting' && id === SETTING.UI_PERFORMANCE) {
|
|
186
|
+
return { value: JSON.stringify({ serverPagination: settings }) };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return null;
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $plugin: mockPlugin }, undefined as unknown as PaginationResourceContext);
|
|
193
|
+
|
|
194
|
+
expect(result).toBe(false);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('should return true if an extension enables the resource', () => {
|
|
198
|
+
mockRootGetters['features/get'].mockReturnValue(true);
|
|
199
|
+
const extensionSettings = { cluster: { resources: { enableAll: true } } };
|
|
200
|
+
|
|
201
|
+
mockPlugin.getAll.mockReturnValue({ [EXT_IDS.SERVER_SIDE_PAGINATION_RESOURCES]: { 'my-ext': () => extensionSettings } });
|
|
202
|
+
|
|
203
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $plugin: mockPlugin }, enabledFor);
|
|
204
|
+
|
|
205
|
+
expect(result).toBe(true);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should still return true if an extension enables the resource but core store does not', () => {
|
|
209
|
+
mockRootGetters['features/get'].mockReturnValue(true);
|
|
210
|
+
const extensionSettings = { cluster: { resources: { enableAll: true } } };
|
|
211
|
+
const defaultSettings = { cluster: { resources: { enableAll: false, enableSome: { enabled: [] } } } };
|
|
212
|
+
|
|
213
|
+
mockPlugin.getAll.mockReturnValue({ [EXT_IDS.SERVER_SIDE_PAGINATION_RESOURCES]: { 'my-ext': () => extensionSettings } });
|
|
214
|
+
|
|
215
|
+
// Mocking PAGINATION_SETTINGS_STORE_DEFAULTS behavior
|
|
216
|
+
jest.spyOn(paginationUtils, 'getStoreDefault').mockReturnValue(defaultSettings);
|
|
217
|
+
|
|
218
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $plugin: mockPlugin }, enabledFor);
|
|
219
|
+
|
|
220
|
+
expect(result).toBe(true);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('should use default store settings and enable the resource', () => {
|
|
224
|
+
mockRootGetters['features/get'].mockReturnValue(true);
|
|
225
|
+
const settings: PaginationSettings = { useDefaultStores: true };
|
|
226
|
+
|
|
227
|
+
mockRootGetters['management/byId'].mockImplementation((type: string, id: string) => {
|
|
228
|
+
if (type === 'management.cattle.io.setting' && id === SETTING.UI_PERFORMANCE) {
|
|
229
|
+
return { value: JSON.stringify({ serverPagination: settings }) };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return null;
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Mocking PAGINATION_SETTINGS_STORE_DEFAULTS behavior
|
|
236
|
+
jest.spyOn(paginationUtils, 'getStoreDefault').mockReturnValue({ cluster: { resources: { enableAll: true } } });
|
|
237
|
+
|
|
238
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $plugin: mockPlugin }, enabledFor);
|
|
239
|
+
|
|
240
|
+
expect(result).toBe(true);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should use custom store settings and enable the resource', () => {
|
|
244
|
+
mockRootGetters['features/get'].mockReturnValue(true);
|
|
245
|
+
const settings: PaginationSettings = {
|
|
246
|
+
useDefaultStores: false,
|
|
247
|
+
stores: { cluster: { resources: { enableSome: { enabled: ['pod'] } } } }
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
mockRootGetters['management/byId'].mockImplementation((type: string, id: string) => {
|
|
251
|
+
if (type === 'management.cattle.io.setting' && id === SETTING.UI_PERFORMANCE) {
|
|
252
|
+
return { value: JSON.stringify({ serverPagination: settings }) };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return null;
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $plugin: mockPlugin }, enabledFor);
|
|
259
|
+
|
|
260
|
+
expect(result).toBe(true);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('should return false if neither extension nor main settings enable the resource', () => {
|
|
264
|
+
mockRootGetters['features/get'].mockReturnValue(true);
|
|
265
|
+
const settings: PaginationSettings = {
|
|
266
|
+
useDefaultStores: false,
|
|
267
|
+
stores: { cluster: { resources: { enableSome: { enabled: ['service'] } } } }
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
mockRootGetters['management/byId'].mockImplementation((type: string, id: string) => {
|
|
271
|
+
if (type === 'management.cattle.io.setting' && id === SETTING.UI_PERFORMANCE) {
|
|
272
|
+
return { value: JSON.stringify({ serverPagination: settings }) };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return null;
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $plugin: mockPlugin }, enabledFor);
|
|
279
|
+
|
|
280
|
+
expect(result).toBe(false);
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
});
|
|
@@ -116,6 +116,10 @@ describe('formRules', () => {
|
|
|
116
116
|
['git@github.com:rancher/dashboard/%20', undefined],
|
|
117
117
|
['git@git.apps.local:fleet/fleet-local.git', undefined],
|
|
118
118
|
['git@git.apps.local:33333/fleet/fleet-local.git', undefined],
|
|
119
|
+
['ssh://git@github.com:rancher/dashboard', undefined],
|
|
120
|
+
['ssh://git@github.com:rancher/dashboard/', undefined],
|
|
121
|
+
['ssh://git@git.apps.local:fleet/fleet-local.git', undefined],
|
|
122
|
+
['ssh://git@git.apps.local:33333/fleet/fleet-local.git', undefined],
|
|
119
123
|
|
|
120
124
|
// Not valid HTTP(s)
|
|
121
125
|
['https://github.com/rancher/ dashboard.git', message],
|
|
@@ -145,6 +149,9 @@ describe('formRules', () => {
|
|
|
145
149
|
['git@git.apps.local:/fleet/fleet-local.git', message],
|
|
146
150
|
['git@.git', message],
|
|
147
151
|
['git@', message],
|
|
152
|
+
['ssh://git@github.com:/rancher/dashboard.git ', message],
|
|
153
|
+
['ssh://git@github.com/rancher/ dashboard.git', message],
|
|
154
|
+
['ssh://git@github.com/rancher/ dashboard', message],
|
|
148
155
|
|
|
149
156
|
[undefined, message],
|
|
150
157
|
['', message]
|
|
@@ -200,8 +200,8 @@ export default function(
|
|
|
200
200
|
return message;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
// Test http(s) protocol
|
|
204
|
-
if (protocol && (!/^(http|
|
|
203
|
+
// Test http(s)/ssh protocol
|
|
204
|
+
if (protocol && (!/^(http|https|ssh)$/gm.test(protocol) || (!url.startsWith('https://') && !url.startsWith('http://') && !url.startsWith('ssh://')))) {
|
|
205
205
|
return message;
|
|
206
206
|
}
|
|
207
207
|
|