@rancher/shell 0.3.29 → 0.5.0
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/ovhcloudmks.svg +122 -0
- package/assets/images/providers/ovhcloudpubliccloud.svg +122 -0
- package/assets/styles/global/_layout.scss +99 -0
- package/assets/translations/en-us.yaml +31 -6
- package/assets/translations/zh-hans.yaml +2 -2
- package/babel.config.js +7 -1
- package/chart/monitoring/alerting/index.vue +7 -21
- package/chart/monitoring/grafana/index.vue +55 -0
- package/chart/monitoring/index.vue +51 -17
- package/chart/monitoring/prometheus/index.vue +37 -43
- package/chart/rancher-backup/index.vue +2 -1
- package/cloud-credential/azure.vue +4 -17
- package/components/AsyncButton.vue +17 -5
- package/components/Certificates.vue +164 -0
- package/components/CodeMirror.vue +19 -21
- package/components/CopyCode.vue +6 -2
- package/components/CopyToClipboard.vue +2 -1
- package/components/CopyToClipboardText.vue +14 -9
- package/components/CruResource.vue +1 -0
- package/components/DraggableZone.vue +2 -2
- package/components/EtcdInfoBanner.vue +5 -5
- package/components/ExplorerProjectsNamespaces.vue +25 -1
- package/components/IconOrSvg.vue +1 -1
- package/components/LandingPagePreference.vue +1 -4
- package/components/Markdown.vue +16 -12
- package/components/PodSecurityAdmission.vue +2 -2
- package/components/Questions/index.vue +1 -1
- package/components/ResourceDetail/Masthead.vue +25 -9
- package/components/ResourceTable.vue +14 -2
- package/components/ResourceYaml.vue +5 -0
- package/components/SideNav.vue +1 -1
- package/components/SingleClusterInfo.vue +1 -4
- package/components/StatusTable.vue +5 -1
- package/components/Tabbed/index.vue +12 -0
- package/components/__tests__/CopyCode.test.ts +5 -4
- package/components/fleet/FleetBundles.vue +5 -11
- package/components/fleet/FleetRepos.vue +62 -27
- package/components/fleet/FleetResources.vue +6 -1
- package/components/fleet/FleetSummary.vue +3 -3
- package/components/fleet/__tests__/FleetSummary.test.ts +316 -0
- package/components/form/ArrayListSelect.vue +10 -0
- package/components/form/Error.vue +3 -3
- package/components/form/Footer.vue +2 -2
- package/components/form/GitPicker.vue +83 -38
- package/components/form/KeyValue.vue +4 -0
- package/components/form/LabeledSelect.vue +4 -0
- package/components/form/Password.vue +3 -1
- package/components/formatter/Checked.vue +11 -3
- package/components/formatter/FleetClusterSummaryGraph.vue +27 -0
- package/components/formatter/FleetSummaryGraph.vue +23 -11
- package/components/formatter/LiveDuration.vue +1 -1
- package/components/formatter/PercentageBar.vue +1 -1
- package/components/formatter/__tests__/Checked.test.ts +19 -0
- package/components/nav/Group.vue +2 -2
- package/components/nav/Header.vue +1 -2
- package/components/nav/TopLevelMenu.vue +36 -6
- package/components/nav/Type.vue +1 -3
- package/components/nav/WindowManager/ContainerLogs.vue +101 -3
- package/components/nav/WindowManager/ContainerShell.vue +6 -1
- package/components/nav/WindowManager/__tests__/ContainerLogs.test.ts +186 -0
- package/components/nav/WindowManager/index.vue +11 -10
- package/components/nav/__tests__/TopLevelMenu.test.ts +33 -0
- package/components/nav/__tests__/Type.test.ts +1 -1
- package/components/nuxt/nuxt-child.js +14 -78
- package/components/nuxt/nuxt.js +1 -1
- package/{layouts → components/templates}/blank.vue +1 -1
- package/{layouts → components/templates}/default.vue +8 -98
- package/{layouts → components/templates}/error.vue +10 -19
- package/{layouts → components/templates}/home.vue +4 -1
- package/{layouts → components/templates}/plain.vue +4 -1
- package/{layouts → components/templates}/standalone.vue +1 -1
- package/{layouts → components/templates}/unauthenticated.vue +1 -1
- package/composables/useCompactInput.test.ts +36 -0
- package/composables/useCompactInput.ts +20 -0
- package/composables/useLabeledFormElement.test.ts +135 -0
- package/composables/useLabeledFormElement.ts +138 -0
- package/config/harvester-manager-types.js +2 -0
- package/config/home-links.js +1 -1
- package/config/private-label.js +22 -0
- package/config/product/explorer.js +3 -0
- package/config/product/fleet.js +6 -1
- package/config/product/manager.js +8 -2
- package/config/query-params.js +1 -0
- package/config/router.js +385 -364
- package/config/settings.ts +1 -0
- package/config/store.js +1 -1
- package/config/system-namespaces.js +3 -0
- package/config/table-headers.js +47 -0
- package/core/plugin-helpers.js +3 -5
- package/core/plugin-routes.ts +56 -114
- package/core/plugin.ts +16 -10
- package/core/plugins-loader.js +7 -9
- package/core/plugins.js +0 -3
- package/creators/app/files/.gitlab-ci.yml +14 -0
- package/creators/app/init +19 -0
- package/detail/fleet.cattle.io.cluster.vue +11 -1
- package/detail/provisioning.cattle.io.cluster.vue +4 -3
- package/dialog/ScaleMachineDownDialog.vue +34 -17
- package/edit/__tests__/service.test.ts +89 -0
- package/edit/auth/googleoauth.vue +1 -5
- package/edit/cloudcredential.vue +2 -0
- package/edit/configmap.vue +2 -1
- package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +2 -2
- package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +12 -3
- package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +2 -1
- package/edit/networking.k8s.io.networkpolicy/__tests__/PolicyRuleTarget.spec.ts +1 -1
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +15 -7
- package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +112 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +473 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/{CustomCommand.tests.ts → CustomCommand.test.ts} +6 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/DrainOptions.test.ts +1 -1
- package/edit/provisioning.cattle.io.cluster/__tests__/index.test.ts +73 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +7 -1
- package/edit/provisioning.cattle.io.cluster/__tests__/utils/cluster.ts +386 -0
- package/edit/provisioning.cattle.io.cluster/import.vue +2 -2
- package/edit/provisioning.cattle.io.cluster/index.vue +92 -36
- package/edit/provisioning.cattle.io.cluster/rke2.vue +171 -583
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +137 -0
- package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +157 -0
- package/edit/provisioning.cattle.io.cluster/{Basics.vue → tabs/Basics.vue} +94 -19
- package/edit/provisioning.cattle.io.cluster/{MachinePool.vue → tabs/MachinePool.vue} +1 -0
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +135 -0
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +189 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +144 -0
- package/edit/provisioning.cattle.io.cluster/tabs/upgrade/index.vue +76 -0
- package/edit/service.vue +12 -0
- package/edit/workload/Upgrading.vue +3 -2
- package/edit/workload/mixins/workload.js +1 -1
- package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +2 -1
- package/initialize/App.js +25 -71
- package/initialize/client.js +21 -162
- package/initialize/index.js +47 -124
- package/list/management.cattle.io.feature.vue +1 -7
- package/list/node.vue +1 -0
- package/machine-config/__tests__/vmwarevsphere.test.ts +100 -21
- package/machine-config/vmwarevsphere.vue +73 -51
- package/middleware/authenticated.js +10 -17
- package/mixins/auth-config.js +2 -7
- package/mixins/brand.js +29 -41
- package/mixins/create-edit-view/index.js +2 -2
- package/mixins/labeled-form-element.ts +6 -1
- package/models/__tests__/management.cattle.io.cluster.test.ts +4 -0
- package/models/__tests__/management.cattle.io.node.ts +85 -0
- package/models/__tests__/management.cattle.io.nodepool.ts +83 -0
- package/models/__tests__/namespace.test.ts +49 -9
- package/models/__tests__/workload.test.ts +91 -0
- package/models/cluster/node.js +4 -4
- package/models/cluster.x-k8s.io.machinedeployment.js +14 -0
- package/models/fleet.cattle.io.cluster.js +4 -0
- package/models/fleet.cattle.io.gitrepo.js +56 -13
- package/models/management.cattle.io.cluster.js +7 -3
- package/models/management.cattle.io.kontainerdriver.js +1 -1
- package/models/management.cattle.io.node.js +18 -14
- package/models/management.cattle.io.nodepool.js +17 -0
- package/models/namespace.js +1 -1
- package/models/pod.js +20 -0
- package/models/provisioning.cattle.io.cluster.js +39 -4
- package/models/secret.js +117 -18
- package/models/workload.js +16 -0
- package/models/workload.service.js +18 -0
- package/package.json +11 -10
- package/pages/about.vue +0 -1
- package/pages/account/create-key.vue +0 -1
- package/pages/account/index.vue +0 -1
- package/pages/auth/login.vue +0 -1
- package/pages/auth/logout.vue +0 -2
- package/pages/auth/setup.vue +0 -4
- package/pages/auth/verify.vue +14 -8
- package/pages/c/_cluster/apps/charts/index.vue +64 -43
- package/pages/c/_cluster/apps/charts/install.vue +4 -4
- package/pages/c/_cluster/apps/index.vue +0 -2
- package/pages/c/_cluster/auth/index.vue +0 -2
- package/pages/c/_cluster/ecm/index.vue +0 -2
- package/pages/c/_cluster/explorer/index.vue +28 -2
- package/pages/c/_cluster/fleet/index.vue +1 -1
- package/pages/c/_cluster/index.vue +0 -2
- package/pages/c/_cluster/settings/banners.vue +0 -2
- package/pages/c/_cluster/settings/brand.vue +0 -2
- package/pages/c/_cluster/settings/index.vue +0 -2
- package/pages/c/_cluster/settings/links.vue +0 -1
- package/pages/c/_cluster/settings/performance.vue +0 -1
- package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +2 -1
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +10 -46
- package/pages/c/_cluster/uiplugins/index.vue +0 -2
- package/pages/diagnostic.vue +1 -2
- package/pages/fail-whale.vue +0 -1
- package/pages/prefs.vue +0 -1
- package/pages/support/index.vue +2 -8
- package/pkg/auto-import.js +1 -1
- package/plugins/axios.js +0 -36
- package/plugins/back-button.js +3 -5
- package/plugins/clean-html-directive.js +1 -19
- package/plugins/clean-html.js +53 -0
- package/plugins/clean-tooltip-directive.js +1 -1
- package/plugins/codemirror-loader.js +1 -1
- package/plugins/codemirror.js +41 -0
- package/plugins/dashboard-store/__tests__/{mutations.spec.ts → mutations.test.ts} +1 -1
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +49 -0
- package/plugins/dashboard-store/__tests__/utils/store-mocks.ts +7 -0
- package/plugins/dashboard-store/actions.js +30 -4
- package/plugins/dashboard-store/classify.js +1 -18
- package/plugins/dashboard-store/getters.js +10 -5
- package/plugins/dashboard-store/index.js +0 -12
- package/plugins/dashboard-store/mutations.js +0 -4
- package/plugins/dashboard-store/resource-class.js +59 -18
- package/plugins/index.js +11 -0
- package/plugins/steve/__tests__/steve-class.spec.ts +59 -0
- package/plugins/steve/__tests__/utils/steve-mocks.ts +31 -0
- package/plugins/steve/getters.js +4 -1
- package/plugins/steve/norman-class.js +19 -0
- package/plugins/steve/steve-class.js +22 -0
- package/plugins/steve/subscribe.js +4 -10
- package/rancher-components/Accordion/Accordion.test.ts +45 -0
- package/rancher-components/Accordion/Accordion.vue +86 -0
- package/rancher-components/Accordion/index.ts +1 -0
- package/rancher-components/BadgeState/BadgeState.vue +3 -3
- package/rancher-components/Banner/Banner.vue +2 -2
- package/rancher-components/Card/Card.vue +3 -3
- package/rancher-components/Form/Checkbox/Checkbox.vue +3 -3
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +18 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +65 -24
- package/rancher-components/Form/Radio/RadioButton.test.ts +7 -3
- package/rancher-components/Form/Radio/RadioButton.vue +13 -7
- package/rancher-components/Form/Radio/RadioGroup.test.ts +30 -0
- package/rancher-components/Form/Radio/RadioGroup.vue +8 -3
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +6 -4
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +7 -4
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +9 -4
- package/rancher-components/StringList/StringList.test.ts +270 -0
- package/rancher-components/StringList/StringList.vue +65 -26
- package/rancher-components/components/Accordion/Accordion.test.ts +45 -0
- package/rancher-components/components/Accordion/Accordion.vue +86 -0
- package/rancher-components/components/Accordion/index.ts +1 -0
- package/rancher-components/components/BadgeState/BadgeState.vue +3 -3
- package/rancher-components/components/Banner/Banner.vue +2 -2
- package/rancher-components/components/Card/Card.vue +3 -3
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +3 -3
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +18 -1
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +57 -24
- package/rancher-components/components/Form/Radio/RadioButton.vue +13 -7
- package/rancher-components/components/Form/Radio/RadioGroup.vue +4 -3
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +6 -4
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +7 -4
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +9 -4
- package/rancher-components/components/StringList/StringList.vue +8 -8
- package/scripts/.gitlab/workflows/build-extension-catalog.gitlab-ci.yml +50 -0
- package/scripts/extension/bundle +19 -7
- package/scripts/extension/helm/scripts/package +11 -3
- package/scripts/extension/parse-tag-name +2 -2
- package/scripts/extension/publish +20 -9
- package/scripts/publish-shell.sh +10 -0
- package/scripts/test-plugins-build.sh +85 -9
- package/server/har-file.js +183 -0
- package/store/catalog.js +1 -1
- package/store/features.js +1 -0
- package/store/i18n.js +11 -0
- package/store/index.js +13 -15
- package/store/prefs.js +33 -35
- package/store/type-map.js +8 -7
- package/tsconfig.json +35 -9
- package/tsconfig.paths.json +21 -0
- package/types/shell/index.d.ts +433 -234
- package/types/vue-shim.d.ts +42 -0
- package/utils/__tests__/create-yaml.test.ts +60 -0
- package/utils/axios.js +0 -19
- package/utils/azure.js +24 -0
- package/utils/clipboard.js +5 -0
- package/utils/create-yaml.js +17 -10
- package/utils/git.ts +1 -1
- package/utils/monitoring.js +1 -1
- package/utils/nuxt.js +18 -39
- package/utils/object.js +14 -0
- package/utils/router.scrollBehavior.js +12 -14
- package/utils/time.js +1 -1
- package/utils/url.ts +1 -1
- package/vue.config.js +23 -2
- package/.DS_Store +0 -0
- package/assets/images/providers/aks-black.svg +0 -28
- package/assets/images/providers/aks.svg +0 -31
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.tests.ts +0 -234
- package/initialize/layouts.ts +0 -26
- package/mixins/fetch.server.js +0 -73
- package/pages/c/index.vue +0 -9
- package/pages/rio/mesh.vue +0 -508
- package/plugins/transitions.js +0 -4
- package/plugins/vue-clipboard2.js +0 -4
- package/tsconfig.default.json +0 -46
- package/yarn-error.log +0 -200
- /package/components/form/__tests__/{NameNsDescription.ts → NameNsDescription.test.ts} +0 -0
- /package/edit/networking.k8s.io.networkpolicy/__tests__/utils/{selectors.ts → selectors.test.ts} +0 -0
- /package/edit/provisioning.cattle.io.cluster/{AgentConfiguration.vue → tabs/AgentConfiguration.vue} +0 -0
- /package/edit/provisioning.cattle.io.cluster/{MemberRoles.vue → tabs/MemberRoles.vue} +0 -0
- /package/edit/provisioning.cattle.io.cluster/{S3Config.vue → tabs/etcd/S3Config.vue} +0 -0
- /package/edit/provisioning.cattle.io.cluster/{ACE.vue → tabs/networking/ACE.vue} +0 -0
- /package/edit/provisioning.cattle.io.cluster/{RegistryConfigs.vue → tabs/registries/RegistryConfigs.vue} +0 -0
- /package/edit/provisioning.cattle.io.cluster/{RegistryMirrors.vue → tabs/registries/RegistryMirrors.vue} +0 -0
- /package/edit/provisioning.cattle.io.cluster/{DrainOptions.vue → tabs/upgrade/DrainOptions.vue} +0 -0
- /package/plugins/dashboard-store/__tests__/{actions.spec.ts → actions.test.ts} +0 -0
- /package/plugins/dashboard-store/__tests__/{getters.spec.ts → getters.test.ts} +0 -0
- /package/rancher-components/BadgeState/{BadgeState.spec.ts → BadgeState.test.ts} +0 -0
- /package/rancher-components/components/BadgeState/{BadgeState.spec.ts → BadgeState.test.ts} +0 -0
package/pages/support/index.vue
CHANGED
|
@@ -10,7 +10,6 @@ import { isRancherPrime } from '@shell/config/version';
|
|
|
10
10
|
import { hasCspAdapter } from 'mixins/brand';
|
|
11
11
|
|
|
12
12
|
export default {
|
|
13
|
-
layout: 'home',
|
|
14
13
|
|
|
15
14
|
components: {
|
|
16
15
|
BannerGraphic,
|
|
@@ -82,13 +81,8 @@ export default {
|
|
|
82
81
|
},
|
|
83
82
|
|
|
84
83
|
serverUrl() {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return window.location.origin;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Server-side rendered
|
|
91
|
-
return this.serverSetting?.value || '';
|
|
84
|
+
// Client-side rendered: use the current window location
|
|
85
|
+
return window.location.origin;
|
|
92
86
|
},
|
|
93
87
|
|
|
94
88
|
supportConfigLink() {
|
package/pkg/auto-import.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const contextFolders = ['chart', 'cloud-credential', 'content', 'detail', 'edit', '
|
|
3
|
+
const contextFolders = ['chart', 'cloud-credential', 'content', 'detail', 'edit', 'list', 'machine-config', 'models', 'promptRemove', 'l10n', 'windowComponents', 'dialog', 'formatters', 'login'];
|
|
4
4
|
const contextMap = contextFolders.reduce((map, obj) => {
|
|
5
5
|
map[obj] = true;
|
|
6
6
|
|
package/plugins/axios.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import https from 'https';
|
|
2
2
|
import { CSRF } from '@shell/config/cookies';
|
|
3
|
-
import { parse as setCookieParser } from 'set-cookie-parser';
|
|
4
|
-
import pkg from '../package.json';
|
|
5
3
|
|
|
6
4
|
export default function({
|
|
7
5
|
$axios, $cookies, isDev, req
|
|
@@ -15,42 +13,8 @@ export default function({
|
|
|
15
13
|
if ( csrf ) {
|
|
16
14
|
config.headers['x-api-csrf'] = csrf;
|
|
17
15
|
}
|
|
18
|
-
|
|
19
|
-
if ( process.server ) {
|
|
20
|
-
config.headers.common['access-control-expose-headers'] = `set-cookie`;
|
|
21
|
-
config.headers.common['user-agent'] = `Dashboard (Mozilla) v${ pkg.version }`;
|
|
22
|
-
|
|
23
|
-
if ( req.headers.cookie ) {
|
|
24
|
-
config.headers.common['cookies'] = req.headers.cookie;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if ( config.url.startsWith('/') ) {
|
|
28
|
-
config.baseURL = `${ req.protocol || 'https' }://${ req.headers.host }`;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
16
|
});
|
|
32
17
|
|
|
33
|
-
if ( process.server ) {
|
|
34
|
-
$axios.onResponse((res) => {
|
|
35
|
-
const parsed = setCookieParser(res.headers['set-cookie'] || []);
|
|
36
|
-
|
|
37
|
-
for ( const opt of parsed ) {
|
|
38
|
-
const key = opt.name;
|
|
39
|
-
const value = opt.value;
|
|
40
|
-
|
|
41
|
-
delete opt.name;
|
|
42
|
-
delete opt.value;
|
|
43
|
-
|
|
44
|
-
opt.encode = (x) => x;
|
|
45
|
-
opt.sameSite = true;
|
|
46
|
-
opt.path = '/';
|
|
47
|
-
opt.secure = true;
|
|
48
|
-
|
|
49
|
-
$cookies.set(key, value, opt);
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
18
|
if ( isDev ) {
|
|
55
19
|
// https://github.com/nuxt-community/axios-module/blob/dev/lib/module.js#L78
|
|
56
20
|
// forces localhost to http, for no obvious reason.
|
package/plugins/back-button.js
CHANGED
|
@@ -1,23 +1,5 @@
|
|
|
1
1
|
import Vue from 'vue';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
const ALLOWED_TAGS = [
|
|
5
|
-
'code',
|
|
6
|
-
'li',
|
|
7
|
-
'a',
|
|
8
|
-
'p',
|
|
9
|
-
'b',
|
|
10
|
-
'br',
|
|
11
|
-
'ul',
|
|
12
|
-
'pre',
|
|
13
|
-
'span',
|
|
14
|
-
'div',
|
|
15
|
-
'i',
|
|
16
|
-
'em',
|
|
17
|
-
'strong',
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
export const purifyHTML = (value) => DOMPurify.sanitize(value, { ALLOWED_TAGS });
|
|
2
|
+
import { purifyHTML } from './clean-html';
|
|
21
3
|
|
|
22
4
|
export const cleanHtmlDirective = {
|
|
23
5
|
inserted(el, binding) {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import DOMPurify from 'dompurify';
|
|
2
|
+
import { uniq } from '@shell/utils/array';
|
|
3
|
+
|
|
4
|
+
const ALLOWED_TAGS = [
|
|
5
|
+
'code',
|
|
6
|
+
'li',
|
|
7
|
+
'a',
|
|
8
|
+
'p',
|
|
9
|
+
'b',
|
|
10
|
+
'br',
|
|
11
|
+
'ul',
|
|
12
|
+
'pre',
|
|
13
|
+
'span',
|
|
14
|
+
'div',
|
|
15
|
+
'i',
|
|
16
|
+
'em',
|
|
17
|
+
'strong',
|
|
18
|
+
'h1',
|
|
19
|
+
'h2',
|
|
20
|
+
'h3',
|
|
21
|
+
'h4',
|
|
22
|
+
'h5',
|
|
23
|
+
'h6',
|
|
24
|
+
'table',
|
|
25
|
+
'thead',
|
|
26
|
+
'tr',
|
|
27
|
+
'th',
|
|
28
|
+
'tbody',
|
|
29
|
+
'td',
|
|
30
|
+
'blockquote'
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
// Allow 'A' tags to keep the target=_blank attribute if they have it
|
|
34
|
+
DOMPurify.addHook('uponSanitizeAttribute', (node, data) => {
|
|
35
|
+
if (node.tagName === 'A' && data.attrName === 'target' && data.attrValue === '_blank') {
|
|
36
|
+
data.forceKeepAttr = true;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Ensure if an 'A' tag has target=_blank that we add noopener, noreferrer and nofollow to the 'rel' attribute
|
|
41
|
+
DOMPurify.addHook('afterSanitizeAttributes', (node) => {
|
|
42
|
+
if (node.tagName === 'A' && node?.target === '_blank') {
|
|
43
|
+
const rel = ['noopener', 'noreferrer', 'nofollow'];
|
|
44
|
+
const existingRel = node.rel?.length ? node.rel.split(' ') : [];
|
|
45
|
+
const combined = uniq([...rel, ...existingRel]);
|
|
46
|
+
|
|
47
|
+
node.setAttribute('rel', combined.join(' '));
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export const purifyHTML = (value, options = { ALLOWED_TAGS }) => {
|
|
52
|
+
return DOMPurify.sanitize(value, options);
|
|
53
|
+
};
|
package/plugins/codemirror.js
CHANGED
|
@@ -125,6 +125,47 @@ CodeMirror.defineExtension('foldLinesMatching', function(regex) {
|
|
|
125
125
|
});
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
+
function countSpaces(line) {
|
|
129
|
+
for (let i = 0; i < line.length; i++) {
|
|
130
|
+
if (line[i] !== ' ') {
|
|
131
|
+
return i;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return line.length;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
CodeMirror.defineExtension('foldYaml', function(path) {
|
|
139
|
+
this.operation(() => {
|
|
140
|
+
let elements = [];
|
|
141
|
+
|
|
142
|
+
for (let i = this.firstLine(), e = this.lastLine(); i <= e; i++) {
|
|
143
|
+
const line = this.getLine(i);
|
|
144
|
+
const index = countSpaces(line);
|
|
145
|
+
const trimmed = line.trim();
|
|
146
|
+
|
|
147
|
+
if (trimmed.endsWith(':') || trimmed.endsWith(': >-')) {
|
|
148
|
+
const name = trimmed.split(':')[0].substr(0, trimmed.length - 1);
|
|
149
|
+
|
|
150
|
+
// Remove all elements of the same are greater index
|
|
151
|
+
elements = elements.filter((e) => e.index < index);
|
|
152
|
+
|
|
153
|
+
// Add on this one
|
|
154
|
+
elements.push({
|
|
155
|
+
index,
|
|
156
|
+
name
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const currentPath = elements.map((e) => e.name).join('.');
|
|
160
|
+
|
|
161
|
+
if (currentPath === path) {
|
|
162
|
+
this.foldCode(CodeMirror.Pos(i, 0), null, 'fold');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
128
169
|
CodeMirror.registerHelper('fold', 'yamlcomments', (cm, start) => {
|
|
129
170
|
if ( !isLineComment(cm, start.line) ) {
|
|
130
171
|
return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { batchChanges } from '@shell/plugins/dashboard-store/mutations';
|
|
1
|
+
import { batchChanges } from '@shell/plugins/dashboard-store/mutations.js';
|
|
2
2
|
import { POD, WORKLOAD_TYPES } from '@shell/config/types';
|
|
3
3
|
import Resource from '@shell/plugins/dashboard-store/resource-class';
|
|
4
4
|
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import Resource from '@shell/plugins/dashboard-store/resource-class.js';
|
|
2
|
+
import { resourceClassJunkObject } from '@shell/plugins/dashboard-store/__tests__/utils/store-mocks';
|
|
3
|
+
|
|
4
|
+
describe('class: Resource', () => {
|
|
5
|
+
describe('given custom resource keys', () => {
|
|
6
|
+
const customResource = resourceClassJunkObject;
|
|
7
|
+
|
|
8
|
+
it('should keep internal keys', () => {
|
|
9
|
+
const resource = new Resource(customResource, {
|
|
10
|
+
getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
|
|
11
|
+
dispatch: jest.fn(),
|
|
12
|
+
rootGetters: { 'i18n/t': jest.fn() },
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
expect({ ...resource }).toStrictEqual(customResource);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('method: save', () => {
|
|
19
|
+
it('should remove all the internal keys', async() => {
|
|
20
|
+
const dispatch = jest.fn();
|
|
21
|
+
const resource = new Resource(customResource, {
|
|
22
|
+
getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
|
|
23
|
+
dispatch,
|
|
24
|
+
rootGetters: { 'i18n/t': jest.fn() },
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const expectation = { type: customResource.type };
|
|
28
|
+
|
|
29
|
+
await resource.save();
|
|
30
|
+
|
|
31
|
+
const opt = {
|
|
32
|
+
data: expectation,
|
|
33
|
+
headers: {
|
|
34
|
+
accept: 'application/json',
|
|
35
|
+
'content-type': 'application/json',
|
|
36
|
+
},
|
|
37
|
+
method: 'post',
|
|
38
|
+
url: undefined,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Data sent should have been cleaned
|
|
42
|
+
expect(dispatch).toHaveBeenCalledWith('request', { opt, type: customResource.type });
|
|
43
|
+
|
|
44
|
+
// Original workload model should remain unchanged
|
|
45
|
+
expect({ ...resource }).toStrictEqual(customResource);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -15,7 +15,8 @@ export const _ALL_IF_AUTHED = 'allIfAuthed';
|
|
|
15
15
|
export const _NONE = 'none';
|
|
16
16
|
|
|
17
17
|
const SCHEMA_CHECK_RETRIES = 15;
|
|
18
|
-
const
|
|
18
|
+
const HAVE_ALL_CHECK_RETRIES = 15;
|
|
19
|
+
const RETRY_LOG = 10;
|
|
19
20
|
|
|
20
21
|
export async function handleSpoofedRequest(rootGetters, schemaStore, opt, product) {
|
|
21
22
|
// Handle spoofed types instead of making an actual request
|
|
@@ -70,6 +71,10 @@ export async function loadSchemas(ctx, watch = true) {
|
|
|
70
71
|
return all;
|
|
71
72
|
}
|
|
72
73
|
|
|
74
|
+
const findAllGetter = (getters, type, opt) => {
|
|
75
|
+
return opt.namespaced ? getters.matching(type, null, opt.namespaced, { skipSelector: true }) : getters.all(type);
|
|
76
|
+
};
|
|
77
|
+
|
|
73
78
|
export default {
|
|
74
79
|
request() {
|
|
75
80
|
throw new Error('Not Implemented');
|
|
@@ -163,7 +168,7 @@ export default {
|
|
|
163
168
|
dispatch('watch', args);
|
|
164
169
|
}
|
|
165
170
|
|
|
166
|
-
return getters
|
|
171
|
+
return findAllGetter(getters, type, opt);
|
|
167
172
|
}
|
|
168
173
|
|
|
169
174
|
let load = (opt.load === undefined ? _ALL : opt.load);
|
|
@@ -328,7 +333,7 @@ export default {
|
|
|
328
333
|
dispatch('watch', args);
|
|
329
334
|
}
|
|
330
335
|
|
|
331
|
-
const all = getters
|
|
336
|
+
const all = findAllGetter(getters, type, opt);
|
|
332
337
|
|
|
333
338
|
if (!opt.incremental && opt.hasManualRefresh) {
|
|
334
339
|
dispatch('resource-fetch/updateManualRefreshIsLoading', false, { root: true });
|
|
@@ -613,7 +618,7 @@ export default {
|
|
|
613
618
|
schema = getters['schemaFor'](type);
|
|
614
619
|
|
|
615
620
|
if (!schema) {
|
|
616
|
-
if (tries ===
|
|
621
|
+
if (tries === RETRY_LOG) {
|
|
617
622
|
console.warn(`Schema for ${ type } not available... retrying...`); // eslint-disable-line no-console
|
|
618
623
|
}
|
|
619
624
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
@@ -628,6 +633,27 @@ export default {
|
|
|
628
633
|
}
|
|
629
634
|
},
|
|
630
635
|
|
|
636
|
+
async waitForHaveAll({ getters }, { type, throwError = false, attempts = HAVE_ALL_CHECK_RETRIES }) {
|
|
637
|
+
let tries = attempts;
|
|
638
|
+
let haveAll = null;
|
|
639
|
+
|
|
640
|
+
while (!haveAll && tries > 0) {
|
|
641
|
+
haveAll = getters['haveAll'](type);
|
|
642
|
+
|
|
643
|
+
if (!haveAll) {
|
|
644
|
+
if (tries === RETRY_LOG) {
|
|
645
|
+
console.warn(`wait for all of ${ type } continuing...`); // eslint-disable-line no-console
|
|
646
|
+
}
|
|
647
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
648
|
+
tries--;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
if (tries === 0 && throwError) {
|
|
653
|
+
throw new Error(`Failed to wait for all of ${ type }`);
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
|
|
631
657
|
incrementLoadCounter({ commit }, resource) {
|
|
632
658
|
commit('incrementLoadCounter', resource);
|
|
633
659
|
},
|
|
@@ -12,24 +12,7 @@ export function classify(ctx, obj, isClone = false) {
|
|
|
12
12
|
|
|
13
13
|
const customModel = ctx.getters['classify'](obj);
|
|
14
14
|
|
|
15
|
-
const out = new customModel(obj, ctx,
|
|
16
|
-
|
|
17
|
-
if ( process.server ) {
|
|
18
|
-
Object.defineProperty(obj, '__rehydrate', {
|
|
19
|
-
value: ctx.state.config.namespace,
|
|
20
|
-
enumerable: true,
|
|
21
|
-
configurable: true
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
if ( isClone ) {
|
|
25
|
-
Object.defineProperty(obj, '__clone', {
|
|
26
|
-
value: true,
|
|
27
|
-
enumerable: true,
|
|
28
|
-
configurable: true,
|
|
29
|
-
writable: true
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
}
|
|
15
|
+
const out = new customModel(obj, ctx, null, isClone);
|
|
33
16
|
|
|
34
17
|
return out;
|
|
35
18
|
}
|
|
@@ -64,19 +64,24 @@ export default {
|
|
|
64
64
|
return state.types[type].list;
|
|
65
65
|
},
|
|
66
66
|
|
|
67
|
-
matching: (state, getters, rootState) => (type, selector, namespace) => {
|
|
68
|
-
let
|
|
67
|
+
matching: (state, getters, rootState) => (type, selector, namespace, config = { skipSelector: false }) => {
|
|
68
|
+
let matching = getters['all'](type);
|
|
69
69
|
|
|
70
70
|
// Filter first by namespace if one is provided, since this is efficient
|
|
71
|
-
if (namespace) {
|
|
72
|
-
|
|
71
|
+
if (namespace && typeof namespace === 'string') {
|
|
72
|
+
matching = matching.filter((obj) => obj.namespace === namespace);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
garbageCollect.gcUpdateLastAccessed({
|
|
76
76
|
state, getters, rootState
|
|
77
77
|
}, type);
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
// Looks like a falsy selector is a thing, so if we're not interested in filtering by the selector... explicitly avoid it
|
|
80
|
+
if (config.skipSelector) {
|
|
81
|
+
return matching;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return matching.filter((obj) => {
|
|
80
85
|
return matches(obj, selector);
|
|
81
86
|
});
|
|
82
87
|
},
|
|
@@ -33,21 +33,9 @@ export default (vuexModule, config, init) => {
|
|
|
33
33
|
const namespace = config.namespace || '';
|
|
34
34
|
|
|
35
35
|
return function(store) {
|
|
36
|
-
// const inst = SteveFactory(namespace, config.baseUrl);
|
|
37
|
-
|
|
38
36
|
store.registerModule(namespace, vuexModule);
|
|
39
37
|
store.commit(`${ namespace }/applyConfig`, config);
|
|
40
38
|
|
|
41
|
-
if ( !process.client ) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// store.subscribe(({ type }, state) => {
|
|
46
|
-
// if ( type === 'auth/loggedOut' ) {
|
|
47
|
-
// store.dispatch(`${ namespace }/unsubscribe`);
|
|
48
|
-
// }
|
|
49
|
-
// });
|
|
50
|
-
|
|
51
39
|
const module = store._modules.root._children[namespace];
|
|
52
40
|
const fromServer = window.__NUXT__;
|
|
53
41
|
|
|
@@ -23,10 +23,6 @@ function registerType(state, type) {
|
|
|
23
23
|
// Not enumerable so they don't get sent back to the client for SSR
|
|
24
24
|
Object.defineProperty(cache, 'map', { value: new Map() });
|
|
25
25
|
|
|
26
|
-
if ( process.server && !cache.list.__rehydrateAll ) {
|
|
27
|
-
Object.defineProperty(cache.list, '__rehydrateAll', { value: `${ state.config.namespace }/${ type }`, enumerable: true });
|
|
28
|
-
}
|
|
29
|
-
|
|
30
26
|
Vue.set(state.types, type, cache);
|
|
31
27
|
}
|
|
32
28
|
|
|
@@ -105,6 +105,7 @@ export const STATES_ENUM = {
|
|
|
105
105
|
ERRORING: 'erroring',
|
|
106
106
|
ERRORS: 'errors',
|
|
107
107
|
EXPIRED: 'expired',
|
|
108
|
+
EXPIRING: 'expiring',
|
|
108
109
|
FAIL: 'fail',
|
|
109
110
|
FAILED: 'failed',
|
|
110
111
|
HEALTHY: 'healthy',
|
|
@@ -167,6 +168,13 @@ export const STATES_ENUM = {
|
|
|
167
168
|
WARNING: 'warning',
|
|
168
169
|
};
|
|
169
170
|
|
|
171
|
+
export function mapStateToEnum(statusString) {
|
|
172
|
+
// e.g. in fleet Status is Capitalized. This function will map it to the enum
|
|
173
|
+
return Object.values(STATES_ENUM).find((val) => {
|
|
174
|
+
return val.toLowerCase() === statusString.toLocaleLowerCase();
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
170
178
|
export const STATES = {
|
|
171
179
|
[STATES_ENUM.IN_USE]: {
|
|
172
180
|
color: 'success', icon: 'dot-open', label: 'In Use', compoundIcon: 'checkmark'
|
|
@@ -253,7 +261,10 @@ export const STATES = {
|
|
|
253
261
|
color: 'error', icon: 'error', label: 'Errors', compoundIcon: 'error'
|
|
254
262
|
},
|
|
255
263
|
[STATES_ENUM.EXPIRED]: {
|
|
256
|
-
color: '
|
|
264
|
+
color: 'error', icon: 'error', label: 'Expired', compoundIcon: 'warning'
|
|
265
|
+
},
|
|
266
|
+
[STATES_ENUM.EXPIRING]: {
|
|
267
|
+
color: 'warning', icon: 'error', label: 'Expiring', compoundIcon: 'error'
|
|
257
268
|
},
|
|
258
269
|
[STATES_ENUM.FAIL]: {
|
|
259
270
|
color: 'error', icon: 'error', label: 'Fail', compoundIcon: 'error'
|
|
@@ -512,6 +523,28 @@ export function stateDisplay(state) {
|
|
|
512
523
|
return key.split(/-/).map(ucFirst).join('-');
|
|
513
524
|
}
|
|
514
525
|
|
|
526
|
+
export function primaryDisplayStatusFromCount(status) {
|
|
527
|
+
const statusOrder = [
|
|
528
|
+
STATES_ENUM.ERROR,
|
|
529
|
+
STATES_ENUM.FAILED,
|
|
530
|
+
STATES_ENUM.WARNING,
|
|
531
|
+
STATES_ENUM.MODIFIED,
|
|
532
|
+
STATES_ENUM.WAIT_APPLIED,
|
|
533
|
+
STATES_ENUM.ORPHANED,
|
|
534
|
+
STATES_ENUM.MISSING,
|
|
535
|
+
STATES_ENUM.UNKNOWN,
|
|
536
|
+
STATES_ENUM.NOT_READY,
|
|
537
|
+
STATES_ENUM.READY,
|
|
538
|
+
];
|
|
539
|
+
|
|
540
|
+
// sort status by order of statusOrder
|
|
541
|
+
const existingStatuses = Object.keys(status).filter((key) => {
|
|
542
|
+
return status[key] > 0 && statusOrder.includes(key.toLowerCase());
|
|
543
|
+
}).sort((a, b) => statusOrder.indexOf(a.toLowerCase()) - statusOrder.indexOf(b.toLowerCase()));
|
|
544
|
+
|
|
545
|
+
return existingStatuses[0] ? existingStatuses[0] : STATES_ENUM.UNKNOWN;
|
|
546
|
+
}
|
|
547
|
+
|
|
515
548
|
export function stateSort(color, display) {
|
|
516
549
|
color = color.replace(/^(text|bg)-/, '');
|
|
517
550
|
|
|
@@ -1089,6 +1122,16 @@ export default class Resource {
|
|
|
1089
1122
|
return this._save(...arguments);
|
|
1090
1123
|
}
|
|
1091
1124
|
|
|
1125
|
+
/**
|
|
1126
|
+
* Remove any unwanted properties from the object that will be saved
|
|
1127
|
+
*/
|
|
1128
|
+
cleanForSave(data, forNew) {
|
|
1129
|
+
delete data.__rehydrate;
|
|
1130
|
+
delete data.__clone;
|
|
1131
|
+
|
|
1132
|
+
return data;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1092
1135
|
/**
|
|
1093
1136
|
* Allow to handle the response of the save request
|
|
1094
1137
|
* @param {*} res Full request response
|
|
@@ -1096,9 +1139,6 @@ export default class Resource {
|
|
|
1096
1139
|
processSaveResponse(res) { }
|
|
1097
1140
|
|
|
1098
1141
|
async _save(opt = {}) {
|
|
1099
|
-
delete this.__rehydrate;
|
|
1100
|
-
delete this.__clone;
|
|
1101
|
-
|
|
1102
1142
|
const forNew = !this.id;
|
|
1103
1143
|
|
|
1104
1144
|
const errors = await this.validationErrors(this, opt.ignoreFields);
|
|
@@ -1145,22 +1185,24 @@ export default class Resource {
|
|
|
1145
1185
|
// @TODO remove this once the API maps steve _type <-> k8s type in both directions
|
|
1146
1186
|
opt.data = this.toSave() || { ...this };
|
|
1147
1187
|
|
|
1148
|
-
if (opt
|
|
1188
|
+
if (opt.data._type) {
|
|
1149
1189
|
opt.data.type = opt.data._type;
|
|
1150
1190
|
}
|
|
1151
1191
|
|
|
1152
|
-
if (opt
|
|
1192
|
+
if (opt.data._name) {
|
|
1153
1193
|
opt.data.name = opt.data._name;
|
|
1154
1194
|
}
|
|
1155
1195
|
|
|
1156
|
-
if (opt
|
|
1196
|
+
if (opt.data._labels) {
|
|
1157
1197
|
opt.data.labels = opt.data._labels;
|
|
1158
1198
|
}
|
|
1159
1199
|
|
|
1160
|
-
if (opt
|
|
1200
|
+
if (opt.data._annotations) {
|
|
1161
1201
|
opt.data.annotations = opt.data._annotations;
|
|
1162
1202
|
}
|
|
1163
1203
|
|
|
1204
|
+
opt.data = this.cleanForSave(opt.data, forNew);
|
|
1205
|
+
|
|
1164
1206
|
// handle "replace" opt as a query param _replace=true for norman PUT requests
|
|
1165
1207
|
if (opt?.replace && opt.method === 'put') {
|
|
1166
1208
|
const argParam = opt.url.includes('?') ? '&' : '?';
|
|
@@ -1218,19 +1260,11 @@ export default class Resource {
|
|
|
1218
1260
|
// ------------------------------------------------------------------
|
|
1219
1261
|
|
|
1220
1262
|
currentRoute() {
|
|
1221
|
-
|
|
1222
|
-
return this.$rootState.$route;
|
|
1223
|
-
} else {
|
|
1224
|
-
return window.$nuxt.$route;
|
|
1225
|
-
}
|
|
1263
|
+
return window.$nuxt.$route;
|
|
1226
1264
|
}
|
|
1227
1265
|
|
|
1228
1266
|
currentRouter() {
|
|
1229
|
-
|
|
1230
|
-
return this.$rootState.$router;
|
|
1231
|
-
} else {
|
|
1232
|
-
return window.$nuxt.$router;
|
|
1233
|
-
}
|
|
1267
|
+
return window.$nuxt.$router;
|
|
1234
1268
|
}
|
|
1235
1269
|
|
|
1236
1270
|
get listLocation() {
|
|
@@ -1931,4 +1965,11 @@ export default class Resource {
|
|
|
1931
1965
|
get creationTimestamp() {
|
|
1932
1966
|
return this.metadata?.creationTimestamp;
|
|
1933
1967
|
}
|
|
1968
|
+
|
|
1969
|
+
/**
|
|
1970
|
+
* Allows model to specify JSON Paths that should be folded in the YAML editor by default
|
|
1971
|
+
*/
|
|
1972
|
+
get yamlFolding() {
|
|
1973
|
+
return [];
|
|
1974
|
+
}
|
|
1934
1975
|
}
|
package/plugins/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load the directives
|
|
3
|
+
*
|
|
4
|
+
* These are included in a function that can be explictly called, so that we can be sure
|
|
5
|
+
* of the execution order, rather than importing them at the top of a file.
|
|
6
|
+
*/
|
|
7
|
+
export function loadDirectives() {
|
|
8
|
+
import('./clean-html-directive');
|
|
9
|
+
import('./clean-tooltip-directive');
|
|
10
|
+
import('./directives');
|
|
11
|
+
}
|