@rancher/shell 3.0.8-rc.9 → 3.0.8
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/apis/impl/apis.ts +61 -0
- package/apis/index.ts +40 -0
- package/apis/intf/modal.ts +90 -0
- package/apis/intf/shell.ts +36 -0
- package/apis/intf/slide-in.ts +98 -0
- package/apis/intf/system.ts +41 -0
- package/apis/shell/__tests__/modal.test.ts +80 -0
- package/apis/shell/__tests__/notifications.test.ts +71 -0
- package/apis/shell/__tests__/slide-in.test.ts +54 -0
- package/apis/shell/__tests__/system.test.ts +129 -0
- package/apis/shell/index.ts +38 -0
- package/apis/shell/modal.ts +41 -0
- package/apis/shell/notifications.ts +65 -0
- package/apis/shell/slide-in.ts +33 -0
- package/apis/shell/system.ts +65 -0
- package/apis/vue-shim.d.ts +11 -0
- package/assets/styles/global/_tooltip.scss +6 -1
- package/assets/translations/en-us.yaml +5 -0
- package/components/ActionMenuShell.vue +3 -1
- package/components/CruResource.vue +8 -1
- package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +50 -1
- package/components/Drawer/ResourceDetailDrawer/composables.ts +19 -0
- package/components/Drawer/ResourceDetailDrawer/index.vue +3 -1
- package/components/LocaleSelector.vue +2 -2
- package/components/ModalManager.vue +11 -1
- package/components/Questions/__tests__/Yaml.test.ts +1 -1
- package/components/RelatedResources.vue +5 -0
- package/components/Resource/Detail/ResourcePopover/index.vue +5 -1
- package/components/ResourceDetail/Masthead/latest.vue +23 -21
- package/components/ResourceDetail/index.vue +3 -0
- package/components/ResourceTable.vue +54 -21
- package/components/SlideInPanelManager.vue +16 -11
- package/components/SortableTable/THead.vue +2 -1
- package/components/SortableTable/index.vue +20 -2
- package/components/Tabbed/index.vue +37 -2
- package/components/__tests__/NamespaceFilter.test.ts +49 -0
- package/components/auth/SelectPrincipal.vue +4 -0
- package/components/auth/login/ldap.vue +3 -3
- package/components/fleet/FleetSecretSelector.vue +1 -1
- package/components/form/KeyValue.vue +1 -1
- package/components/form/NameNsDescription.vue +1 -1
- package/components/form/NodeScheduling.vue +2 -2
- package/components/form/ResourceTabs/composable.ts +2 -2
- package/components/form/ResourceTabs/index.vue +0 -2
- package/components/form/__tests__/NameNsDescription.test.ts +42 -0
- package/components/formatter/LinkName.vue +5 -0
- package/components/nav/Group.vue +25 -7
- package/components/nav/Header.vue +1 -1
- package/components/nav/NamespaceFilter.vue +1 -0
- package/components/nav/Type.vue +17 -6
- package/components/nav/WindowManager/panels/TabBodyContainer.vue +1 -1
- package/components/nav/__tests__/Type.test.ts +59 -0
- package/composables/cruResource.ts +27 -0
- package/composables/focusTrap.ts +3 -1
- package/composables/resourceDetail.ts +15 -0
- package/composables/useLabeledFormElement.ts +3 -4
- package/config/product/fleet.js +1 -1
- package/config/router/navigation-guards/clusters.js +3 -3
- package/config/router/navigation-guards/products.js +1 -1
- package/config/router/routes.js +1 -5
- package/core/__tests__/extension-manager-impl.test.js +437 -0
- package/core/extension-manager-impl.js +6 -27
- package/core/plugin-helpers.ts +2 -2
- package/core/plugin.ts +9 -1
- package/core/plugins-loader.js +2 -2
- package/core/types-provisioning.ts +4 -0
- package/core/types.ts +35 -0
- package/detail/provisioning.cattle.io.cluster.vue +8 -6
- package/dialog/DeveloperLoadExtensionDialog.vue +1 -1
- package/dialog/MoveNamespaceDialog.vue +20 -4
- package/dialog/SearchDialog.vue +1 -0
- package/dialog/__tests__/MoveNamespaceDialog.test.ts +249 -0
- package/directives/__tests__/clean-tooltip.test.ts +298 -0
- package/directives/clean-tooltip.ts +234 -0
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +2 -2
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +98 -1
- package/edit/fleet.cattle.io.helmop.vue +5 -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/edit/resources.cattle.io.restore.vue +1 -1
- package/edit/workload/Job.vue +2 -2
- package/edit/workload/index.vue +1 -1
- package/initialize/install-plugins.js +4 -5
- package/machine-config/azure.vue +1 -1
- package/machine-config/components/GCEImage.vue +1 -1
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +16 -0
- package/models/chart.js +70 -74
- package/models/management.cattle.io.cluster.js +1 -1
- package/models/provisioning.cattle.io.cluster.js +11 -3
- package/package.json +7 -7
- package/pages/auth/login.vue +3 -3
- package/pages/auth/setup.vue +1 -1
- package/pages/auth/verify.vue +3 -3
- package/pages/c/_cluster/apps/charts/index.vue +122 -24
- package/pages/c/_cluster/apps/charts/install.vue +33 -0
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +1 -1
- package/pages/c/_cluster/fleet/index.vue +4 -7
- package/pages/c/_cluster/settings/index.vue +5 -0
- package/pkg/auto-import.js +3 -3
- package/pkg/dynamic-importer.lib.js +1 -1
- package/pkg/import.js +1 -1
- package/plugins/__tests__/mutations.tests.ts +179 -0
- package/plugins/dashboard-store/getters.js +1 -1
- package/plugins/dashboard-store/model-loader.js +1 -1
- package/plugins/dashboard-store/mutations.js +23 -2
- package/plugins/dashboard-store/resource-class.js +8 -3
- package/plugins/plugin.js +2 -2
- package/plugins/steve/__tests__/steve-pagination-utils.test.ts +301 -128
- package/plugins/steve/steve-class.js +1 -1
- package/plugins/steve/steve-pagination-utils.ts +108 -43
- package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
- package/rancher-components/RcDropdown/useDropdownContext.ts +2 -4
- package/rancher-components/RcItemCard/RcItemCard.vue +1 -1
- package/scripts/publish-shell.sh +25 -0
- package/store/__tests__/catalog.test.ts +1 -1
- package/store/__tests__/type-map.test.ts +164 -2
- package/store/auth.js +23 -11
- package/store/i18n.js +3 -3
- package/store/index.js +5 -3
- package/store/notifications.ts +2 -0
- package/store/prefs.js +2 -2
- package/store/type-map.js +17 -7
- package/types/internal-api/shell/modal.d.ts +6 -6
- package/types/notifications/index.ts +126 -15
- package/types/rancher/index.d.ts +9 -0
- package/types/shell/index.d.ts +16 -1
- package/types/vue-shim.d.ts +5 -4
- package/utils/__tests__/router.test.js +238 -0
- package/utils/cluster.js +4 -1
- package/utils/fleet.ts +8 -1
- package/utils/pagination-utils.ts +2 -2
- package/utils/pagination-wrapper.ts +1 -1
- package/utils/router.js +50 -0
- package/utils/unit-tests/pagination-utils.spec.ts +8 -8
- package/vue.config.js +3 -3
- package/composables/useExtensionManager.ts +0 -17
- package/core/__test__/extension-manager-impl.test.js +0 -236
- package/core/plugins.js +0 -38
- package/directives/clean-tooltip.js +0 -32
- package/plugins/internal-api/index.ts +0 -37
- package/plugins/internal-api/shared/base-api.ts +0 -13
- package/plugins/internal-api/shell/shell.api.ts +0 -108
- package/types/internal-api/shell/growl.d.ts +0 -25
- package/types/internal-api/shell/slideIn.d.ts +0 -15
package/components/nav/Group.vue
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import Type from '@shell/components/nav/Type';
|
|
3
|
+
import { filterLocationValidParams } from '@shell/utils/router';
|
|
3
4
|
export default {
|
|
4
5
|
name: 'Group',
|
|
5
6
|
|
|
@@ -41,6 +42,11 @@ export default {
|
|
|
41
42
|
fixedOpen: {
|
|
42
43
|
type: Boolean,
|
|
43
44
|
default: false,
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
highlightRoute: {
|
|
48
|
+
type: Boolean,
|
|
49
|
+
default: true,
|
|
44
50
|
}
|
|
45
51
|
},
|
|
46
52
|
|
|
@@ -73,7 +79,8 @@ export default {
|
|
|
73
79
|
const overviewRoute = grp?.route;
|
|
74
80
|
|
|
75
81
|
if (overviewRoute && grp.overview) {
|
|
76
|
-
const
|
|
82
|
+
const validRoute = filterLocationValidParams(this.$router, overviewRoute || {});
|
|
83
|
+
const route = this.$router.resolve(validRoute);
|
|
77
84
|
|
|
78
85
|
return this.$route.fullPath.split('#')[0] === route?.fullPath;
|
|
79
86
|
}
|
|
@@ -89,6 +96,10 @@ export default {
|
|
|
89
96
|
set(v) {
|
|
90
97
|
this.expanded = v;
|
|
91
98
|
}
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
headerRoute() {
|
|
102
|
+
return filterLocationValidParams(this.$router, this.group.children[0].route);
|
|
92
103
|
}
|
|
93
104
|
},
|
|
94
105
|
|
|
@@ -134,7 +145,9 @@ export default {
|
|
|
134
145
|
const route = item.route;
|
|
135
146
|
|
|
136
147
|
if (route) {
|
|
137
|
-
this.$router
|
|
148
|
+
const validRoute = filterLocationValidParams(this.$router, route);
|
|
149
|
+
|
|
150
|
+
this.$router.replace(validRoute);
|
|
138
151
|
} else if (item) {
|
|
139
152
|
this.routeToFirstChild(item);
|
|
140
153
|
}
|
|
@@ -143,7 +156,9 @@ export default {
|
|
|
143
156
|
|
|
144
157
|
routeToFirstChild(item) {
|
|
145
158
|
if (item.children.length && item.children[0].route) {
|
|
146
|
-
this.$router
|
|
159
|
+
const validRoute = filterLocationValidParams(this.$router, item.children[0].route);
|
|
160
|
+
|
|
161
|
+
this.$router.replace(validRoute);
|
|
147
162
|
}
|
|
148
163
|
},
|
|
149
164
|
|
|
@@ -191,7 +206,8 @@ export default {
|
|
|
191
206
|
const matchesNavLevel = navLevels.filter((param) => !this.$route.params[param] || this.$route.params[param] !== item.route.params[param]).length === 0;
|
|
192
207
|
const withoutHash = this.$route.hash ? this.$route.fullPath.slice(0, this.$route.fullPath.indexOf(this.$route.hash)) : this.$route.fullPath;
|
|
193
208
|
const withoutQuery = withoutHash.split('?')[0];
|
|
194
|
-
const
|
|
209
|
+
const validItemRoute = filterLocationValidParams(this.$router, item.route);
|
|
210
|
+
const itemFullPath = this.$router.resolve(validItemRoute).fullPath;
|
|
195
211
|
|
|
196
212
|
if (matchesNavLevel || itemFullPath === withoutQuery) {
|
|
197
213
|
return true;
|
|
@@ -233,7 +249,7 @@ export default {
|
|
|
233
249
|
<template>
|
|
234
250
|
<div
|
|
235
251
|
class="accordion"
|
|
236
|
-
:class="{[`depth-${depth}`]: true, 'expanded': isExpanded, 'has-children': hasChildren, 'group-highlight': isGroupActive }"
|
|
252
|
+
:class="{[`depth-${depth}`]: true, 'expanded': isExpanded, 'has-children': hasChildren, 'group-highlight': highlightRoute && isGroupActive }"
|
|
237
253
|
>
|
|
238
254
|
<div
|
|
239
255
|
v-if="showHeader || (!onlyHasOverview && canCollapse)"
|
|
@@ -242,7 +258,7 @@ export default {
|
|
|
242
258
|
<div
|
|
243
259
|
v-if="showHeader"
|
|
244
260
|
class="header"
|
|
245
|
-
:class="{'active': isOverview, 'noHover': !canCollapse || fixedOpen}"
|
|
261
|
+
:class="{'active': highlightRoute && isOverview, 'noHover': !canCollapse || fixedOpen}"
|
|
246
262
|
role="button"
|
|
247
263
|
:tabindex="fixedOpen ? -1 : 0"
|
|
248
264
|
:aria-label="group.labelDisplay || group.label || ''"
|
|
@@ -253,7 +269,7 @@ export default {
|
|
|
253
269
|
<slot name="header">
|
|
254
270
|
<router-link
|
|
255
271
|
v-if="hasOverview"
|
|
256
|
-
:to="
|
|
272
|
+
:to="headerRoute"
|
|
257
273
|
:exact="group.children[0].exact"
|
|
258
274
|
:tabindex="-1"
|
|
259
275
|
>
|
|
@@ -311,6 +327,7 @@ export default {
|
|
|
311
327
|
:can-collapse="canCollapse"
|
|
312
328
|
:group="child"
|
|
313
329
|
:fixed-open="fixedOpen"
|
|
330
|
+
:highlight-route="highlightRoute"
|
|
314
331
|
@selected="groupSelected($event)"
|
|
315
332
|
@expand="expandGroup($event)"
|
|
316
333
|
@close="close($event)"
|
|
@@ -322,6 +339,7 @@ export default {
|
|
|
322
339
|
:is-root="depth == 0 && !showHeader"
|
|
323
340
|
:type="child"
|
|
324
341
|
:depth="depth"
|
|
342
|
+
:highlight-route="highlightRoute"
|
|
325
343
|
@selected="selectType($event)"
|
|
326
344
|
/>
|
|
327
345
|
</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
|
@@ -3,6 +3,7 @@ import Favorite from '@shell/components/nav/Favorite';
|
|
|
3
3
|
import { TYPE_MODES } from '@shell/store/type-map';
|
|
4
4
|
|
|
5
5
|
import TabTitle from '@shell/components/TabTitle';
|
|
6
|
+
import { filterLocationValidParams } from '@shell/utils/router';
|
|
6
7
|
|
|
7
8
|
const showFavoritesFor = [TYPE_MODES.FAVORITE, TYPE_MODES.USED];
|
|
8
9
|
|
|
@@ -27,6 +28,11 @@ export default {
|
|
|
27
28
|
type: Number,
|
|
28
29
|
default: 0,
|
|
29
30
|
},
|
|
31
|
+
|
|
32
|
+
highlightRoute: {
|
|
33
|
+
type: Boolean,
|
|
34
|
+
default: true,
|
|
35
|
+
},
|
|
30
36
|
},
|
|
31
37
|
|
|
32
38
|
data() {
|
|
@@ -57,7 +63,7 @@ export default {
|
|
|
57
63
|
},
|
|
58
64
|
|
|
59
65
|
isActive() {
|
|
60
|
-
const typeFullPath = this.$router.resolve(this.
|
|
66
|
+
const typeFullPath = this.$router.resolve(this.typeRoute)?.fullPath.toLowerCase();
|
|
61
67
|
const pageFullPath = this.$route.fullPath?.toLowerCase().split('#')[0]; // Ignore the shebang when comparing routes
|
|
62
68
|
const routeMetaNav = this.$route.meta?.nav;
|
|
63
69
|
|
|
@@ -88,6 +94,10 @@ export default {
|
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
return typeFullPath === pageFullPath;
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
typeRoute() {
|
|
100
|
+
return filterLocationValidParams(this.$router, this.type.route);
|
|
91
101
|
}
|
|
92
102
|
|
|
93
103
|
},
|
|
@@ -100,7 +110,8 @@ export default {
|
|
|
100
110
|
selectType() {
|
|
101
111
|
// Prevent issues if custom NavLink is used #5047
|
|
102
112
|
if (this.type?.route) {
|
|
103
|
-
const
|
|
113
|
+
const validRoute = filterLocationValidParams(this.$router, this.type.route);
|
|
114
|
+
const typePath = this.$router.resolve(validRoute)?.fullPath;
|
|
104
115
|
|
|
105
116
|
if (typePath !== this.$route.fullPath) {
|
|
106
117
|
this.$emit('selected');
|
|
@@ -117,16 +128,16 @@ export default {
|
|
|
117
128
|
:key="type.name"
|
|
118
129
|
v-slot="{ href, navigate,isExactActive }"
|
|
119
130
|
custom
|
|
120
|
-
:to="
|
|
131
|
+
:to="typeRoute"
|
|
121
132
|
>
|
|
122
133
|
<li
|
|
123
134
|
class="child nav-type"
|
|
124
|
-
:class="{'root': isRoot, [`depth-${depth}`]: true, 'router-link-active': isActive, 'router-link-exact-active': isExactActive}"
|
|
135
|
+
:class="{'root': isRoot, [`depth-${depth}`]: true, 'router-link-active': highlightRoute && isActive, 'router-link-exact-active': highlightRoute && isExactActive}"
|
|
125
136
|
@click="navigate"
|
|
126
137
|
@keypress.enter="navigate"
|
|
127
138
|
>
|
|
128
139
|
<TabTitle
|
|
129
|
-
v-if="isExactActive"
|
|
140
|
+
v-if="highlightRoute && isExactActive"
|
|
130
141
|
:show-child="false"
|
|
131
142
|
>
|
|
132
143
|
{{ type.labelKey ? t(type.labelKey) : (type.labelDisplay || type.label) }}
|
|
@@ -136,7 +147,7 @@ export default {
|
|
|
136
147
|
:aria-label="type.labelKey ? t(type.labelKey) : (type.labelDisplay || type.label)"
|
|
137
148
|
:href="href"
|
|
138
149
|
class="type-link"
|
|
139
|
-
:aria-current="isActive ? 'page' : undefined"
|
|
150
|
+
:aria-current="highlightRoute && isActive ? 'page' : undefined"
|
|
140
151
|
@click="selectType(); navigate($event);"
|
|
141
152
|
@mouseenter="setNear(true)"
|
|
142
153
|
@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, {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { inject, provide } from 'vue';
|
|
2
|
+
const IS_IN_RESOURCE_EDIT_PAGE_KEY = 'isInResourceEditKey';
|
|
3
|
+
const IS_IN_RESOURCE_CREATE_PAGE_KEY = 'isInResourceCreateKey';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Used to determine if the current component was instantiated as an ancestor of a CruResource EDIT page.
|
|
7
|
+
* @returns true if the component is an ancestor of CruResource EDIT page, otherwise false
|
|
8
|
+
*/
|
|
9
|
+
export function useIsInResourceEditPage() {
|
|
10
|
+
return inject(IS_IN_RESOURCE_EDIT_PAGE_KEY, false);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Used to determine if the current component was instantiated as an ancestor of a CruResource CREATE page.
|
|
15
|
+
* @returns true if the component is an ancestor of CruResource CREATE page, otherwise false
|
|
16
|
+
*/
|
|
17
|
+
export function useIsInResourceCreatePage() {
|
|
18
|
+
return inject(IS_IN_RESOURCE_CREATE_PAGE_KEY, false);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function useResourceEditPageProvider() {
|
|
22
|
+
provide(IS_IN_RESOURCE_EDIT_PAGE_KEY, true);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function useResourceCreatePageProvider() {
|
|
26
|
+
provide(IS_IN_RESOURCE_CREATE_PAGE_KEY, true);
|
|
27
|
+
}
|
package/composables/focusTrap.ts
CHANGED
|
@@ -57,8 +57,10 @@ export function useWatcherBasedSetupFocusTrapWithDestroyIncluded(watchVar:any, f
|
|
|
57
57
|
|
|
58
58
|
focusTrapInstance = createFocusTrap(focusEl, opts);
|
|
59
59
|
|
|
60
|
+
const activate = () => focusTrapInstance.activate();
|
|
61
|
+
|
|
60
62
|
nextTick(() => {
|
|
61
|
-
|
|
63
|
+
setTimeout(activate, 0);
|
|
62
64
|
});
|
|
63
65
|
});
|
|
64
66
|
} else if (!neu && focusTrapInstance && Object.keys(focusTrapInstance).length && !useUnmountHook) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { inject, provide } from 'vue';
|
|
2
|
+
|
|
3
|
+
const IS_IN_RESOURCE_DETAIL_PAGE_KEY = 'isInResourceDetailKey';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Used to determine if the current component was instantiated as an ancestor of a ResourceDetail.
|
|
7
|
+
* @returns true if the component is an ancestor of ResourceDetail, otherwise false
|
|
8
|
+
*/
|
|
9
|
+
export function useIsInResourceDetailPage() {
|
|
10
|
+
return inject(IS_IN_RESOURCE_DETAIL_PAGE_KEY, false);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function useResourceDetailPageProvider() {
|
|
14
|
+
provide(IS_IN_RESOURCE_DETAIL_PAGE_KEY, true);
|
|
15
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ref, computed, ComputedRef, Ref,
|
|
2
|
+
ref, computed, ComputedRef, Ref,
|
|
3
|
+
EmitFn
|
|
3
4
|
} from 'vue';
|
|
4
5
|
import { _VIEW, _EDIT } from '@shell/config/query-params';
|
|
5
6
|
|
|
@@ -72,9 +73,7 @@ export const labeledFormElementProps = {
|
|
|
72
73
|
}
|
|
73
74
|
};
|
|
74
75
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
export const useLabeledFormElement = (props: LabeledFormElementProps, emit: typeof labeledFormElementEmits): UseLabeledFormElement => {
|
|
76
|
+
export const useLabeledFormElement = (props: LabeledFormElementProps, emit: EmitFn<['update:validation']>): UseLabeledFormElement => {
|
|
78
77
|
const raised = ref(props.mode === _VIEW || !!`${ props.value }`);
|
|
79
78
|
const focused = ref(false);
|
|
80
79
|
const blurred = ref<number | null>(null);
|
package/config/product/fleet.js
CHANGED
|
@@ -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
|
}
|
package/config/router/routes.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { NAME as APPS } from '@shell/config/product/apps';
|
|
2
|
-
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
3
2
|
import { NAME as MANAGER } from '@shell/config/product/manager';
|
|
4
3
|
import {
|
|
5
4
|
CAPI, MANAGEMENT, BACKUP_RESTORE, COMPLIANCE, VIRTUAL_TYPES
|
|
@@ -184,10 +183,7 @@ export default [
|
|
|
184
183
|
redirect(to) {
|
|
185
184
|
return {
|
|
186
185
|
name: 'c-cluster-explorer',
|
|
187
|
-
params: {
|
|
188
|
-
...(to?.params || {}),
|
|
189
|
-
product: EXPLORER,
|
|
190
|
-
}
|
|
186
|
+
params: { ...(to?.params || {}) }
|
|
191
187
|
};
|
|
192
188
|
}
|
|
193
189
|
},
|