@rancher/shell 0.3.5 → 0.3.6
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/providers/outscale.svg +19 -0
- package/assets/styles/base/_basic.scss +18 -0
- package/assets/styles/base/_mixins.scss +0 -11
- package/assets/styles/base/_variables.scss +2 -4
- package/assets/styles/global/_button.scss +12 -2
- package/assets/translations/en-us.yaml +22 -1
- package/assets/translations/zh-hans.yaml +30 -10
- package/chart/gatekeeper.vue +3 -2
- package/chart/istio.vue +29 -3
- package/components/BrandImage.vue +1 -4
- package/components/Carousel.vue +85 -37
- package/components/EtcdInfoBanner.vue +7 -3
- package/components/ExplorerMembers.vue +100 -5
- package/components/ExplorerProjectsNamespaces.vue +32 -2
- package/components/GrafanaDashboard.vue +9 -2
- package/components/SortableTable/index.vue +23 -11
- package/components/SortableTable/selection.js +58 -50
- package/components/Wizard.vue +4 -2
- package/components/auth/RoleDetailEdit.vue +2 -2
- package/components/form/HookOption.vue +14 -10
- package/components/form/Labels.vue +32 -27
- package/components/form/MatchExpressions.vue +2 -2
- package/components/form/Members/ClusterPermissionsEditor.vue +32 -7
- package/components/form/NameNsDescription.vue +1 -1
- package/components/form/ProjectMemberEditor.vue +46 -21
- package/components/form/Tolerations.vue +4 -1
- package/components/form/ValueFromResource.vue +14 -9
- package/components/form/WorkloadPorts.vue +2 -2
- package/components/form/__tests__/NameNsDescription.ts +27 -0
- package/components/formatter/WorkloadHealthScale.vue +8 -2
- package/components/nav/NamespaceFilter.vue +8 -0
- package/{nuxt/components → components/nuxt}/nuxt.js +1 -1
- package/{nuxt → config}/middleware.js +8 -8
- package/config/product/explorer.js +24 -3
- package/config/query-params.js +1 -0
- package/config/router.js +1 -1
- package/{nuxt → config}/store.js +82 -79
- package/config/table-headers.js +46 -12
- package/config/types.js +7 -0
- package/core/plugin.ts +4 -2
- package/core/types.ts +258 -1
- package/creators/app/files/tsconfig.json +0 -1
- package/creators/app/files/vue.config.js +0 -1
- package/creators/pkg/files/.github/workflows/build-extension.yml +3 -4
- package/creators/pkg/files/tsconfig.json +0 -1
- package/creators/pkg/pkg.package.json +3 -3
- package/detail/constraints.gatekeeper.sh.constraint.vue +14 -7
- package/detail/fleet.cattle.io.clustergroup.vue +7 -1
- package/edit/fleet.cattle.io.gitrepo.vue +16 -1
- package/edit/logging.banzaicloud.io.output/index.vue +18 -5
- package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
- package/edit/namespace.vue +12 -8
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -4
- package/edit/provisioning.cattle.io.cluster/import.vue +23 -25
- package/edit/provisioning.cattle.io.cluster/rke2.vue +96 -18
- package/edit/workload/mixins/workload.js +6 -7
- package/edit/workload/storage/Mount.vue +3 -3
- package/initialize/App.js +206 -0
- package/{nuxt → initialize}/client.js +406 -360
- package/{nuxt → initialize}/index.js +21 -22
- package/layouts/standalone.vue +13 -0
- package/list/catalog.cattle.io.clusterrepo.vue +1 -0
- package/list/rbac.authorization.k8s.io.clusterrolebinding.vue +48 -0
- package/list/workload.vue +6 -4
- package/mixins/chart.js +29 -1
- package/mixins/fetch.client.js +95 -0
- package/{nuxt/mixins → mixins}/fetch.server.js +30 -26
- package/mixins/labeled-form-element.ts +2 -2
- package/models/constraints.gatekeeper.sh.constraint.js +37 -0
- package/models/pod.js +4 -0
- package/models/rbac.authorization.k8s.io.clusterrolebinding.js +16 -0
- package/models/rbac.authorization.k8s.io.rolebinding.js +16 -0
- package/package.json +9 -13
- package/pages/c/_cluster/apps/charts/install.vue +61 -39
- package/pages/diagnostic.vue +32 -25
- package/pages/rio/mesh.vue +1 -2
- package/pkg/tsconfig.json +0 -1
- package/plugins/clean-html-directive.js +3 -0
- package/plugins/dashboard-store/index.js +1 -1
- package/plugins/plugin.js +0 -14
- package/plugins/portal-vue.js +4 -0
- package/rancher-components/components/Banner/Banner.test.ts +3 -5
- package/rancher-components/components/Banner/Banner.vue +1 -0
- package/rancher-components/components/Form/Radio/RadioButton.test.ts +31 -0
- package/rancher-components/components/Form/Radio/RadioButton.vue +14 -3
- package/scripts/extension/publish +42 -23
- package/scripts/serve-pkgs +6 -2
- package/store/type-map.js +1 -1
- package/tsconfig.json +0 -1
- package/types/rancher/index.d.ts +2 -0
- package/types/shell/index.d.ts +353 -284
- package/utils/__tests__/grafana.test.ts +44 -0
- package/utils/axios.js +190 -0
- package/{nuxt → utils}/cookie-universal-nuxt.js +7 -6
- package/utils/dom.js +15 -0
- package/utils/grafana.js +35 -16
- package/{nuxt/utils.js → utils/nuxt.js} +265 -236
- package/utils/router.scrollBehavior.js +1 -1
- package/vue.config.js +30 -19
- package/nuxt/App.js +0 -210
- package/nuxt/axios.js +0 -186
- package/nuxt/empty.js +0 -1
- package/nuxt/jsonp.js +0 -82
- package/nuxt/loading.html +0 -39
- package/nuxt/mixins/fetch.client.js +0 -90
- package/nuxt/portal-vue.js +0 -4
- package/nuxt/server.js +0 -312
- package/nuxt/views/app.template.html +0 -9
- package/nuxt/views/error.html +0 -23
- package/plugins/dashboard-store/extensions.js +0 -22
- /package/{nuxt/components → components/nuxt}/nuxt-build-indicator.vue +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-child.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-error.vue +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-link.client.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-link.server.js +0 -0
- /package/{nuxt/components → components/nuxt}/nuxt-loading.vue +0 -0
|
@@ -77,6 +77,26 @@ const ADVANCED = 'advanced';
|
|
|
77
77
|
const HARVESTER = 'harvester';
|
|
78
78
|
const HARVESTER_CLOUD_PROVIDER = 'harvester-cloud-provider';
|
|
79
79
|
|
|
80
|
+
const NETBIOS_TRUNCATION_LENGTH = 15;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Classes to be adopted by the node badges in Machine pools
|
|
84
|
+
*/
|
|
85
|
+
const NODE_TOTAL = {
|
|
86
|
+
error: {
|
|
87
|
+
color: 'bg-error',
|
|
88
|
+
icon: 'icon-x',
|
|
89
|
+
},
|
|
90
|
+
warning: {
|
|
91
|
+
color: 'bg-warning',
|
|
92
|
+
icon: 'icon-warning',
|
|
93
|
+
},
|
|
94
|
+
success: {
|
|
95
|
+
color: 'bg-success',
|
|
96
|
+
icon: 'icon-checkmark'
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
80
100
|
export default {
|
|
81
101
|
components: {
|
|
82
102
|
ACE,
|
|
@@ -286,6 +306,13 @@ export default {
|
|
|
286
306
|
const lastDefaultPodSecurityPolicyTemplateName = this.value.spec.defaultPodSecurityPolicyTemplateName;
|
|
287
307
|
const previousKubernetesVersion = this.value.spec.kubernetesVersion;
|
|
288
308
|
|
|
309
|
+
const truncateLimit = this.value.machinePoolDefaults?.hostnameLengthLimit;
|
|
310
|
+
|
|
311
|
+
// Is hostname truncation supported by the backend?
|
|
312
|
+
const provSchema = this.$store.getters['management/schemaFor'](CAPI.RANCHER_CLUSTER);
|
|
313
|
+
const specSchemaName = provSchema?.resourceFields?.spec?.type;
|
|
314
|
+
const specSchema = specSchemaName ? this.$store.getters['management/schemaFor'](specSchemaName) : {};
|
|
315
|
+
|
|
289
316
|
return {
|
|
290
317
|
loadedOnce: false,
|
|
291
318
|
lastIdx: 0,
|
|
@@ -321,6 +348,9 @@ export default {
|
|
|
321
348
|
cisOverride: false,
|
|
322
349
|
cisPsaChangeBanner: false,
|
|
323
350
|
psps: null, // List of policies if any
|
|
351
|
+
truncateHostnames: truncateLimit === NETBIOS_TRUNCATION_LENGTH,
|
|
352
|
+
truncateLimit,
|
|
353
|
+
supportsTruncation: !!specSchema?.resourceFields?.machinePoolDefaults,
|
|
324
354
|
};
|
|
325
355
|
},
|
|
326
356
|
|
|
@@ -337,6 +367,10 @@ export default {
|
|
|
337
367
|
return this.value.spec.rkeConfig;
|
|
338
368
|
},
|
|
339
369
|
|
|
370
|
+
hostnameTruncationManuallySet() {
|
|
371
|
+
return this.truncateLimit && this.truncateLimit !== NETBIOS_TRUNCATION_LENGTH;
|
|
372
|
+
},
|
|
373
|
+
|
|
340
374
|
/**
|
|
341
375
|
* Check presence of PSPs as template or CLI creation
|
|
342
376
|
*/
|
|
@@ -703,11 +737,11 @@ export default {
|
|
|
703
737
|
|
|
704
738
|
for ( const role of roles ) {
|
|
705
739
|
counts[role] = 0;
|
|
706
|
-
out.color[role] =
|
|
707
|
-
out.icon[role] =
|
|
740
|
+
out.color[role] = NODE_TOTAL.success.color;
|
|
741
|
+
out.icon[role] = NODE_TOTAL.success.icon;
|
|
708
742
|
}
|
|
709
743
|
|
|
710
|
-
for ( const row of this.machinePools ) {
|
|
744
|
+
for ( const row of this.machinePools || [] ) {
|
|
711
745
|
if ( row.remove ) {
|
|
712
746
|
continue;
|
|
713
747
|
}
|
|
@@ -729,27 +763,27 @@ export default {
|
|
|
729
763
|
}
|
|
730
764
|
|
|
731
765
|
if ( counts.etcd === 0 ) {
|
|
732
|
-
out.color.etcd =
|
|
733
|
-
out.icon.etcd =
|
|
766
|
+
out.color.etcd = NODE_TOTAL.error.color;
|
|
767
|
+
out.icon.etcd = NODE_TOTAL.error.icon;
|
|
734
768
|
} else if ( counts.etcd === 1 || counts.etcd % 2 === 0 || counts.etcd > 7 ) {
|
|
735
|
-
out.color.etcd =
|
|
736
|
-
out.icon.etcd =
|
|
769
|
+
out.color.etcd = NODE_TOTAL.warning.color;
|
|
770
|
+
out.icon.etcd = NODE_TOTAL.warning.icon;
|
|
737
771
|
}
|
|
738
772
|
|
|
739
773
|
if ( counts.controlPlane === 0 ) {
|
|
740
|
-
out.color.controlPlane =
|
|
741
|
-
out.icon.controlPlane =
|
|
774
|
+
out.color.controlPlane = NODE_TOTAL.error.color;
|
|
775
|
+
out.icon.controlPlane = NODE_TOTAL.error.icon;
|
|
742
776
|
} else if ( counts.controlPlane === 1 ) {
|
|
743
|
-
out.color.controlPlane =
|
|
744
|
-
out.icon.controlPlane =
|
|
777
|
+
out.color.controlPlane = NODE_TOTAL.warning.color;
|
|
778
|
+
out.icon.controlPlane = NODE_TOTAL.warning.icon;
|
|
745
779
|
}
|
|
746
780
|
|
|
747
781
|
if ( counts.worker === 0 ) {
|
|
748
|
-
out.color.worker =
|
|
749
|
-
out.icon.worker =
|
|
782
|
+
out.color.worker = NODE_TOTAL.error.color;
|
|
783
|
+
out.icon.worker = NODE_TOTAL.error.icon;
|
|
750
784
|
} else if ( counts.worker === 1 ) {
|
|
751
|
-
out.color.worker =
|
|
752
|
-
out.icon.worker =
|
|
785
|
+
out.color.worker = NODE_TOTAL.warning.color;
|
|
786
|
+
out.icon.worker = NODE_TOTAL.warning.icon;
|
|
753
787
|
}
|
|
754
788
|
|
|
755
789
|
return out;
|
|
@@ -1061,6 +1095,21 @@ export default {
|
|
|
1061
1095
|
nlToBr,
|
|
1062
1096
|
set,
|
|
1063
1097
|
|
|
1098
|
+
/**
|
|
1099
|
+
* set instanceNameLimit to 15 to all pool machine if truncateHostnames checkbox is clicked
|
|
1100
|
+
*/
|
|
1101
|
+
truncateName() {
|
|
1102
|
+
if (this.truncateHostnames) {
|
|
1103
|
+
this.value.machinePoolDefaults = this.value.machinePoolDefaults || {};
|
|
1104
|
+
this.value.machinePoolDefaults.hostnameLengthLimit = 15;
|
|
1105
|
+
} else {
|
|
1106
|
+
delete this.value.machinePoolDefaults.hostnameLengthLimit;
|
|
1107
|
+
|
|
1108
|
+
if (Object.keys(this.value.machinePoolDefaults).length === 0) {
|
|
1109
|
+
delete this.value.machinePoolDefaults;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
},
|
|
1064
1113
|
/**
|
|
1065
1114
|
* Define PSP deprecation and restrict use of PSP based on min k8s version and current/edited mode
|
|
1066
1115
|
*/
|
|
@@ -1219,7 +1268,6 @@ export default {
|
|
|
1219
1268
|
}
|
|
1220
1269
|
|
|
1221
1270
|
await this.syncMachineConfigWithLatest(entry);
|
|
1222
|
-
|
|
1223
1271
|
// Capitals and such aren't allowed;
|
|
1224
1272
|
set(entry.pool, 'name', normalizeName(entry.pool.name) || 'pool');
|
|
1225
1273
|
|
|
@@ -1269,8 +1317,17 @@ export default {
|
|
|
1269
1317
|
}
|
|
1270
1318
|
},
|
|
1271
1319
|
|
|
1320
|
+
/**
|
|
1321
|
+
* Ensure that all the existing node roles pool are at least 1 each
|
|
1322
|
+
*/
|
|
1323
|
+
hasRequiredNodes() {
|
|
1324
|
+
return this.nodeTotals?.color && Object.values(this.nodeTotals.color).every(color => color !== NODE_TOTAL.error.color);
|
|
1325
|
+
},
|
|
1326
|
+
|
|
1272
1327
|
validationPassed() {
|
|
1273
|
-
|
|
1328
|
+
const validMachinePools = this.hasMachinePools ? this.hasRequiredNodes() : true;
|
|
1329
|
+
|
|
1330
|
+
return (this.provider === 'custom' || this.isElementalCluster || !!this.credentialId) && validMachinePools;
|
|
1274
1331
|
},
|
|
1275
1332
|
|
|
1276
1333
|
cancelCredential() {
|
|
@@ -2540,8 +2597,29 @@ export default {
|
|
|
2540
2597
|
:label="t('cluster.rke2.address.nodePortRange.label')"
|
|
2541
2598
|
/>
|
|
2542
2599
|
</div>
|
|
2600
|
+
<div
|
|
2601
|
+
v-if="supportsTruncation"
|
|
2602
|
+
class="col span-6"
|
|
2603
|
+
>
|
|
2604
|
+
<Checkbox
|
|
2605
|
+
v-if="!isView || isView && !hostnameTruncationManuallySet"
|
|
2606
|
+
v-model="truncateHostnames"
|
|
2607
|
+
class="mt-20"
|
|
2608
|
+
:disabled="isEdit || isView || hostnameTruncationManuallySet"
|
|
2609
|
+
:mode="mode"
|
|
2610
|
+
:label="t('cluster.rke2.truncateHostnames')"
|
|
2611
|
+
@input="truncateName"
|
|
2612
|
+
/>
|
|
2613
|
+
<Banner
|
|
2614
|
+
v-if="hostnameTruncationManuallySet"
|
|
2615
|
+
color="info"
|
|
2616
|
+
>
|
|
2617
|
+
<div class="text">
|
|
2618
|
+
{{ t('cluster.machinePool.truncationCluster', { limit: truncateLimit }) }}
|
|
2619
|
+
</div>
|
|
2620
|
+
</Banner>
|
|
2621
|
+
</div>
|
|
2543
2622
|
</div>
|
|
2544
|
-
|
|
2545
2623
|
<div
|
|
2546
2624
|
v-if="serverArgs['tls-san']"
|
|
2547
2625
|
class="row mb-20"
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
SERVICE_ACCOUNT,
|
|
12
12
|
CAPI,
|
|
13
13
|
POD,
|
|
14
|
+
LIST_WORKLOAD_TYPES,
|
|
14
15
|
} from '@shell/config/types';
|
|
15
16
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
16
17
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
@@ -490,21 +491,19 @@ export default {
|
|
|
490
491
|
return this.$store.getters['cluster/schemaFor'](this.type);
|
|
491
492
|
},
|
|
492
493
|
|
|
493
|
-
|
|
494
|
-
|
|
494
|
+
// array of id, label, description, initials for type selection step
|
|
495
|
+
workloadSubTypes() {
|
|
496
|
+
const workloadTypes = omitBy(LIST_WORKLOAD_TYPES, (type) => {
|
|
495
497
|
return (
|
|
496
498
|
type === WORKLOAD_TYPES.REPLICA_SET ||
|
|
497
499
|
type === WORKLOAD_TYPES.REPLICATION_CONTROLLER
|
|
498
500
|
);
|
|
499
501
|
});
|
|
500
|
-
},
|
|
501
502
|
|
|
502
|
-
// array of id, label, description, initials for type selection step
|
|
503
|
-
workloadSubTypes() {
|
|
504
503
|
const out = [];
|
|
505
504
|
|
|
506
|
-
for (const prop in
|
|
507
|
-
const type =
|
|
505
|
+
for (const prop in workloadTypes) {
|
|
506
|
+
const type = workloadTypes[prop];
|
|
508
507
|
const subtype = {
|
|
509
508
|
id: type,
|
|
510
509
|
description: `workload.typeDescriptions.'${ type }'`,
|
|
@@ -138,13 +138,13 @@ export default {
|
|
|
138
138
|
<style lang='scss'>
|
|
139
139
|
.mount-headers, .mount-rows{
|
|
140
140
|
display: grid;
|
|
141
|
-
grid-template-columns:
|
|
141
|
+
grid-template-columns: 42% 42% 5% auto;
|
|
142
142
|
grid-gap: $column-gutter;
|
|
143
143
|
margin-bottom: 10px;
|
|
144
144
|
align-items: center;
|
|
145
145
|
|
|
146
|
-
.remove {
|
|
147
|
-
|
|
146
|
+
.remove BUTTON {
|
|
147
|
+
padding: 0px;
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import Vue from 'vue';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
getMatchedComponentsInstances, getChildrenComponentInstancesUsingFetch, promisify, globalHandleError, sanitizeComponent
|
|
5
|
+
} from '../utils/nuxt';
|
|
6
|
+
import NuxtError from '../layouts/error.vue';
|
|
7
|
+
import NuxtLoading from '../components/nav/GlobalLoading.vue';
|
|
8
|
+
|
|
9
|
+
import '../assets/styles/app.scss';
|
|
10
|
+
|
|
11
|
+
import blank from '../layouts/blank.vue';
|
|
12
|
+
import defaultLayout from '../layouts/default.vue';
|
|
13
|
+
import home from '../layouts/home.vue';
|
|
14
|
+
import plain from '../layouts/plain.vue';
|
|
15
|
+
import unauthenticated from '../layouts/unauthenticated.vue';
|
|
16
|
+
import standalone from '../layouts/standalone.vue';
|
|
17
|
+
|
|
18
|
+
const layouts = {
|
|
19
|
+
_blank: sanitizeComponent(blank), _default: sanitizeComponent(defaultLayout), _home: sanitizeComponent(home), _plain: sanitizeComponent(plain), _unauthenticated: sanitizeComponent(unauthenticated), _standalone: sanitizeComponent(standalone)
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
render(h) {
|
|
24
|
+
const loadingEl = h('NuxtLoading', { ref: 'loading' });
|
|
25
|
+
|
|
26
|
+
const layoutEl = h(this.layout || 'nuxt');
|
|
27
|
+
const templateEl = h('div', {
|
|
28
|
+
domProps: { id: '__layout' },
|
|
29
|
+
key: this.layoutName
|
|
30
|
+
}, [layoutEl]);
|
|
31
|
+
|
|
32
|
+
const transitionEl = h('transition', {
|
|
33
|
+
props: {
|
|
34
|
+
name: 'layout',
|
|
35
|
+
mode: 'out-in'
|
|
36
|
+
},
|
|
37
|
+
on: {
|
|
38
|
+
beforeEnter(el) {
|
|
39
|
+
// Ensure to trigger scroll event after calling scrollBehavior
|
|
40
|
+
window.$nuxt.$nextTick(() => {
|
|
41
|
+
window.$nuxt.$emit('triggerScroll');
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}, [templateEl]);
|
|
46
|
+
|
|
47
|
+
return h('div', { domProps: { id: '__nuxt' } }, [
|
|
48
|
+
loadingEl,
|
|
49
|
+
// h(NuxtBuildIndicator), // The build indicator doesn't work as is right now and emits an error in the console so I'm leaving it out for now
|
|
50
|
+
transitionEl
|
|
51
|
+
]);
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
data: () => ({
|
|
55
|
+
isOnline: true,
|
|
56
|
+
|
|
57
|
+
layout: null,
|
|
58
|
+
layoutName: '',
|
|
59
|
+
|
|
60
|
+
nbFetching: 0
|
|
61
|
+
}),
|
|
62
|
+
|
|
63
|
+
beforeCreate() {
|
|
64
|
+
Vue.util.defineReactive(this, 'nuxt', this.$options.nuxt);
|
|
65
|
+
},
|
|
66
|
+
created() {
|
|
67
|
+
// Add this.$nuxt in child instances
|
|
68
|
+
this.$root.$options.$nuxt = this;
|
|
69
|
+
|
|
70
|
+
if (process.client) {
|
|
71
|
+
// add to window so we can listen when ready
|
|
72
|
+
window.$nuxt = this;
|
|
73
|
+
|
|
74
|
+
this.refreshOnlineStatus();
|
|
75
|
+
// Setup the listeners
|
|
76
|
+
window.addEventListener('online', this.refreshOnlineStatus);
|
|
77
|
+
window.addEventListener('offline', this.refreshOnlineStatus);
|
|
78
|
+
}
|
|
79
|
+
// Add $nuxt.error()
|
|
80
|
+
this.error = this.nuxt.error;
|
|
81
|
+
// Add $nuxt.context
|
|
82
|
+
this.context = this.$options.context;
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
mounted() {
|
|
86
|
+
this.$loading = this.$refs.loading;
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
watch: { 'nuxt.err': 'errorChanged' },
|
|
90
|
+
|
|
91
|
+
computed: {
|
|
92
|
+
isOffline() {
|
|
93
|
+
return !this.isOnline;
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
isFetching() {
|
|
97
|
+
return this.nbFetching > 0;
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
methods: {
|
|
102
|
+
refreshOnlineStatus() {
|
|
103
|
+
if (process.client) {
|
|
104
|
+
if (typeof window.navigator.onLine === 'undefined') {
|
|
105
|
+
// If the browser doesn't support connection status reports
|
|
106
|
+
// assume that we are online because most apps' only react
|
|
107
|
+
// when they now that the connection has been interrupted
|
|
108
|
+
this.isOnline = true;
|
|
109
|
+
} else {
|
|
110
|
+
this.isOnline = window.navigator.onLine;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
async refresh() {
|
|
116
|
+
const pages = getMatchedComponentsInstances(this.$route);
|
|
117
|
+
|
|
118
|
+
if (!pages.length) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
this.$loading.start();
|
|
122
|
+
|
|
123
|
+
const promises = pages.map((page) => {
|
|
124
|
+
const p = [];
|
|
125
|
+
|
|
126
|
+
// Old fetch
|
|
127
|
+
if (page.$options.fetch && page.$options.fetch.length) {
|
|
128
|
+
p.push(promisify(page.$options.fetch, this.context));
|
|
129
|
+
}
|
|
130
|
+
if (page.$fetch) {
|
|
131
|
+
p.push(page.$fetch());
|
|
132
|
+
} else {
|
|
133
|
+
// Get all component instance to call $fetch
|
|
134
|
+
for (const component of getChildrenComponentInstancesUsingFetch(page.$vnode.componentInstance)) {
|
|
135
|
+
p.push(component.$fetch());
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (page.$options.asyncData) {
|
|
140
|
+
p.push(
|
|
141
|
+
promisify(page.$options.asyncData, this.context)
|
|
142
|
+
.then((newData) => {
|
|
143
|
+
for (const key in newData) {
|
|
144
|
+
Vue.set(page.$data, key, newData[key]);
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return Promise.all(p);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
await Promise.all(promises);
|
|
155
|
+
} catch (error) {
|
|
156
|
+
this.$loading.fail(error);
|
|
157
|
+
globalHandleError(error);
|
|
158
|
+
this.error(error);
|
|
159
|
+
}
|
|
160
|
+
this.$loading.finish();
|
|
161
|
+
},
|
|
162
|
+
errorChanged() {
|
|
163
|
+
if (this.nuxt.err) {
|
|
164
|
+
if (this.$loading) {
|
|
165
|
+
if (this.$loading.fail) {
|
|
166
|
+
this.$loading.fail(this.nuxt.err);
|
|
167
|
+
}
|
|
168
|
+
if (this.$loading.finish) {
|
|
169
|
+
this.$loading.finish();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let errorLayout = (NuxtError.options || NuxtError).layout;
|
|
174
|
+
|
|
175
|
+
if (typeof errorLayout === 'function') {
|
|
176
|
+
errorLayout = errorLayout(this.context);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.setLayout(errorLayout);
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
setLayout(layout) {
|
|
184
|
+
if (layout && typeof layout !== 'string') {
|
|
185
|
+
throw new Error('[nuxt] Avoid using non-string value as layout property.');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (!layout || !layouts[`_${ layout }`]) {
|
|
189
|
+
layout = 'default';
|
|
190
|
+
}
|
|
191
|
+
this.layoutName = layout;
|
|
192
|
+
this.layout = layouts[`_${ layout }`];
|
|
193
|
+
|
|
194
|
+
return this.layout;
|
|
195
|
+
},
|
|
196
|
+
loadLayout(layout) {
|
|
197
|
+
if (!layout || !layouts[`_${ layout }`]) {
|
|
198
|
+
layout = 'default';
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return Promise.resolve(layouts[`_${ layout }`]);
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
components: { NuxtLoading }
|
|
206
|
+
};
|