@rancher/shell 3.0.8-rc.10 → 3.0.8-rc.12
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/components/ResourceTable.vue +1 -1
- package/components/SortableTable/index.vue +1 -1
- package/components/auth/login/ldap.vue +3 -3
- package/components/form/NodeScheduling.vue +2 -2
- package/components/nav/Group.vue +9 -2
- package/components/nav/Header.vue +1 -1
- package/components/nav/Type.vue +8 -3
- package/components/nav/__tests__/Type.test.ts +59 -0
- package/config/router/navigation-guards/clusters.js +3 -3
- package/config/router/navigation-guards/products.js +1 -1
- package/core/extension-manager-impl.js +5 -5
- package/core/plugin-helpers.ts +2 -2
- package/core/plugins-loader.js +2 -2
- package/core/types-provisioning.ts +4 -0
- package/detail/provisioning.cattle.io.cluster.vue +6 -6
- package/dialog/DeveloperLoadExtensionDialog.vue +1 -1
- package/dialog/SearchDialog.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +21 -21
- package/edit/provisioning.cattle.io.cluster/index.vue +5 -5
- package/edit/provisioning.cattle.io.cluster/rke2.vue +8 -8
- package/models/management.cattle.io.cluster.js +1 -1
- package/models/provisioning.cattle.io.cluster.js +1 -1
- package/package.json +3 -3
- package/pages/auth/login.vue +3 -3
- package/pages/auth/setup.vue +1 -1
- package/pages/auth/verify.vue +3 -3
- package/pkg/auto-import.js +3 -3
- package/pkg/dynamic-importer.lib.js +1 -1
- package/pkg/import.js +1 -1
- package/plugins/dashboard-store/getters.js +1 -1
- package/plugins/dashboard-store/model-loader.js +1 -1
- package/plugins/dashboard-store/resource-class.js +6 -2
- package/plugins/plugin.js +2 -2
- package/plugins/steve/steve-class.js +1 -1
- package/store/__tests__/catalog.test.ts +1 -1
- package/store/auth.js +1 -1
- package/store/i18n.js +3 -3
- package/store/index.js +5 -3
- package/store/type-map.js +4 -4
- package/types/shell/index.d.ts +1 -0
- package/utils/pagination-utils.ts +2 -2
- package/utils/pagination-wrapper.ts +1 -1
- package/utils/unit-tests/pagination-utils.spec.ts +8 -8
- package/vue.config.js +3 -3
|
@@ -316,7 +316,7 @@ export default {
|
|
|
316
316
|
|
|
317
317
|
// add custom table columns provided by the extensions ExtensionPoint.TABLE_COL hook
|
|
318
318
|
// gate it so that we prevent errors on older versions of dashboard
|
|
319
|
-
if (this.$store.$
|
|
319
|
+
if (this.$store.$extension?.getUIConfig) {
|
|
320
320
|
// { column: TableColumn, paginationColumn: PaginationTableColumn }[]
|
|
321
321
|
const extensionCols = getApplicableExtensionEnhancements(this, ExtensionPoint.TABLE_COL, TableColumnLocation.RESOURCE, this.$route);
|
|
322
322
|
|
|
@@ -765,7 +765,7 @@ export default {
|
|
|
765
765
|
needRef = true;
|
|
766
766
|
} else {
|
|
767
767
|
// Check if we have a formatter from a plugin
|
|
768
|
-
const pluginFormatter = this.$
|
|
768
|
+
const pluginFormatter = this.$extension?.getDynamic('formatters', c.formatter);
|
|
769
769
|
|
|
770
770
|
if (pluginFormatter) {
|
|
771
771
|
component = defineAsyncComponent(pluginFormatter);
|
|
@@ -181,7 +181,7 @@ export default {
|
|
|
181
181
|
:options="selectNodeOptions"
|
|
182
182
|
:mode="mode"
|
|
183
183
|
:data-testid="'node-scheduling-selectNode'"
|
|
184
|
-
@
|
|
184
|
+
@update:value="update"
|
|
185
185
|
/>
|
|
186
186
|
</div>
|
|
187
187
|
<template v-if="selectNode === 'nodeSelector'">
|
|
@@ -205,7 +205,7 @@ export default {
|
|
|
205
205
|
v-model:value="nodeAffinity"
|
|
206
206
|
:mode="mode"
|
|
207
207
|
:data-testid="'node-scheduling-nodeAffinity'"
|
|
208
|
-
@
|
|
208
|
+
@update:value="update"
|
|
209
209
|
/>
|
|
210
210
|
</template>
|
|
211
211
|
</div>
|
package/components/nav/Group.vue
CHANGED
|
@@ -41,6 +41,11 @@ export default {
|
|
|
41
41
|
fixedOpen: {
|
|
42
42
|
type: Boolean,
|
|
43
43
|
default: false,
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
highlightRoute: {
|
|
47
|
+
type: Boolean,
|
|
48
|
+
default: true,
|
|
44
49
|
}
|
|
45
50
|
},
|
|
46
51
|
|
|
@@ -233,7 +238,7 @@ export default {
|
|
|
233
238
|
<template>
|
|
234
239
|
<div
|
|
235
240
|
class="accordion"
|
|
236
|
-
:class="{[`depth-${depth}`]: true, 'expanded': isExpanded, 'has-children': hasChildren, 'group-highlight': isGroupActive }"
|
|
241
|
+
:class="{[`depth-${depth}`]: true, 'expanded': isExpanded, 'has-children': hasChildren, 'group-highlight': highlightRoute && isGroupActive }"
|
|
237
242
|
>
|
|
238
243
|
<div
|
|
239
244
|
v-if="showHeader || (!onlyHasOverview && canCollapse)"
|
|
@@ -242,7 +247,7 @@ export default {
|
|
|
242
247
|
<div
|
|
243
248
|
v-if="showHeader"
|
|
244
249
|
class="header"
|
|
245
|
-
:class="{'active': isOverview, 'noHover': !canCollapse || fixedOpen}"
|
|
250
|
+
:class="{'active': highlightRoute && isOverview, 'noHover': !canCollapse || fixedOpen}"
|
|
246
251
|
role="button"
|
|
247
252
|
:tabindex="fixedOpen ? -1 : 0"
|
|
248
253
|
:aria-label="group.labelDisplay || group.label || ''"
|
|
@@ -311,6 +316,7 @@ export default {
|
|
|
311
316
|
:can-collapse="canCollapse"
|
|
312
317
|
:group="child"
|
|
313
318
|
:fixed-open="fixedOpen"
|
|
319
|
+
:highlight-route="highlightRoute"
|
|
314
320
|
@selected="groupSelected($event)"
|
|
315
321
|
@expand="expandGroup($event)"
|
|
316
322
|
@close="close($event)"
|
|
@@ -322,6 +328,7 @@ export default {
|
|
|
322
328
|
:is-root="depth == 0 && !showHeader"
|
|
323
329
|
:type="child"
|
|
324
330
|
:depth="depth"
|
|
331
|
+
:highlight-route="highlightRoute"
|
|
325
332
|
@selected="selectType($event)"
|
|
326
333
|
/>
|
|
327
334
|
</template>
|
|
@@ -254,7 +254,7 @@ export default {
|
|
|
254
254
|
this.extensionHeaderActions = getApplicableExtensionEnhancements(this, ExtensionPoint.ACTION, ActionLocation.HEADER, neu);
|
|
255
255
|
this.updateExtensionActionsEnabled();
|
|
256
256
|
|
|
257
|
-
this.navHeaderRight = this.$
|
|
257
|
+
this.navHeaderRight = this.$extension?.getDynamic('component', 'NavHeaderRight');
|
|
258
258
|
}
|
|
259
259
|
},
|
|
260
260
|
immediate: true,
|
package/components/nav/Type.vue
CHANGED
|
@@ -27,6 +27,11 @@ export default {
|
|
|
27
27
|
type: Number,
|
|
28
28
|
default: 0,
|
|
29
29
|
},
|
|
30
|
+
|
|
31
|
+
highlightRoute: {
|
|
32
|
+
type: Boolean,
|
|
33
|
+
default: true,
|
|
34
|
+
},
|
|
30
35
|
},
|
|
31
36
|
|
|
32
37
|
data() {
|
|
@@ -121,12 +126,12 @@ export default {
|
|
|
121
126
|
>
|
|
122
127
|
<li
|
|
123
128
|
class="child nav-type"
|
|
124
|
-
:class="{'root': isRoot, [`depth-${depth}`]: true, 'router-link-active': isActive, 'router-link-exact-active': isExactActive}"
|
|
129
|
+
:class="{'root': isRoot, [`depth-${depth}`]: true, 'router-link-active': highlightRoute && isActive, 'router-link-exact-active': highlightRoute && isExactActive}"
|
|
125
130
|
@click="navigate"
|
|
126
131
|
@keypress.enter="navigate"
|
|
127
132
|
>
|
|
128
133
|
<TabTitle
|
|
129
|
-
v-if="isExactActive"
|
|
134
|
+
v-if="highlightRoute && isExactActive"
|
|
130
135
|
:show-child="false"
|
|
131
136
|
>
|
|
132
137
|
{{ type.labelKey ? t(type.labelKey) : (type.labelDisplay || type.label) }}
|
|
@@ -136,7 +141,7 @@ export default {
|
|
|
136
141
|
:aria-label="type.labelKey ? t(type.labelKey) : (type.labelDisplay || type.label)"
|
|
137
142
|
:href="href"
|
|
138
143
|
class="type-link"
|
|
139
|
-
:aria-current="isActive ? 'page' : undefined"
|
|
144
|
+
:aria-current="highlightRoute && isActive ? 'page' : undefined"
|
|
140
145
|
@click="selectType(); navigate($event);"
|
|
141
146
|
@mouseenter="setNear(true)"
|
|
142
147
|
@mouseleave="setNear(false)"
|
|
@@ -250,6 +250,65 @@ describe('component: Type', () => {
|
|
|
250
250
|
});
|
|
251
251
|
});
|
|
252
252
|
|
|
253
|
+
describe('should respect highlightRoute prop', () => {
|
|
254
|
+
it('should not use active class when highlightRoute is false even if route is active', () => {
|
|
255
|
+
const wrapper = shallowMount(Type as any, {
|
|
256
|
+
props: { type: defaultRouteTypeProp, highlightRoute: false },
|
|
257
|
+
|
|
258
|
+
global: {
|
|
259
|
+
directives: { cleanHtml: (identity) => identity },
|
|
260
|
+
|
|
261
|
+
mocks: {
|
|
262
|
+
$store: storeMock, $router: routerMock, $route: routeMock
|
|
263
|
+
},
|
|
264
|
+
stubs: { routerLink: createChildRenderingRouterLinkStub() },
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
const elementWithSelector = wrapper.find(`.${ activeClass }`);
|
|
269
|
+
|
|
270
|
+
expect(elementWithSelector.exists()).toBe(false);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it('should not use exact active class when highlightRoute is false even if route is exact active', () => {
|
|
274
|
+
const wrapper = shallowMount(Type as any, {
|
|
275
|
+
props: { type: defaultRouteTypeProp, highlightRoute: false },
|
|
276
|
+
|
|
277
|
+
global: {
|
|
278
|
+
directives: { cleanHtml: (identity) => identity },
|
|
279
|
+
|
|
280
|
+
mocks: {
|
|
281
|
+
$store: storeMock, $router: routerMock, $route: routeMock
|
|
282
|
+
},
|
|
283
|
+
stubs: { routerLink: createChildRenderingRouterLinkStub({ isExactActive: true }) },
|
|
284
|
+
},
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
const elementWithSelector = wrapper.find(`.${ exactActiveClass }`);
|
|
288
|
+
|
|
289
|
+
expect(elementWithSelector.exists()).toBe(false);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('should use active class when highlightRoute is true (default) and route is active', () => {
|
|
293
|
+
const wrapper = shallowMount(Type as any, {
|
|
294
|
+
props: { type: defaultRouteTypeProp, highlightRoute: true },
|
|
295
|
+
|
|
296
|
+
global: {
|
|
297
|
+
directives: { cleanHtml: (identity) => identity },
|
|
298
|
+
|
|
299
|
+
mocks: {
|
|
300
|
+
$store: storeMock, $router: routerMock, $route: routeMock
|
|
301
|
+
},
|
|
302
|
+
stubs: { routerLink: createChildRenderingRouterLinkStub() },
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
const elementWithSelector = wrapper.find(`.${ activeClass }`);
|
|
307
|
+
|
|
308
|
+
expect(elementWithSelector.exists()).toBe(true);
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
|
|
253
312
|
describe('should handle the favorite icon appropriately', () => {
|
|
254
313
|
it('should show favorite icon if mouse is over and type is favorite', async() => {
|
|
255
314
|
const wrapper = shallowMount(Type as any, {
|
|
@@ -30,12 +30,12 @@ export async function loadClusters(to, from, next, { store }) {
|
|
|
30
30
|
const oldPkg = getPackageFromRoute(from);
|
|
31
31
|
const oldProduct = getProductFromRoute(from);
|
|
32
32
|
|
|
33
|
-
// TODO: Replace all references to store.$
|
|
33
|
+
// TODO: Replace all references to store.$extension.
|
|
34
34
|
// Unfortunately the initialization code has circular dependencies between creating
|
|
35
35
|
// the router and creating the store that will need to be untangled before this can be tackled.
|
|
36
36
|
|
|
37
37
|
// Leave an old pkg where we weren't before?
|
|
38
|
-
const oldPkgPlugin = oldPkg ? Object.values(store.$
|
|
38
|
+
const oldPkgPlugin = oldPkg ? Object.values(store.$extension.getPlugins()).find((p) => p.name === oldPkg) : null;
|
|
39
39
|
|
|
40
40
|
if (oldPkg && oldPkg !== pkg ) {
|
|
41
41
|
// Execute anything optional the plugin wants to. For example resetting it's store to remove data
|
|
@@ -53,7 +53,7 @@ export async function loadClusters(to, from, next, { store }) {
|
|
|
53
53
|
];
|
|
54
54
|
|
|
55
55
|
// Entering a new package where we weren't before?
|
|
56
|
-
const newPkgPlugin = pkg ? Object.values(store.$
|
|
56
|
+
const newPkgPlugin = pkg ? Object.values(store.$extension.getPlugins()).find((p) => p.name === pkg) : null;
|
|
57
57
|
|
|
58
58
|
// Note - We can't block on oldPkg !== newPkg because on a fresh load the `from` route equals the `to` route
|
|
59
59
|
if (pkg && (oldPkg !== pkg || from.fullPath === to.fullPath)) {
|
|
@@ -9,7 +9,7 @@ export async function loadProducts(to, from, next, { store }) {
|
|
|
9
9
|
// GC should be notified of route change before any find/get request is made that might be used for that page
|
|
10
10
|
store.dispatch('gcRouteChanged', to);
|
|
11
11
|
|
|
12
|
-
await applyProducts(store, store.$
|
|
12
|
+
await applyProducts(store, store.$extension);
|
|
13
13
|
setProduct(store, to);
|
|
14
14
|
next();
|
|
15
15
|
}
|
|
@@ -35,13 +35,13 @@ const createExtensionManager = (context) => {
|
|
|
35
35
|
/**
|
|
36
36
|
* When an extension adds a model extension, it provides the class - we will instantiate that class and store and use that
|
|
37
37
|
*/
|
|
38
|
-
function instantiateModelExtension($
|
|
38
|
+
function instantiateModelExtension($extension, clz) {
|
|
39
39
|
const context = {
|
|
40
|
-
dispatch:
|
|
41
|
-
getters:
|
|
42
|
-
t:
|
|
40
|
+
dispatch: store.dispatch,
|
|
41
|
+
getters: store.getters,
|
|
42
|
+
t: store.getters['i18n/t'],
|
|
43
43
|
$axios,
|
|
44
|
-
$extension
|
|
44
|
+
$extension,
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
return new clz(context);
|
package/core/plugin-helpers.ts
CHANGED
|
@@ -147,8 +147,8 @@ export function getApplicableExtensionEnhancements<T>(
|
|
|
147
147
|
const extensionEnhancements: T[] = [];
|
|
148
148
|
|
|
149
149
|
// gate it so that we prevent errors on older versions of dashboard
|
|
150
|
-
if (pluginCtx.$
|
|
151
|
-
const actions = pluginCtx.$
|
|
150
|
+
if (pluginCtx.$extension?.getUIConfig) {
|
|
151
|
+
const actions = pluginCtx.$extension.getUIConfig(actionType, uiArea);
|
|
152
152
|
|
|
153
153
|
actions.forEach((action: any, i: number) => {
|
|
154
154
|
if (checkExtensionRouteBinding(currRoute, action.locationConfig, context || {})) {
|
package/core/plugins-loader.js
CHANGED
|
@@ -13,10 +13,10 @@ export default function({
|
|
|
13
13
|
store,
|
|
14
14
|
$axios,
|
|
15
15
|
redirect,
|
|
16
|
-
$
|
|
16
|
+
$extension,
|
|
17
17
|
}, inject) {
|
|
18
18
|
if (dynamicLoader) {
|
|
19
|
-
dynamicLoader.default($
|
|
19
|
+
dynamicLoader.default($extension);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
// The libraries we build have Vue externalised, so we need to expose Vue as a global for
|
|
@@ -96,15 +96,15 @@ export default {
|
|
|
96
96
|
await this.value.waitForProvisioner();
|
|
97
97
|
|
|
98
98
|
// Support for the 'provisioner' extension
|
|
99
|
-
const extClass = this.$
|
|
99
|
+
const extClass = this.$extension.getDynamic('provisioner', this.value.machineProvider);
|
|
100
100
|
|
|
101
101
|
if (extClass) {
|
|
102
102
|
this.extProvider = new extClass({
|
|
103
|
-
dispatch:
|
|
104
|
-
getters:
|
|
105
|
-
axios:
|
|
106
|
-
$
|
|
107
|
-
$t:
|
|
103
|
+
dispatch: this.$store.dispatch,
|
|
104
|
+
getters: this.$store.getters,
|
|
105
|
+
axios: this.$store.$axios,
|
|
106
|
+
$extension: this.$store.app.$extension,
|
|
107
|
+
$t: this.t
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
this.extDetailTabs = {
|
package/dialog/SearchDialog.vue
CHANGED
|
@@ -112,8 +112,8 @@ describe('component: rke2', () => {
|
|
|
112
112
|
global: {
|
|
113
113
|
mocks: {
|
|
114
114
|
...defaultMocks,
|
|
115
|
-
$store:
|
|
116
|
-
$
|
|
115
|
+
$store: { dispatch: () => jest.fn(), getters: defaultGetters },
|
|
116
|
+
$extension: { getDynamic: jest.fn(() => undefined ) }
|
|
117
117
|
},
|
|
118
118
|
|
|
119
119
|
stubs: defaultStubs,
|
|
@@ -143,8 +143,8 @@ describe('component: rke2', () => {
|
|
|
143
143
|
global: {
|
|
144
144
|
mocks: {
|
|
145
145
|
...defaultMocks,
|
|
146
|
-
$store:
|
|
147
|
-
$
|
|
146
|
+
$store: { dispatch: () => jest.fn(), getters: defaultGetters },
|
|
147
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
148
148
|
},
|
|
149
149
|
|
|
150
150
|
stubs: defaultStubs,
|
|
@@ -174,8 +174,8 @@ describe('component: rke2', () => {
|
|
|
174
174
|
global: {
|
|
175
175
|
mocks: {
|
|
176
176
|
...defaultMocks,
|
|
177
|
-
$store:
|
|
178
|
-
$
|
|
177
|
+
$store: { dispatch: () => jest.fn(), getters: defaultGetters },
|
|
178
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
179
179
|
},
|
|
180
180
|
|
|
181
181
|
stubs: defaultStubs,
|
|
@@ -231,7 +231,7 @@ describe('component: rke2', () => {
|
|
|
231
231
|
},
|
|
232
232
|
getters: defaultGetters
|
|
233
233
|
},
|
|
234
|
-
$
|
|
234
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
235
235
|
},
|
|
236
236
|
|
|
237
237
|
stubs: defaultStubs,
|
|
@@ -275,7 +275,7 @@ describe('component: rke2', () => {
|
|
|
275
275
|
'management/findAll': () => ([]),
|
|
276
276
|
}
|
|
277
277
|
},
|
|
278
|
-
$
|
|
278
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
279
279
|
},
|
|
280
280
|
|
|
281
281
|
stubs: defaultStubs,
|
|
@@ -324,7 +324,7 @@ describe('component: rke2', () => {
|
|
|
324
324
|
'management/findAll': () => ([]),
|
|
325
325
|
}
|
|
326
326
|
},
|
|
327
|
-
$
|
|
327
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
328
328
|
},
|
|
329
329
|
|
|
330
330
|
stubs: defaultStubs,
|
|
@@ -369,8 +369,8 @@ describe('component: rke2', () => {
|
|
|
369
369
|
global: {
|
|
370
370
|
mocks: {
|
|
371
371
|
...defaultMocks,
|
|
372
|
-
$store:
|
|
373
|
-
$
|
|
372
|
+
$store: { dispatch: () => jest.fn(), getters: defaultGetters },
|
|
373
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
374
374
|
},
|
|
375
375
|
stubs: defaultStubs
|
|
376
376
|
}
|
|
@@ -409,8 +409,8 @@ describe('component: rke2', () => {
|
|
|
409
409
|
global: {
|
|
410
410
|
mocks: {
|
|
411
411
|
...defaultMocks,
|
|
412
|
-
$store:
|
|
413
|
-
$
|
|
412
|
+
$store: { dispatch: () => jest.fn(), getters: defaultGetters },
|
|
413
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
414
414
|
},
|
|
415
415
|
stubs: defaultStubs
|
|
416
416
|
}
|
|
@@ -441,8 +441,8 @@ describe('component: rke2', () => {
|
|
|
441
441
|
global: {
|
|
442
442
|
mocks: {
|
|
443
443
|
...defaultMocks,
|
|
444
|
-
$store:
|
|
445
|
-
$
|
|
444
|
+
$store: { dispatch: () => jest.fn(), getters: defaultGetters },
|
|
445
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
446
446
|
},
|
|
447
447
|
stubs: defaultStubs
|
|
448
448
|
}
|
|
@@ -489,8 +489,8 @@ describe('component: rke2', () => {
|
|
|
489
489
|
global: {
|
|
490
490
|
mocks: {
|
|
491
491
|
...defaultMocks,
|
|
492
|
-
$store:
|
|
493
|
-
$
|
|
492
|
+
$store: { dispatch: () => jest.fn(), getters: defaultGetters },
|
|
493
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
494
494
|
},
|
|
495
495
|
stubs: defaultStubs
|
|
496
496
|
}
|
|
@@ -536,8 +536,8 @@ describe('component: rke2', () => {
|
|
|
536
536
|
global: {
|
|
537
537
|
mocks: {
|
|
538
538
|
...defaultMocks,
|
|
539
|
-
$store:
|
|
540
|
-
$
|
|
539
|
+
$store: { dispatch: () => jest.fn(), getters: defaultGetters },
|
|
540
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
541
541
|
},
|
|
542
542
|
stubs: defaultStubs
|
|
543
543
|
}
|
|
@@ -600,8 +600,8 @@ describe('component: rke2', () => {
|
|
|
600
600
|
global: {
|
|
601
601
|
mocks: {
|
|
602
602
|
...defaultMocks,
|
|
603
|
-
$store:
|
|
604
|
-
$
|
|
603
|
+
$store: { dispatch: () => jest.fn(), getters: defaultGetters },
|
|
604
|
+
$extension: { getDynamic: jest.fn(() => undefined ) },
|
|
605
605
|
},
|
|
606
606
|
|
|
607
607
|
stubs: defaultStubs,
|
|
@@ -332,9 +332,9 @@ export default {
|
|
|
332
332
|
// Keeping this for non Rancher-managed kontainer drivers
|
|
333
333
|
this.kontainerDrivers.filter((x) => (isImport ? x.showImport : x.showCreate)).forEach((obj) => {
|
|
334
334
|
if ( vueKontainerTypes.includes(obj.driverName) ) {
|
|
335
|
-
addType(this.$
|
|
335
|
+
addType(this.$extension, obj.driverName, 'hosted', false);
|
|
336
336
|
} else {
|
|
337
|
-
addType(this.$
|
|
337
|
+
addType(this.$extension, obj.driverName, 'hosted', false, (isImport ? obj.emberImportPath : obj.emberCreatePath));
|
|
338
338
|
}
|
|
339
339
|
});
|
|
340
340
|
if (!isImport) {
|
|
@@ -351,7 +351,7 @@ export default {
|
|
|
351
351
|
|
|
352
352
|
// If Elemental is installed, then add the elemental cluster provider
|
|
353
353
|
if (isElementalActive) {
|
|
354
|
-
addType(this.$
|
|
354
|
+
addType(this.$extension, ELEMENTAL_CLUSTER_PROVIDER, 'custom2', false);
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
// Only add the RKE2 options if RKE2 is enabled
|
|
@@ -359,10 +359,10 @@ export default {
|
|
|
359
359
|
machineTypes.forEach((type) => {
|
|
360
360
|
const id = type.spec.displayName || type.id;
|
|
361
361
|
|
|
362
|
-
addType(this.$
|
|
362
|
+
addType(this.$extension, id, _RKE2, false, null, undefined, type);
|
|
363
363
|
});
|
|
364
364
|
|
|
365
|
-
addType(this.$
|
|
365
|
+
addType(this.$extension, 'custom', 'custom2', false);
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
368
|
// Add from extensions
|
|
@@ -502,7 +502,7 @@ export default {
|
|
|
502
502
|
* 2) Override via hardcoded setting
|
|
503
503
|
*/
|
|
504
504
|
cloudCredentialsOverride() {
|
|
505
|
-
const cloudCredential = this.$
|
|
505
|
+
const cloudCredential = this.$extension.getDynamic('cloud-credential', this.provider);
|
|
506
506
|
|
|
507
507
|
if (cloudCredential === undefined) {
|
|
508
508
|
return CLOUD_CREDENTIAL_OVERRIDE[this.provider];
|
|
@@ -527,16 +527,16 @@ export default {
|
|
|
527
527
|
* Extension provider where being provisioned by an extension
|
|
528
528
|
*/
|
|
529
529
|
extensionProvider() {
|
|
530
|
-
const extClass = this.$
|
|
530
|
+
const extClass = this.$extension.getDynamic('provisioner', this.provider);
|
|
531
531
|
|
|
532
532
|
if (extClass) {
|
|
533
533
|
return new extClass({
|
|
534
|
-
dispatch:
|
|
535
|
-
getters:
|
|
536
|
-
axios:
|
|
537
|
-
$
|
|
538
|
-
$t:
|
|
539
|
-
isCreate:
|
|
534
|
+
dispatch: this.$store.dispatch,
|
|
535
|
+
getters: this.$store.getters,
|
|
536
|
+
axios: this.$store.$axios,
|
|
537
|
+
$extension: this.$store.app.$extension,
|
|
538
|
+
$t: this.t,
|
|
539
|
+
isCreate: this.isCreate
|
|
540
540
|
});
|
|
541
541
|
}
|
|
542
542
|
|
|
@@ -255,7 +255,7 @@ export default class MgmtCluster extends SteveModel {
|
|
|
255
255
|
dispatch: this.$dispatch,
|
|
256
256
|
getters: this.$getters,
|
|
257
257
|
axios: this.$axios,
|
|
258
|
-
$extension: this.$
|
|
258
|
+
$extension: this.$extension,
|
|
259
259
|
t: (...args) => this.t.apply(this, args),
|
|
260
260
|
};
|
|
261
261
|
|
|
@@ -277,7 +277,7 @@ export default class ProvCluster extends SteveModel {
|
|
|
277
277
|
dispatch: this.$dispatch,
|
|
278
278
|
getters: this.$getters,
|
|
279
279
|
axios: this.$axios,
|
|
280
|
-
$extension: this.$
|
|
280
|
+
$extension: this.$extension,
|
|
281
281
|
t: (...args) => this.t.apply(this, args),
|
|
282
282
|
};
|
|
283
283
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/shell",
|
|
3
|
-
"version": "3.0.8-rc.
|
|
3
|
+
"version": "3.0.8-rc.12",
|
|
4
4
|
"description": "Rancher Dashboard Shell",
|
|
5
|
-
"repository": "https://github.com/
|
|
5
|
+
"repository": "https://github.com/rancher/dashboard",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "SUSE",
|
|
8
8
|
"private": false,
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
"vuedraggable": "4.1.0",
|
|
141
141
|
"vuex": "4.1.0",
|
|
142
142
|
"webpack-bundle-analyzer": "4.10.2",
|
|
143
|
-
"webpack-virtual-modules": "0.
|
|
143
|
+
"webpack-virtual-modules": "0.6.2",
|
|
144
144
|
"worker-loader": "3.0.8",
|
|
145
145
|
"xterm-addon-canvas": "0.5.0",
|
|
146
146
|
"xterm-addon-fit": "0.8.0",
|
package/pages/auth/login.vue
CHANGED
|
@@ -315,9 +315,9 @@ export default {
|
|
|
315
315
|
// so we manually load them here - other SSO auth providers bounce out and back to the Dashboard, so on the bounce-back
|
|
316
316
|
// the plugins will load via the boot-time plugin
|
|
317
317
|
await loadPlugins({
|
|
318
|
-
app:
|
|
319
|
-
store:
|
|
320
|
-
$
|
|
318
|
+
app: this.$store.app,
|
|
319
|
+
store: this.$store,
|
|
320
|
+
$extension: this.$store.$extension,
|
|
321
321
|
});
|
|
322
322
|
|
|
323
323
|
if (this.firstLogin || user[0]?.mustChangePassword) {
|
package/pages/auth/setup.vue
CHANGED
|
@@ -209,7 +209,7 @@ export default {
|
|
|
209
209
|
const promises = [];
|
|
210
210
|
|
|
211
211
|
try {
|
|
212
|
-
await applyProducts(this.$store, this.$
|
|
212
|
+
await applyProducts(this.$store, this.$extension);
|
|
213
213
|
await this.$store.dispatch('loadManagement');
|
|
214
214
|
|
|
215
215
|
if ( this.mustChangePassword ) {
|
package/pages/auth/verify.vue
CHANGED
|
@@ -119,9 +119,9 @@ export default {
|
|
|
119
119
|
|
|
120
120
|
// Load plugins
|
|
121
121
|
await loadPlugins({
|
|
122
|
-
app:
|
|
123
|
-
store:
|
|
124
|
-
$
|
|
122
|
+
app: this.$store.app,
|
|
123
|
+
store: this.$store,
|
|
124
|
+
$extension: this.$store.$extension,
|
|
125
125
|
});
|
|
126
126
|
|
|
127
127
|
this.$router.replace(backTo);
|
package/pkg/auto-import.js
CHANGED
|
@@ -15,7 +15,7 @@ function registerFile(file, type, pkg, f) {
|
|
|
15
15
|
const importType = (f === 'models') ? 'require' : 'import';
|
|
16
16
|
const chunkName = (f === 'l10n') ? '' : `/* webpackChunkName: "${ f }" */`;
|
|
17
17
|
|
|
18
|
-
return ` $
|
|
18
|
+
return ` $extension.register('${ f }', '${ type }', () => ${ importType }(${ chunkName }'${ pkg }/${ f }/${ file }'));\n`;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
function register(file, pkg, f) {
|
|
@@ -29,7 +29,7 @@ function register(file, pkg, f) {
|
|
|
29
29
|
// This ensures that the webpackChunkName is respected (require.context does not support this) - so when build as a library
|
|
30
30
|
// the code splitting will be respected
|
|
31
31
|
function generateTypeImport(pkg, dir) {
|
|
32
|
-
let content = 'export function importTypes($
|
|
32
|
+
let content = 'export function importTypes($extension) { \n';
|
|
33
33
|
|
|
34
34
|
// Auto-import if the folder exists
|
|
35
35
|
contextFolders.forEach((f) => {
|
|
@@ -77,7 +77,7 @@ function generateTypeImport(pkg, dir) {
|
|
|
77
77
|
// and then restart the dev server for it to be picked up.
|
|
78
78
|
function generateDynamicTypeImport(pkg, dir) {
|
|
79
79
|
const template = fs.readFileSync(path.join(__dirname, 'import.js'), { encoding: 'utf8' });
|
|
80
|
-
let content = 'export function importTypes($
|
|
80
|
+
let content = 'export function importTypes($extension) { \n';
|
|
81
81
|
|
|
82
82
|
// Auto-import if the folder exists
|
|
83
83
|
contextFolders.forEach((f) => {
|
package/pkg/import.js
CHANGED
|
@@ -6,5 +6,5 @@ _NAME.forEach((f) => {
|
|
|
6
6
|
|
|
7
7
|
name = name.substr(0, ext);
|
|
8
8
|
|
|
9
|
-
$
|
|
9
|
+
$extension.register('DIR', name, () => REQUIRE(CHUNK`BASE/DIR/${ name }EXT`)); // eslint-disable-line no-undef
|
|
10
10
|
});
|
|
@@ -543,7 +543,7 @@ export default {
|
|
|
543
543
|
const store = state.config.namespace;
|
|
544
544
|
const resource = id || context ? { id, context } : null;
|
|
545
545
|
|
|
546
|
-
return paginationUtils.isEnabled({ rootGetters, $
|
|
546
|
+
return paginationUtils.isEnabled({ rootGetters, $extension: rootState.$extension }, { store, resource });
|
|
547
547
|
},
|
|
548
548
|
|
|
549
549
|
/**
|
|
@@ -610,7 +610,11 @@ export default class Resource {
|
|
|
610
610
|
}
|
|
611
611
|
|
|
612
612
|
get '$plugin'() {
|
|
613
|
-
return this.$ctx.rootState?.$
|
|
613
|
+
return this.$ctx.rootState?.$extension;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
get '$extension'() {
|
|
617
|
+
return this.$ctx.rootState?.$extension;
|
|
614
618
|
}
|
|
615
619
|
|
|
616
620
|
get customValidationRules() {
|
|
@@ -1777,7 +1781,7 @@ export default class Resource {
|
|
|
1777
1781
|
CustomValidators[validatorName](pathValue, this.$rootGetters, errors, validatorArgs, displayKey, data);
|
|
1778
1782
|
} else if (!isEmpty(validatorName) && !validatorExists) {
|
|
1779
1783
|
// Check if validator is imported from plugin
|
|
1780
|
-
const pluginValidator = this.$rootState.$
|
|
1784
|
+
const pluginValidator = this.$rootState.$extension?.getValidator(validatorName);
|
|
1781
1785
|
|
|
1782
1786
|
if (pluginValidator) {
|
|
1783
1787
|
pluginValidator(pathValue, this.$rootGetters, errors, validatorArgs, displayKey, data);
|
package/plugins/plugin.js
CHANGED
|
@@ -44,7 +44,7 @@ export default async function(context) {
|
|
|
44
44
|
const res = await allHashSettled(fetches);
|
|
45
45
|
|
|
46
46
|
// Initialize the built-in extensions now - this is now done here so that built-in extensions get the same, correct environment data (version etc)
|
|
47
|
-
context.$
|
|
47
|
+
context.$extension.loadBuiltinExtensions();
|
|
48
48
|
|
|
49
49
|
if (res.plugins?.status === 'rejected') {
|
|
50
50
|
throw new Error(res.reason);
|
|
@@ -60,7 +60,7 @@ export default async function(context) {
|
|
|
60
60
|
const shouldNotLoad = shouldNotLoadPlugin(plugin, { rancherVersion, kubeVersion }, context.store.getters['uiplugins/plugins'] || []); // Error key string or boolean
|
|
61
61
|
|
|
62
62
|
if (!shouldNotLoad) {
|
|
63
|
-
hash[plugin.name] = context.$
|
|
63
|
+
hash[plugin.name] = context.$extension.loadPluginAsync(plugin);
|
|
64
64
|
} else {
|
|
65
65
|
context.store.dispatch('uiplugins/setError', { name: plugin.name, error: shouldNotLoad });
|
|
66
66
|
}
|
|
@@ -47,7 +47,7 @@ export default class SteveModel extends HybridModel {
|
|
|
47
47
|
* Get all model extensions for this model
|
|
48
48
|
*/
|
|
49
49
|
get modelExtensions() {
|
|
50
|
-
return this.$
|
|
50
|
+
return this.$extension.getDynamic(EXT_IDS.MODEL_EXTENSION, this.type) || [];
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
cleanForSave(data, forNew) {
|
package/store/auth.js
CHANGED
package/store/i18n.js
CHANGED
|
@@ -285,8 +285,8 @@ export const actions = {
|
|
|
285
285
|
return;
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
-
const lastLoad = rootState.$
|
|
289
|
-
const i18nExt = rootState.$
|
|
288
|
+
const lastLoad = rootState.$extension?.lastLoad;
|
|
289
|
+
const i18nExt = rootState.$extension?.getDynamic('l10n', locale);
|
|
290
290
|
const reload = lastLoaded < lastLoad;
|
|
291
291
|
|
|
292
292
|
lastLoaded = lastLoad;
|
|
@@ -314,7 +314,7 @@ export const actions = {
|
|
|
314
314
|
|
|
315
315
|
// load all of the default locales from the plugins for fallback
|
|
316
316
|
if (locale !== DEFAULT_LOCALE) {
|
|
317
|
-
const defaultI18nExt = rootState.$
|
|
317
|
+
const defaultI18nExt = rootState.$extension?.getDynamic('l10n', DEFAULT_LOCALE);
|
|
318
318
|
|
|
319
319
|
if (defaultI18nExt && defaultI18nExt.length) {
|
|
320
320
|
defaultI18nExt.forEach((fn) => {
|
package/store/index.js
CHANGED
|
@@ -233,7 +233,7 @@ const updateActiveNamespaceCache = (state, activeNamespaceCache) => {
|
|
|
233
233
|
* Are we in the vai enabled world where mgmt clusters are paginated?
|
|
234
234
|
*/
|
|
235
235
|
const paginateClusters = ({ rootGetters, state }) => {
|
|
236
|
-
return paginationUtils.isEnabled({ rootGetters, $
|
|
236
|
+
return paginationUtils.isEnabled({ rootGetters, $extension: state.$extension }, { store: 'management', resource: { id: MANAGEMENT.CLUSTER, context: 'side-bar' } });
|
|
237
237
|
};
|
|
238
238
|
|
|
239
239
|
export const state = () => {
|
|
@@ -262,6 +262,7 @@ export const state = () => {
|
|
|
262
262
|
$router: markRaw({}),
|
|
263
263
|
$route: markRaw({}),
|
|
264
264
|
$plugin: markRaw({}),
|
|
265
|
+
$extension: markRaw({}),
|
|
265
266
|
showWorkspaceSwitcher: true,
|
|
266
267
|
localCluster: null,
|
|
267
268
|
};
|
|
@@ -775,6 +776,7 @@ export const mutations = {
|
|
|
775
776
|
},
|
|
776
777
|
|
|
777
778
|
setPlugin(state, pluginDefinition) {
|
|
779
|
+
state.$extension = markRaw(pluginDefinition || {});
|
|
778
780
|
state.$plugin = markRaw(pluginDefinition || {});
|
|
779
781
|
},
|
|
780
782
|
|
|
@@ -1195,7 +1197,7 @@ export const actions = {
|
|
|
1195
1197
|
|
|
1196
1198
|
store.dispatch('gcStopIntervals');
|
|
1197
1199
|
|
|
1198
|
-
Object.values(this.$
|
|
1200
|
+
Object.values(this.$extension.getPlugins()).forEach((p) => {
|
|
1199
1201
|
if (p.onLogOut) {
|
|
1200
1202
|
p.onLogOut(store);
|
|
1201
1203
|
}
|
|
@@ -1254,7 +1256,7 @@ export const actions = {
|
|
|
1254
1256
|
dashboardClientInit({ dispatch, commit, rootState }, context) {
|
|
1255
1257
|
commit('setRouter', context.app.router);
|
|
1256
1258
|
commit('setRoute', context.route);
|
|
1257
|
-
commit('setPlugin', context.app.$
|
|
1259
|
+
commit('setPlugin', context.app.$extension);
|
|
1258
1260
|
|
|
1259
1261
|
dispatch('management/rehydrateSubscribe');
|
|
1260
1262
|
dispatch('cluster/rehydrateSubscribe');
|
package/store/type-map.js
CHANGED
|
@@ -365,7 +365,7 @@ export function DSL(store, product, module = 'type-map') {
|
|
|
365
365
|
|
|
366
366
|
let called = false;
|
|
367
367
|
|
|
368
|
-
export async function applyProducts(store, $
|
|
368
|
+
export async function applyProducts(store, $extension) {
|
|
369
369
|
if (called) {
|
|
370
370
|
return;
|
|
371
371
|
}
|
|
@@ -379,7 +379,7 @@ export async function applyProducts(store, $plugin) {
|
|
|
379
379
|
}
|
|
380
380
|
}
|
|
381
381
|
// Load the products from all plugins
|
|
382
|
-
$
|
|
382
|
+
$extension.loadProducts();
|
|
383
383
|
}
|
|
384
384
|
|
|
385
385
|
export function productsLoaded() {
|
|
@@ -2026,7 +2026,7 @@ function hasCustom(state, rootState, kind, key, fallback) {
|
|
|
2026
2026
|
}
|
|
2027
2027
|
|
|
2028
2028
|
// Check to see if the custom kind is provided by a plugin (ignore booleans)
|
|
2029
|
-
const pluginComponent = rootState.$
|
|
2029
|
+
const pluginComponent = rootState.$extension.getDynamic(kind, key);
|
|
2030
2030
|
|
|
2031
2031
|
if (typeof pluginComponent !== 'boolean' && !!pluginComponent) {
|
|
2032
2032
|
cache[key] = true;
|
|
@@ -2046,7 +2046,7 @@ function hasCustom(state, rootState, kind, key, fallback) {
|
|
|
2046
2046
|
}
|
|
2047
2047
|
|
|
2048
2048
|
function loadExtension(rootState, kind, key, fallback) {
|
|
2049
|
-
const ext = rootState.$
|
|
2049
|
+
const ext = rootState.$extension.getDynamic(kind, key);
|
|
2050
2050
|
|
|
2051
2051
|
if (ext) {
|
|
2052
2052
|
if (typeof ext === 'function') {
|
package/types/shell/index.d.ts
CHANGED
|
@@ -165,7 +165,7 @@ class PaginationUtils {
|
|
|
165
165
|
/**
|
|
166
166
|
* Is pagination enabled at a global level or for a specific resource
|
|
167
167
|
*/
|
|
168
|
-
isEnabled({ rootGetters, $
|
|
168
|
+
isEnabled({ rootGetters, $extension }: any, enabledFor: PaginationResourceContext) {
|
|
169
169
|
// Cache must be enabled to support pagination api
|
|
170
170
|
if (!this.isSteveCacheEnabled({ rootGetters })) {
|
|
171
171
|
return false;
|
|
@@ -184,7 +184,7 @@ class PaginationUtils {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
// Does an extension say this type is enabled?
|
|
187
|
-
const plugin = $
|
|
187
|
+
const plugin = $extension as ExtensionManager;
|
|
188
188
|
const paginationExtensionPoints = plugin.getAll()[EXT_IDS.SERVER_SIDE_PAGINATION_RESOURCES];
|
|
189
189
|
|
|
190
190
|
if (paginationExtensionPoints) {
|
|
@@ -69,7 +69,7 @@ class PaginationWrapper<T extends object> {
|
|
|
69
69
|
this.classify = formatResponse?.classify || false;
|
|
70
70
|
this.reactive = formatResponse?.reactive || false;
|
|
71
71
|
|
|
72
|
-
this.isEnabled = paginationUtils.isEnabled({ rootGetters: $store.getters, $
|
|
72
|
+
this.isEnabled = paginationUtils.isEnabled({ rootGetters: $store.getters, $extension: this.$store.$extension }, enabledFor);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
async request({ pagination, forceWatch }: {
|
|
@@ -163,14 +163,14 @@ describe('pagination-utils', () => {
|
|
|
163
163
|
|
|
164
164
|
it('should return false if steve cache is disabled', () => {
|
|
165
165
|
mockRootGetters['features/get'].mockImplementation((feature: string) => feature === STEVE_CACHE ? false : undefined);
|
|
166
|
-
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $
|
|
166
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $extension: mockPlugin }, enabledFor);
|
|
167
167
|
|
|
168
168
|
expect(result).toBe(false);
|
|
169
169
|
});
|
|
170
170
|
|
|
171
171
|
it('should return false if pagination settings are not defined', () => {
|
|
172
172
|
jest.spyOn(paginationUtils, 'getSettings').mockReturnValue(undefined);
|
|
173
|
-
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $
|
|
173
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $extension: mockPlugin }, enabledFor);
|
|
174
174
|
|
|
175
175
|
expect(result).toBe(false);
|
|
176
176
|
|
|
@@ -189,7 +189,7 @@ describe('pagination-utils', () => {
|
|
|
189
189
|
return null;
|
|
190
190
|
});
|
|
191
191
|
|
|
192
|
-
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $
|
|
192
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $extension: mockPlugin }, undefined as unknown as PaginationResourceContext);
|
|
193
193
|
|
|
194
194
|
expect(result).toBe(false);
|
|
195
195
|
});
|
|
@@ -200,7 +200,7 @@ describe('pagination-utils', () => {
|
|
|
200
200
|
|
|
201
201
|
mockPlugin.getAll.mockReturnValue({ [EXT_IDS.SERVER_SIDE_PAGINATION_RESOURCES]: { 'my-ext': () => extensionSettings } });
|
|
202
202
|
|
|
203
|
-
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $
|
|
203
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $extension: mockPlugin }, enabledFor);
|
|
204
204
|
|
|
205
205
|
expect(result).toBe(true);
|
|
206
206
|
});
|
|
@@ -215,7 +215,7 @@ describe('pagination-utils', () => {
|
|
|
215
215
|
// Mocking PAGINATION_SETTINGS_STORE_DEFAULTS behavior
|
|
216
216
|
jest.spyOn(paginationUtils, 'getStoreDefault').mockReturnValue(defaultSettings);
|
|
217
217
|
|
|
218
|
-
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $
|
|
218
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $extension: mockPlugin }, enabledFor);
|
|
219
219
|
|
|
220
220
|
expect(result).toBe(true);
|
|
221
221
|
});
|
|
@@ -235,7 +235,7 @@ describe('pagination-utils', () => {
|
|
|
235
235
|
// Mocking PAGINATION_SETTINGS_STORE_DEFAULTS behavior
|
|
236
236
|
jest.spyOn(paginationUtils, 'getStoreDefault').mockReturnValue({ cluster: { resources: { enableAll: true } } });
|
|
237
237
|
|
|
238
|
-
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $
|
|
238
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $extension: mockPlugin }, enabledFor);
|
|
239
239
|
|
|
240
240
|
expect(result).toBe(true);
|
|
241
241
|
});
|
|
@@ -255,7 +255,7 @@ describe('pagination-utils', () => {
|
|
|
255
255
|
return null;
|
|
256
256
|
});
|
|
257
257
|
|
|
258
|
-
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $
|
|
258
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $extension: mockPlugin }, enabledFor);
|
|
259
259
|
|
|
260
260
|
expect(result).toBe(true);
|
|
261
261
|
});
|
|
@@ -275,7 +275,7 @@ describe('pagination-utils', () => {
|
|
|
275
275
|
return null;
|
|
276
276
|
});
|
|
277
277
|
|
|
278
|
-
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $
|
|
278
|
+
const result = paginationUtils.isEnabled({ rootGetters: mockRootGetters, $extension: mockPlugin }, enabledFor);
|
|
279
279
|
|
|
280
280
|
expect(result).toBe(false);
|
|
281
281
|
});
|
package/vue.config.js
CHANGED
|
@@ -323,16 +323,16 @@ const getVirtualModules = (dir, includePkg) => {
|
|
|
323
323
|
|
|
324
324
|
// Package file must have rancher field to be a plugin
|
|
325
325
|
if (includePkg(name) && library.rancher) {
|
|
326
|
-
reqs += `$
|
|
326
|
+
reqs += `$extension.registerBuiltinExtension('${ name }', require(\'~/pkg/${ name }\')); `;
|
|
327
327
|
}
|
|
328
328
|
});
|
|
329
329
|
}
|
|
330
330
|
|
|
331
331
|
Object.keys(librariesIndex).forEach((i) => {
|
|
332
|
-
reqs += `$
|
|
332
|
+
reqs += `$extension.loadAsync('${ i }', '/pkg/${ i }/${ librariesIndex[i] }');`;
|
|
333
333
|
});
|
|
334
334
|
|
|
335
|
-
return new VirtualModulesPlugin({ 'node_modules/@rancher/dynamic.js': `export default function ($
|
|
335
|
+
return new VirtualModulesPlugin({ 'node_modules/@rancher/dynamic.js': `export default function ($extension) { ${ reqs } };` });
|
|
336
336
|
};
|
|
337
337
|
|
|
338
338
|
const getAutoImport = () => new webpack.NormalModuleReplacementPlugin(/^@rancher\/auto-import$/, (resource) => {
|