@rancher/shell 0.1.4 → 0.1.21

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.
Files changed (152) hide show
  1. package/assets/brand/suse/favicon.png +0 -0
  2. package/assets/images/generic-plugin.svg +1 -7
  3. package/assets/translations/en-us.yaml +81 -47
  4. package/components/CommunityLinks.vue +40 -49
  5. package/components/ExplorerProjectsNamespaces.vue +20 -3
  6. package/components/LazyImage.vue +21 -8
  7. package/components/PromptRemove.vue +2 -2
  8. package/components/ResourceList/Masthead.vue +21 -1
  9. package/components/ResourceList/ResourceLoadingIndicator.vue +0 -8
  10. package/components/ResourceList/index.vue +9 -23
  11. package/components/SortableTable/index.vue +13 -10
  12. package/components/Tabbed/index.vue +25 -7
  13. package/components/TypeDescription.vue +10 -1
  14. package/components/fleet/FleetClusters.vue +6 -0
  15. package/components/fleet/FleetRepos.vue +7 -1
  16. package/components/form/Command.vue +5 -0
  17. package/components/form/EnvVars.vue +5 -0
  18. package/components/form/NameNsDescription.vue +3 -1
  19. package/components/form/NodeScheduling.vue +6 -1
  20. package/components/form/PodAffinity.vue +5 -0
  21. package/components/form/ServiceNameSelect.vue +5 -0
  22. package/components/form/ValueFromResource.vue +7 -1
  23. package/components/nav/TopLevelMenu.vue +2 -1
  24. package/config/home-links.js +155 -0
  25. package/config/private-label.js +1 -1
  26. package/config/product/manager.js +0 -2
  27. package/config/product/uiplugins.js +1 -1
  28. package/config/settings.js +3 -1
  29. package/config/uiplugins.js +63 -6
  30. package/config/version.js +17 -0
  31. package/core/plugin.ts +12 -0
  32. package/core/plugins.js +29 -5
  33. package/core/types.ts +6 -0
  34. package/creators/app/{.eslintignore → files/.eslintignore} +0 -0
  35. package/creators/app/{.eslintrc.js → files/.eslintrc.js} +0 -0
  36. package/creators/app/{.vscode → files/.vscode}/settings.json +0 -0
  37. package/creators/app/{babel.config.js → files/babel.config.js} +0 -0
  38. package/creators/app/{nuxt.config.js → files/nuxt.config.js} +0 -0
  39. package/creators/app/{tsconfig.json → files/tsconfig.json} +2 -1
  40. package/creators/app/init +16 -17
  41. package/creators/app/package.json +6 -0
  42. package/creators/pkg/{babel.config.js → files/babel.config.js} +0 -0
  43. package/creators/pkg/{index.ts → files/index.ts} +0 -0
  44. package/creators/pkg/{tsconfig.json → files/tsconfig.json} +13 -12
  45. package/creators/pkg/{vue.config.js → files/vue.config.js} +0 -0
  46. package/creators/pkg/init +1 -1
  47. package/creators/update/init +54 -0
  48. package/creators/update/package.json +20 -0
  49. package/creators/update/upgrade +56 -0
  50. package/creators/update/yarn-error.log +54 -0
  51. package/detail/workload/index.vue +1 -0
  52. package/edit/persistentvolume/index.vue +48 -13
  53. package/edit/persistentvolumeclaim.vue +31 -13
  54. package/edit/provisioning.cattle.io.cluster/rke2.vue +27 -19
  55. package/edit/workload/index.vue +19 -9
  56. package/edit/workload/mixins/workload.js +109 -114
  57. package/edit/workload/storage/index.vue +11 -17
  58. package/edit/workload/storage/persistentVolumeClaim/index.vue +5 -0
  59. package/edit/workload/storage/secret.vue +6 -1
  60. package/list/catalog.cattle.io.app.vue +10 -9
  61. package/list/catalog.cattle.io.clusterrepo.vue +6 -61
  62. package/list/cis.cattle.io.clusterscan.vue +12 -12
  63. package/list/fleet.cattle.io.bundle.vue +33 -28
  64. package/list/fleet.cattle.io.cluster.vue +26 -22
  65. package/list/fleet.cattle.io.clustergroup.vue +6 -0
  66. package/list/fleet.cattle.io.clusterregistrationtoken.vue +28 -24
  67. package/list/fleet.cattle.io.gitrepo.vue +25 -14
  68. package/list/helm.cattle.io.projecthelmchart.vue +52 -33
  69. package/list/logging.banzaicloud.io.clusterflow.vue +7 -12
  70. package/list/logging.banzaicloud.io.flow.vue +7 -14
  71. package/list/management.cattle.io.cluster.vue +26 -15
  72. package/list/management.cattle.io.feature.vue +13 -8
  73. package/list/management.cattle.io.user.vue +38 -19
  74. package/list/monitoring.coreos.com.alertmanagerconfig.vue +8 -15
  75. package/list/namespace.vue +14 -1
  76. package/list/node.vue +13 -16
  77. package/list/persistentvolume.vue +16 -9
  78. package/list/persistentvolumeclaim.vue +5 -8
  79. package/list/provisioning.cattle.io.cluster.vue +34 -8
  80. package/list/service.vue +24 -12
  81. package/list/ui.cattle.io.navlink.vue +6 -0
  82. package/list/workload.vue +2 -2
  83. package/middleware/authenticated.js +6 -0
  84. package/mixins/resource-fetch.js +12 -18
  85. package/mixins/resource-manager.js +126 -0
  86. package/models/catalog.cattle.io.uiplugin.js +4 -0
  87. package/models/pod.js +15 -5
  88. package/models/provisioning.cattle.io.cluster.js +4 -0
  89. package/models/workload.service.js +10 -0
  90. package/nuxt.config.js +2 -1
  91. package/package.json +1 -1
  92. package/pages/auth/login.vue +10 -0
  93. package/pages/auth/verify.vue +9 -0
  94. package/pages/c/_cluster/settings/DefaultLinksEditor.vue +108 -0
  95. package/pages/c/_cluster/settings/links.vue +53 -101
  96. package/pages/c/_cluster/settings/performance.vue +90 -7
  97. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +3 -3
  98. package/pages/c/_cluster/uiplugins/InstallDialog.vue +71 -20
  99. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +21 -5
  100. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +2 -7
  101. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +23 -15
  102. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +11 -4
  103. package/pages/c/_cluster/uiplugins/index.vue +179 -65
  104. package/pages/support/index.vue +31 -142
  105. package/plugins/dashboard-store/actions.js +19 -0
  106. package/plugins/dashboard-store/getters.js +20 -3
  107. package/plugins/dashboard-store/mutations.js +13 -7
  108. package/plugins/plugin.js +18 -15
  109. package/plugins/steve/getters.js +12 -0
  110. package/plugins/version.js +21 -0
  111. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +6 -7
  112. package/rancher-components/components/BadgeState/BadgeState.spec.ts +12 -0
  113. package/rancher-components/components/BadgeState/BadgeState.vue +107 -0
  114. package/rancher-components/components/BadgeState/index.ts +1 -0
  115. package/rancher-components/components/Banner/Banner.test.ts +13 -0
  116. package/rancher-components/components/Banner/Banner.vue +163 -0
  117. package/rancher-components/components/Banner/index.ts +1 -0
  118. package/rancher-components/components/Card/Card.vue +150 -0
  119. package/rancher-components/components/Card/index.ts +1 -0
  120. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +77 -0
  121. package/rancher-components/components/Form/Checkbox/Checkbox.vue +395 -0
  122. package/rancher-components/components/Form/Checkbox/index.ts +1 -0
  123. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +29 -0
  124. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +343 -0
  125. package/rancher-components/components/Form/LabeledInput/index.ts +1 -0
  126. package/rancher-components/components/Form/Radio/RadioButton.vue +270 -0
  127. package/rancher-components/components/Form/Radio/RadioGroup.vue +235 -0
  128. package/rancher-components/components/Form/Radio/index.ts +2 -0
  129. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +168 -0
  130. package/rancher-components/components/Form/TextArea/index.ts +1 -0
  131. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +107 -0
  132. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +137 -0
  133. package/rancher-components/components/Form/ToggleSwitch/index.ts +1 -0
  134. package/rancher-components/components/Form/index.ts +5 -0
  135. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +137 -0
  136. package/rancher-components/components/LabeledTooltip/index.ts +1 -0
  137. package/scripts/publish-shell.sh +39 -6
  138. package/scripts/record-deps.js +37 -0
  139. package/scripts/test-plugins-build.sh +8 -5
  140. package/scripts/typegen.sh +84 -0
  141. package/store/auth.js +3 -0
  142. package/store/index.js +12 -3
  143. package/types/shell/index.d.ts +3046 -0
  144. package/utils/favicon.js +8 -2
  145. package/utils/gc/gc-interval.ts +40 -0
  146. package/utils/gc/gc-root-store.js +76 -0
  147. package/utils/gc/gc-route-changed.ts +44 -0
  148. package/utils/gc/gc-types.ts +21 -0
  149. package/utils/gc/gc.ts +282 -0
  150. package/config/footer.js +0 -18
  151. package/creators/pkg/nuxt.config.js +0 -6
  152. package/yarn-error.log +0 -195
@@ -1,17 +1,13 @@
1
1
  <script>
2
- import { options } from '@shell/config/footer';
3
2
  import BannerGraphic from '@shell/components/BannerGraphic';
4
- import AsyncButton from '@shell/components/AsyncButton';
5
3
  import IndentedPanel from '@shell/components/IndentedPanel';
6
- import { Card } from '@components/Card';
7
4
  import CommunityLinks from '@shell/components/CommunityLinks';
8
5
  import { CATALOG, MANAGEMENT } from '@shell/config/types';
9
- import { getVendor, setBrand } from '@shell/config/private-label';
6
+ import { getVendor } from '@shell/config/private-label';
10
7
  import { SETTING } from '@shell/config/settings';
11
8
  import { findBy } from '@shell/utils/array';
12
9
  import { addParam } from '@shell/utils/url';
13
-
14
- const KEY_REGEX = /^[0-9a-fA-F]{16}$/;
10
+ import { isRancherPrime } from '@shell/config/version';
15
11
 
16
12
  export default {
17
13
  layout: 'home',
@@ -19,8 +15,6 @@ export default {
19
15
  components: {
20
16
  BannerGraphic,
21
17
  IndentedPanel,
22
- AsyncButton,
23
- Card,
24
18
  CommunityLinks
25
19
  },
26
20
 
@@ -50,7 +44,6 @@ export default {
50
44
  if ( this.$store.getters['management/canList'](CATALOG.APP) ) {
51
45
  this.apps = await this.$store.dispatch('management/findAll', { type: CATALOG.APP });
52
46
  }
53
- this.supportSetting = await fetchOrCreateSetting('has-support', 'false');
54
47
  this.brandSetting = await fetchOrCreateSetting(SETTING.BRAND, '');
55
48
  this.serverUrlSetting = await fetchOrCreateSetting(SETTING.SERVER_URL, '');
56
49
  this.uiIssuesSetting = await this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.ISSUES });
@@ -61,7 +54,6 @@ export default {
61
54
  apps: [],
62
55
  vendor: getVendor(),
63
56
  supportKey: '',
64
- supportSetting: null,
65
57
  brandSetting: null,
66
58
  uiIssuesSetting: null,
67
59
  serverSetting: null,
@@ -79,6 +71,10 @@ export default {
79
71
  return findBy(this.apps, 'metadata.name', 'rancher-csp-adapter' );
80
72
  },
81
73
 
74
+ hasSupport() {
75
+ return this.hasAWSSupport || isRancherPrime();
76
+ },
77
+
82
78
  hasAWSSupport() {
83
79
  return !!this.cspAdapter;
84
80
  },
@@ -101,74 +97,15 @@ export default {
101
97
  return `${ this.serverUrl }/v1/generateSUSERancherSupportConfig`;
102
98
  },
103
99
 
104
- hasSupport() {
105
- // NB: This is temporary until API implemented
106
- return false;
107
- },
108
-
109
- options() {
110
- if (!this.uiIssuesSetting?.value) {
111
- return;
112
- }
113
-
114
- // Load defaults for suppoet page
115
- return options(true, this.uiIssuesSetting?.value);
116
- },
117
-
118
100
  title() {
119
101
  return this.hasSupport ? 'support.suse.title' : 'support.community.title';
120
102
  },
121
103
 
122
- validSupportKey() {
123
- return !!this.supportKey.match(KEY_REGEX);
124
- },
125
-
126
104
  sccLink() {
127
105
  return this.hasAWSSupport ? addParam('https://scc.suse.com', 'from_marketplace', '1') : 'https://scc.suse.com';
128
106
  }
129
107
  },
130
108
 
131
- methods: {
132
- async addSubscription(done) {
133
- try {
134
- this.supportSetting.value = 'true';
135
- this.brandSetting.value = 'suse';
136
- await Promise.all([this.supportSetting.save(), this.brandSetting.save()]);
137
- setBrand('suse');
138
- done(true);
139
- this.$modal.hide('toggle-support');
140
- } catch {
141
- done(false);
142
- }
143
- },
144
-
145
- async removeSubscription(done) {
146
- try {
147
- this.supportSetting.value = 'false';
148
- this.brandSetting.value = '';
149
- await Promise.all([this.supportSetting.save(), this.brandSetting.save()]);
150
- setBrand('');
151
- done(true);
152
- this.$modal.hide('toggle-support');
153
- } catch {
154
- done(false);
155
- }
156
- },
157
-
158
- showDialog(isAdd) {
159
- this.isRemoveDialog = isAdd;
160
- this.supportKey = '';
161
- this.$modal.show('toggle-support');
162
- },
163
-
164
- dialogOpened() {
165
- const input = this.$refs.subscriptionIDInput;
166
-
167
- if (input) {
168
- input.focus();
169
- }
170
- },
171
- }
172
109
  };
173
110
  </script>
174
111
  <template>
@@ -177,10 +114,18 @@ export default {
177
114
 
178
115
  <IndentedPanel>
179
116
  <div class="content mt-20">
180
- <div class="promo">
117
+ <div class="promo col main-panel">
181
118
  <div class="box mb-20 box-primary">
182
119
  <h2>{{ t('support.suse.access.title') }}</h2>
183
- <div>
120
+ <div v-if="!hasSupport" class="external support-links mt-20">
121
+ <div class="support-link">
122
+ <a class="support-link" href="https://rancher.com/support-maintenance-terms" target="_blank" rel="noopener noreferrer nofollow">{{ t('support.community.learnMore') }}</a>
123
+ </div>
124
+ <div class="support-link">
125
+ <a class="support-link" href="https://rancher.com/pricing" target="_blank" rel="noopener noreferrer nofollow">{{ t('support.community.pricing') }}</a>
126
+ </div>
127
+ </div>
128
+ <div v-else>
184
129
  <p class="pb-10">
185
130
  {{ hasAWSSupport ? t("support.suse.access.aws.text") : t("support.suse.access.text") }}
186
131
  </p>
@@ -198,74 +143,28 @@ export default {
198
143
  <div>{{ t(`${key}.text`) }}</div>
199
144
  </div>
200
145
  </div>
201
-
202
- <div v-if="!hasSupport" class="register row">
203
- <div>
204
- {{ t('support.subscription.haveSupport') }}
205
- </div>
206
- <button class="ml-5 btn role-secondary btn-sm" type="button" @click="showDialog(false)">
207
- {{ t('support.subscription.addSubscription') }}
208
- </button>
209
- </div>
210
- <div v-if="hasSupport && !hasAWSSupport" class="register row">
211
- <a class="remove-link" @click="showDialog(true)">
212
- {{ t('support.subscription.removeSubscription') }}
213
- </a>
214
- </div>
215
- </div>
216
- <div class="community">
217
- <CommunityLinks :link-options="options">
218
- <div v-if="!hasSupport" class="external support-links" :class="{ 'mt-15': !!options}">
219
- <div class="support-link">
220
- <a class="support-link" href="https://rancher.com/support-maintenance-terms" target="_blank" rel="noopener noreferrer nofollow">{{ t('support.community.learnMore') }}</a>
221
- </div>
222
- <div class="support-link">
223
- <a class="support-link" href="https://rancher.com/pricing" target="_blank" rel="noopener noreferrer nofollow">{{ t('support.community.pricing') }}</a>
224
- </div>
225
- </div>
226
- </CommunityLinks>
227
146
  </div>
147
+ <CommunityLinks :is-support-page="true" class="community col side-panel span-3" />
228
148
  </div>
229
149
  </IndentedPanel>
230
- <modal
231
- name="toggle-support"
232
- height="auto"
233
- :width="340"
234
- @opened="dialogOpened"
235
- >
236
- <Card :show-highlight-border="false" class="toggle-support">
237
- <template #title>
238
- {{ isRemoveDialog? t('support.subscription.removeTitle') : t('support.subscription.addTitle') }}
239
- </template>
240
- <template #body>
241
- <div v-if="isRemoveDialog" class="mt-20">
242
- {{ t('support.subscription.removeBody') }}
243
- </div>
244
- <div v-else class="mt-20">
245
- <p class="pb-10">
246
- {{ t('support.subscription.addLabel') }}
247
- </p>
248
- <input ref="subscriptionIDInput" v-model="supportKey" />
249
- </div>
250
- </template>
251
- <template #actions>
252
- <button type="button" class="btn role-secondary" @click="$modal.hide('toggle-support')">
253
- {{ t('generic.cancel') }}
254
- </button>
255
- <AsyncButton v-if="!isRemoveDialog" :disabled="!validSupportKey" class="pull-right" @click="addSubscription" />
256
- <AsyncButton v-else :action-label="t('generic.remove')" class="pull-right" @click="removeSubscription" />
257
- </template>
258
- </Card>
259
- </modal>
260
150
  </div>
261
151
  </template>
262
152
  <style lang="scss" scoped>
263
153
  .content {
264
- display: grid;
265
- grid-column-gap: 20px;
266
- grid-row-gap: 20px;
267
- grid-template-columns: 70% 30%;
268
- }
154
+
155
+ display: flex;
156
+ align-items: stretch;
157
+ .col {
158
+ margin: 0
159
+ }
160
+ .main-panel {
161
+ flex: auto;
162
+ }
163
+
164
+ .side-panel {
165
+ margin-left: 1.75%;
166
+ }
167
+ }
269
168
 
270
169
  .toggle-support {
271
170
  height: 100%;
@@ -280,16 +179,6 @@ export default {
280
179
  }
281
180
  }
282
181
 
283
- .community {
284
- border-left: 1px solid var(--border);
285
- padding-left: 20px;
286
- > h2 {
287
- font-size: 18px;
288
- font-weight: 300;
289
- margin-bottom: 20px;
290
- }
291
- }
292
-
293
182
  .support-link:not(:first-child) {
294
183
  margin: 15px 0 0 0;
295
184
  }
@@ -5,6 +5,7 @@ import { SPOOFED_API_PREFIX, SPOOFED_PREFIX } from '@shell/store/type-map';
5
5
  import { createYaml } from '@shell/utils/create-yaml';
6
6
  import { classify } from '@shell/plugins/dashboard-store/classify';
7
7
  import { normalizeType } from './normalize';
8
+ import garbageCollect from '@shell/utils/gc/gc';
8
9
 
9
10
  export const _ALL = 'all';
10
11
  export const _MERGE = 'merge';
@@ -316,6 +317,8 @@ export default {
316
317
  dispatch('resource-fetch/updateManualRefreshIsLoading', false, { root: true });
317
318
  }
318
319
 
320
+ garbageCollect.gcUpdateLastAccessed(ctx, type);
321
+
319
322
  return all;
320
323
  },
321
324
 
@@ -371,6 +374,8 @@ export default {
371
374
  });
372
375
  }
373
376
 
377
+ garbageCollect.gcUpdateLastAccessed(ctx, type);
378
+
374
379
  return getters.matching( type, selector, namespace );
375
380
  },
376
381
 
@@ -426,6 +431,8 @@ export default {
426
431
 
427
432
  out = getters.byId(type, id);
428
433
 
434
+ garbageCollect.gcUpdateLastAccessed(ctx, type);
435
+
429
436
  return out;
430
437
  },
431
438
 
@@ -490,6 +497,10 @@ export default {
490
497
  return classify(ctx, data);
491
498
  },
492
499
 
500
+ createMany(ctx, data) {
501
+ return data.map(d => classify(ctx, d));
502
+ },
503
+
493
504
  createPopulated(ctx, userData) {
494
505
  const data = ctx.getters['defaultFor'](userData.type);
495
506
 
@@ -587,5 +598,13 @@ export default {
587
598
 
588
599
  incrementLoadCounter({ commit }, resource) {
589
600
  commit('incrementLoadCounter', resource);
601
+ },
602
+
603
+ garbageCollect(ctx, ignoreTypes) {
604
+ return garbageCollect.garbageCollect(ctx, ignoreTypes);
605
+ },
606
+
607
+ gcResetStore({ state }) {
608
+ garbageCollect.gcResetStore(state);
590
609
  }
591
610
  };
@@ -9,10 +9,11 @@ import Resource from '@shell/plugins/dashboard-store/resource-class';
9
9
  import mutations from './mutations';
10
10
  import { keyFieldFor, normalizeType } from './normalize';
11
11
  import { lookup } from './model-loader';
12
+ import garbageCollect from '@shell/utils/gc/gc';
12
13
 
13
14
  export default {
14
15
 
15
- all: (state, getters) => (type) => {
16
+ all: (state, getters, rootState) => (type) => {
16
17
  type = getters.normalizeType(type);
17
18
 
18
19
  if ( !getters.typeRegistered(type) ) {
@@ -22,10 +23,14 @@ export default {
22
23
  mutations.registerType(state, type);
23
24
  }
24
25
 
26
+ garbageCollect.gcUpdateLastAccessed({
27
+ state, getters, rootState
28
+ }, type);
29
+
25
30
  return state.types[type].list;
26
31
  },
27
32
 
28
- matching: (state, getters) => (type, selector, namespace) => {
33
+ matching: (state, getters, rootState) => (type, selector, namespace) => {
29
34
  let all = getters['all'](type);
30
35
 
31
36
  // Filter first by namespace if one is provided, since this is efficient
@@ -33,16 +38,24 @@ export default {
33
38
  all = all.filter(obj => obj.namespace === namespace);
34
39
  }
35
40
 
41
+ garbageCollect.gcUpdateLastAccessed({
42
+ state, getters, rootState
43
+ }, type);
44
+
36
45
  return all.filter((obj) => {
37
46
  return matches(obj, selector);
38
47
  });
39
48
  },
40
49
 
41
- byId: (state, getters) => (type, id) => {
50
+ byId: (state, getters, rootState) => (type, id) => {
42
51
  type = getters.normalizeType(type);
43
52
  const entry = state.types[type];
44
53
 
45
54
  if ( entry ) {
55
+ garbageCollect.gcUpdateLastAccessed({
56
+ state, getters, rootState
57
+ }, type);
58
+
46
59
  return entry.map.get(id);
47
60
  }
48
61
  },
@@ -300,5 +313,9 @@ export default {
300
313
  }
301
314
 
302
315
  return 0;
316
+ },
317
+
318
+ gcIgnoreTypes: () => {
319
+ return {};
303
320
  }
304
321
  };
@@ -3,18 +3,19 @@ import { addObject, addObjects, clear, removeObject } from '@shell/utils/array';
3
3
  import { SCHEMA } from '@shell/config/types';
4
4
  import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
5
5
  import { classify } from '@shell/plugins/dashboard-store/classify';
6
+ import garbageCollect from '@shell/utils/gc/gc';
6
7
 
7
8
  function registerType(state, type) {
8
9
  let cache = state.types[type];
9
10
 
10
11
  if ( !cache ) {
11
12
  cache = {
12
- list: [],
13
- haveAll: false,
14
- haveSelector: {},
15
- revision: 0, // The highest known resourceVersion from the server for this type
16
- generation: 0, // Updated every time something is loaded for this type
17
- loadCounter: 0, // Used to cancel incremental loads if the page changes during load
13
+ list: [],
14
+ haveAll: false,
15
+ haveSelector: {},
16
+ revision: 0, // The highest known resourceVersion from the server for this type
17
+ generation: 0, // Updated every time something is loaded for this type
18
+ loadCounter: 0, // Used to cancel incremental loads if the page changes during load
18
19
  };
19
20
 
20
21
  // Not enumerable so they don't get sent back to the client for SSR
@@ -120,6 +121,8 @@ export function forgetType(state, type) {
120
121
  cache.map.clear();
121
122
  delete state.types[type];
122
123
 
124
+ garbageCollect.gcResetType(state, type);
125
+
123
126
  return true;
124
127
  }
125
128
  }
@@ -131,6 +134,8 @@ export function resetStore(state, commit) {
131
134
  for ( const type of Object.keys(state.types) ) {
132
135
  commit(`${ state.config.namespace }/forgetType`, type);
133
136
  }
137
+
138
+ garbageCollect.gcResetStore(state);
134
139
  }
135
140
 
136
141
  export function remove(state, obj, getters) {
@@ -308,5 +313,6 @@ export default {
308
313
  if (typeData) {
309
314
  typeData.loadCounter++;
310
315
  }
311
- }
316
+ },
317
+
312
318
  };
package/plugins/plugin.js CHANGED
@@ -1,10 +1,10 @@
1
1
  // This plugin loads any UI Plugins at app load time
2
2
  import { allHashSettled } from '@shell/utils/promise';
3
- import { shouldLoadPlugin, UI_PLUGIN_BASE_URL } from '@shell/config/uiplugins';
3
+ import { shouldNotLoadPlugin, UI_PLUGIN_BASE_URL } from '@shell/config/uiplugins';
4
4
 
5
5
  const META_NAME_PREFIX = 'app-autoload-';
6
6
 
7
- export default async(context) => {
7
+ export default async function(context) {
8
8
  // UI Plugins declared in the HTML head
9
9
  const meta = context.app?.head?.meta || [];
10
10
  const hash = {};
@@ -28,27 +28,28 @@ export default async(context) => {
28
28
  }
29
29
 
30
30
  if (loadPlugins) {
31
- const { store, $plugin } = context;
31
+ // TODO: Get rancher version using the new API (can't use setting as we have not loading the store)
32
+ const rancherVersion = undefined;
32
33
 
33
34
  // Fetch list of installed plugins from endpoint
34
35
  try {
35
- const res = await store.dispatch('management/request', {
36
- url: `${ UI_PLUGIN_BASE_URL }/index.json`,
37
- headers: { accept: 'application/json' }
36
+ const res = await context.store.dispatch('management/request', {
37
+ url: `${ UI_PLUGIN_BASE_URL }/index.json`,
38
+ method: 'GET',
39
+ headers: { accept: 'application/json' },
40
+ redirectUnauthorized: false,
38
41
  });
39
42
 
40
43
  if (res) {
41
44
  const entries = res.entries || res.Entries || {};
42
45
 
43
46
  Object.values(entries).forEach((plugin) => {
44
- if (shouldLoadPlugin(plugin)) {
45
- let url;
47
+ const shouldNotLoad = shouldNotLoadPlugin(plugin, rancherVersion); // Error key string or false
46
48
 
47
- if (plugin?.metadata?.['direct'] === 'true') {
48
- url = plugin.endpoint;
49
- }
50
-
51
- hash[plugin.name] = $plugin.loadAsyncByNameAndVersion(plugin.name, plugin.version, url);
49
+ if (!shouldNotLoad) {
50
+ hash[plugin.name] = context.$plugin.loadPluginAsync(plugin);
51
+ } else {
52
+ context.store.dispatch('uiplugins/setError', { name: plugin.name, error: shouldNotLoad });
52
53
  }
53
54
  });
54
55
  }
@@ -67,8 +68,10 @@ export default async(context) => {
67
68
  console.error(`Failed to load plugin: ${ name }`); // eslint-disable-line no-console
68
69
 
69
70
  // Record error in the uiplugins store, so that we can show this to the user
70
- context.store.dispatch('uiplugins/setError', { name, error: true });
71
+ context.store.dispatch('uiplugins/setError', { name, error: 'plugins.error.load' });
71
72
  }
72
73
  });
73
74
  }
74
- };
75
+
76
+ return true;
77
+ }
@@ -1,6 +1,7 @@
1
1
  import { isArray } from '@shell/utils/array';
2
2
  import { BY_TYPE } from '@shell/plugins/dashboard-store/classify';
3
3
  import { lookup } from '@shell/plugins/dashboard-store/model-loader';
4
+ import { NAMESPACE, SCHEMA, COUNT, UI } from '@shell/config/types';
4
5
 
5
6
  import SteveModel from './steve-class';
6
7
  import HybridModel, { cleanHybridResources } from './hybrid-class';
@@ -12,6 +13,13 @@ export const STEVE_MODEL_TYPES = {
12
13
  BY_TYPE: 'byType'
13
14
  };
14
15
 
16
+ const GC_IGNORE_TYPES = {
17
+ [COUNT]: true,
18
+ [NAMESPACE]: true,
19
+ [SCHEMA]: true,
20
+ [UI.NAV_LINK]: true,
21
+ };
22
+
15
23
  export default {
16
24
  urlOptions: () => (url, opt) => {
17
25
  opt = opt || {};
@@ -110,4 +118,8 @@ export default {
110
118
  return map?.list || [];
111
119
  },
112
120
 
121
+ gcIgnoreTypes: () => {
122
+ return GC_IGNORE_TYPES;
123
+ }
124
+
113
125
  };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Fetch version metadata from backend /rancherversion API and store it
3
+ *
4
+ * This metadata does not change for an installation of Rancher
5
+ */
6
+
7
+ import { setVersionData } from '@shell/config/version';
8
+
9
+ export default async function({ store }) {
10
+ try {
11
+ const response = await store.dispatch('rancher/request', {
12
+ url: '/rancherversion',
13
+ method: 'get',
14
+ redirectUnauthorized: false
15
+ });
16
+
17
+ setVersionData(response);
18
+ } catch (e) {
19
+ console.warn('Failed to fetch Rancher version metadata', e); // eslint-disable-line no-console
20
+ }
21
+ }
@@ -1,16 +1,15 @@
1
1
  <script lang="ts">
2
- import Vue from 'vue';
2
+ import Vue, { VueConstructor } from 'vue';
3
3
  import debounce from 'lodash/debounce';
4
4
  import { _EDIT, _VIEW } from '@shell/config/query-params';
5
5
 
6
- declare module 'vue/types/vue' {
7
- /* eslint-disable no-unused-vars */
8
- interface Vue {
9
- queueResize(): void;
10
- }
6
+ interface TextAreaResize {
7
+ queueResize(): void;
11
8
  }
12
9
 
13
- export default Vue.extend({
10
+ export default (
11
+ Vue as VueConstructor<Vue & TextAreaResize>
12
+ ).extend({
14
13
  inheritAttrs: false,
15
14
 
16
15
  props: {
@@ -0,0 +1,12 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import { BadgeState } from './index';
3
+
4
+ describe('BadgeState.vue', () => {
5
+ it('renders props.msg when passed', () => {
6
+ const label = 'Hello, World!';
7
+
8
+ const wrapper = shallowMount(BadgeState, { propsData: { label } });
9
+
10
+ expect(wrapper.find('span').text()).toMatch(label);
11
+ });
12
+ });
@@ -0,0 +1,107 @@
1
+ <script lang="ts">
2
+ import Vue, { PropType } from 'vue';
3
+
4
+ interface Badge {
5
+ stateBackground: string;
6
+ stateDisplay: string;
7
+ }
8
+
9
+ /**
10
+ * Badge state component.
11
+ * <p>Represents a badge whose label and color is either taken from the value property or
12
+ * from the label and color properties. The state property takes precedence.</p>
13
+ */
14
+ export default Vue.extend({
15
+ props: {
16
+ /**
17
+ * A value having the properties `stateBackground` and `stateDisplay`
18
+ */
19
+ value: {
20
+ type: Object as PropType<Badge>,
21
+ default: null
22
+ },
23
+
24
+ /**
25
+ * Badge color. `stateBackground` of the value property takes precedence if supplied
26
+ */
27
+ color: {
28
+ type: String,
29
+ default: null
30
+ },
31
+
32
+ /**
33
+ * Optional icon to be shown before the label
34
+ */
35
+ icon: {
36
+ type: String,
37
+ default: null
38
+ },
39
+
40
+ /**
41
+ * Label to display in the badge. `stateDisplay` of the value property takes precedence if supplied
42
+ */
43
+ label: {
44
+ type: String,
45
+ default: null
46
+ }
47
+ },
48
+
49
+ computed: {
50
+ bg(): string | null {
51
+ return this.value?.stateBackground || this.color;
52
+ },
53
+
54
+ msg(): string | null {
55
+ return this.value?.stateDisplay || this.label;
56
+ }
57
+ }
58
+ });
59
+ </script>
60
+
61
+ <template>
62
+ <span :class="{'badge-state': true, [bg]: true}">
63
+ <i v-if="icon" class="icon" :class="{[icon]: true, 'mr-5': !!msg}" />{{ msg }}
64
+ </span>
65
+ </template>
66
+
67
+ <style lang="scss" scoped>
68
+ .badge-state {
69
+ align-items: center;
70
+ display: inline-flex;
71
+ padding: 2px 10px;
72
+ border: 1px solid transparent;
73
+ border-radius: 20px;
74
+
75
+ &.bg-info {
76
+ border-color: var(--primary);
77
+ }
78
+
79
+ &.bg-error {
80
+ border-color: var(--error);
81
+ }
82
+
83
+ &.bg-warning {
84
+ border-color: var(--warning);
85
+ }
86
+
87
+ // Successful states are de-emphasized by using [text-]color instead of background-color
88
+ &.bg-success {
89
+ color: var(--success);
90
+ background: transparent;
91
+ border-color: var(--success);
92
+ }
93
+ }
94
+ </style>
95
+ <style lang="scss">
96
+ // TODO: #6005
97
+ // Investigate why this is here.. I don't think that styles for sortable table should belong here
98
+ .sortable-table TD .badge-state {
99
+ @include clip;
100
+ display: inline-block;
101
+ max-width: 100%;
102
+ position: relative;
103
+ max-width: 110px;
104
+ font-size: .85em;
105
+ vertical-align: middle;
106
+ }
107
+ </style>