@vc-shell/framework 1.0.67 → 1.0.69
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/CHANGELOG.md +1590 -0
- package/core/composables/index.ts +1 -0
- package/core/composables/useErrorHandler/index.ts +44 -0
- package/core/composables/useNotifications/index.ts +13 -3
- package/core/plugins/error-interceptor/index.ts +17 -0
- package/core/plugins/error-interceptor/interceptor.ts +43 -0
- package/core/plugins/index.ts +1 -0
- package/core/plugins/validation/rules.ts +10 -0
- package/dist/core/composables/index.d.ts +1 -0
- package/dist/core/composables/index.d.ts.map +1 -1
- package/dist/core/composables/useErrorHandler/index.d.ts +8 -0
- package/dist/core/composables/useErrorHandler/index.d.ts.map +1 -0
- package/dist/core/composables/useNotifications/index.d.ts.map +1 -1
- package/dist/core/plugins/error-interceptor/index.d.ts +107 -0
- package/dist/core/plugins/error-interceptor/index.d.ts.map +1 -0
- package/dist/core/plugins/error-interceptor/interceptor.d.ts +39 -0
- package/dist/core/plugins/error-interceptor/interceptor.d.ts.map +1 -0
- package/dist/core/plugins/index.d.ts +1 -0
- package/dist/core/plugins/index.d.ts.map +1 -1
- package/dist/core/plugins/validation/rules.d.ts +1 -0
- package/dist/core/plugins/validation/rules.d.ts.map +1 -1
- package/dist/framework.mjs +24421 -23446
- package/dist/index.css +1 -1
- package/dist/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts.map +1 -1
- package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -1
- package/dist/shared/components/notifications/components/index.d.ts +2 -0
- package/dist/shared/components/notifications/components/index.d.ts.map +1 -0
- package/dist/shared/components/notifications/components/notification-container/index.d.ts +131 -0
- package/dist/shared/components/notifications/components/notification-container/index.d.ts.map +1 -0
- package/dist/shared/components/notifications/composables/index.d.ts +3 -0
- package/dist/shared/components/notifications/composables/index.d.ts.map +1 -0
- package/dist/shared/components/notifications/composables/useContainer/index.d.ts +27 -0
- package/dist/shared/components/notifications/composables/useContainer/index.d.ts.map +1 -0
- package/dist/shared/components/notifications/composables/useInstance/index.d.ts +9 -0
- package/dist/shared/components/notifications/composables/useInstance/index.d.ts.map +1 -0
- package/dist/shared/components/notifications/core/index.d.ts +2 -0
- package/dist/shared/components/notifications/core/index.d.ts.map +1 -0
- package/dist/shared/components/notifications/core/notification.d.ts +12 -0
- package/dist/shared/components/notifications/core/notification.d.ts.map +1 -0
- package/dist/shared/components/notifications/index.d.ts +15 -0
- package/dist/shared/components/notifications/index.d.ts.map +1 -0
- package/dist/shared/components/notifications/types/index.d.ts +15 -0
- package/dist/shared/components/notifications/types/index.d.ts.map +1 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/modules/assets/components/assets-details/assets-details.vue.d.ts +8 -1
- package/dist/shared/modules/assets/components/assets-details/assets-details.vue.d.ts.map +1 -1
- package/dist/shared/modules/assets/components/assets-details/index.d.ts +121 -23
- package/dist/shared/modules/assets/components/assets-details/index.d.ts.map +1 -1
- package/dist/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts +8 -1
- package/dist/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts.map +1 -1
- package/dist/shared/modules/assets-manager/components/assets-manager/index.d.ts +144 -28
- package/dist/shared/modules/assets-manager/components/assets-manager/index.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-notification/index.d.ts +49 -100
- package/dist/ui/components/molecules/vc-notification/index.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-notification/vc-notification.vue.d.ts +10 -31
- package/dist/ui/components/molecules/vc-notification/vc-notification.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/index.d.ts +0 -2
- package/dist/ui/components/organisms/vc-app/index.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts +0 -1
- package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-blade/index.d.ts +1 -0
- package/dist/ui/components/organisms/vc-blade/index.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts +1 -0
- package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue.d.ts +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/vc-table.vue.d.ts.map +1 -1
- package/package.json +6 -8
- package/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue +63 -33
- package/shared/components/blade-navigation/composables/useBladeNavigation/index.ts +0 -2
- package/shared/components/notifications/components/index.ts +1 -0
- package/shared/components/notifications/components/notification-container/index.ts +80 -0
- package/shared/components/notifications/composables/index.ts +2 -0
- package/shared/components/notifications/composables/useContainer/index.ts +190 -0
- package/shared/components/notifications/composables/useInstance/index.ts +46 -0
- package/shared/components/notifications/core/index.ts +1 -0
- package/shared/components/notifications/core/notification.ts +96 -0
- package/shared/components/notifications/index.ts +17 -0
- package/shared/components/notifications/styles/index.scss +9 -0
- package/shared/components/notifications/types/index.ts +16 -0
- package/shared/index.ts +8 -1
- package/shared/modules/assets/components/assets-details/assets-details.vue +6 -0
- package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +6 -0
- package/ui/components/molecules/vc-notification/index.ts +1 -8
- package/ui/components/molecules/vc-notification/vc-notification.vue +60 -25
- package/ui/components/organisms/vc-app/index.ts +0 -1
- package/ui/components/organisms/vc-app/vc-app.vue +9 -9
- package/ui/components/organisms/vc-blade/vc-blade.vue +44 -1
- package/ui/components/organisms/vc-popup/vc-popup.vue +1 -1
- package/ui/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue +1 -1
- package/ui/components/organisms/vc-table/vc-table.vue +12 -2
- package/ui/locales/en.json +6 -0
- package/LICENSE +0 -12
package/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue
CHANGED
|
@@ -1,46 +1,76 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@
|
|
8
|
-
|
|
9
|
-
:
|
|
10
|
-
:maximized="findStateById(0)"
|
|
11
|
-
:blades="blades"
|
|
12
|
-
:param="resolveParam"
|
|
13
|
-
:key="route"
|
|
14
|
-
:ref="(el: IBladeElement) => setParentRef(el, Component)"
|
|
15
|
-
@expand:blade="handleMaximizeBlade(0, true)"
|
|
16
|
-
@collapse:blade="handleMaximizeBlade(0, false)"
|
|
2
|
+
<ErrorInterceptor
|
|
3
|
+
capture
|
|
4
|
+
v-slot="{ error, reset }"
|
|
5
|
+
>
|
|
6
|
+
<router-view
|
|
7
|
+
@vnode-before-unmount="reset"
|
|
8
|
+
v-slot="{ Component, route }"
|
|
9
|
+
:key="route.path"
|
|
17
10
|
>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
<component
|
|
12
|
+
:is="Component"
|
|
13
|
+
:closable="false"
|
|
14
|
+
v-show="$isMobile.value ? !blades.length : blades.length <= 1"
|
|
15
|
+
@open:blade="onBladeOpen($event, 0)"
|
|
16
|
+
:options="parentBladeOptions"
|
|
17
|
+
:expanded="blades.length === 0"
|
|
18
|
+
:maximized="findStateById(0)"
|
|
19
|
+
:blades="blades"
|
|
20
|
+
:param="resolveParam"
|
|
21
|
+
:key="route.path"
|
|
22
|
+
:ref="(el: IBladeElement) => setParentRef(el, Component)"
|
|
23
|
+
@expand:blade="handleMaximizeBlade(0, true)"
|
|
24
|
+
@collapse:blade="handleMaximizeBlade(0, false)"
|
|
25
|
+
>
|
|
26
|
+
<template
|
|
27
|
+
v-slot:error
|
|
28
|
+
v-if="error"
|
|
29
|
+
>{{ error }}</template
|
|
30
|
+
>
|
|
31
|
+
</component>
|
|
32
|
+
</router-view>
|
|
33
|
+
</ErrorInterceptor>
|
|
34
|
+
|
|
35
|
+
<template
|
|
21
36
|
v-for="(blade, i) in blades"
|
|
22
|
-
v-show="i >= blades.length - ($isMobile.value ? 1 : 2)"
|
|
23
37
|
:key="`blade_${i + 1}`"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
>
|
|
39
|
+
<ErrorInterceptor
|
|
40
|
+
v-slot="{ error }"
|
|
41
|
+
capture
|
|
42
|
+
>
|
|
43
|
+
<component
|
|
44
|
+
v-show="i >= blades.length - ($isMobile.value ? 1 : 2)"
|
|
45
|
+
:is="blade.component"
|
|
46
|
+
:param="blade.param"
|
|
47
|
+
:closable="i >= 0"
|
|
48
|
+
:expanded="i === blades.length - 1"
|
|
49
|
+
:maximized="findStateById(blade.idx)"
|
|
50
|
+
:options="blade.bladeOptions"
|
|
51
|
+
@open:blade="onBladeOpen($event, blade.idx)"
|
|
52
|
+
@close:blade="onBladeClose(i)"
|
|
53
|
+
@close:children="$emit('onClose', i + 1)"
|
|
54
|
+
@parent:call="$emit('onParentCall', { id: i, args: $event })"
|
|
55
|
+
@expand:blade="handleMaximizeBlade(blade.idx, true)"
|
|
56
|
+
@collapse:blade="handleMaximizeBlade(blade.idx, false)"
|
|
57
|
+
:ref="(el: IBladeElement) => setBladesRef(el, blade)"
|
|
58
|
+
>
|
|
59
|
+
<template
|
|
60
|
+
v-slot:error
|
|
61
|
+
v-if="error"
|
|
62
|
+
>{{ error }}</template
|
|
63
|
+
>
|
|
64
|
+
</component>
|
|
65
|
+
</ErrorInterceptor>
|
|
66
|
+
</template>
|
|
38
67
|
</template>
|
|
39
68
|
|
|
40
69
|
<script lang="ts" setup>
|
|
41
70
|
import { computed, ref, VNode } from "vue";
|
|
42
71
|
import { useRoute } from "vue-router";
|
|
43
72
|
import { IBladeContainer, IBladeElement, IBladeEvent, IParentCallArgs, IBladeRef } from "./../../../../../shared";
|
|
73
|
+
import { ErrorInterceptor } from "./../../../../../core/plugins/error-interceptor";
|
|
44
74
|
|
|
45
75
|
export interface Props {
|
|
46
76
|
blades: IBladeContainer[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as NotificationContainer } from "./notification-container";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { VcNotification } from "./../../../../../ui/components";
|
|
2
|
+
import { PropType, computed, defineComponent, h } from "vue";
|
|
3
|
+
import { NotificationType } from "../../types";
|
|
4
|
+
import { useContainer } from "../../composables";
|
|
5
|
+
|
|
6
|
+
const NotificationContainer = defineComponent({
|
|
7
|
+
name: "NotificationContainer",
|
|
8
|
+
inheritAttrs: false,
|
|
9
|
+
props: {
|
|
10
|
+
limit: {
|
|
11
|
+
type: Number,
|
|
12
|
+
required: false,
|
|
13
|
+
default: undefined,
|
|
14
|
+
},
|
|
15
|
+
pauseOnHover: {
|
|
16
|
+
type: Boolean,
|
|
17
|
+
required: false,
|
|
18
|
+
default: true,
|
|
19
|
+
},
|
|
20
|
+
timeout: {
|
|
21
|
+
type: [Number, Boolean],
|
|
22
|
+
required: false,
|
|
23
|
+
default: 3000,
|
|
24
|
+
},
|
|
25
|
+
content: {
|
|
26
|
+
type: String,
|
|
27
|
+
required: false,
|
|
28
|
+
default: "",
|
|
29
|
+
},
|
|
30
|
+
notificationId: {
|
|
31
|
+
type: [String, Number],
|
|
32
|
+
required: false,
|
|
33
|
+
default: "",
|
|
34
|
+
},
|
|
35
|
+
updateId: {
|
|
36
|
+
type: [String, Number],
|
|
37
|
+
required: false,
|
|
38
|
+
default: "",
|
|
39
|
+
},
|
|
40
|
+
type: {
|
|
41
|
+
type: String as PropType<NotificationType>,
|
|
42
|
+
required: false,
|
|
43
|
+
default: "default",
|
|
44
|
+
},
|
|
45
|
+
closeNotification: {
|
|
46
|
+
type: Function as PropType<() => void>,
|
|
47
|
+
required: false,
|
|
48
|
+
default: undefined,
|
|
49
|
+
},
|
|
50
|
+
onOpen: {
|
|
51
|
+
type: Function as PropType<<T>(payload: T) => void>,
|
|
52
|
+
required: false,
|
|
53
|
+
default: undefined,
|
|
54
|
+
},
|
|
55
|
+
onClose: {
|
|
56
|
+
type: Function as PropType<<T>(payload: T) => void>,
|
|
57
|
+
required: false,
|
|
58
|
+
default: undefined,
|
|
59
|
+
},
|
|
60
|
+
payload: {
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
+
type: [String, Object] as PropType<Record<string, any>>,
|
|
63
|
+
required: false,
|
|
64
|
+
default: () => ({}),
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
setup() {
|
|
68
|
+
const { notificationContainer } = useContainer();
|
|
69
|
+
const notificationsList = computed(() => {
|
|
70
|
+
return notificationContainer.value || [];
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return () =>
|
|
74
|
+
notificationsList.value.map((item) => {
|
|
75
|
+
return h(VcNotification, { ...item, key: item.notificationId });
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export default NotificationContainer;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { createApp, nextTick, reactive, ref, Ref } from "vue";
|
|
2
|
+
import { NotificationOptions } from "../../types";
|
|
3
|
+
import { NotificationContainer } from "../../components";
|
|
4
|
+
import { useInstance } from "../useInstance";
|
|
5
|
+
import * as _ from "lodash-es";
|
|
6
|
+
|
|
7
|
+
interface PendingNotification {
|
|
8
|
+
notificationId: string | number;
|
|
9
|
+
notificationProps: NotificationOptions;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface PendingContainer {
|
|
13
|
+
items: PendingNotification[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface IUseContainer {
|
|
17
|
+
defaultOptions: NotificationOptions;
|
|
18
|
+
pending: PendingContainer;
|
|
19
|
+
notificationContainer: Ref<NotificationOptions[]>;
|
|
20
|
+
actions: {
|
|
21
|
+
add(options: NotificationOptions): void;
|
|
22
|
+
remove(id: string | number): void;
|
|
23
|
+
clear(): void;
|
|
24
|
+
dismiss(notificationId: string | number): void;
|
|
25
|
+
};
|
|
26
|
+
getAllNotifications(): NotificationOptions[];
|
|
27
|
+
appendInstance(options: NotificationOptions): void;
|
|
28
|
+
generateNotificationId(): string;
|
|
29
|
+
getNotification(notificationId: string): NotificationOptions;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const pending = reactive<PendingContainer>({ items: [] });
|
|
33
|
+
const notificationContainer: Ref<NotificationOptions[]> = ref([]);
|
|
34
|
+
|
|
35
|
+
const { clearContainer, unmountComponent, saveInstance } = useInstance();
|
|
36
|
+
|
|
37
|
+
export function useContainer(): IUseContainer {
|
|
38
|
+
const defaultOptions = reactive<NotificationOptions>({
|
|
39
|
+
timeout: 3000,
|
|
40
|
+
pauseOnHover: true,
|
|
41
|
+
limit: 3,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
function getAllNotifications() {
|
|
45
|
+
return notificationContainer.value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function existPendingItem() {
|
|
49
|
+
return pending.items.length > 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function appendFromPending() {
|
|
53
|
+
if (pending.items.length > 0) {
|
|
54
|
+
const append = pending.items.shift();
|
|
55
|
+
appendInstance(append?.notificationProps);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getNotification(notificationId: string | number) {
|
|
60
|
+
const notification = getAllNotifications();
|
|
61
|
+
|
|
62
|
+
return notification.find((item) => item.notificationId === notificationId);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function generateRoot() {
|
|
66
|
+
const rootInstance = document.querySelector(".notification");
|
|
67
|
+
const notificationContainer = document.querySelector(".notification__container");
|
|
68
|
+
const existRenderRoot = !!notificationContainer;
|
|
69
|
+
|
|
70
|
+
const container = rootInstance || document.createElement("div");
|
|
71
|
+
const renderRoot = document.createElement("div");
|
|
72
|
+
|
|
73
|
+
renderRoot.className = "notification__container";
|
|
74
|
+
renderRoot.id = "notification";
|
|
75
|
+
|
|
76
|
+
if (!rootInstance) {
|
|
77
|
+
container.className = "notification";
|
|
78
|
+
document.body.appendChild(container);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!existRenderRoot) {
|
|
82
|
+
container.appendChild(renderRoot);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return renderRoot;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function appendInstance(options: NotificationOptions) {
|
|
89
|
+
const isExist = (notificationContainer.value || []).length > 0;
|
|
90
|
+
|
|
91
|
+
if (!isExist && !document.querySelector(`.notification__container`)) {
|
|
92
|
+
const dom = generateRoot();
|
|
93
|
+
const instance = createApp(NotificationContainer, options as Record<string, unknown>);
|
|
94
|
+
instance.mount(dom);
|
|
95
|
+
saveInstance(instance, dom.id);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
nextTick(() => {
|
|
99
|
+
if (options.updateId) {
|
|
100
|
+
actions.update(options);
|
|
101
|
+
} else {
|
|
102
|
+
actions.add(options);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function generateNotificationId() {
|
|
108
|
+
return Math.random().toString(36).substring(2, 9);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const actions = {
|
|
112
|
+
add(options: NotificationOptions) {
|
|
113
|
+
if (!notificationContainer.value.find((item) => item.notificationId === options.notificationId)) {
|
|
114
|
+
nextTick(() => {
|
|
115
|
+
notificationContainer.value?.push(options);
|
|
116
|
+
if (options.onOpen && typeof options?.onOpen === "function") {
|
|
117
|
+
options.onOpen(options.payload ?? {});
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
remove(id: string | number) {
|
|
123
|
+
if (id) {
|
|
124
|
+
const container = document.querySelector(".notification");
|
|
125
|
+
if (container) {
|
|
126
|
+
let notification = notificationContainer.value.find((item) => item.notificationId === id);
|
|
127
|
+
_.remove(notificationContainer.value, (item) => {
|
|
128
|
+
return item.notificationId === id;
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
if (!notificationContainer.value.length && !existPendingItem()) {
|
|
132
|
+
unmountComponent();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
appendFromPending();
|
|
136
|
+
|
|
137
|
+
nextTick(() => {
|
|
138
|
+
if (notification?.onClose && typeof notification?.onClose === "function") {
|
|
139
|
+
notification.onClose(notification.payload ?? {});
|
|
140
|
+
notification = undefined;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
clear() {
|
|
147
|
+
clearContainer();
|
|
148
|
+
},
|
|
149
|
+
dismiss(notificationId: string | number) {
|
|
150
|
+
if (notificationId) {
|
|
151
|
+
const allNotifications = getAllNotifications();
|
|
152
|
+
allNotifications.forEach((item) => {
|
|
153
|
+
if (item.notificationId === notificationId) {
|
|
154
|
+
const node = document.getElementById(String(notificationId));
|
|
155
|
+
|
|
156
|
+
if (node) {
|
|
157
|
+
setTimeout(() => {
|
|
158
|
+
actions.remove(notificationId);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
update(option: NotificationOptions) {
|
|
166
|
+
if (option.updateId) {
|
|
167
|
+
const item = notificationContainer.value?.find((item) => item.notificationId === option.notificationId);
|
|
168
|
+
if (item) {
|
|
169
|
+
for (const name in option) {
|
|
170
|
+
if (name in option) {
|
|
171
|
+
const value = option[name];
|
|
172
|
+
item[name] = value;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
defaultOptions,
|
|
182
|
+
pending,
|
|
183
|
+
notificationContainer,
|
|
184
|
+
actions,
|
|
185
|
+
getAllNotifications,
|
|
186
|
+
appendInstance,
|
|
187
|
+
getNotification,
|
|
188
|
+
generateNotificationId,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { App, Ref, ref } from "vue";
|
|
2
|
+
import { useContainer } from "./../useContainer";
|
|
3
|
+
|
|
4
|
+
interface IUseInstance {
|
|
5
|
+
saveInstance(app: App<Element>, id: string): void;
|
|
6
|
+
unmountComponent(): void;
|
|
7
|
+
clearContainer(): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const containerInstance: Ref<App<Element>> = ref();
|
|
11
|
+
|
|
12
|
+
export function useInstance(): IUseInstance {
|
|
13
|
+
const { pending, notificationContainer } = useContainer();
|
|
14
|
+
|
|
15
|
+
function saveInstance(app: App<Element>, id: string) {
|
|
16
|
+
const container = document.getElementById(id);
|
|
17
|
+
if (container) {
|
|
18
|
+
containerInstance.value = app;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function unmountComponent() {
|
|
23
|
+
try {
|
|
24
|
+
containerInstance.value.unmount();
|
|
25
|
+
document.getElementById("notification")?.remove();
|
|
26
|
+
containerInstance.value = undefined;
|
|
27
|
+
notificationContainer.value = [];
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error(error);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function clearContainer() {
|
|
34
|
+
if (containerInstance.value) {
|
|
35
|
+
unmountComponent();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
pending.items = [];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
saveInstance,
|
|
43
|
+
unmountComponent,
|
|
44
|
+
clearContainer,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { notification } from "./notification";
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { mergeProps } from "vue";
|
|
2
|
+
import { NotificationOptions } from "../types";
|
|
3
|
+
import { useContainer } from "../composables";
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
defaultOptions,
|
|
7
|
+
pending,
|
|
8
|
+
actions,
|
|
9
|
+
getNotification,
|
|
10
|
+
getAllNotifications,
|
|
11
|
+
appendInstance,
|
|
12
|
+
generateNotificationId,
|
|
13
|
+
} = useContainer();
|
|
14
|
+
|
|
15
|
+
function checkPending(limit?: number) {
|
|
16
|
+
const visibleCount = getAllNotifications().length;
|
|
17
|
+
const limitCount = limit ?? 0;
|
|
18
|
+
return limitCount > 0 && visibleCount + pending.items.length >= limitCount;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function resolvePending(options) {
|
|
22
|
+
if (checkPending(options.limit)) {
|
|
23
|
+
pending.items.push({
|
|
24
|
+
notificationId: options.notificationId,
|
|
25
|
+
notificationProps: options,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function showNotification(content: string, options: NotificationOptions) {
|
|
31
|
+
options = mergeProps(defaultOptions as Record<string, unknown>, options as Record<string, unknown>);
|
|
32
|
+
|
|
33
|
+
if (
|
|
34
|
+
!options.notificationId ||
|
|
35
|
+
(typeof options.notificationId !== "string" && typeof options.notificationId !== "number")
|
|
36
|
+
) {
|
|
37
|
+
options.notificationId = generateNotificationId();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
options = {
|
|
41
|
+
...options,
|
|
42
|
+
content,
|
|
43
|
+
closeNotification: () => notification.remove(options.notificationId),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
resolvePending(options);
|
|
47
|
+
|
|
48
|
+
if (!pending.items.length) {
|
|
49
|
+
appendInstance(options);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return options.notificationId;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const notification = (content: string, options?: NotificationOptions) =>
|
|
56
|
+
showNotification(content, { ...options, type: "default" });
|
|
57
|
+
|
|
58
|
+
notification.error = (content: string, options?: NotificationOptions) =>
|
|
59
|
+
showNotification(content, { ...options, type: "error" });
|
|
60
|
+
|
|
61
|
+
notification.warning = (content: string, options?: NotificationOptions) =>
|
|
62
|
+
showNotification(content, { ...options, type: "warning" });
|
|
63
|
+
|
|
64
|
+
notification.success = (content: string, options?: NotificationOptions) =>
|
|
65
|
+
showNotification(content, { ...options, type: "success" });
|
|
66
|
+
|
|
67
|
+
notification.clearAll = () => {
|
|
68
|
+
actions.clear();
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
notification.remove = (notificationId?: number | string) => {
|
|
72
|
+
if (notificationId) {
|
|
73
|
+
actions.dismiss(notificationId);
|
|
74
|
+
} else {
|
|
75
|
+
actions.clear();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
notification.update = (notificationId: string | number, options: NotificationOptions) => {
|
|
80
|
+
const item = getNotification(String(notificationId));
|
|
81
|
+
if (item) {
|
|
82
|
+
const updatedOptions = {
|
|
83
|
+
...item,
|
|
84
|
+
...options,
|
|
85
|
+
updateId: generateNotificationId(),
|
|
86
|
+
notificationId: options.notificationId || notificationId,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const content = updatedOptions.content || item.content;
|
|
90
|
+
delete updatedOptions.content;
|
|
91
|
+
|
|
92
|
+
showNotification(content, updatedOptions);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export { notification };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as components from "./components";
|
|
2
|
+
import { createModule } from "../../../core/plugins";
|
|
3
|
+
import "./styles/index.scss";
|
|
4
|
+
|
|
5
|
+
// Declare globally
|
|
6
|
+
declare module "@vue/runtime-core" {
|
|
7
|
+
export interface GlobalComponents {
|
|
8
|
+
VcNotificationContainer: (typeof components)["NotificationContainer"];
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const VcNotificationComponent = createModule(components);
|
|
13
|
+
|
|
14
|
+
export * from "./components";
|
|
15
|
+
export * from "./composables";
|
|
16
|
+
export * from "./types";
|
|
17
|
+
export * from "./core";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type NotificationType = "success" | "error" | "warning" | "default";
|
|
2
|
+
|
|
3
|
+
export interface NotificationOptions {
|
|
4
|
+
limit?: number;
|
|
5
|
+
pauseOnHover?: boolean;
|
|
6
|
+
timeout?: number | boolean;
|
|
7
|
+
content?: string;
|
|
8
|
+
notificationId?: number | string;
|
|
9
|
+
type?: NotificationType;
|
|
10
|
+
closeNotification?(): void;
|
|
11
|
+
onOpen?: <T>(payload: T) => void;
|
|
12
|
+
onClose?: <T>(payload: T) => void;
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
payload?: string | Record<string, any>;
|
|
15
|
+
updateId?: string | number;
|
|
16
|
+
}
|
package/shared/index.ts
CHANGED
|
@@ -3,10 +3,16 @@ import { AssetsDetailsModule } from "./modules/assets";
|
|
|
3
3
|
import { VcAppSwitcherComponent } from "./components/app-switcher";
|
|
4
4
|
import { VcBladeNavigationComponent } from "./components/blade-navigation";
|
|
5
5
|
import { AssetsManagerModule } from "./modules/assets-manager";
|
|
6
|
+
import { VcNotificationComponent } from "./components/notifications";
|
|
6
7
|
|
|
7
8
|
export const SharedModule = {
|
|
8
9
|
install(app: App): void {
|
|
9
|
-
app
|
|
10
|
+
app
|
|
11
|
+
.use(AssetsDetailsModule)
|
|
12
|
+
.use(AssetsManagerModule)
|
|
13
|
+
.use(VcBladeNavigationComponent)
|
|
14
|
+
.use(VcAppSwitcherComponent)
|
|
15
|
+
.use(VcNotificationComponent);
|
|
10
16
|
},
|
|
11
17
|
};
|
|
12
18
|
|
|
@@ -15,3 +21,4 @@ export * from "./modules/assets-manager";
|
|
|
15
21
|
|
|
16
22
|
export * from "./components/app-switcher";
|
|
17
23
|
export * from "./components/blade-navigation";
|
|
24
|
+
export * from "./components/notifications";
|
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
@expand="$emit('expand:blade')"
|
|
10
10
|
@collapse="$emit('collapse:blade')"
|
|
11
11
|
>
|
|
12
|
+
<template
|
|
13
|
+
v-slot:error
|
|
14
|
+
v-if="$slots['error']"
|
|
15
|
+
>
|
|
16
|
+
<slot name="error"></slot>
|
|
17
|
+
</template>
|
|
12
18
|
<!-- Blade contents -->
|
|
13
19
|
<div class="tw-flex tw-grow-1 tw-border-t tw-border-solid tw-border-t-[#eaedf3]">
|
|
14
20
|
<div class="assets-details__content tw-grow tw-basis-0 tw-w-full">
|
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
@expand="$emit('expand:blade')"
|
|
10
10
|
@collapse="$emit('collapse:blade')"
|
|
11
11
|
>
|
|
12
|
+
<template
|
|
13
|
+
v-slot:error
|
|
14
|
+
v-if="$slots['error']"
|
|
15
|
+
>
|
|
16
|
+
<slot name="error"></slot>
|
|
17
|
+
</template>
|
|
12
18
|
<div
|
|
13
19
|
class="tw-relative tw-h-full"
|
|
14
20
|
@dragover.prevent.stop="dragOver"
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import { VNode } from "vue";
|
|
2
1
|
import _Notification from "./vc-notification.vue";
|
|
3
2
|
|
|
4
|
-
export const VcNotification = _Notification as typeof _Notification
|
|
5
|
-
new (): {
|
|
6
|
-
$slots: {
|
|
7
|
-
default: () => VNode[];
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
|
-
};
|
|
3
|
+
export const VcNotification = _Notification as typeof _Notification;
|