@rancher/shell 3.0.12-rc.1 → 3.0.12-rc.2

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 (134) hide show
  1. package/assets/images/providers/entraid-black.svg +4 -0
  2. package/assets/images/providers/entraid.svg +9 -0
  3. package/assets/images/vendor/entraid.svg +9 -0
  4. package/assets/styles/app.scss +0 -1
  5. package/assets/translations/en-us.yaml +19 -17
  6. package/assets/translations/zh-hans.yaml +4 -8
  7. package/chart/__tests__/S3.test.ts +10 -3
  8. package/components/CountBox.vue +20 -0
  9. package/components/CreateDriver.vue +0 -12
  10. package/components/DetailText.vue +12 -3
  11. package/components/SelectIconGrid.vue +5 -0
  12. package/components/__tests__/CountBox.test.ts +72 -0
  13. package/components/__tests__/DetailText.test.ts +113 -0
  14. package/components/fleet/FleetClusterTargets/index.vue +18 -1
  15. package/components/form/InputWithSelect.vue +18 -10
  16. package/components/form/KeyValue.vue +17 -1
  17. package/components/form/LabeledSelect.vue +82 -24
  18. package/components/form/Select.vue +73 -56
  19. package/components/form/ServiceNameSelect.vue +13 -11
  20. package/components/form/__tests__/KeyValue.test.ts +66 -0
  21. package/components/form/__tests__/NodeScheduling.test.ts +9 -0
  22. package/components/form/labeled-select-utils/useLabeledSelectPagination.ts +138 -0
  23. package/components/nav/Group.vue +7 -6
  24. package/components/nav/Header.vue +24 -3
  25. package/components/nav/NotificationCenter/Notification.vue +4 -1
  26. package/components/nav/NotificationCenter/NotificationHeader.vue +20 -8
  27. package/components/nav/NotificationCenter/__tests__/NotificationHeader.test.ts +80 -0
  28. package/components/nav/Type.vue +8 -7
  29. package/components/nav/WindowManager/index.vue +2 -1
  30. package/components/nav/WorkspaceSwitcher.vue +13 -0
  31. package/components/nav/__tests__/Group.test.ts +67 -0
  32. package/components/nav/__tests__/Header.test.ts +235 -0
  33. package/components/nav/__tests__/Type.test.ts +20 -3
  34. package/components/templates/default.vue +34 -4
  35. package/components/templates/home.vue +12 -25
  36. package/components/templates/plain.vue +13 -26
  37. package/composables/useLabeledFormElement.ts +10 -2
  38. package/composables/useLabeledSelect.ts +60 -0
  39. package/composables/useUserRetentionValidation.ts +1 -49
  40. package/config/cookies.js +0 -1
  41. package/config/labels-annotations.js +1 -0
  42. package/config/query-params.js +1 -0
  43. package/config/router/routes.js +0 -8
  44. package/core/__tests__/plugin-products.test.ts +616 -25
  45. package/core/plugin-products-base.ts +31 -14
  46. package/core/plugin-products-helpers.ts +5 -4
  47. package/core/plugin-types.ts +18 -3
  48. package/core/types.ts +3 -1
  49. package/detail/__tests__/management.cattle.io.fleetworkspace.test.ts +128 -0
  50. package/detail/management.cattle.io.fleetworkspace.vue +49 -0
  51. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +9 -0
  52. package/edit/__tests__/kontainerDriver.test.ts +0 -13
  53. package/edit/__tests__/nodeDriver.test.ts +5 -11
  54. package/edit/__tests__/resources.cattle.io.restore.test.ts +9 -0
  55. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
  56. package/edit/auth/__tests__/oidc.test.ts +54 -0
  57. package/edit/auth/azuread.vue +1 -1
  58. package/edit/auth/oidc.vue +8 -0
  59. package/edit/kontainerDriver.vue +1 -2
  60. package/edit/nodeDriver.vue +0 -2
  61. package/edit/provisioning.cattle.io.cluster/AgentEnv.vue +1 -0
  62. package/edit/provisioning.cattle.io.cluster/__tests__/AgentEnv.test.ts +25 -0
  63. package/edit/provisioning.cattle.io.cluster/index.vue +70 -99
  64. package/initialize/App.vue +29 -2
  65. package/initialize/install-plugins.js +0 -2
  66. package/list/__tests__/management.cattle.io.feature.test.ts +105 -0
  67. package/list/catalog.cattle.io.app.vue +25 -5
  68. package/list/management.cattle.io.feature.vue +1 -1
  69. package/list/management.cattle.io.fleetworkspace.vue +8 -0
  70. package/machine-config/amazonec2.vue +1 -0
  71. package/mixins/chart.js +40 -9
  72. package/models/__tests__/catalog.cattle.io.app.test.ts +15 -1
  73. package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +84 -0
  74. package/models/__tests__/chart.test.ts +99 -6
  75. package/models/__tests__/management.cattle.io.feature.test.ts +131 -0
  76. package/models/__tests__/monitoring.coreos.com.alertmanagerconfig.test.ts +98 -0
  77. package/models/catalog.cattle.io.app.js +21 -17
  78. package/models/catalog.cattle.io.clusterrepo.js +39 -11
  79. package/models/chart.js +33 -19
  80. package/models/fleet-application.js +1 -1
  81. package/models/fleet.cattle.io.bundle.js +1 -1
  82. package/models/kontainerdriver.js +11 -0
  83. package/models/management.cattle.io.authconfig.js +5 -1
  84. package/models/management.cattle.io.cluster.js +0 -53
  85. package/models/management.cattle.io.feature.js +3 -3
  86. package/models/management.cattle.io.kontainerdriver.js +1 -26
  87. package/models/monitoring.coreos.com.alertmanagerconfig.js +31 -17
  88. package/models/nodedriver.js +7 -0
  89. package/package.json +13 -12
  90. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +189 -0
  91. package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +55 -0
  92. package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +53 -0
  93. package/pages/c/_cluster/apps/charts/chart.vue +217 -33
  94. package/pages/c/_cluster/apps/charts/index.vue +2 -2
  95. package/pages/c/_cluster/apps/charts/install.vue +8 -3
  96. package/pages/c/_cluster/auth/user.retention/index.vue +55 -22
  97. package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -7
  98. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +39 -2
  99. package/pages/c/_cluster/uiplugins/__tests__/PluginInfoPanel.test.ts +61 -0
  100. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +15 -10
  101. package/pages/c/_cluster/uiplugins/index.vue +23 -25
  102. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +205 -1
  103. package/rancher-components/Form/LabeledInput/LabeledInput.vue +82 -4
  104. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +1 -1
  105. package/scripts/test-plugins-build.sh +5 -2
  106. package/server/server-middleware.js +2 -2
  107. package/static/humans.txt +1 -0
  108. package/static/robots.txt +34 -0
  109. package/static/welcome-cow.svg +18 -0
  110. package/store/__tests__/catalog.test.ts +161 -11
  111. package/store/auth.js +0 -3
  112. package/store/catalog.js +60 -8
  113. package/types/shell/index.d.ts +26 -22
  114. package/utils/__tests__/git.test.ts +270 -0
  115. package/utils/__tests__/inactivity.test.ts +316 -0
  116. package/utils/__tests__/object.test.ts +77 -0
  117. package/utils/__tests__/time.test.ts +14 -1
  118. package/utils/__tests__/url.test.ts +246 -0
  119. package/utils/object.js +33 -2
  120. package/utils/time.ts +5 -0
  121. package/vue.config.js +0 -9
  122. package/assets/images/providers/azuread-black.svg +0 -22
  123. package/assets/images/providers/azuread.svg +0 -25
  124. package/assets/images/vendor/azuread.svg +0 -18
  125. package/assets/styles/fonts/_dots.scss +0 -18
  126. package/components/EmberPage.vue +0 -622
  127. package/components/EmberPageView.vue +0 -39
  128. package/components/form/labeled-select-utils/labeled-select-pagination.ts +0 -116
  129. package/mixins/labeled-form-element.ts +0 -225
  130. package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -28
  131. package/pages/c/_cluster/manager/pages/_page.vue +0 -22
  132. package/pages/c/_cluster/mcapps/pages/_page.vue +0 -22
  133. package/plugins/ember-cookie.js +0 -17
  134. package/utils/ember-page.js +0 -30
@@ -1,622 +0,0 @@
1
- <script>
2
- import Loading from '@shell/components/Loading';
3
- import { mapGetters, mapState } from 'vuex';
4
- import { NAME as MANAGER } from '@shell/config/product/manager';
5
- import { CAPI, MANAGEMENT } from '@shell/config/types';
6
- import { SETTING } from '@shell/config/settings';
7
- import { findEmberPage, clearEmberInactiveTimer, startEmberInactiveTimer, EMBER_FRAME } from '@shell/utils/ember-page';
8
-
9
- const EMBER_FRAME_HIDE_CLASS = 'ember-iframe-hidden';
10
- const PAGE_CHECK_TIMEOUT = 30000;
11
- const WINDOW_MANAGER = 'horizontal-window-manager';
12
-
13
- // Pages that we should intercept when loaded in the IFRAME and instead
14
- // navigate to a page in Cluster Dashboard
15
- // example if the Ember clusters page that is navigated to when the user presses cancel on some pages
16
- // we intercept this and go the the vue Clusters page instead
17
- const INTERCEPTS = {
18
- 'global-admin.clusters.index': {
19
- name: 'c-cluster-product-resource',
20
- params: {
21
- cluster: '',
22
- product: MANAGER,
23
- resource: CAPI.RANCHER_CLUSTER,
24
- }
25
- },
26
- 'authenticated.cluster.index': {
27
- name: 'c-cluster-product-resource',
28
- params: {
29
- cluster: '',
30
- product: MANAGER,
31
- resource: CAPI.RANCHER_CLUSTER,
32
- }
33
- },
34
- 'authenticated.cluster.istio.cluster-setting': { name: 'c-cluster-explorer-tools' },
35
- };
36
-
37
- export default {
38
- emits: ['before-nav'],
39
-
40
- components: { Loading },
41
-
42
- props: {
43
- src: {
44
- type: String,
45
- required: true
46
- },
47
- pop: {
48
- type: Boolean,
49
- default: false
50
- },
51
- inline: {
52
- type: String,
53
- default: ''
54
- },
55
- // force inline pages to reuse cached Ember pages
56
- forceInlineReuse: {
57
- type: Boolean,
58
- default: false
59
- },
60
- // Do not reuse cached pages
61
- forceNew: {
62
- type: Boolean,
63
- default: false
64
- }
65
- },
66
-
67
- data() {
68
- return {
69
- iframeEl: null,
70
- loaded: true,
71
- loadRequired: false,
72
- emberCheck: null,
73
- error: false,
74
- heightSync: null,
75
- frameHeight: -1,
76
- frameWidth: -1,
77
- wmHeight: -1,
78
- showHeaderBanner: false,
79
- showFooterBanner: false,
80
- };
81
- },
82
-
83
- computed: {
84
- ...mapGetters({ theme: 'prefs/theme' }),
85
- ...mapGetters(['clusterId', 'productId']),
86
- ...mapState('wm', ['open']),
87
- locale() {
88
- return this.$store.getters['i18n/current']();
89
- }
90
- },
91
-
92
- watch: {
93
- theme(theme) {
94
- this.notifyTheme(theme);
95
- },
96
-
97
- // Update when source property changes
98
- src(nue, old) {
99
- if (nue !== old) {
100
- this.initFrame();
101
- }
102
- },
103
-
104
- // Watch on the window manager opening/closing
105
- open(nue, old) {
106
- if (nue !== old) {
107
- if (nue) {
108
- this.syncSize();
109
- } else {
110
- clearTimeout(this.heightSync);
111
- const iframeEl = findEmberPage();
112
-
113
- // Reset the height when the window manager is closed
114
- this.heightSync = null;
115
- this.wmHeight = -1;
116
-
117
- if (iframeEl) {
118
- iframeEl.style.height = '';
119
- }
120
- }
121
- }
122
- },
123
- locale() {
124
- this.syncLocale();
125
- }
126
- },
127
-
128
- mounted() {
129
- // Embedded page visited, so cancel time to remove IFRAME when inactive
130
- clearEmberInactiveTimer();
131
- window.addEventListener('message', this.receiveMessage);
132
- this.initFrame();
133
- },
134
-
135
- beforeUnmount() {
136
- window.removeEventListener('message', this.receiveMessage);
137
-
138
- if (this.heightSync) {
139
- clearTimeout(this.heightSync);
140
- }
141
-
142
- if (this.inline) {
143
- const iframeEl = findEmberPage();
144
-
145
- // Remove the IFRAME - we can't reuse it one its been moved inline
146
- if (iframeEl) {
147
- iframeEl.remove();
148
- }
149
- }
150
-
151
- // Hide the iframe
152
- if (this.iframeEl) {
153
- this.iframeEl.classList.add(EMBER_FRAME_HIDE_CLASS);
154
- }
155
-
156
- // Cancel any pending http request to check Ember UI availability
157
- if (this.emberCheck) {
158
- this.emberCheck.cancel('User left page');
159
- }
160
-
161
- // Set up a timer to remove the IFrame after a period of inactivity
162
- startEmberInactiveTimer();
163
- },
164
-
165
- methods: {
166
- addBannerClasses(elm, prefix) {
167
- if (!elm) {
168
- return;
169
- }
170
-
171
- elm.classList.remove(`${ prefix }-top-banner`);
172
- elm.classList.remove(`${ prefix }-one-banner`);
173
- elm.classList.remove(`${ prefix }-two-banners`);
174
-
175
- if (this.showHeaderBanner) {
176
- elm.classList.add(`${ prefix }-top-banner`);
177
- if (this.showFooterBanner) {
178
- elm.classList.add(`${ prefix }-two-banners`);
179
- }
180
- } else if (this.showFooterBanner) {
181
- elm.classList.add(`${ prefix }-one-banner`);
182
- }
183
- },
184
-
185
- async initFrame() {
186
- const bannerSetting = await this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.BANNERS);
187
-
188
- try {
189
- const parsed = JSON.parse(bannerSetting.value);
190
-
191
- this.showHeaderBanner = parsed.showHeader === 'true';
192
- this.showFooterBanner = parsed.showFooter === 'true';
193
- } catch {}
194
-
195
- this.loaded = true;
196
- this.loadRequired = false;
197
-
198
- // Get the existing iframe if it exists
199
- let iframeEl = findEmberPage();
200
-
201
- // If the iframe already exists, check if it is ready for us to reuse
202
- // by navigating within the app that is already loaded
203
- if (iframeEl !== null) {
204
- const ready = iframeEl.getAttribute('data-ready') === 'true';
205
- const lastDidLoad = iframeEl.getAttribute('data-loaded') === 'true';
206
- const doNotReuse = (!!this.inline && !this.forceInlineReuse) || this.forceNew;
207
- // Was not inline but now is - can't reuse
208
- const inlineChanged = !!this.inline && (iframeEl.parentElement === document.body);
209
-
210
- if (!ready || doNotReuse || !lastDidLoad || inlineChanged) {
211
- iframeEl.remove();
212
- iframeEl = null;
213
- }
214
- }
215
-
216
- if (iframeEl === null && process.env.dev) {
217
- // Fetch a page to check that the Ember UI is available
218
- try {
219
- this.error = false;
220
- this.loaded = false;
221
- this.emberCheck = this.$axios.CancelToken.source();
222
-
223
- // Make a head request to a known asset of the Ember UI
224
- const pageUrl = `${ window.location.origin }/assets/images/logos/rke.svg`;
225
- const response = await this.$axios.head(pageUrl, {
226
- timeout: PAGE_CHECK_TIMEOUT,
227
- cancelToken: this.emberCheck.token,
228
- });
229
-
230
- if (response.status !== 200) {
231
- this.loaded = true;
232
- this.error = true;
233
- }
234
- } catch (e) {
235
- if (!this.$axios.isCancel(e)) {
236
- this.loaded = true;
237
- this.error = true;
238
- }
239
- }
240
- }
241
-
242
- if (this.error) {
243
- return;
244
- }
245
-
246
- if (iframeEl === null) {
247
- iframeEl = document.createElement('iframe');
248
- iframeEl.setAttribute('id', EMBER_FRAME);
249
- iframeEl.setAttribute('data-testid', EMBER_FRAME);
250
- iframeEl.classList.add(EMBER_FRAME_HIDE_CLASS);
251
-
252
- if (this.inline) {
253
- const frameParent = document.getElementById(this.inline);
254
-
255
- frameParent.appendChild(iframeEl);
256
- } else {
257
- document.body.append(iframeEl);
258
- }
259
- iframeEl.setAttribute('src', this.src);
260
- } else {
261
- // Reset scroll position to top
262
- if (iframeEl.contentWindow?.scrollTo) {
263
- iframeEl.contentWindow.scrollTo(0, 0);
264
- }
265
-
266
- // Post a message to navigate within the existing app
267
- iframeEl.contentWindow.postMessage({
268
- action: 'navigate',
269
- name: this.src
270
- });
271
-
272
- // Ensure iframe gets the latest theme if it has changed
273
- this.notifyTheme(this.theme);
274
-
275
- const currentUrl = iframeEl.contentWindow.location.pathname;
276
- const src = this.trimURL(this.src);
277
-
278
- if (src !== currentUrl) {
279
- iframeEl.classList.add(EMBER_FRAME_HIDE_CLASS);
280
- } else {
281
- iframeEl.classList.remove(EMBER_FRAME_HIDE_CLASS);
282
- }
283
- }
284
-
285
- this.iframeEl = iframeEl;
286
-
287
- if (!this.inline) {
288
- iframeEl.classList.add('ember-iframe');
289
- iframeEl.classList.remove('ember-iframe-inline');
290
- this.addBannerClasses(this.$refs.emberPage, 'fixed');
291
- this.addBannerClasses(iframeEl, 'ember-iframe');
292
-
293
- // If the window manager is open, sync the size
294
- if (this.open) {
295
- this.syncSize();
296
- }
297
- } else {
298
- iframeEl.classList.remove('ember-iframe');
299
- iframeEl.classList.add('ember-iframe-inline');
300
- iframeEl.height = 0;
301
- this.syncSize();
302
- }
303
- },
304
-
305
- syncSize() {
306
- if (this.heightSync) {
307
- clearTimeout(this.heightSync);
308
- }
309
-
310
- this.heightSync = setTimeout(() => {
311
- this.dosyncSize();
312
- this.syncSize();
313
- }, 500);
314
- },
315
-
316
- dosyncSize() {
317
- if (this.inline) {
318
- const iframeEl = findEmberPage();
319
- const doc = iframeEl.contentWindow.document;
320
- const app = doc.getElementById('application');
321
- const h = app?.offsetHeight;
322
-
323
- if (h && this.frameHeight !== h) {
324
- this.frameHeight = h;
325
- iframeEl.height = h;
326
- }
327
-
328
- const frameParent = document.getElementById(this.inline);
329
- const w = frameParent.offsetWidth;
330
-
331
- if (w && this.frameWidth !== w) {
332
- this.frameWidth = w;
333
- iframeEl.width = w;
334
- }
335
- } else {
336
- // Ensure the height takes into count the window manger height
337
- const wm = document.getElementById(WINDOW_MANAGER);
338
-
339
- if (wm) {
340
- const wmh = wm.offsetHeight;
341
-
342
- if (wmh !== this.wmHeight) {
343
- // Adjust the bottom
344
- const iframeEl = findEmberPage();
345
-
346
- iframeEl.style.height = `calc(100vh - var(--header-height) - ${ wmh }px)`;
347
- this.wmHeight = wmh;
348
- }
349
- }
350
- }
351
- },
352
-
353
- notifyTheme(theme) {
354
- const iframeEl = findEmberPage();
355
-
356
- if (iframeEl) {
357
- const emberTheme = theme === 'light' ? 'ui-light' : 'ui-dark';
358
-
359
- // Ensure the embedded UI uses the correct theme
360
- iframeEl.contentWindow.postMessage({
361
- action: 'set-theme',
362
- name: emberTheme
363
- });
364
- }
365
- },
366
-
367
- trimURL(url) {
368
- if (url && url.endsWith('/')) {
369
- url = url.substr(0, url.length - 1);
370
- }
371
-
372
- return url;
373
- },
374
-
375
- // We use PostMessage between the Embedded Ember UI and the Dashboard UI
376
- receiveMessage(event) {
377
- const msg = event.data;
378
-
379
- if (msg.action === 'navigate') {
380
- this.$router.replace({
381
- name: 'c-cluster-explorer',
382
- params: { cluster: msg.cluster }
383
- });
384
- } else if (msg.action === 'before-navigation') {
385
- this.$emit('before-nav', msg.target);
386
-
387
- // Ember willTransition event
388
- if (INTERCEPTS[msg.target]) {
389
- const dest = INTERCEPTS[msg.target];
390
-
391
- if (this.isCurrentRoute(dest)) {
392
- this.setLoaded(true);
393
-
394
- return;
395
- }
396
-
397
- this.setLoaded(false);
398
- this.$router.replace(this.fillRoute(dest));
399
- }
400
- } else if (msg.action === 'loading') {
401
- this.setLoaded(!msg.state);
402
- this.updateFrameVisibility();
403
- } else if (msg.action === 'ready') {
404
- // Echo back a ping
405
- this.iframeEl.contentWindow.postMessage({ action: 'echo-back' });
406
- this.iframeEl.setAttribute('data-ready', true);
407
-
408
- const doc = this.iframeEl.contentWindow?.document?.body;
409
-
410
- if (this.inline) {
411
- doc.classList.add('embedded-no-overflow');
412
- } else {
413
- doc.classList.remove('embedded-no-overflow');
414
- }
415
- this.syncLocale();
416
- } else if (msg.action === 'need-to-load') {
417
- this.loadRequired = true;
418
- } else if (msg.action === 'did-transition') {
419
- if (!this.loadRequired) {
420
- this.setLoaded(true);
421
- this.updateFrameVisibility();
422
- this.dosyncSize();
423
- }
424
- } else if (msg.action === 'dashboard') {
425
- this.iframeEl.setAttribute('data-ready', false);
426
- this.$router.replace(msg.page);
427
- } else if (msg.action === 'reload') {
428
- this.loaded = false;
429
- this.iframeEl.remove();
430
- this.initFrame();
431
- } else if ( msg.action === 'logout' ) {
432
- this.loaded = false;
433
- this.iframeEl.remove();
434
- this.initFrame();
435
- this.$store.dispatch('auth/logout');
436
- }
437
- },
438
-
439
- setLoaded(loaded) {
440
- this.loaded = loaded;
441
- if (this.iframeEl) {
442
- this.iframeEl.setAttribute('data-loaded', loaded);
443
- }
444
- },
445
-
446
- updateFrameVisibility() {
447
- if (this.loaded) {
448
- if (this.iframeEl) {
449
- this.iframeEl.classList.remove(EMBER_FRAME_HIDE_CLASS);
450
-
451
- // Notify the embedded UI of the primary and primary text colors
452
- const primary = window.getComputedStyle(document.body).getPropertyValue('--primary');
453
- const primaryText = window.getComputedStyle(document.body).getPropertyValue('--primary-text');
454
-
455
- this.iframeEl.contentWindow.postMessage({
456
- action: 'colors',
457
- primary,
458
- primaryText,
459
- });
460
- }
461
- }
462
- },
463
-
464
- fillRoute(route) {
465
- if (typeof route === 'object') {
466
- // Fill in standard params
467
- if (route.params) {
468
- if ('cluster' in route.params) {
469
- route.params.cluster = this.clusterId;
470
- }
471
- if ('product' in route.params) {
472
- route.params.product = this.productId;
473
- }
474
- }
475
- }
476
-
477
- return route;
478
- },
479
-
480
- isCurrentRoute(route) {
481
- const current = this.$route;
482
-
483
- if (current.name === route.name) {
484
- let same = true;
485
-
486
- Object.keys(current.params).forEach((p) => {
487
- if (route.params[p] !== current.params[p]) {
488
- same = false;
489
- }
490
- });
491
-
492
- return same;
493
- }
494
-
495
- return false;
496
- },
497
-
498
- syncLocale() {
499
- const iframeEl = findEmberPage();
500
-
501
- iframeEl?.contentWindow?.ls('user-language')?.sideLoadLanguage(this.locale);
502
- }
503
- }
504
- };
505
- </script>
506
-
507
- <template>
508
- <div
509
- ref="emberPage"
510
- class="ember-page"
511
- >
512
- <Loading
513
- v-if="!inline"
514
- :loading="!loaded"
515
- mode="content"
516
- :no-delay="true"
517
- />
518
- <div
519
- v-if="inline && !loaded"
520
- v-clean-html="t('generic.loading', {}, true)"
521
- class="inline-loading"
522
- />
523
- <div
524
- v-if="error"
525
- class="ember-page-error"
526
- >
527
- <div>{{ t('embedding.unavailable') }}</div>
528
- <button
529
- class="btn role-primary"
530
- @click="initFrame()"
531
- >
532
- {{ t('embedding.retry') }}
533
- </button>
534
- </div>
535
- </div>
536
- </template>
537
-
538
- <style lang="scss" scoped>
539
- $banner-height: 2em;
540
-
541
- .fixed-top-banner {
542
- top: calc(#{$banner-height} + var(--header-height));
543
- }
544
-
545
- .fixed-one-banner {
546
- height: calc(100vh - var(--header-height) - #{$banner-height});
547
- }
548
-
549
- .fixed-two-banners {
550
- height: calc(100vh - var(--header-height) - #{$banner-height} - #{$banner-height});
551
- }
552
-
553
- .ember-page {
554
- display: flex;
555
- height: 100%;
556
- padding: 0;
557
- }
558
-
559
- .frame {
560
- flex: 1;
561
- visibility: hidden;
562
- }
563
- .frame.pop {
564
- margin: -20px;
565
- }
566
-
567
- .loading {
568
- visibility: visible;
569
- }
570
- .ember-page-error {
571
- display: flex;
572
- align-items: center;
573
- flex: 1;
574
- flex-direction: column;
575
- justify-content: center;
576
- > div {
577
- font-size: 20px;
578
- padding-bottom: 20px;
579
- }
580
- }
581
- .inline-loading {
582
- border: 1px solid var(--border);
583
- border-radius: 5px;
584
- padding: 10px;
585
- text-align: center;
586
- width: 100%;
587
- }
588
- </style>
589
- <style lang="scss">
590
- $banner-height: 2em;
591
-
592
- .ember-iframe {
593
- border: 0;
594
- left: calc(var(--nav-width) + $app-bar-collapsed-width);
595
- height: calc(100vh - var(--header-height));
596
- position: absolute;
597
- top: var(--header-height);
598
- width: calc(100vw - var(--nav-width) - $app-bar-collapsed-width);
599
- visibility: show;
600
- }
601
-
602
- .ember-iframe-top-banner {
603
- top: calc(#{$banner-height} + var(--header-height));
604
- }
605
-
606
- .ember-iframe-one-banner {
607
- height: calc(100vh - var(--header-height) - #{$banner-height});
608
- }
609
-
610
- .ember-iframe-two-banners {
611
- height: calc(100vh - var(--header-height) - #{$banner-height} - #{$banner-height});
612
- }
613
-
614
- .ember-iframe-inline {
615
- border: 0;
616
- overflow: hidden;
617
- }
618
-
619
- .ember-iframe-hidden {
620
- visibility: hidden;
621
- }
622
- </style>
@@ -1,39 +0,0 @@
1
- <script>
2
- import EmberPage from '@shell/components/EmberPage';
3
-
4
- export default {
5
- components: { EmberPage },
6
-
7
- props: {
8
- pages: {
9
- type: Object,
10
- required: true
11
- },
12
- },
13
-
14
- data() {
15
- const page = this.$route.params.page;
16
- let src;
17
-
18
- if (page) {
19
- src = this.pages[page];
20
- }
21
-
22
- return {
23
- src,
24
- page
25
- };
26
- },
27
- };
28
- </script>
29
-
30
- <template>
31
- <EmberPage
32
- v-if="src"
33
- :src="src"
34
- />
35
- <div v-else>
36
- <h1>{{ t('generic.notFound') }}</h1>
37
- <h2>{{ page }}</h2>
38
- </div>
39
- </template>