@rancher/shell 0.1.3 → 0.1.4

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 (131) hide show
  1. package/assets/brand/suse/dark/rancher-logo.svg +1 -148
  2. package/assets/brand/suse/rancher-logo.svg +1 -130
  3. package/assets/images/featured/img1.jpg +0 -0
  4. package/assets/images/featured.jpg +0 -0
  5. package/assets/images/generic-plugin.svg +7 -0
  6. package/assets/styles/themes/_dark.scss +3 -0
  7. package/assets/styles/themes/_light.scss +3 -0
  8. package/assets/styles/themes/_suse.scss +1 -1
  9. package/assets/translations/en-us.yaml +183 -45
  10. package/assets/translations/zh-hans.yaml +21 -24
  11. package/components/AsyncButton.vue +17 -2
  12. package/components/ButtonDropdown.vue +4 -0
  13. package/components/Carousel.vue +291 -0
  14. package/components/CommunityLinks.vue +69 -18
  15. package/components/CruResource.vue +11 -3
  16. package/components/Dialog.vue +102 -0
  17. package/components/ExplorerMembers.vue +2 -4
  18. package/components/ExplorerProjectsNamespaces.vue +6 -7
  19. package/components/IconMessage.vue +9 -1
  20. package/components/LocaleSelector.vue +62 -29
  21. package/components/ResourceTable.vue +7 -2
  22. package/components/SimpleBox.vue +6 -4
  23. package/components/SortableTable/index.vue +11 -21
  24. package/components/Tabbed/Tab.vue +5 -0
  25. package/components/Tabbed/index.vue +29 -2
  26. package/components/auth/Principal.vue +1 -0
  27. package/components/fleet/FleetBundles.vue +8 -3
  28. package/components/fleet/FleetSummary.vue +6 -0
  29. package/components/form/KeyValue.vue +80 -58
  30. package/components/form/NameNsDescription.vue +10 -4
  31. package/components/form/ResourceTabs/index.vue +5 -1
  32. package/components/formatter/ClusterLink.vue +3 -7
  33. package/components/nav/NamespaceFilter.vue +3 -3
  34. package/components/nav/TopLevelMenu.vue +10 -28
  35. package/config/footer.js +13 -14
  36. package/config/labels-annotations.js +2 -1
  37. package/config/product/explorer.js +5 -4
  38. package/config/product/legacy.js +0 -47
  39. package/config/product/multi-cluster-apps.js +0 -12
  40. package/config/product/settings.js +12 -1
  41. package/config/product/uiplugins.js +17 -0
  42. package/config/settings.js +21 -2
  43. package/config/types.js +5 -1
  44. package/config/uiplugins.js +60 -0
  45. package/content/docs/en-us/getting-started.md +1 -26
  46. package/core/plugins.js +12 -0
  47. package/detail/provisioning.cattle.io.cluster.vue +3 -3
  48. package/detail/workload/index.vue +2 -2
  49. package/dialog/DiagnosticTimingsDialog.vue +116 -0
  50. package/dialog/RotateCertificatesDialog.vue +9 -3
  51. package/edit/auth/azuread.vue +28 -9
  52. package/edit/networking.k8s.io.ingress/index.vue +2 -2
  53. package/edit/persistentvolume/index.vue +3 -0
  54. package/edit/pod.vue +27 -0
  55. package/edit/provisioning.cattle.io.cluster/rke2.vue +76 -5
  56. package/edit/service.vue +7 -5
  57. package/edit/workload/__tests__/Upgrading.test.ts +1 -0
  58. package/edit/workload/index.vue +13 -1
  59. package/edit/workload/mixins/workload.js +13 -13
  60. package/edit/workload/storage/ContainerMountPaths.vue +240 -0
  61. package/edit/workload/storage/Mount.vue +1 -0
  62. package/edit/workload/storage/awsElasticBlockStore.vue +20 -1
  63. package/edit/workload/storage/azureDisk.vue +22 -2
  64. package/edit/workload/storage/azureFile.vue +20 -2
  65. package/edit/workload/storage/csi/index.vue +23 -1
  66. package/edit/workload/storage/gcePersistentDisk.vue +20 -2
  67. package/edit/workload/storage/index.vue +23 -49
  68. package/edit/workload/storage/vsphereVolume.vue +11 -1
  69. package/layouts/default.vue +14 -8
  70. package/layouts/home.vue +9 -4
  71. package/layouts/plain.vue +10 -5
  72. package/list/management.cattle.io.setting.vue +3 -3
  73. package/list/provisioning.cattle.io.cluster.vue +1 -1
  74. package/machine-config/harvester.vue +5 -3
  75. package/models/catalog.cattle.io.uiplugin.js +34 -0
  76. package/models/cluster/node.js +25 -2
  77. package/models/fleet.cattle.io.bundle.js +1 -1
  78. package/models/harvesterhci.io.management.cluster.js +11 -5
  79. package/models/provisioning.cattle.io.cluster.js +12 -6
  80. package/models/workload.js +5 -3
  81. package/nuxt.config.js +69 -25
  82. package/package.json +108 -109
  83. package/pages/auth/login.vue +1 -1
  84. package/pages/c/_cluster/apps/charts/index.vue +46 -1
  85. package/pages/c/_cluster/apps/charts/install.vue +10 -9
  86. package/pages/c/_cluster/explorer/index.vue +72 -9
  87. package/pages/c/_cluster/explorer/tools/index.vue +12 -5
  88. package/pages/c/_cluster/mcapps/index.vue +1 -1
  89. package/pages/c/_cluster/settings/brand.vue +0 -40
  90. package/pages/c/_cluster/settings/links.vue +200 -0
  91. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +232 -0
  92. package/pages/c/_cluster/uiplugins/InstallDialog.vue +242 -0
  93. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +284 -0
  94. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +130 -0
  95. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +253 -0
  96. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +115 -0
  97. package/pages/c/_cluster/uiplugins/index.vue +694 -0
  98. package/pages/diagnostic.vue +185 -101
  99. package/pages/docs/_doc.vue +3 -1
  100. package/pages/home.vue +21 -56
  101. package/pages/prefs.vue +108 -88
  102. package/pages/safeMode.vue +17 -0
  103. package/pages/support/index.vue +23 -15
  104. package/pkg/dynamic-importer.lib.js +4 -0
  105. package/plugins/dashboard-store/resource-class.js +2 -2
  106. package/plugins/formatters.js +15 -0
  107. package/plugins/plugin.js +56 -4
  108. package/plugins/steve/mutations.js +1 -1
  109. package/plugins/steve/subscribe.js +94 -72
  110. package/plugins/steve/web-worker.steve-sub-worker.js +24 -15
  111. package/promptRemove/management.cattle.io.globalrole.vue +47 -0
  112. package/promptRemove/management.cattle.io.roletemplate.vue +47 -0
  113. package/promptRemove/mixin/roleDeletionCheck.js +97 -0
  114. package/scripts/publish-shell.sh +1 -1
  115. package/scripts/sync-shell-deps +37 -0
  116. package/store/catalog.js +9 -8
  117. package/store/i18n.js +10 -1
  118. package/store/prefs.js +16 -0
  119. package/store/type-map.js +32 -5
  120. package/store/uiplugins.ts +15 -61
  121. package/utils/__tests__/object.test.ts +0 -24
  122. package/utils/__tests__/selector.test.ts +1 -1
  123. package/utils/dynamic-importer.js +4 -0
  124. package/utils/grafana.js +2 -6
  125. package/utils/socket.js +41 -20
  126. package/utils/string.js +1 -7
  127. package/utils/validators/formRules/__tests__/index.test.ts +108 -0
  128. package/utils/validators/formRules/index.ts +9 -1
  129. package/yarn-error.log +195 -0
  130. package/pages/plugins.vue +0 -387
  131. package/server/verdaccio-middleware.js +0 -56
package/pages/prefs.vue CHANGED
@@ -1,32 +1,41 @@
1
1
  <script>
2
2
  import day from 'dayjs';
3
3
  import { mapGetters } from 'vuex';
4
+ import { isAdminUser } from '@shell/store/type-map';
4
5
  import BackLink from '@shell/components/BackLink';
5
6
  import BackRoute from '@shell/mixins/back-link';
6
7
  import ButtonGroup from '@shell/components/ButtonGroup';
7
8
  import { Checkbox } from '@components/Form/Checkbox';
8
9
  import LandingPagePreference from '@shell/components/LandingPagePreference';
9
10
  import {
10
- mapPref, THEME, KEYMAP, DEV, DATE_FORMAT, TIME_FORMAT, ROWS_PER_PAGE, HIDE_DESC, SHOW_PRE_RELEASE, MENU_MAX_CLUSTERS
11
+ mapPref, THEME, KEYMAP, DATE_FORMAT, TIME_FORMAT, ROWS_PER_PAGE, HIDE_DESC, SHOW_PRE_RELEASE, MENU_MAX_CLUSTERS,
12
+ VIEW_IN_API, ALL_NAMESPACES, THEME_SHORTCUT, PLUGIN_DEVELOPER
11
13
  } from '@shell/store/prefs';
12
14
  import LabeledSelect from '@shell/components/form/LabeledSelect';
13
15
  import { addObject } from '@shell/utils/array';
16
+ import LocaleSelector from '@shell/components/LocaleSelector';
14
17
 
15
18
  export default {
16
19
  layout: 'plain',
17
20
  components: {
18
- BackLink, ButtonGroup, LabeledSelect, Checkbox, LandingPagePreference
21
+ BackLink, ButtonGroup, LabeledSelect, Checkbox, LandingPagePreference, LocaleSelector
19
22
  },
20
- mixins: [BackRoute],
21
- computed: {
22
- keymap: mapPref(KEYMAP),
23
- dev: mapPref(DEV),
24
- dateFormat: mapPref(DATE_FORMAT),
25
- timeFormat: mapPref(TIME_FORMAT),
26
- perPage: mapPref(ROWS_PER_PAGE),
27
- hideDesc: mapPref(HIDE_DESC),
28
- showPreRelease: mapPref(SHOW_PRE_RELEASE),
29
- menuMaxClusters: mapPref(MENU_MAX_CLUSTERS),
23
+ mixins: [BackRoute],
24
+ data() {
25
+ return { admin: isAdminUser(this.$store.getters) };
26
+ },
27
+ computed: {
28
+ keymap: mapPref(KEYMAP),
29
+ viewInApi: mapPref(VIEW_IN_API),
30
+ allNamespaces: mapPref(ALL_NAMESPACES),
31
+ themeShortcut: mapPref(THEME_SHORTCUT),
32
+ dateFormat: mapPref(DATE_FORMAT),
33
+ timeFormat: mapPref(TIME_FORMAT),
34
+ perPage: mapPref(ROWS_PER_PAGE),
35
+ hideDesc: mapPref(HIDE_DESC),
36
+ showPreRelease: mapPref(SHOW_PRE_RELEASE),
37
+ menuMaxClusters: mapPref(MENU_MAX_CLUSTERS),
38
+ pluginDeveloper: mapPref(PLUGIN_DEVELOPER),
30
39
 
31
40
  ...mapGetters(['isSingleProduct']),
32
41
 
@@ -137,101 +146,112 @@ export default {
137
146
  this.hideDesc = val;
138
147
  }
139
148
  },
140
- },
149
+ }
141
150
  };
142
151
  </script>
143
152
 
144
153
  <template>
145
154
  <div>
146
155
  <BackLink :link="backLink" />
147
- <h1 v-t="'prefs.title'" />
148
-
149
- <h4 v-t="'prefs.theme.label'" />
150
- <div>
151
- <ButtonGroup v-model="theme" :options="themeOptions" />
156
+ <h1 v-t="'prefs.title'" class="mb-20" />
157
+ <!-- Language -->
158
+ <div class="mt-10 mb-10">
159
+ <h4 v-t="'prefs.language'" />
160
+ <div class="row">
161
+ <div class="col span-4">
162
+ <LocaleSelector />
163
+ </div>
164
+ </div>
152
165
  </div>
153
- <div class="mt-10">
154
- <t k="prefs.theme.autoDetail" :pm="pm" :am="am" />
166
+ <!-- Theme -->
167
+ <div class="mt-10 mb-10">
168
+ <hr />
169
+ <h4 v-t="'prefs.theme.label'" />
170
+ <ButtonGroup v-model="theme" :options="themeOptions" />
171
+ <div class="mt-10">
172
+ <t k="prefs.theme.autoDetail" :pm="pm" :am="am" />
173
+ </div>
155
174
  </div>
156
- <div v-if="!isSingleProduct">
175
+ <!-- Login landing page -->
176
+ <div v-if="!isSingleProduct" class="mt-10 mb-10">
157
177
  <hr />
158
178
  <h4 v-t="'prefs.landing.label'" />
159
179
  <LandingPagePreference />
160
180
  </div>
161
- <hr />
162
- <h4 v-t="'prefs.displaySettings.title'" />
163
- <p class="set-landing-leadin">
164
- {{ t('prefs.displaySettings.detail', {}, raw=true) }}
165
- </p>
166
- <div class="row mt-20">
167
- <div class="col span-4">
168
- <LabeledSelect
169
- v-model="dateFormat"
170
- :label="t('prefs.dateFormat.label')"
171
- :options="dateOptions"
172
- />
173
- </div>
174
- <div class="col span-4">
175
- <LabeledSelect
176
- v-model="timeFormat"
177
- :label="t('prefs.timeFormat.label')"
178
- :options="timeOptions"
179
- />
181
+ <!-- Display Settings -->
182
+ <div class="mt-10 mb-10">
183
+ <hr />
184
+ <h4 v-t="'prefs.displaySettings.title'" />
185
+ <p class="set-landing-leadin">
186
+ {{ t('prefs.displaySettings.detail', {}, raw=true) }}
187
+ </p>
188
+ <div class="row mt-20">
189
+ <div class="col span-4">
190
+ <LabeledSelect
191
+ v-model="dateFormat"
192
+ :label="t('prefs.dateFormat.label')"
193
+ :options="dateOptions"
194
+ />
195
+ </div>
196
+ <div class="col span-4">
197
+ <LabeledSelect
198
+ v-model="timeFormat"
199
+ :label="t('prefs.timeFormat.label')"
200
+ :options="timeOptions"
201
+ />
202
+ </div>
180
203
  </div>
181
- </div>
182
204
 
183
- <div class="row mt-20">
184
- <div class="col span-4">
185
- <LabeledSelect
186
- v-model.number="perPage"
187
- :label="t('prefs.perPage.label')"
188
- :options="perPageOptions"
189
- option-key="value"
190
- option-label="label"
191
- placeholder="Select a row count"
192
- />
193
- </div>
194
- <div class="col span-4">
195
- <LabeledSelect
196
- v-model.number="menuMaxClusters"
197
- :label="t('prefs.clusterToShow.label')"
198
- :options="menuClusterOptions"
199
- option-key="value"
200
- option-label="label"
201
- placeholder="Select a row count"
202
- />
205
+ <div class="row mt-20">
206
+ <div class="col span-4">
207
+ <LabeledSelect
208
+ v-model.number="perPage"
209
+ :label="t('prefs.perPage.label')"
210
+ :options="perPageOptions"
211
+ option-key="value"
212
+ option-label="label"
213
+ placeholder="Select a row count"
214
+ />
215
+ </div>
216
+ <div class="col span-4">
217
+ <LabeledSelect
218
+ v-model.number="menuMaxClusters"
219
+ :label="t('prefs.clusterToShow.label')"
220
+ :options="menuClusterOptions"
221
+ option-key="value"
222
+ option-label="label"
223
+ placeholder="Select a row count"
224
+ />
225
+ </div>
203
226
  </div>
204
227
  </div>
205
-
206
- <hr />
207
- <div class="row">
208
- <div class="col prefs-advanced">
209
- <h4 v-t="'prefs.advanced'" />
210
- <Checkbox v-model="dev" :label="t('prefs.dev.label', {}, true)" />
211
- <p class="wrap-text">
212
- {{ t('prefs.advancedTooltip') }}
213
- </p>
214
- <br>
215
- <Checkbox v-if="!isSingleProduct" v-model="hideDescriptions" :label="t('prefs.hideDesc.label')" class="mt-10" />
216
- </div>
228
+ <!-- Advanced Features -->
229
+ <div class="col adv-features mt-10 mb-10">
230
+ <hr />
231
+ <h4 v-t="'prefs.advFeatures.title'" />
232
+ <Checkbox v-model="viewInApi" :label="t('prefs.advFeatures.viewInApi', {}, true)" class="mt-10" />
233
+ <br />
234
+ <Checkbox v-model="allNamespaces" :label="t('prefs.advFeatures.allNamespaces', {}, true)" class="mt-20" />
235
+ <br />
236
+ <Checkbox v-model="themeShortcut" :label="t('prefs.advFeatures.themeShortcut', {}, true)" class="mt-20" />
237
+ <br />
238
+ <Checkbox v-if="!isSingleProduct" v-model="hideDescriptions" :label="t('prefs.hideDesc.label')" class="mt-20" />
239
+ <template v-if="admin">
240
+ <br />
241
+ <Checkbox v-model="pluginDeveloper" :label="t('prefs.advFeatures.pluginDeveloper', {}, true)" class="mt-20" />
242
+ </template>
217
243
  </div>
218
-
219
- <hr />
220
- <div class="row">
221
- <div class="col span-12">
222
- <h4 v-t="'prefs.keymap.label'" />
223
- <ButtonGroup v-model="keymap" :options="keymapOptions" />
224
- </div>
244
+ <!-- YAML editor key mapping -->
245
+ <div class="col mt-10 mb-10">
246
+ <hr />
247
+ <h4 v-t="'prefs.keymap.label'" />
248
+ <ButtonGroup v-model="keymap" :options="keymapOptions" />
225
249
  </div>
226
-
227
- <div v-if="!isSingleProduct">
250
+ <!-- Helm Charts -->
251
+ <div v-if="!isSingleProduct" class="col mt-10 mb-40">
228
252
  <hr />
229
- <div class="row mb-20">
230
- <div class="col span-12">
231
- <h4 v-t="'prefs.helm.label'" />
232
- <ButtonGroup v-model="showPreRelease" :options="helmOptions" />
233
- </div>
234
- </div>
253
+ <h4 v-t="'prefs.helm.label'" />
254
+ <ButtonGroup v-model="showPreRelease" :options="helmOptions" />
235
255
  </div>
236
256
  </div>
237
257
  </template>
@@ -0,0 +1,17 @@
1
+ <script>
2
+ export default {
3
+ middleware({ redirect, store } ) {
4
+ const dashboardHome = { name: 'home' };
5
+ const t = store.getters['i18n/t'];
6
+
7
+ setTimeout(() => {
8
+ store.dispatch('growl/success', {
9
+ title: t('plugins.safeMode.title'),
10
+ message: t('plugins.safeMode.message')
11
+ }, { root: true });
12
+ }, 1000);
13
+
14
+ return redirect(dashboardHome);
15
+ }
16
+ };
17
+ </script>
@@ -52,7 +52,6 @@ export default {
52
52
  }
53
53
  this.supportSetting = await fetchOrCreateSetting('has-support', 'false');
54
54
  this.brandSetting = await fetchOrCreateSetting(SETTING.BRAND, '');
55
- this.communitySetting = await fetchOrCreateSetting(SETTING.COMMUNITY_LINKS, 'true');
56
55
  this.serverUrlSetting = await fetchOrCreateSetting(SETTING.SERVER_URL, '');
57
56
  this.uiIssuesSetting = await this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.ISSUES });
58
57
  },
@@ -65,7 +64,6 @@ export default {
65
64
  supportSetting: null,
66
65
  brandSetting: null,
67
66
  uiIssuesSetting: null,
68
- communitySetting: null,
69
67
  serverSetting: null,
70
68
  promos: [
71
69
  'support.promos.one',
@@ -104,11 +102,17 @@ export default {
104
102
  },
105
103
 
106
104
  hasSupport() {
107
- return (this.supportSetting?.value && this.supportSetting?.value !== 'false') || this.hasAWSSupport;
105
+ // NB: This is temporary until API implemented
106
+ return false;
108
107
  },
109
108
 
110
109
  options() {
111
- return options( this.uiIssuesSetting?.value, this.communitySetting?.value === 'false');
110
+ if (!this.uiIssuesSetting?.value) {
111
+ return;
112
+ }
113
+
114
+ // Load defaults for suppoet page
115
+ return options(true, this.uiIssuesSetting?.value);
112
116
  },
113
117
 
114
118
  title() {
@@ -194,11 +198,7 @@ export default {
194
198
  <div>{{ t(`${key}.text`) }}</div>
195
199
  </div>
196
200
  </div>
197
- <div v-if="!hasSupport" class="external">
198
- <a href="https://rancher.com/support-maintenance-terms" target="_blank" rel="noopener noreferrer nofollow">{{ t('support.community.learnMore') }} <i class="icon icon-external-link" /></a>
199
- or
200
- <a href="https://rancher.com/pricing" target="_blank" rel="noopener noreferrer nofollow">{{ t('support.community.pricing') }} <i class="icon icon-external-link" /></a>
201
- </div>
201
+
202
202
  <div v-if="!hasSupport" class="register row">
203
203
  <div>
204
204
  {{ t('support.subscription.haveSupport') }}
@@ -214,7 +214,16 @@ export default {
214
214
  </div>
215
215
  </div>
216
216
  <div class="community">
217
- <CommunityLinks />
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>
218
227
  </div>
219
228
  </div>
220
229
  </IndentedPanel>
@@ -279,13 +288,12 @@ export default {
279
288
  font-weight: 300;
280
289
  margin-bottom: 20px;
281
290
  }
282
- .support-link {
283
- margin: 10px 0;
284
- }
285
291
  }
286
- .external {
287
- margin-top: 20px;
292
+
293
+ .support-link:not(:first-child) {
294
+ margin: 15px 0 0 0;
288
295
  }
296
+
289
297
  .register {
290
298
  display: flex;
291
299
  align-items: center;
@@ -53,6 +53,10 @@ export function resolveList(key) {
53
53
  return undefined;
54
54
  }
55
55
 
56
+ export function resolveChart(key) {
57
+ return undefined;
58
+ }
59
+
56
60
  export function resolveEdit(key) {
57
61
  return undefined;
58
62
  }
@@ -9,7 +9,7 @@ import {
9
9
  AS,
10
10
  MODE
11
11
  } from '@shell/config/query-params';
12
- import { DEV } from '@shell/store/prefs';
12
+ import { VIEW_IN_API } from '@shell/store/prefs';
13
13
  import { addObject, addObjects, findBy, removeAt } from '@shell/utils/array';
14
14
  import CustomValidators from '@shell/utils/custom-validators';
15
15
  import { downloadFile, generateZip } from '@shell/utils/download';
@@ -966,7 +966,7 @@ export default class Resource {
966
966
  }
967
967
 
968
968
  get canViewInApi() {
969
- return this.hasLink('self') && this.$rootGetters['prefs/get'](DEV);
969
+ return this.hasLink('self') && this.$rootGetters['prefs/get'](VIEW_IN_API);
970
970
  }
971
971
 
972
972
  get canYaml() {
@@ -0,0 +1,15 @@
1
+ // This registers all of the built-in formatters into the SortableTable cache
2
+
3
+ // We do it here to keep it away from plugins
4
+ // It was in SortableTable itself, but this causes plugins to pull in all formatters and their dependencies
5
+
6
+ import { FORMATTERS } from '@shell/components/SortableTable';
7
+
8
+ const components = require.context('@shell/components/formatter', false, /[A-Z]\w+\.(vue)$/);
9
+
10
+ components.keys().forEach((fileName) => {
11
+ const componentConfig = components(fileName);
12
+ const componentName = fileName.split('/').pop().split('.')[0];
13
+
14
+ FORMATTERS[componentName] = componentConfig.default || componentConfig;
15
+ });
package/plugins/plugin.js CHANGED
@@ -1,10 +1,11 @@
1
- // This plugin loads any extensions at app load time
2
-
3
- import { allHash } from '@shell/utils/promise';
1
+ // This plugin loads any UI Plugins at app load time
2
+ import { allHashSettled } from '@shell/utils/promise';
3
+ import { shouldLoadPlugin, UI_PLUGIN_BASE_URL } from '@shell/config/uiplugins';
4
4
 
5
5
  const META_NAME_PREFIX = 'app-autoload-';
6
6
 
7
7
  export default async(context) => {
8
+ // UI Plugins declared in the HTML head
8
9
  const meta = context.app?.head?.meta || [];
9
10
  const hash = {};
10
11
 
@@ -18,5 +19,56 @@ export default async(context) => {
18
19
  }
19
20
  });
20
21
 
21
- await allHash(hash);
22
+ // Provide a mechanism to load the UI without the plugins loaded - in case there is a problem
23
+ let loadPlugins = true;
24
+
25
+ if (context.route?.path.endsWith('/safeMode')) {
26
+ loadPlugins = false;
27
+ console.warn('Safe Mode - plugins will not be loaded'); // eslint-disable-line no-console
28
+ }
29
+
30
+ if (loadPlugins) {
31
+ const { store, $plugin } = context;
32
+
33
+ // Fetch list of installed plugins from endpoint
34
+ try {
35
+ const res = await store.dispatch('management/request', {
36
+ url: `${ UI_PLUGIN_BASE_URL }/index.json`,
37
+ headers: { accept: 'application/json' }
38
+ });
39
+
40
+ if (res) {
41
+ const entries = res.entries || res.Entries || {};
42
+
43
+ Object.values(entries).forEach((plugin) => {
44
+ if (shouldLoadPlugin(plugin)) {
45
+ let url;
46
+
47
+ if (plugin?.metadata?.['direct'] === 'true') {
48
+ url = plugin.endpoint;
49
+ }
50
+
51
+ hash[plugin.name] = $plugin.loadAsyncByNameAndVersion(plugin.name, plugin.version, url);
52
+ }
53
+ });
54
+ }
55
+ } catch (e) {
56
+ console.error('Could not load UI Plugin list', e); // eslint-disable-line no-console
57
+ }
58
+
59
+ // Load all of the plugins
60
+ const pluginLoads = await allHashSettled(hash);
61
+
62
+ // Some pluigns may have failed to load - store this
63
+ Object.keys(pluginLoads).forEach((name) => {
64
+ const res = pluginLoads[name];
65
+
66
+ if (res?.status === 'rejected') {
67
+ console.error(`Failed to load plugin: ${ name }`); // eslint-disable-line no-console
68
+
69
+ // 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
+ }
72
+ });
73
+ }
22
74
  };
@@ -64,7 +64,7 @@ export default {
64
64
 
65
65
  if (worker) {
66
66
  // Store raw json objects, not the proxies
67
- worker.loadSchema(data);
67
+ worker.postMessage({ loadSchemas: data });
68
68
  }
69
69
  }
70
70
  },