@rancher/shell 0.3.15 → 0.3.17
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/wechat-qr-code.jpg +0 -0
- package/assets/translations/en-us.yaml +70 -15
- package/assets/translations/zh-hans.yaml +155 -33
- package/chart/__tests__/S3.test.ts +50 -0
- package/chart/rancher-backup/S3.vue +21 -0
- package/chart/rancher-backup/index.vue +4 -0
- package/cloud-credential/generic.vue +1 -1
- package/components/BannerGraphic.vue +1 -0
- package/components/CommunityLinks.vue +1 -0
- package/components/CruResource.vue +1 -1
- package/components/EmberPage.vue +1 -0
- package/components/FileDiff.vue +92 -85
- package/components/GrafanaDashboard.vue +7 -1
- package/components/ResourceDetail/index.vue +4 -12
- package/components/ResourceList/index.vue +1 -1
- package/components/ResourceTable.vue +50 -2
- package/components/SimpleBox.vue +1 -0
- package/components/SortableTable/index.vue +5 -1
- package/components/YamlEditor.vue +1 -0
- package/components/auth/RoleDetailEdit.vue +1 -0
- package/components/form/GitPicker.vue +1 -1
- package/components/form/NameNsDescription.vue +28 -12
- package/components/form/NodeAffinity.vue +2 -2
- package/components/form/PodAffinity.vue +8 -3
- package/components/form/ResourceTabs/index.vue +8 -2
- package/components/form/Select.vue +16 -0
- package/components/form/__tests__/NodeAffinity.test.ts +38 -0
- package/components/form/__tests__/PodAffinity.test.ts +46 -0
- package/components/formatter/ClusterLink.vue +8 -4
- package/components/formatter/ImageName.vue +23 -0
- package/components/formatter/PodImages.vue +7 -1
- package/components/formatter/__tests__/ClusterLink.test.ts +101 -0
- package/components/nav/Header.vue +2 -2
- package/config/__test__/home-links.test.ts +62 -0
- package/config/home-links.js +15 -3
- package/config/labels-annotations.js +5 -1
- package/config/product/auth.js +1 -1
- package/config/router.js +0 -9
- package/config/settings.ts +4 -0
- package/config/table-headers.js +6 -5
- package/config/uiplugins.js +50 -5
- package/core/plugin-helpers.js +20 -12
- package/core/plugin.ts +9 -0
- package/core/plugins.js +1 -1
- package/core/types-provisioning.ts +253 -0
- package/core/types.ts +17 -3
- package/detail/autoscaling.horizontalpodautoscaler/index.vue +50 -1
- package/detail/catalog.cattle.io.clusterrepo.vue +8 -1
- package/detail/node.vue +6 -6
- package/detail/pod.vue +2 -6
- package/detail/provisioning.cattle.io.cluster.vue +46 -7
- package/detail/workload/index.vue +9 -9
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +62 -0
- package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +56 -0
- package/edit/auth/github.vue +1 -0
- package/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue +130 -0
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +79 -0
- package/edit/fleet.cattle.io.gitrepo.vue +18 -1
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +8 -3
- package/edit/namespace.vue +9 -1
- package/edit/networking.k8s.io.ingress/RulePath.vue +0 -2
- package/edit/provisioning.cattle.io.cluster/AgentConfiguration.vue +1 -30
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +79 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +52 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +330 -150
- package/edit/ui.cattle.io.navlink.vue +2 -1
- package/initialize/App.js +3 -13
- package/initialize/layouts.ts +26 -0
- package/list/provisioning.cattle.io.cluster.vue +8 -1
- package/middleware/authenticated.js +93 -5
- package/mixins/brand.js +39 -3
- package/mixins/child-hook.js +2 -2
- package/mixins/create-edit-view/impl.js +2 -2
- package/models/fleet.cattle.io.gitrepo.js +1 -0
- package/models/provisioning.cattle.io.cluster.js +9 -1
- package/package.json +3 -3
- package/pages/about.vue +8 -2
- package/pages/auth/login.vue +10 -0
- package/pages/auth/logout.vue +11 -3
- package/pages/auth/setup.vue +4 -0
- package/pages/c/_cluster/apps/charts/index.vue +5 -2
- package/pages/c/_cluster/apps/charts/install.vue +5 -0
- package/pages/c/_cluster/auth/roles/index.vue +1 -1
- package/pages/c/_cluster/explorer/index.vue +1 -10
- package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +177 -0
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +19 -3
- package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +90 -21
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +107 -37
- package/pages/c/_cluster/uiplugins/index.vue +155 -44
- package/pages/docs/_doc.vue +9 -3
- package/pages/home.vue +10 -5
- package/pages/support/index.vue +10 -4
- package/pkg/auto-import.js +1 -1
- package/plugins/clean-tooltip-directive.js +1 -1
- package/plugins/dashboard-store/resource-class.js +35 -2
- package/plugins/plugin.js +9 -1
- package/plugins/steve/actions.js +22 -0
- package/rancher-components/BadgeState/BadgeState.vue +5 -1
- package/rancher-components/Banner/Banner.test.ts +51 -1
- package/rancher-components/Banner/Banner.vue +134 -53
- package/rancher-components/Card/Card.vue +24 -7
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
- package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
- package/rancher-components/Form/Radio/RadioButton.vue +30 -13
- package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
- package/rancher-components/StringList/StringList.test.ts +453 -49
- package/rancher-components/StringList/StringList.vue +92 -58
- package/scripts/extension/publish +2 -2
- package/scripts/typegen.sh +1 -0
- package/server/server-middleware.js +4 -12
- package/store/index.js +13 -0
- package/store/prefs.js +0 -3
- package/store/type-map.js +17 -29
- package/types/shell/index.d.ts +243 -90
- package/utils/kube.js +9 -0
- package/utils/object.js +27 -0
- package/utils/settings.ts +2 -2
- package/vue.config.js +3 -2
- package/pages/safeMode.vue +0 -17
- package/rancher-components/components/BadgeState/BadgeState.spec.ts +0 -12
- package/rancher-components/components/BadgeState/BadgeState.vue +0 -111
- package/rancher-components/components/BadgeState/index.ts +0 -1
- package/rancher-components/components/Banner/Banner.test.ts +0 -63
- package/rancher-components/components/Banner/Banner.vue +0 -244
- package/rancher-components/components/Banner/index.ts +0 -1
- package/rancher-components/components/Card/Card.vue +0 -167
- package/rancher-components/components/Card/index.ts +0 -1
- package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +0 -68
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +0 -420
- package/rancher-components/components/Form/Checkbox/index.ts +0 -1
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +0 -23
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +0 -355
- package/rancher-components/components/Form/LabeledInput/index.ts +0 -1
- package/rancher-components/components/Form/Radio/RadioButton.vue +0 -287
- package/rancher-components/components/Form/Radio/RadioGroup.vue +0 -254
- package/rancher-components/components/Form/Radio/index.ts +0 -2
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +0 -170
- package/rancher-components/components/Form/TextArea/index.ts +0 -1
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +0 -94
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +0 -149
- package/rancher-components/components/Form/ToggleSwitch/index.ts +0 -1
- package/rancher-components/components/Form/index.ts +0 -5
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -151
- package/rancher-components/components/LabeledTooltip/index.ts +0 -1
- package/rancher-components/components/StringList/StringList.test.ts +0 -484
- package/rancher-components/components/StringList/StringList.vue +0 -611
- package/rancher-components/components/StringList/index.ts +0 -1
- /package/rancher-components/{components/Card → Card}/Card.test.ts +0 -0
- /package/rancher-components/{components/Form → Form}/Radio/RadioButton.test.ts +0 -0
package/utils/object.js
CHANGED
|
@@ -218,6 +218,33 @@ export function diff(from, to) {
|
|
|
218
218
|
return out;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Super simple lodash isEqual equivalent.
|
|
223
|
+
*
|
|
224
|
+
* Only checks root properties for strict equality
|
|
225
|
+
*/
|
|
226
|
+
function isEqualBasic(from, to) {
|
|
227
|
+
const fromKeys = Object.keys(from || {});
|
|
228
|
+
const toKeys = Object.keys(to || {});
|
|
229
|
+
|
|
230
|
+
if (fromKeys.length !== toKeys.length) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
for (let i = 0; i < fromKeys.length; i++) {
|
|
235
|
+
const fromValue = from[fromKeys[i]];
|
|
236
|
+
const toValue = to[fromKeys[i]];
|
|
237
|
+
|
|
238
|
+
if (fromValue !== toValue) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export { isEqualBasic as isEqual };
|
|
247
|
+
|
|
221
248
|
export function changeset(from, to, parentPath = []) {
|
|
222
249
|
let out = {};
|
|
223
250
|
|
package/utils/settings.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MANAGEMENT } from '@shell/config/types';
|
|
2
2
|
import { Store } from 'vuex';
|
|
3
3
|
import { DEFAULT_PERF_SETTING, SETTING } from '@shell/config/settings';
|
|
4
|
-
import { GC_PREFERENCES } from 'utils/gc/gc-types';
|
|
4
|
+
import { GC_PREFERENCES } from '@shell/utils/gc/gc-types';
|
|
5
5
|
|
|
6
6
|
export const fetchOrCreateSetting = async(store: Store<any>, id: string, val: string, save = true): Promise<any> => {
|
|
7
7
|
let setting;
|
|
@@ -56,7 +56,7 @@ export const getPerformanceSetting = (rootGetters: Record<string, (arg0: string,
|
|
|
56
56
|
manualRefresh: {};
|
|
57
57
|
disableWebsocketNotification: boolean;
|
|
58
58
|
garbageCollection: GC_PREFERENCES;
|
|
59
|
-
forceNsFilterV2:
|
|
59
|
+
forceNsFilterV2: any;
|
|
60
60
|
advancedWorker: {};
|
|
61
61
|
} => {
|
|
62
62
|
const perfSettingResource = rootGetters['management/byId'](MANAGEMENT.SETTING, SETTING.UI_PERFORMANCE);
|
package/vue.config.js
CHANGED
|
@@ -4,6 +4,7 @@ const serveStatic = require('serve-static');
|
|
|
4
4
|
const webpack = require('webpack');
|
|
5
5
|
const { generateDynamicTypeImport } = require('./pkg/auto-import');
|
|
6
6
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
|
7
|
+
const serverMiddlewares = require('./server/server-middleware.js');
|
|
7
8
|
|
|
8
9
|
// Suppress info level logging messages from http-proxy-middleware
|
|
9
10
|
// This hides all of the "[HPM Proxy created] ..." messages
|
|
@@ -218,8 +219,6 @@ module.exports = function(dir, _appConfig) {
|
|
|
218
219
|
serverMiddleware.push({ path: `/pkg/`, handler: serveStatic(`${ dir }/dist-pkg/`) });
|
|
219
220
|
// Endpoint to download and unpack a tgz from the local verdaccio rgistry (dev)
|
|
220
221
|
serverMiddleware.push(path.resolve(dir, SHELL, 'server', 'verdaccio-middleware'));
|
|
221
|
-
// Add the standard dashboard server middleware after the middleware added to serve up UI packages
|
|
222
|
-
serverMiddleware.push(path.resolve(dir, SHELL, 'server', 'server-middleware'));
|
|
223
222
|
|
|
224
223
|
// ===============================================================================================
|
|
225
224
|
// Dashboard nuxt configuration
|
|
@@ -319,6 +318,8 @@ module.exports = function(dir, _appConfig) {
|
|
|
319
318
|
process.exit(1);
|
|
320
319
|
});
|
|
321
320
|
|
|
321
|
+
app.use(serverMiddlewares);
|
|
322
|
+
|
|
322
323
|
Object.keys(proxy).forEach((p) => {
|
|
323
324
|
const px = createProxyMiddleware({
|
|
324
325
|
...proxy[p],
|
package/pages/safeMode.vue
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
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>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { shallowMount } from '@vue/test-utils';
|
|
2
|
-
import { BadgeState } from './index';
|
|
3
|
-
|
|
4
|
-
describe('BadgeState.vue', () => {
|
|
5
|
-
it('renders props.msg when passed', () => {
|
|
6
|
-
const label = 'Hello, World!';
|
|
7
|
-
|
|
8
|
-
const wrapper = shallowMount(BadgeState, { propsData: { label } });
|
|
9
|
-
|
|
10
|
-
expect(wrapper.find('span').text()).toMatch(label);
|
|
11
|
-
});
|
|
12
|
-
});
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import Vue, { PropType } from 'vue';
|
|
3
|
-
|
|
4
|
-
interface Badge {
|
|
5
|
-
stateBackground: string;
|
|
6
|
-
stateDisplay: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Badge state component.
|
|
11
|
-
* <p>Represents a badge whose label and color is either taken from the value property or
|
|
12
|
-
* from the label and color properties. The state property takes precedence.</p>
|
|
13
|
-
*/
|
|
14
|
-
export default Vue.extend({
|
|
15
|
-
props: {
|
|
16
|
-
/**
|
|
17
|
-
* A value having the properties `stateBackground` and `stateDisplay`
|
|
18
|
-
*/
|
|
19
|
-
value: {
|
|
20
|
-
type: Object as PropType<Badge>,
|
|
21
|
-
default: null
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Badge color. `stateBackground` of the value property takes precedence if supplied
|
|
26
|
-
*/
|
|
27
|
-
color: {
|
|
28
|
-
type: String,
|
|
29
|
-
default: null
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Optional icon to be shown before the label
|
|
34
|
-
*/
|
|
35
|
-
icon: {
|
|
36
|
-
type: String,
|
|
37
|
-
default: null
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Label to display in the badge. `stateDisplay` of the value property takes precedence if supplied
|
|
42
|
-
*/
|
|
43
|
-
label: {
|
|
44
|
-
type: String,
|
|
45
|
-
default: null
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
computed: {
|
|
50
|
-
bg(): string | null {
|
|
51
|
-
return this.value?.stateBackground || this.color;
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
msg(): string | null {
|
|
55
|
-
return this.value?.stateDisplay || this.label;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
</script>
|
|
60
|
-
|
|
61
|
-
<template>
|
|
62
|
-
<span :class="{'badge-state': true, [bg]: true}">
|
|
63
|
-
<i
|
|
64
|
-
v-if="icon"
|
|
65
|
-
class="icon"
|
|
66
|
-
:class="{[icon]: true, 'mr-5': !!msg}"
|
|
67
|
-
/>{{ msg }}
|
|
68
|
-
</span>
|
|
69
|
-
</template>
|
|
70
|
-
|
|
71
|
-
<style lang="scss" scoped>
|
|
72
|
-
.badge-state {
|
|
73
|
-
align-items: center;
|
|
74
|
-
display: inline-flex;
|
|
75
|
-
padding: 2px 10px;
|
|
76
|
-
border: 1px solid transparent;
|
|
77
|
-
border-radius: 20px;
|
|
78
|
-
|
|
79
|
-
&.bg-info {
|
|
80
|
-
border-color: var(--primary);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
&.bg-error {
|
|
84
|
-
border-color: var(--error);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
&.bg-warning {
|
|
88
|
-
border-color: var(--warning);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Successful states are de-emphasized by using [text-]color instead of background-color
|
|
92
|
-
&.bg-success {
|
|
93
|
-
color: var(--success);
|
|
94
|
-
background: transparent;
|
|
95
|
-
border-color: var(--success);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
</style>
|
|
99
|
-
<style lang="scss">
|
|
100
|
-
// TODO: #6005
|
|
101
|
-
// Investigate why this is here.. I don't think that styles for sortable table should belong here
|
|
102
|
-
.sortable-table TD .badge-state {
|
|
103
|
-
@include clip;
|
|
104
|
-
display: inline-block;
|
|
105
|
-
max-width: 100%;
|
|
106
|
-
position: relative;
|
|
107
|
-
max-width: 110px;
|
|
108
|
-
font-size: .85em;
|
|
109
|
-
vertical-align: middle;
|
|
110
|
-
}
|
|
111
|
-
</style>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as BadgeState } from './BadgeState.vue';
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { mount } from '@vue/test-utils';
|
|
2
|
-
import { Banner } from './index';
|
|
3
|
-
import { cleanHtmlDirective } from '@shell/plugins/clean-html-directive';
|
|
4
|
-
|
|
5
|
-
describe('component: Banner', () => {
|
|
6
|
-
it('should display text based on label', () => {
|
|
7
|
-
const label = 'test';
|
|
8
|
-
const wrapper = mount(
|
|
9
|
-
Banner,
|
|
10
|
-
{
|
|
11
|
-
directives: { cleanHtmlDirective },
|
|
12
|
-
propsData: { label }
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
const element = wrapper.find('span').element;
|
|
16
|
-
|
|
17
|
-
expect(element.textContent).toBe(label);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should display an icon', () => {
|
|
21
|
-
const icon = 'my-icon';
|
|
22
|
-
const wrapper = mount(Banner, { propsData: { icon } });
|
|
23
|
-
|
|
24
|
-
const element = wrapper.find(`.${ icon }`).element;
|
|
25
|
-
|
|
26
|
-
expect(element.classList).toContain(icon);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('should not display an icon', () => {
|
|
30
|
-
const wrapper = mount(Banner);
|
|
31
|
-
|
|
32
|
-
const element = wrapper.find(`[data-testid="banner-icon"]`).element;
|
|
33
|
-
|
|
34
|
-
expect(element).not.toBeDefined();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('should emit close event', () => {
|
|
38
|
-
const wrapper = mount(Banner, { propsData: { closable: true } });
|
|
39
|
-
const element = wrapper.find(`[data-testid="banner-close"]`).element;
|
|
40
|
-
|
|
41
|
-
element.click();
|
|
42
|
-
|
|
43
|
-
expect(wrapper.emitted('close')).toHaveLength(1);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('should add the right color', () => {
|
|
47
|
-
const color = 'red';
|
|
48
|
-
const wrapper = mount(Banner, { propsData: { color } });
|
|
49
|
-
|
|
50
|
-
const element = wrapper.element;
|
|
51
|
-
|
|
52
|
-
expect(element.classList).toContain(color);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('should stack the banner messages', () => {
|
|
56
|
-
const stacked = true;
|
|
57
|
-
const wrapper = mount(Banner, { propsData: { stacked } });
|
|
58
|
-
|
|
59
|
-
const element = wrapper.find(`[data-testid="banner-content"]`).element;
|
|
60
|
-
|
|
61
|
-
expect(element.classList).toContain('stacked');
|
|
62
|
-
});
|
|
63
|
-
});
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import Vue from 'vue';
|
|
3
|
-
import { nlToBr } from '@shell/utils/string';
|
|
4
|
-
import { stringify } from '@shell/utils/error';
|
|
5
|
-
|
|
6
|
-
export default Vue.extend({
|
|
7
|
-
props: {
|
|
8
|
-
/**
|
|
9
|
-
* A color class that represents the color of the banner.
|
|
10
|
-
* @values primary, secondary, success, warning, error, info
|
|
11
|
-
*/
|
|
12
|
-
color: {
|
|
13
|
-
type: String,
|
|
14
|
-
default: 'secondary'
|
|
15
|
-
},
|
|
16
|
-
/**
|
|
17
|
-
* The label to display as the banner's default content.
|
|
18
|
-
*/
|
|
19
|
-
label: {
|
|
20
|
-
type: [String, Error, Object],
|
|
21
|
-
default: null
|
|
22
|
-
},
|
|
23
|
-
/**
|
|
24
|
-
* The i18n key for the label to display as the banner's default content.
|
|
25
|
-
*/
|
|
26
|
-
labelKey: {
|
|
27
|
-
type: String,
|
|
28
|
-
default: null
|
|
29
|
-
},
|
|
30
|
-
/**
|
|
31
|
-
* Add icon for the banner
|
|
32
|
-
*/
|
|
33
|
-
icon: {
|
|
34
|
-
type: String,
|
|
35
|
-
default: null
|
|
36
|
-
},
|
|
37
|
-
/**
|
|
38
|
-
* Toggles the banner's close button.
|
|
39
|
-
*/
|
|
40
|
-
closable: {
|
|
41
|
-
type: Boolean,
|
|
42
|
-
default: false
|
|
43
|
-
},
|
|
44
|
-
/**
|
|
45
|
-
* Toggles the stacked class for the banner.
|
|
46
|
-
*/
|
|
47
|
-
stacked: {
|
|
48
|
-
type: Boolean,
|
|
49
|
-
default: false
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
computed: {
|
|
53
|
-
/**
|
|
54
|
-
* Return message text as label.
|
|
55
|
-
*/
|
|
56
|
-
messageLabel(): string | void {
|
|
57
|
-
return !(typeof this.label === 'string') ? stringify(this.label) : undefined;
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
methods: { nlToBr }
|
|
61
|
-
});
|
|
62
|
-
</script>
|
|
63
|
-
<template>
|
|
64
|
-
<div
|
|
65
|
-
class="banner"
|
|
66
|
-
:class="{
|
|
67
|
-
[color]: true,
|
|
68
|
-
}"
|
|
69
|
-
>
|
|
70
|
-
<div
|
|
71
|
-
v-if="icon"
|
|
72
|
-
class="banner__icon"
|
|
73
|
-
data-testid="banner-icon"
|
|
74
|
-
>
|
|
75
|
-
<i
|
|
76
|
-
class="icon icon-2x"
|
|
77
|
-
:class="icon"
|
|
78
|
-
/>
|
|
79
|
-
</div>
|
|
80
|
-
<div
|
|
81
|
-
class="banner__content"
|
|
82
|
-
data-testid="banner-content"
|
|
83
|
-
:class="{
|
|
84
|
-
closable,
|
|
85
|
-
stacked,
|
|
86
|
-
icon
|
|
87
|
-
}"
|
|
88
|
-
>
|
|
89
|
-
<slot>
|
|
90
|
-
<t
|
|
91
|
-
v-if="labelKey"
|
|
92
|
-
:k="labelKey"
|
|
93
|
-
:raw="true"
|
|
94
|
-
/>
|
|
95
|
-
<span v-else-if="messageLabel">{{ messageLabel }}</span>
|
|
96
|
-
<span
|
|
97
|
-
v-else
|
|
98
|
-
v-clean-html="nlToBr(label)"
|
|
99
|
-
/>
|
|
100
|
-
</slot>
|
|
101
|
-
<div
|
|
102
|
-
v-if="closable"
|
|
103
|
-
class="banner__content__closer"
|
|
104
|
-
@click="$emit('close')"
|
|
105
|
-
>
|
|
106
|
-
<i
|
|
107
|
-
data-testid="banner-close"
|
|
108
|
-
class="icon icon-close closer-icon"
|
|
109
|
-
/>
|
|
110
|
-
</div>
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
</template>
|
|
114
|
-
|
|
115
|
-
<style lang="scss" scoped>
|
|
116
|
-
$left-border-size: 4px;
|
|
117
|
-
$icon-size: 24px;
|
|
118
|
-
|
|
119
|
-
.banner {
|
|
120
|
-
display: flex;
|
|
121
|
-
margin: 15px 0;
|
|
122
|
-
position: relative;
|
|
123
|
-
width: 100%;
|
|
124
|
-
color: var(--body-text);
|
|
125
|
-
|
|
126
|
-
&__icon {
|
|
127
|
-
width: $icon-size * 2;
|
|
128
|
-
flex-grow: 1;
|
|
129
|
-
display: flex;
|
|
130
|
-
justify-content: center;
|
|
131
|
-
align-items: center;
|
|
132
|
-
box-sizing: content-box;
|
|
133
|
-
|
|
134
|
-
.primary & {
|
|
135
|
-
background: var(--primary);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
.secondary & {
|
|
139
|
-
background: var(--default);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.success & {
|
|
143
|
-
background: var(--success);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
.info & {
|
|
147
|
-
background: var(--info);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.warning & {
|
|
151
|
-
background: var(--warning);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
.error & {
|
|
155
|
-
background: var(--error);
|
|
156
|
-
color: var(--primary-text);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
&__content {
|
|
161
|
-
padding: 10px;
|
|
162
|
-
transition: all 0.2s ease;
|
|
163
|
-
line-height: 20px;
|
|
164
|
-
width: 100%;
|
|
165
|
-
border-left: solid $left-border-size transparent;
|
|
166
|
-
display: flex;
|
|
167
|
-
gap: 3px;
|
|
168
|
-
|
|
169
|
-
.primary & {
|
|
170
|
-
background: var(--primary);
|
|
171
|
-
border-color: var(--primary);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
.secondary & {
|
|
175
|
-
background: var(--default-banner-bg);
|
|
176
|
-
border-color: var(--default);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
.success & {
|
|
180
|
-
background: var(--success-banner-bg);
|
|
181
|
-
border-color: var(--success);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
.info & {
|
|
185
|
-
background: var(--info-banner-bg);
|
|
186
|
-
border-color: var(--info);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
.warning & {
|
|
190
|
-
background: var(--warning-banner-bg);
|
|
191
|
-
border-color: var(--warning);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
.error & {
|
|
195
|
-
background: var(--error-banner-bg);
|
|
196
|
-
border-color: var(--error);
|
|
197
|
-
color: var(--error);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
&.stacked {
|
|
201
|
-
padding: 0 10px;
|
|
202
|
-
margin: 0;
|
|
203
|
-
transition: none;
|
|
204
|
-
&:first-child {
|
|
205
|
-
padding-top: 10px;
|
|
206
|
-
}
|
|
207
|
-
&:last-child {
|
|
208
|
-
padding-bottom: 10px;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
&.closable {
|
|
213
|
-
padding-right: $icon-size * 2;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
&__closer {
|
|
217
|
-
display: flex;
|
|
218
|
-
align-items: center;
|
|
219
|
-
|
|
220
|
-
cursor: pointer;
|
|
221
|
-
position: absolute;
|
|
222
|
-
top: 0;
|
|
223
|
-
right: 0;
|
|
224
|
-
bottom: 0;
|
|
225
|
-
width: $icon-size;
|
|
226
|
-
line-height: $icon-size;
|
|
227
|
-
text-align: center;
|
|
228
|
-
|
|
229
|
-
.closer-icon {
|
|
230
|
-
opacity: 0.7;
|
|
231
|
-
|
|
232
|
-
&:hover {
|
|
233
|
-
opacity: 1;
|
|
234
|
-
color: var(--link);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
&.icon {
|
|
240
|
-
border-left: none;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
</style>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as Banner } from './Banner.vue';
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import Vue from 'vue';
|
|
3
|
-
|
|
4
|
-
export default Vue.extend({
|
|
5
|
-
name: 'Card',
|
|
6
|
-
props: {
|
|
7
|
-
/**
|
|
8
|
-
* The card's title.
|
|
9
|
-
*/
|
|
10
|
-
title: {
|
|
11
|
-
type: String,
|
|
12
|
-
default: ''
|
|
13
|
-
},
|
|
14
|
-
/**
|
|
15
|
-
* The text content for the card's body.
|
|
16
|
-
*/
|
|
17
|
-
content: {
|
|
18
|
-
type: String,
|
|
19
|
-
default: ''
|
|
20
|
-
},
|
|
21
|
-
/**
|
|
22
|
-
* The function to invoke when the default action button is clicked.
|
|
23
|
-
*/
|
|
24
|
-
buttonAction: {
|
|
25
|
-
type: Function,
|
|
26
|
-
default: (): void => { }
|
|
27
|
-
},
|
|
28
|
-
/**
|
|
29
|
-
* The text for the default action button.
|
|
30
|
-
*/
|
|
31
|
-
buttonText: {
|
|
32
|
-
type: String,
|
|
33
|
-
default: 'go'
|
|
34
|
-
},
|
|
35
|
-
/**
|
|
36
|
-
* Toggles the card's highlight-border class.
|
|
37
|
-
*/
|
|
38
|
-
showHighlightBorder: {
|
|
39
|
-
type: Boolean,
|
|
40
|
-
default: true
|
|
41
|
-
},
|
|
42
|
-
/**
|
|
43
|
-
* Toggles the card's Actions section.
|
|
44
|
-
*/
|
|
45
|
-
showActions: {
|
|
46
|
-
type: Boolean,
|
|
47
|
-
default: true
|
|
48
|
-
},
|
|
49
|
-
sticky: {
|
|
50
|
-
type: Boolean,
|
|
51
|
-
default: false,
|
|
52
|
-
},
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
</script>
|
|
56
|
-
|
|
57
|
-
<template>
|
|
58
|
-
<div
|
|
59
|
-
class="card-container"
|
|
60
|
-
:class="{'highlight-border': showHighlightBorder, 'card-sticky': sticky}"
|
|
61
|
-
data-testid="card"
|
|
62
|
-
>
|
|
63
|
-
<div class="card-wrap">
|
|
64
|
-
<div
|
|
65
|
-
class="card-title"
|
|
66
|
-
data-testid="card-title-slot"
|
|
67
|
-
>
|
|
68
|
-
<slot name="title">
|
|
69
|
-
{{ title }}
|
|
70
|
-
</slot>
|
|
71
|
-
</div>
|
|
72
|
-
<hr>
|
|
73
|
-
<div
|
|
74
|
-
class="card-body"
|
|
75
|
-
data-testid="card-body-slot"
|
|
76
|
-
>
|
|
77
|
-
<slot name="body">
|
|
78
|
-
{{ content }}
|
|
79
|
-
</slot>
|
|
80
|
-
</div>
|
|
81
|
-
<div
|
|
82
|
-
v-if="showActions"
|
|
83
|
-
class="card-actions"
|
|
84
|
-
data-testid="card-actions-slot"
|
|
85
|
-
>
|
|
86
|
-
<slot name="actions">
|
|
87
|
-
<button
|
|
88
|
-
class="btn role-primary"
|
|
89
|
-
@click="buttonAction"
|
|
90
|
-
>
|
|
91
|
-
{{ buttonText }}
|
|
92
|
-
</button>
|
|
93
|
-
</slot>
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
96
|
-
</div>
|
|
97
|
-
</template>
|
|
98
|
-
|
|
99
|
-
<style lang='scss'>
|
|
100
|
-
.card-container {
|
|
101
|
-
&.highlight-border {
|
|
102
|
-
border-left: 5px solid var(--primary);
|
|
103
|
-
}
|
|
104
|
-
border-radius: var(--border-radius);
|
|
105
|
-
display: flex;
|
|
106
|
-
flex-basis: 40%;
|
|
107
|
-
margin: 10px;
|
|
108
|
-
min-height: 100px;
|
|
109
|
-
padding: 10px;
|
|
110
|
-
box-shadow: 0 0 20px var(--shadow);
|
|
111
|
-
&:not(.top) {
|
|
112
|
-
align-items: top;
|
|
113
|
-
flex-direction: row;
|
|
114
|
-
justify-content: start;
|
|
115
|
-
}
|
|
116
|
-
.card-wrap {
|
|
117
|
-
width: 100%;
|
|
118
|
-
}
|
|
119
|
-
& .card-body {
|
|
120
|
-
color: var(--input-label);
|
|
121
|
-
display: flex;
|
|
122
|
-
flex-direction: column;
|
|
123
|
-
justify-content: center;
|
|
124
|
-
}
|
|
125
|
-
& .card-actions {
|
|
126
|
-
align-self: end;
|
|
127
|
-
display: flex;
|
|
128
|
-
padding-top: 20px;
|
|
129
|
-
}
|
|
130
|
-
& .card-title {
|
|
131
|
-
align-items: center;
|
|
132
|
-
display: flex;
|
|
133
|
-
width: 100%;
|
|
134
|
-
h5 {
|
|
135
|
-
margin: 0;
|
|
136
|
-
}
|
|
137
|
-
.flex-right {
|
|
138
|
-
margin-left: auto;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Sticky mode will stick header and footer to top and bottom with content in the middle scrolling
|
|
143
|
-
&.card-sticky {
|
|
144
|
-
// display: flex;
|
|
145
|
-
// flex-direction: column;
|
|
146
|
-
overflow: hidden;
|
|
147
|
-
|
|
148
|
-
.card-wrap {
|
|
149
|
-
display: flex;
|
|
150
|
-
flex-direction: column;
|
|
151
|
-
|
|
152
|
-
.card-body {
|
|
153
|
-
justify-content: flex-start;
|
|
154
|
-
overflow: scroll;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
> * {
|
|
158
|
-
flex: 0;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.card-body {
|
|
162
|
-
flex: 1;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
</style>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as Card } from './Card.vue';
|