@rancher/shell 3.0.5 → 3.0.7
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/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/_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 +33 -21
- package/components/ClusterIconMenu.vue +1 -1
- package/components/ClusterProviderIcon.vue +1 -1
- package/components/CodeMirror.vue +1 -1
- package/components/FilterPanel.vue +8 -1
- package/components/IconOrSvg.vue +40 -29
- package/components/PaginatedResourceTable.vue +7 -2
- package/components/PromptRemove.vue +5 -0
- package/components/ResourceDetail/index.vue +1 -0
- package/components/ResourceTable.vue +30 -20
- package/components/SortableTable/sorting.js +3 -1
- package/components/Tabbed/index.vue +5 -5
- package/components/form/ResourceTabs/index.vue +37 -18
- package/components/form/SecretSelector.vue +6 -2
- package/components/nav/Group.vue +29 -9
- package/components/nav/Header.vue +6 -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/explorer.js +9 -8
- package/config/table-headers.js +9 -0
- package/config/uiplugins.js +1 -1
- package/core/plugin.ts +33 -9
- package/core/types.ts +37 -6
- package/detail/provisioning.cattle.io.cluster.vue +1 -0
- package/dialog/InstallExtensionDialog.vue +71 -45
- package/dialog/UninstallExtensionDialog.vue +2 -1
- package/dialog/__tests__/InstallExtensionDialog.test.ts +111 -0
- package/edit/auth/oidc.vue +86 -16
- package/list/catalog.cattle.io.clusterrepo.vue +2 -2
- package/mixins/__tests__/chart.test.ts +1 -1
- package/mixins/chart.js +1 -1
- package/models/event.js +7 -0
- package/models/provisioning.cattle.io.cluster.js +9 -0
- package/package.json +2 -2
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +6 -0
- package/pages/c/_cluster/apps/charts/StatusLabel.vue +4 -3
- package/pages/c/_cluster/apps/charts/index.vue +12 -11
- package/pages/c/_cluster/explorer/EventsTable.vue +3 -6
- package/pages/c/_cluster/settings/performance.vue +1 -1
- 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/plugins/__tests__/subscribe.events.test.ts +194 -0
- package/plugins/dashboard-store/actions.js +3 -0
- package/plugins/dashboard-store/getters.js +1 -1
- package/plugins/dashboard-store/resource-class.js +15 -4
- 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 +26 -31
- 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/test-plugins-build.sh +4 -5
- package/scripts/typegen.sh +2 -0
- package/store/auth.js +2 -2
- package/store/index.js +12 -22
- package/types/extension-manager.ts +8 -1
- package/types/resources/settings.d.ts +24 -17
- package/types/shell/index.d.ts +534 -336
- package/types/store/subscribe-events.types.ts +70 -0
- package/types/store/subscribe.types.ts +6 -22
- package/types/store/vuex.d.ts +2 -1
- package/types/vue-shim.d.ts +2 -5
- package/utils/pagination-utils.ts +98 -30
- package/utils/pagination-wrapper.ts +6 -8
- 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
package/components/nav/Group.vue
CHANGED
|
@@ -381,21 +381,21 @@ export default {
|
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
&.active {
|
|
384
|
-
color: var(--primary-hover-text);
|
|
385
|
-
background-color: var(--primary-hover-bg);
|
|
384
|
+
color: var(--on-active, var(--primary-hover-text));
|
|
385
|
+
background-color: var(--active-nav, var(--primary-hover-bg));
|
|
386
386
|
|
|
387
387
|
h6 {
|
|
388
388
|
padding: 8px 0 8px 16px;
|
|
389
389
|
font-weight: bold;
|
|
390
|
-
color: var(--primary-hover-text);
|
|
390
|
+
color: var(--on-active, var(--primary-hover-text));
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
&:hover {
|
|
394
|
-
background-color: var(--primary-hover-bg);
|
|
394
|
+
background-color: var(--nav-active-hover, var(--primary-hover-bg));
|
|
395
395
|
}
|
|
396
396
|
|
|
397
397
|
~ I {
|
|
398
|
-
color: var(--primary-hover-text);
|
|
398
|
+
color: var(--on-active, var(--primary-hover-text));
|
|
399
399
|
}
|
|
400
400
|
}
|
|
401
401
|
&:hover:not(.active) {
|
|
@@ -433,8 +433,24 @@ export default {
|
|
|
433
433
|
margin-left: 0;
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
+
.child:hover {
|
|
437
|
+
background: var(--nav-hover, var(--nav-active));
|
|
438
|
+
}
|
|
439
|
+
|
|
436
440
|
&.group-highlight {
|
|
437
|
-
background: var(--nav-active);
|
|
441
|
+
background: var(--category-active, var(--nav-active));
|
|
442
|
+
|
|
443
|
+
.active.header {
|
|
444
|
+
&:hover {
|
|
445
|
+
background-color: var(--nav-active-hover)
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.child, .header {
|
|
450
|
+
&:hover {
|
|
451
|
+
background: var(--category-active-hover, var(--primary));
|
|
452
|
+
}
|
|
453
|
+
}
|
|
438
454
|
}
|
|
439
455
|
}
|
|
440
456
|
|
|
@@ -480,13 +496,17 @@ export default {
|
|
|
480
496
|
padding: 0;
|
|
481
497
|
|
|
482
498
|
A, A I {
|
|
483
|
-
color: var(--primary-hover-text);
|
|
499
|
+
color: var(--on-active, var(--primary-hover-text));
|
|
484
500
|
}
|
|
485
501
|
|
|
486
502
|
A {
|
|
487
|
-
color: var(--primary-hover-text);
|
|
488
|
-
background-color: var(--primary-hover-bg);
|
|
503
|
+
color: var(--on-active, var(--primary-hover-text));
|
|
504
|
+
background-color: var(--active-nav, var(--primary-hover-bg));
|
|
489
505
|
font-weight: bold;
|
|
506
|
+
|
|
507
|
+
&:hover {
|
|
508
|
+
background: var(--nav-active-hover);
|
|
509
|
+
}
|
|
490
510
|
}
|
|
491
511
|
}
|
|
492
512
|
|
|
@@ -843,16 +843,14 @@ export default {
|
|
|
843
843
|
align-items: center;
|
|
844
844
|
display: flex;
|
|
845
845
|
margin-right: 8px;
|
|
846
|
-
height: 55px;
|
|
847
|
-
margin-left: 5px;
|
|
848
846
|
max-width: 200px;
|
|
849
847
|
padding: 12px 0;
|
|
850
848
|
}
|
|
851
849
|
|
|
852
850
|
.side-menu-logo-img {
|
|
853
851
|
object-fit: contain;
|
|
854
|
-
height: 21px;
|
|
855
852
|
max-width: 200px;
|
|
853
|
+
height: 36px;
|
|
856
854
|
}
|
|
857
855
|
|
|
858
856
|
> * {
|
|
@@ -933,8 +931,8 @@ export default {
|
|
|
933
931
|
:deep() div .btn.role-tertiary {
|
|
934
932
|
border: 1px solid var(--header-btn-bg);
|
|
935
933
|
border: none;
|
|
936
|
-
background: var(--header-btn-bg);
|
|
937
|
-
color: var(--header-btn-text);
|
|
934
|
+
background: var(--tertiary-header, var(--header-btn-bg));
|
|
935
|
+
color: var(--on-tertiary-header, var(--header-btn-text));
|
|
938
936
|
padding: 0 10px;
|
|
939
937
|
line-height: 32px;
|
|
940
938
|
min-height: 32px;
|
|
@@ -945,8 +943,8 @@ export default {
|
|
|
945
943
|
}
|
|
946
944
|
|
|
947
945
|
&:hover {
|
|
948
|
-
background: var(--primary);
|
|
949
|
-
color: #fff;
|
|
946
|
+
background: var(--tertiary-header-hover, var(--primary));
|
|
947
|
+
color: var(--on-tertiary-header-hover, #fff);
|
|
950
948
|
}
|
|
951
949
|
|
|
952
950
|
&[disabled=disabled] {
|
|
@@ -1079,7 +1077,7 @@ export default {
|
|
|
1079
1077
|
.user-name {
|
|
1080
1078
|
display: flex;
|
|
1081
1079
|
align-items: center;
|
|
1082
|
-
color: var(--secondary);
|
|
1080
|
+
color: var(--body-text, var(--secondary));
|
|
1083
1081
|
}
|
|
1084
1082
|
|
|
1085
1083
|
.user-menu {
|
|
@@ -139,12 +139,6 @@ export abstract class BaseTopLevelMenuHelper {
|
|
|
139
139
|
this.$store = $store;
|
|
140
140
|
|
|
141
141
|
this.hasProvCluster = this.$store.getters[`management/schemaFor`](CAPI.RANCHER_CLUSTER);
|
|
142
|
-
|
|
143
|
-
// Reduce flicker when component is recreated on a different layout
|
|
144
|
-
const { clustersPinned = [], clustersOthers = [] } = this.$store.getters['sideNavCache'] || {};
|
|
145
|
-
|
|
146
|
-
this.clustersPinned.push(...clustersPinned);
|
|
147
|
-
this.clustersOthers.push(...clustersOthers);
|
|
148
142
|
}
|
|
149
143
|
|
|
150
144
|
protected convertToCluster(mgmtCluster: MgmtCluster, provCluster: ProvCluster): TopLevelMenuCluster {
|
|
@@ -163,10 +157,6 @@ export abstract class BaseTopLevelMenuHelper {
|
|
|
163
157
|
clusterRoute: { name: 'c-cluster-explorer', params: { cluster: mgmtCluster.id } }
|
|
164
158
|
};
|
|
165
159
|
}
|
|
166
|
-
|
|
167
|
-
protected cacheClusters() {
|
|
168
|
-
this.$store.dispatch('setSideNavCache', { clustersPinned: this.clustersPinned, clustersOthers: this.clustersOthers });
|
|
169
|
-
}
|
|
170
160
|
}
|
|
171
161
|
|
|
172
162
|
/**
|
|
@@ -202,9 +192,9 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
|
|
|
202
192
|
this.clustersOthersWrapper = new PaginationWrapper({
|
|
203
193
|
$store,
|
|
204
194
|
id: 'tlm-unpinned-clusters',
|
|
205
|
-
onChange: () => {
|
|
195
|
+
onChange: async() => {
|
|
206
196
|
if (this.args) {
|
|
207
|
-
this.update(this.args);
|
|
197
|
+
await this.update(this.args);
|
|
208
198
|
}
|
|
209
199
|
},
|
|
210
200
|
enabledFor: {
|
|
@@ -220,9 +210,9 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
|
|
|
220
210
|
this.provClusterWrapper = new PaginationWrapper({
|
|
221
211
|
$store,
|
|
222
212
|
id: 'tlm-prov-clusters',
|
|
223
|
-
onChange: () => {
|
|
213
|
+
onChange: async() => {
|
|
224
214
|
if (this.args) {
|
|
225
|
-
this.update(this.args);
|
|
215
|
+
await this.update(this.args);
|
|
226
216
|
}
|
|
227
217
|
},
|
|
228
218
|
enabledFor: {
|
|
@@ -276,8 +266,6 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
|
|
|
276
266
|
|
|
277
267
|
this.clustersPinned.push(..._clustersPinned);
|
|
278
268
|
this.clustersOthers.push(..._clustersNotPinned);
|
|
279
|
-
|
|
280
|
-
this.cacheClusters();
|
|
281
269
|
}
|
|
282
270
|
|
|
283
271
|
async destroy() {
|
|
@@ -390,7 +378,6 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
|
|
|
390
378
|
private async updateProvCluster(notPinned: MgmtCluster[], pinned: MgmtCluster[]): Promise<ProvCluster[]> {
|
|
391
379
|
return this.provClusterWrapper.request({
|
|
392
380
|
pagination: {
|
|
393
|
-
|
|
394
381
|
filters: [
|
|
395
382
|
PaginationParamFilter.createMultipleFields(
|
|
396
383
|
[...notPinned, ...pinned]
|
|
@@ -399,7 +386,6 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
|
|
|
399
386
|
}))
|
|
400
387
|
)
|
|
401
388
|
],
|
|
402
|
-
|
|
403
389
|
page: 1,
|
|
404
390
|
sort: [],
|
|
405
391
|
projectsOrNamespaces: []
|
|
@@ -432,8 +418,6 @@ export class TopLevelMenuHelperLegacy extends BaseTopLevelMenuHelper implements
|
|
|
432
418
|
|
|
433
419
|
this.clustersPinned.push(..._clustersPinned);
|
|
434
420
|
this.clustersOthers.push(..._clustersNotPinned);
|
|
435
|
-
|
|
436
|
-
this.cacheClusters();
|
|
437
421
|
}
|
|
438
422
|
|
|
439
423
|
async destroy() {
|
|
@@ -581,3 +565,46 @@ export class TopLevelMenuHelperLegacy extends BaseTopLevelMenuHelper implements
|
|
|
581
565
|
return sorted;
|
|
582
566
|
}
|
|
583
567
|
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Retain state of the side nav, no matter when the TopLevelMenu component is created/deleted (on layout change)
|
|
571
|
+
*
|
|
572
|
+
* This means there's no flickering when the user changes pages and the side nav component re-renders
|
|
573
|
+
*
|
|
574
|
+
* Also it means we're not unwatching then watching the clusters
|
|
575
|
+
*/
|
|
576
|
+
class TopLevelMenuHelperService {
|
|
577
|
+
private _helper?: TopLevelMenuHelper;
|
|
578
|
+
public init($store: VuexStore) {
|
|
579
|
+
if (this._helper) {
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
const canPagination = $store.getters[`management/paginationEnabled`]({
|
|
584
|
+
id: MANAGEMENT.CLUSTER,
|
|
585
|
+
context: 'side-bar',
|
|
586
|
+
}) && $store.getters[`management/paginationEnabled`]({
|
|
587
|
+
id: CAPI.RANCHER_CLUSTER,
|
|
588
|
+
context: 'side-bar',
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
this._helper = canPagination ? new TopLevelMenuHelperPagination({ $store }) : new TopLevelMenuHelperLegacy({ $store });
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
public async reset() {
|
|
595
|
+
await this._helper?.destroy();
|
|
596
|
+
delete this._helper;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
get helper(): TopLevelMenuHelper {
|
|
600
|
+
if (!this._helper) {
|
|
601
|
+
throw new Error('Unable to use the side nav cluster helper (not initialised)');
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
return this._helper;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const instance = new TopLevelMenuHelperService();
|
|
609
|
+
|
|
610
|
+
export default instance;
|
|
@@ -14,7 +14,7 @@ import { SETTING } from '@shell/config/settings';
|
|
|
14
14
|
import { getProductFromRoute } from '@shell/utils/router';
|
|
15
15
|
import { isRancherPrime } from '@shell/config/version';
|
|
16
16
|
import Pinned from '@shell/components/nav/Pinned';
|
|
17
|
-
import
|
|
17
|
+
import sideNavService from '@shell/components/nav/TopLevelMenu.helper';
|
|
18
18
|
import { debounce } from 'lodash';
|
|
19
19
|
import { sameContents } from '@shell/utils/array';
|
|
20
20
|
|
|
@@ -27,6 +27,8 @@ export default {
|
|
|
27
27
|
},
|
|
28
28
|
|
|
29
29
|
data() {
|
|
30
|
+
sideNavService.init(this.$store);
|
|
31
|
+
|
|
30
32
|
const { displayVersion, fullVersion } = getVersionInfo(this.$store);
|
|
31
33
|
const hasProvCluster = this.$store.getters[`management/schemaFor`](CAPI.RANCHER_CLUSTER);
|
|
32
34
|
|
|
@@ -37,7 +39,7 @@ export default {
|
|
|
37
39
|
id: CAPI.RANCHER_CLUSTER,
|
|
38
40
|
context: 'side-bar',
|
|
39
41
|
});
|
|
40
|
-
const helper =
|
|
42
|
+
const helper = sideNavService.helper;
|
|
41
43
|
const provClusters = !canPagination && hasProvCluster ? this.$store.getters[`management/all`](CAPI.RANCHER_CLUSTER) : [];
|
|
42
44
|
const mgmtClusters = !canPagination ? this.$store.getters[`management/all`](MANAGEMENT.CLUSTER) : [];
|
|
43
45
|
|
|
@@ -327,7 +329,6 @@ export default {
|
|
|
327
329
|
|
|
328
330
|
beforeUnmount() {
|
|
329
331
|
document.removeEventListener('keyup', this.handler);
|
|
330
|
-
this.helper?.destroy();
|
|
331
332
|
},
|
|
332
333
|
|
|
333
334
|
methods: {
|
|
@@ -1073,6 +1074,14 @@ export default {
|
|
|
1073
1074
|
width: 300px;
|
|
1074
1075
|
overflow: auto;
|
|
1075
1076
|
|
|
1077
|
+
& .category {
|
|
1078
|
+
& a.router-link-active {
|
|
1079
|
+
&:hover {
|
|
1080
|
+
color: var(--on-active, var(--default));
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1076
1085
|
.option {
|
|
1077
1086
|
align-items: center;
|
|
1078
1087
|
cursor: pointer;
|
|
@@ -1119,6 +1128,15 @@ export default {
|
|
|
1119
1128
|
}
|
|
1120
1129
|
}
|
|
1121
1130
|
|
|
1131
|
+
&:not(.active-menu-link) {
|
|
1132
|
+
&:hover {
|
|
1133
|
+
.pin {
|
|
1134
|
+
display: block;
|
|
1135
|
+
color: var(--body-text-hover);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1122
1140
|
&:hover {
|
|
1123
1141
|
text-decoration: none;
|
|
1124
1142
|
|
|
@@ -1178,19 +1196,31 @@ export default {
|
|
|
1178
1196
|
outline-offset: -4px;
|
|
1179
1197
|
}
|
|
1180
1198
|
|
|
1181
|
-
background: var(--primary-hover-bg);
|
|
1182
|
-
color: var(--primary-hover-text);
|
|
1199
|
+
background: var(--active-nav, var(--primary-hover-bg));
|
|
1200
|
+
color: var(--on-active, var(--primary-hover-text));
|
|
1183
1201
|
|
|
1184
1202
|
svg {
|
|
1185
|
-
fill: var(--primary-hover-text);
|
|
1203
|
+
fill: var(--on-active, var(--primary-hover-text));
|
|
1186
1204
|
}
|
|
1187
1205
|
|
|
1188
1206
|
i {
|
|
1189
|
-
color: var(--primary-hover-text);
|
|
1207
|
+
color: var(--on-active, var(--primary-hover-text));
|
|
1190
1208
|
}
|
|
1191
1209
|
|
|
1192
1210
|
div .description {
|
|
1193
|
-
color: var(--default);
|
|
1211
|
+
color: var(--on-active, var(--default));
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
&:hover {
|
|
1215
|
+
background: var(--active-hover, var(--primary-hover-bg));
|
|
1216
|
+
|
|
1217
|
+
div {
|
|
1218
|
+
color: var(--on-active, var(--default));
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
svg {
|
|
1222
|
+
fill: var(--on-active, var(--primary-hover-text));
|
|
1223
|
+
}
|
|
1194
1224
|
}
|
|
1195
1225
|
}
|
|
1196
1226
|
|
|
@@ -1201,8 +1231,8 @@ export default {
|
|
|
1201
1231
|
}
|
|
1202
1232
|
|
|
1203
1233
|
&:hover {
|
|
1204
|
-
color: var(--primary-hover-text);
|
|
1205
|
-
background: var(--primary-hover-bg);
|
|
1234
|
+
color: var(--tertiary-hover-app-bar, var(--primary-hover-text));
|
|
1235
|
+
background: var(--nav-hover-top-level, var(--primary-hover-bg));
|
|
1206
1236
|
> div {
|
|
1207
1237
|
color: var(--primary-hover-text);
|
|
1208
1238
|
|
|
@@ -1211,10 +1241,10 @@ export default {
|
|
|
1211
1241
|
}
|
|
1212
1242
|
}
|
|
1213
1243
|
svg {
|
|
1214
|
-
fill: var(--primary-hover-text);
|
|
1244
|
+
fill: var(--tertiary-hover-app-bar, var(--primary-hover-text));
|
|
1215
1245
|
}
|
|
1216
1246
|
div {
|
|
1217
|
-
color: var(--primary-hover-text);
|
|
1247
|
+
color: var(--tertiary-hover-app-bar, var(--primary-hover-text));
|
|
1218
1248
|
}
|
|
1219
1249
|
&.disabled {
|
|
1220
1250
|
background: transparent;
|
|
@@ -1549,8 +1579,8 @@ export default {
|
|
|
1549
1579
|
overflow: hidden;
|
|
1550
1580
|
& IMG {
|
|
1551
1581
|
object-fit: contain;
|
|
1552
|
-
height: 21px;
|
|
1553
1582
|
max-width: 200px;
|
|
1583
|
+
height: 36px;
|
|
1554
1584
|
}
|
|
1555
1585
|
}
|
|
1556
1586
|
|
|
@@ -1592,7 +1622,7 @@ export default {
|
|
|
1592
1622
|
padding: 8px 20px;
|
|
1593
1623
|
|
|
1594
1624
|
&:hover {
|
|
1595
|
-
background-color: var(--primary-hover-bg);
|
|
1625
|
+
background-color: var(--active-hover, var(--primary-hover-bg));
|
|
1596
1626
|
color: var(--primary-hover-text);
|
|
1597
1627
|
text-decoration: none;
|
|
1598
1628
|
}
|
package/components/nav/Type.vue
CHANGED
|
@@ -3,6 +3,7 @@ import { mount, Wrapper } from '@vue/test-utils';
|
|
|
3
3
|
import { CAPI, COUNT, MANAGEMENT } from '@shell/config/types';
|
|
4
4
|
import { PINNED_CLUSTERS } from '@shell/store/prefs';
|
|
5
5
|
import { nextTick } from 'vue';
|
|
6
|
+
import sideNavService from '@shell/components/nav/TopLevelMenu.helper';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* `clusters` doubles up as both mgmt and prov clusters (don't shoot the messenger)
|
|
@@ -53,6 +54,7 @@ const waitForIt = async() => {
|
|
|
53
54
|
describe('topLevelMenu', () => {
|
|
54
55
|
beforeEach(() => {
|
|
55
56
|
jest.useFakeTimers();
|
|
57
|
+
sideNavService.reset();
|
|
56
58
|
});
|
|
57
59
|
|
|
58
60
|
afterEach(() => {
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
STATE, NAME as NAME_COL, NAMESPACE as NAMESPACE_COL, AGE, OBJECT,
|
|
4
4
|
EVENT_LAST_SEEN_TIME,
|
|
5
5
|
EVENT_TYPE,
|
|
6
|
-
SECRET_CLONE
|
|
6
|
+
SECRET_CLONE,
|
|
7
|
+
EVENT_FIRST_SEEN_TIME
|
|
7
8
|
} from '@shell/config/table-headers';
|
|
8
9
|
|
|
9
10
|
// This file contains table headers
|
|
@@ -56,10 +57,17 @@ export const STEVE_EVENT_OBJECT = {
|
|
|
56
57
|
search: 'involvedObject.kind',
|
|
57
58
|
};
|
|
58
59
|
|
|
60
|
+
export const STEVE_EVENT_FIRST_SEEN = {
|
|
61
|
+
...EVENT_FIRST_SEEN_TIME,
|
|
62
|
+
|
|
63
|
+
value: 'metadata.fields.7',
|
|
64
|
+
sort: 'metadata.fields.7:desc',
|
|
65
|
+
};
|
|
66
|
+
|
|
59
67
|
export const STEVE_EVENT_LAST_SEEN = {
|
|
60
68
|
...EVENT_LAST_SEEN_TIME,
|
|
61
69
|
value: 'metadata.fields.0',
|
|
62
|
-
sort: 'metadata.fields.0',
|
|
70
|
+
sort: 'metadata.fields.0:desc',
|
|
63
71
|
};
|
|
64
72
|
|
|
65
73
|
export const STEVE_EVENT_TYPE = {
|
|
@@ -22,11 +22,12 @@ import {
|
|
|
22
22
|
ACCESS_KEY, DESCRIPTION, EXPIRES, EXPIRY_STATE, LAST_USED, SUB_TYPE, AGE_NORMAN, SCOPE_NORMAN, PERSISTENT_VOLUME_CLAIM, RECLAIM_POLICY, PV_REASON, WORKLOAD_HEALTH_SCALE, POD_RESTARTS,
|
|
23
23
|
DURATION, MESSAGE, REASON, EVENT_TYPE, OBJECT, ROLE, ROLES, VERSION, INTERNAL_EXTERNAL_IP, KUBE_NODE_OS, CPU, RAM, SECRET_DATA,
|
|
24
24
|
EVENT_LAST_SEEN_TIME,
|
|
25
|
+
EVENT_FIRST_SEEN_TIME,
|
|
25
26
|
} from '@shell/config/table-headers';
|
|
26
27
|
|
|
27
28
|
import { DSL } from '@shell/store/type-map';
|
|
28
29
|
import {
|
|
29
|
-
STEVE_AGE_COL, STEVE_EVENT_LAST_SEEN, STEVE_EVENT_OBJECT, STEVE_EVENT_TYPE, STEVE_LIST_GROUPS, STEVE_NAMESPACE_COL, STEVE_NAME_COL, STEVE_STATE_COL
|
|
30
|
+
STEVE_AGE_COL, STEVE_EVENT_FIRST_SEEN, STEVE_EVENT_LAST_SEEN, STEVE_EVENT_OBJECT, STEVE_EVENT_TYPE, STEVE_LIST_GROUPS, STEVE_NAMESPACE_COL, STEVE_NAME_COL, STEVE_STATE_COL
|
|
30
31
|
} from '@shell/config/pagination-table-headers';
|
|
31
32
|
|
|
32
33
|
import { COLUMN_BREAKPOINTS } from '@shell/types/store/type-map';
|
|
@@ -294,7 +295,7 @@ export function init(store) {
|
|
|
294
295
|
STEVE_NAMESPACE_COL,
|
|
295
296
|
{
|
|
296
297
|
...INGRESS_TARGET,
|
|
297
|
-
sort: 'spec.rules[0].host',
|
|
298
|
+
sort: 'spec.rules[0].host',
|
|
298
299
|
search: false, // This is broken in normal world, so disable here
|
|
299
300
|
},
|
|
300
301
|
{
|
|
@@ -337,7 +338,7 @@ export function init(store) {
|
|
|
337
338
|
);
|
|
338
339
|
|
|
339
340
|
headers(EVENT,
|
|
340
|
-
[STATE, EVENT_LAST_SEEN_TIME, EVENT_TYPE, REASON, OBJECT, 'Subobject', 'Source', MESSAGE,
|
|
341
|
+
[STATE, EVENT_LAST_SEEN_TIME, EVENT_TYPE, REASON, OBJECT, 'Subobject', 'Source', MESSAGE, EVENT_FIRST_SEEN_TIME, 'Count', NAME_COL, NAMESPACE_COL],
|
|
341
342
|
[
|
|
342
343
|
STEVE_STATE_COL,
|
|
343
344
|
STEVE_EVENT_LAST_SEEN,
|
|
@@ -347,7 +348,7 @@ export function init(store) {
|
|
|
347
348
|
'Subobject',
|
|
348
349
|
'Source',
|
|
349
350
|
MESSAGE,
|
|
350
|
-
|
|
351
|
+
STEVE_EVENT_FIRST_SEEN,
|
|
351
352
|
'Count',
|
|
352
353
|
STEVE_NAME_COL,
|
|
353
354
|
STEVE_NAMESPACE_COL,
|
|
@@ -359,10 +360,10 @@ export function init(store) {
|
|
|
359
360
|
STEVE_STATE_COL,
|
|
360
361
|
STEVE_NAME_COL,
|
|
361
362
|
STEVE_NAMESPACE_COL,
|
|
362
|
-
HPA_REFERENCE,
|
|
363
|
-
MIN_REPLICA,
|
|
364
|
-
MAX_REPLICA,
|
|
365
|
-
CURRENT_REPLICA,
|
|
363
|
+
HPA_REFERENCE,
|
|
364
|
+
MIN_REPLICA,
|
|
365
|
+
MAX_REPLICA,
|
|
366
|
+
CURRENT_REPLICA,
|
|
366
367
|
STEVE_AGE_COL
|
|
367
368
|
]
|
|
368
369
|
);
|
package/config/table-headers.js
CHANGED
|
@@ -541,6 +541,15 @@ export const LAST_SEEN_TIME = {
|
|
|
541
541
|
tooltip: 'tableHeaders.lastSeenTooltip'
|
|
542
542
|
};
|
|
543
543
|
|
|
544
|
+
export const EVENT_FIRST_SEEN_TIME = {
|
|
545
|
+
name: 'firstSeen',
|
|
546
|
+
labelKey: 'tableHeaders.firstSeen',
|
|
547
|
+
tooltip: 'tableHeaders.firstSeenTooltip',
|
|
548
|
+
|
|
549
|
+
value: 'firstSeen',
|
|
550
|
+
sort: 'firstSeen:desc',
|
|
551
|
+
};
|
|
552
|
+
|
|
544
553
|
export const EVENT_LAST_SEEN_TIME = {
|
|
545
554
|
...LAST_SEEN_TIME,
|
|
546
555
|
defaultSort: true,
|
package/config/uiplugins.js
CHANGED
|
@@ -107,7 +107,7 @@ export function uiPluginAnnotation(chart, name) {
|
|
|
107
107
|
/**
|
|
108
108
|
* Parse the Rancher version string
|
|
109
109
|
*/
|
|
110
|
-
function parseRancherVersion(v) {
|
|
110
|
+
export function parseRancherVersion(v) {
|
|
111
111
|
let parsedVersion = semver.coerce(v)?.version;
|
|
112
112
|
const splitArr = parsedVersion?.split('.');
|
|
113
113
|
|
package/core/plugin.ts
CHANGED
|
@@ -16,24 +16,32 @@ import {
|
|
|
16
16
|
ModelExtensionConstructor,
|
|
17
17
|
PluginRouteRecordRaw, RegisterStore, UnregisterStore, CoreStoreSpecifics, CoreStoreConfig,
|
|
18
18
|
NavHooks, OnNavToPackage, OnNavAwayFromPackage, OnLogIn, OnLogOut,
|
|
19
|
-
|
|
19
|
+
PaginationTableColumn,
|
|
20
|
+
ExtensionEnvironment,
|
|
21
|
+
ServerSidePaginationExtensionConfig
|
|
20
22
|
} from './types';
|
|
21
23
|
import coreStore, { coreStoreModule, coreStoreState } from '@shell/plugins/dashboard-store';
|
|
22
24
|
import { defineAsyncComponent, markRaw, Component } from 'vue';
|
|
23
25
|
import { getVersionData, CURRENT_RANCHER_VERSION } from '@shell/config/version';
|
|
26
|
+
import { ExtensionManagerTypes } from '@shell/types/extension-manager';
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
/** Registration IDs used for different extension points in the extensions catalog */
|
|
26
29
|
export const EXT_IDS = {
|
|
27
|
-
MODELS:
|
|
28
|
-
MODEL_EXTENSION:
|
|
29
|
-
|
|
30
|
+
MODELS: 'models',
|
|
31
|
+
MODEL_EXTENSION: 'model-extension',
|
|
32
|
+
/**
|
|
33
|
+
* Extension can provide resources that use server-side-pagination
|
|
34
|
+
*/
|
|
35
|
+
SERVER_SIDE_PAGINATION_RESOURCES: 'server-side-pagination',
|
|
36
|
+
} as const;
|
|
37
|
+
export type EXT_IDS_VALUES = (typeof EXT_IDS)[keyof typeof EXT_IDS];
|
|
30
38
|
|
|
31
39
|
export type ProductFunction = (plugin: IPlugin, store: any) => void;
|
|
32
40
|
|
|
33
41
|
export class Plugin implements IPlugin {
|
|
34
42
|
public id: string;
|
|
35
43
|
public name: string;
|
|
36
|
-
public types:
|
|
44
|
+
public types: ExtensionManagerTypes = {};
|
|
37
45
|
public l10n: { [key: string]: Function[] } = {};
|
|
38
46
|
public modelExtensions: { [key: string]: Function[] } = {};
|
|
39
47
|
public locales: { locale: string, label: string}[] = [];
|
|
@@ -247,10 +255,21 @@ export class Plugin implements IPlugin {
|
|
|
247
255
|
}
|
|
248
256
|
|
|
249
257
|
/**
|
|
250
|
-
* Adds a new column to a
|
|
258
|
+
* Adds a new column to a ResourceTable
|
|
259
|
+
*
|
|
260
|
+
* @param where
|
|
261
|
+
* @param when
|
|
262
|
+
* @param action
|
|
263
|
+
* @param column
|
|
264
|
+
* The information required to show a header and values for a column in a table
|
|
265
|
+
* @param paginationColumn
|
|
266
|
+
* As per `column`, but is used where server-side pagination is enabled
|
|
251
267
|
*/
|
|
252
|
-
addTableColumn(where: string, when: LocationConfig | string, column: TableColumn): void {
|
|
253
|
-
this._addUIConfig(ExtensionPoint.TABLE_COL, where, when,
|
|
268
|
+
addTableColumn(where: string, when: LocationConfig | string, column: TableColumn, paginationColumn?: PaginationTableColumn): void {
|
|
269
|
+
this._addUIConfig(ExtensionPoint.TABLE_COL, where, when, {
|
|
270
|
+
column,
|
|
271
|
+
paginationColumn
|
|
272
|
+
});
|
|
254
273
|
}
|
|
255
274
|
|
|
256
275
|
setHomePage(component: any) {
|
|
@@ -348,6 +367,11 @@ export class Plugin implements IPlugin {
|
|
|
348
367
|
}
|
|
349
368
|
}
|
|
350
369
|
|
|
370
|
+
public enableServerSidePagination(config: ServerSidePaginationExtensionConfig) {
|
|
371
|
+
console.info(`Extension "${ this.name || this.id }" is enabling server-side pagination for some resources`, config); // eslint-disable-line no-console
|
|
372
|
+
this.register(EXT_IDS.SERVER_SIDE_PAGINATION_RESOURCES, this.id, () => config);
|
|
373
|
+
}
|
|
374
|
+
|
|
351
375
|
public async onLogOut(store: any) {
|
|
352
376
|
await Promise.all(this.stores.map((s: any) => store.dispatch(`${ s.storeName }/onLogout`)));
|
|
353
377
|
|