@vc-shell/framework 1.1.69 → 1.1.71
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 +18 -0
- package/core/services/app-bar-mobile-buttons-service.ts +6 -2
- package/dist/core/services/app-bar-mobile-buttons-service.d.ts.map +1 -1
- package/dist/framework.js +6236 -6189
- package/dist/index.css +1 -1
- package/dist/shared/components/app-switcher/components/vc-app-switcher/vc-app-switcher.vue.d.ts.map +1 -1
- package/dist/shared/components/generic-dropdown/generic-dropdown.vue.d.ts.map +1 -1
- package/dist/shared/components/notification-dropdown/notification-dropdown.vue.d.ts.map +1 -1
- package/dist/shared/components/sidebar/sidebar.vue.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/atoms/vc-tooltip/vc-tooltip.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-multivalue/vc-multivalue.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-select/vc-select.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarContent.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarHeader.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarOverlay.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarSlots.vue.d.ts +3 -0
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarSlots.vue.d.ts.map +1 -0
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/MenuSidebar.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/composables/useAppSlots.d.ts +28 -0
- package/dist/ui/components/organisms/vc-app/composables/useAppSlots.d.ts.map +1 -0
- package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-desktop-view/_internal/vc-table-row/vc-table-row.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/composables/useTableColumnResize.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/composables/useTableState.d.ts.map +1 -1
- package/dist/{vendor-floating-ui-core-DpX2jufl.js → vendor-floating-ui-core-3dy7r5mx.js} +1 -1
- package/dist/{vendor-floating-ui-dom-C4AKN5Mo.js → vendor-floating-ui-dom-DCjH_QK4.js} +6 -6
- package/dist/{vendor-floating-ui-utils-CRaCuFxS.js → vendor-floating-ui-utils-D2sT7feD.js} +15 -15
- package/dist/{vendor-floating-ui-vue-OwtolkBv.js → vendor-floating-ui-vue-BUBCqiRN.js} +12 -12
- package/package.json +4 -4
- package/shared/components/app-switcher/components/vc-app-switcher/vc-app-switcher.vue +3 -1
- package/shared/components/generic-dropdown/generic-dropdown.vue +15 -10
- package/shared/components/notification-dropdown/notification-dropdown.vue +1 -0
- package/shared/components/sidebar/sidebar.vue +1 -1
- package/ui/components/atoms/vc-tooltip/vc-tooltip.vue +1 -1
- package/ui/components/molecules/vc-multivalue/vc-multivalue.vue +1 -1
- package/ui/components/molecules/vc-select/vc-select.vue +1 -1
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarContent.vue +5 -5
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarHeader.vue +5 -8
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarOverlay.vue +1 -1
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarSlots.vue +118 -0
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/MenuSidebar.vue +12 -8
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +3 -74
- package/ui/components/organisms/vc-app/composables/useAppSlots.ts +75 -0
- package/ui/components/organisms/vc-app/vc-app.vue +30 -42
- package/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue +1 -1
- package/ui/components/organisms/vc-table/_internal/vc-table-desktop-view/_internal/vc-table-row/vc-table-row.vue +5 -1
- package/ui/components/organisms/vc-table/composables/useTableColumnResize.ts +0 -1
- package/ui/components/organisms/vc-table/composables/useTableState.ts +17 -16
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- Desktop version -->
|
|
3
|
+
<template v-if="isDesktop && !isMenuOpen">
|
|
4
|
+
<AppBarContent :expanded="isExpanded">
|
|
5
|
+
<template #navmenu>
|
|
6
|
+
<component
|
|
7
|
+
:is="slots.navmenu"
|
|
8
|
+
v-if="slots.navmenu"
|
|
9
|
+
/>
|
|
10
|
+
</template>
|
|
11
|
+
<template #user-dropdown>
|
|
12
|
+
<component
|
|
13
|
+
:is="slots.userDropdown"
|
|
14
|
+
v-if="slots.userDropdown"
|
|
15
|
+
/>
|
|
16
|
+
</template>
|
|
17
|
+
</AppBarContent>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<!-- Menu sidebar (both desktop and mobile) -->
|
|
21
|
+
<MenuSidebar
|
|
22
|
+
v-if="isMenuOpen"
|
|
23
|
+
:is-opened="isMenuOpen"
|
|
24
|
+
:expanded="isExpanded"
|
|
25
|
+
@update:is-opened="closeMenu"
|
|
26
|
+
>
|
|
27
|
+
<template #navmenu>
|
|
28
|
+
<component
|
|
29
|
+
:is="slots.navmenu"
|
|
30
|
+
v-if="slots.navmenu"
|
|
31
|
+
/>
|
|
32
|
+
</template>
|
|
33
|
+
<template #user-dropdown>
|
|
34
|
+
<component
|
|
35
|
+
:is="slots.userDropdown"
|
|
36
|
+
v-if="slots.userDropdown"
|
|
37
|
+
/>
|
|
38
|
+
</template>
|
|
39
|
+
<template #app-switcher>
|
|
40
|
+
<component
|
|
41
|
+
:is="slots.appSwitcher"
|
|
42
|
+
v-if="slots.appSwitcher"
|
|
43
|
+
/>
|
|
44
|
+
</template>
|
|
45
|
+
<template #widgets>
|
|
46
|
+
<AppBarWidgetsMenu />
|
|
47
|
+
</template>
|
|
48
|
+
<template #widgets-active-content>
|
|
49
|
+
<AppBarWidgetContent />
|
|
50
|
+
</template>
|
|
51
|
+
</MenuSidebar>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script lang="ts" setup>
|
|
55
|
+
import { computed, inject, ref, h, defineComponent } from "vue";
|
|
56
|
+
import { useAppMenuState } from "../../composables/useAppMenuState";
|
|
57
|
+
import { useAppSlots } from "../../../composables/useAppSlots";
|
|
58
|
+
import { useAppBarWidgets } from "../composables/useAppBarWidgets";
|
|
59
|
+
import AppBarContent from "./AppBarContent.vue";
|
|
60
|
+
import MenuSidebar from "./MenuSidebar.vue";
|
|
61
|
+
import AppBarWidgetsMenu from "./AppBarWidgetsMenu.vue";
|
|
62
|
+
|
|
63
|
+
// Create AppBarWidgetContent component inline
|
|
64
|
+
|
|
65
|
+
const AppBarWidgetContent = defineComponent({
|
|
66
|
+
setup() {
|
|
67
|
+
const { currentWidget, hideAllWidgets, isAnyWidgetVisible } = useAppBarWidgets();
|
|
68
|
+
const isMobile = inject("isMobile", ref(false));
|
|
69
|
+
|
|
70
|
+
return () => {
|
|
71
|
+
if (!isAnyWidgetVisible.value || !currentWidget.value?.component) return null;
|
|
72
|
+
|
|
73
|
+
return h(
|
|
74
|
+
"div",
|
|
75
|
+
{
|
|
76
|
+
class: [
|
|
77
|
+
"app-bar-widget-content",
|
|
78
|
+
{
|
|
79
|
+
"app-bar-widget-content--mobile": isMobile.value,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
[
|
|
84
|
+
h(currentWidget.value.component, {
|
|
85
|
+
...currentWidget.value.props,
|
|
86
|
+
onClose: hideAllWidgets,
|
|
87
|
+
}),
|
|
88
|
+
],
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const { state, closeAll } = useAppMenuState();
|
|
95
|
+
const slots = useAppSlots();
|
|
96
|
+
|
|
97
|
+
const isDesktop = inject("isDesktop", ref(true));
|
|
98
|
+
|
|
99
|
+
const isExpanded = computed(() => state.value.isSidebarExpanded);
|
|
100
|
+
const isMenuOpen = computed(() => state.value.isMenuOpen);
|
|
101
|
+
|
|
102
|
+
const closeMenu = () => {
|
|
103
|
+
closeAll();
|
|
104
|
+
};
|
|
105
|
+
</script>
|
|
106
|
+
|
|
107
|
+
<style lang="scss">
|
|
108
|
+
.app-bar-slots {
|
|
109
|
+
@apply tw-h-full;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.app-bar-widget-content {
|
|
113
|
+
@apply tw-overflow-auto tw-max-h-[250px];
|
|
114
|
+
&--mobile {
|
|
115
|
+
// Mobile specific styles if needed
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
</style>
|
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
<div
|
|
12
12
|
class="menu-sidebar__wrapper"
|
|
13
13
|
:class="{
|
|
14
|
+
'menu-sidebar__wrapper--desktop': $isDesktop.value,
|
|
14
15
|
'menu-sidebar__wrapper--expanded': $isDesktop.value && expanded,
|
|
15
|
-
'menu-sidebar__wrapper--collapsed': $isDesktop.value && !expanded,
|
|
16
16
|
}"
|
|
17
17
|
>
|
|
18
18
|
<div
|
|
19
|
+
v-if="!isEmbedded"
|
|
19
20
|
class="menu-sidebar__header"
|
|
20
21
|
:class="{
|
|
21
22
|
'menu-sidebar__header--mobile': $isMobile.value,
|
|
@@ -64,7 +65,8 @@
|
|
|
64
65
|
<!-- eslint-disable @typescript-eslint/no-explicit-any -->
|
|
65
66
|
<script lang="ts" setup>
|
|
66
67
|
import { Sidebar } from "../../../../../../../shared/components/sidebar";
|
|
67
|
-
import { MaybeRef } from "vue";
|
|
68
|
+
import { MaybeRef, inject } from "vue";
|
|
69
|
+
import { EMBEDDED_MODE } from "../../../../../../../injection-keys";
|
|
68
70
|
|
|
69
71
|
defineProps<{
|
|
70
72
|
isOpened: boolean;
|
|
@@ -82,24 +84,26 @@ defineSlots<{
|
|
|
82
84
|
"widgets-active-content": (props: any) => any;
|
|
83
85
|
widgets: (props: any) => any;
|
|
84
86
|
}>();
|
|
87
|
+
|
|
88
|
+
const isEmbedded = inject(EMBEDDED_MODE);
|
|
85
89
|
</script>
|
|
86
90
|
|
|
87
91
|
<style lang="scss">
|
|
88
92
|
.menu-sidebar {
|
|
89
93
|
&__wrapper {
|
|
90
|
-
@apply tw-absolute tw-top-0 tw-left-0 tw-w-full
|
|
94
|
+
@apply tw-absolute tw-top-0 tw-left-0 tw-w-full tw-bottom-0 tw-z-10 tw-flex tw-flex-col;
|
|
91
95
|
|
|
92
|
-
&--
|
|
93
|
-
@apply tw-
|
|
96
|
+
&--desktop {
|
|
97
|
+
@apply tw-w-[var(--app-bar-width)] tw-z-[12];
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
&--
|
|
97
|
-
@apply tw-
|
|
100
|
+
&--expanded {
|
|
101
|
+
@apply tw-absolute tw-top-0 tw-left-0;
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
&__content {
|
|
102
|
-
@apply tw-flex tw-flex-col tw-h-
|
|
106
|
+
@apply tw-flex tw-flex-col tw-h-[calc(100vh-var(--app-bar-height))] tw-bg-[var(--app-bar-background)] tw-flex-1 tw-relative;
|
|
103
107
|
|
|
104
108
|
&:before {
|
|
105
109
|
content: "";
|
|
@@ -37,8 +37,6 @@
|
|
|
37
37
|
'vc-app-bar__wrapper--mobile': $isMobile.value,
|
|
38
38
|
'vc-app-bar__wrapper--hover-collapsed': $isDesktop.value && !isHoverExpanded && !state.isSidebarExpanded,
|
|
39
39
|
}"
|
|
40
|
-
@mouseenter="collapseButtonHover = true"
|
|
41
|
-
@mouseleave="collapseButtonHover = false"
|
|
42
40
|
>
|
|
43
41
|
<AppBarHeader
|
|
44
42
|
:logo="logo"
|
|
@@ -59,49 +57,7 @@
|
|
|
59
57
|
</template>
|
|
60
58
|
</AppBarHeader>
|
|
61
59
|
|
|
62
|
-
<
|
|
63
|
-
v-if="state.isMenuOpen"
|
|
64
|
-
:is-opened="state.isMenuOpen"
|
|
65
|
-
:expanded="state.isSidebarExpanded"
|
|
66
|
-
@update:is-opened="handleMenuClose"
|
|
67
|
-
>
|
|
68
|
-
<template #navmenu>
|
|
69
|
-
<slot name="navmenu" />
|
|
70
|
-
</template>
|
|
71
|
-
<template #user-dropdown>
|
|
72
|
-
<slot name="user-dropdown" />
|
|
73
|
-
</template>
|
|
74
|
-
<template #app-switcher>
|
|
75
|
-
<slot name="app-switcher" />
|
|
76
|
-
</template>
|
|
77
|
-
<template #widgets>
|
|
78
|
-
<AppBarWidgetsMenu />
|
|
79
|
-
</template>
|
|
80
|
-
<template #widgets-active-content>
|
|
81
|
-
<div
|
|
82
|
-
v-if="isAnyWidgetVisible"
|
|
83
|
-
:class="['vc-app-bar__menu-dropdowns', { 'vc-app-bar__menu-dropdowns--mobile': $isMobile.value }]"
|
|
84
|
-
>
|
|
85
|
-
<component
|
|
86
|
-
:is="currentWidget?.component"
|
|
87
|
-
v-bind="currentWidget?.props || {}"
|
|
88
|
-
@close="hideAllWidgets"
|
|
89
|
-
/>
|
|
90
|
-
</div>
|
|
91
|
-
</template>
|
|
92
|
-
</MenuSidebar>
|
|
93
|
-
|
|
94
|
-
<AppBarContent
|
|
95
|
-
v-if="$isDesktop.value"
|
|
96
|
-
:expanded="state.isSidebarExpanded"
|
|
97
|
-
>
|
|
98
|
-
<template #navmenu>
|
|
99
|
-
<slot name="navmenu" />
|
|
100
|
-
</template>
|
|
101
|
-
<template #user-dropdown>
|
|
102
|
-
<slot name="user-dropdown" />
|
|
103
|
-
</template>
|
|
104
|
-
</AppBarContent>
|
|
60
|
+
<AppBarSlots />
|
|
105
61
|
</div>
|
|
106
62
|
</div>
|
|
107
63
|
</div>
|
|
@@ -110,12 +66,9 @@
|
|
|
110
66
|
<script lang="ts" setup>
|
|
111
67
|
import { VcIcon } from "../../../../";
|
|
112
68
|
import { useAppMenuState } from "../composables/useAppMenuState";
|
|
113
|
-
import { useAppBarWidgets } from "./composables/useAppBarWidgets";
|
|
114
69
|
import AppBarHeader from "./_internal/AppBarHeader.vue";
|
|
115
70
|
import AppBarMobileActions from "./_internal/AppBarMobileActions.vue";
|
|
116
|
-
import
|
|
117
|
-
import AppBarContent from "./_internal/AppBarContent.vue";
|
|
118
|
-
import AppBarWidgetsMenu from "./_internal/AppBarWidgetsMenu.vue";
|
|
71
|
+
import AppBarSlots from "./_internal/AppBarSlots.vue";
|
|
119
72
|
import { ref, computed, provide, inject } from "vue";
|
|
120
73
|
|
|
121
74
|
export interface Props {
|
|
@@ -139,38 +92,14 @@ defineProps<Props>();
|
|
|
139
92
|
defineEmits<Emits>();
|
|
140
93
|
defineSlots<Slots>();
|
|
141
94
|
|
|
142
|
-
const {
|
|
143
|
-
state,
|
|
144
|
-
toggleSidebar,
|
|
145
|
-
toggleMenu: toggleMenuState,
|
|
146
|
-
closeAll,
|
|
147
|
-
toggleHoverExpanded,
|
|
148
|
-
isHoverExpanded,
|
|
149
|
-
} = useAppMenuState();
|
|
150
|
-
|
|
151
|
-
const { currentWidget, hideAllWidgets, isAnyWidgetVisible } = useAppBarWidgets();
|
|
95
|
+
const { state, toggleSidebar, toggleMenu, closeAll, toggleHoverExpanded, isHoverExpanded } = useAppMenuState();
|
|
152
96
|
|
|
153
97
|
const isMobile = inject("isMobile", ref(false));
|
|
154
98
|
const isDesktop = inject("isDesktop", ref(true));
|
|
155
|
-
const collapseButtonHover = ref(false);
|
|
156
99
|
|
|
157
100
|
// Provide appMenuState for child components
|
|
158
101
|
provide("appMenuState", { closeAll });
|
|
159
102
|
|
|
160
|
-
const toggleMenu = () => {
|
|
161
|
-
toggleMenuState();
|
|
162
|
-
if (!state.value.isMenuOpen) {
|
|
163
|
-
hideAllWidgets();
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const handleMenuClose = (value: boolean) => {
|
|
168
|
-
if (!value) {
|
|
169
|
-
closeAll();
|
|
170
|
-
hideAllWidgets();
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
|
|
174
103
|
// Simple hover effect processing
|
|
175
104
|
const handleHoverExpand = (shouldExpand?: boolean) => {
|
|
176
105
|
toggleHoverExpanded(shouldExpand);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { inject, provide, InjectionKey, Slots, VNode, h, Ref } from "vue";
|
|
2
|
+
import VcAppMenu from "../_internal/vc-app-menu/vc-app-menu.vue";
|
|
3
|
+
import { UserDropdownButton } from "../../../../../shared/components";
|
|
4
|
+
import { components } from "../../../../../shared/components/app-switcher";
|
|
5
|
+
import { AppDescriptor } from "../../../../../core/api/platform";
|
|
6
|
+
import { EMBEDDED_MODE } from "../../../../../injection-keys";
|
|
7
|
+
|
|
8
|
+
export interface AppSlots {
|
|
9
|
+
navmenu?: () => VNode | VNode[];
|
|
10
|
+
userDropdown?: () => VNode | VNode[];
|
|
11
|
+
appSwitcher?: () => VNode | VNode[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const APP_SLOTS_KEY: InjectionKey<AppSlots> = Symbol("app-slots");
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Provide app slots to child components
|
|
18
|
+
*/
|
|
19
|
+
export function provideAppSlots(
|
|
20
|
+
slots: Slots,
|
|
21
|
+
props: {
|
|
22
|
+
disableMenu?: boolean;
|
|
23
|
+
disableAppSwitcher?: boolean;
|
|
24
|
+
version?: string;
|
|
25
|
+
avatar?: string;
|
|
26
|
+
name?: string;
|
|
27
|
+
role?: string;
|
|
28
|
+
appsList?: Ref<AppDescriptor[]>;
|
|
29
|
+
isEmbedded?: boolean;
|
|
30
|
+
},
|
|
31
|
+
handlers: {
|
|
32
|
+
onMenuItemClick?: (item: any) => void;
|
|
33
|
+
switchApp?: (event: any) => void;
|
|
34
|
+
},
|
|
35
|
+
) {
|
|
36
|
+
|
|
37
|
+
const appSlots: AppSlots = {
|
|
38
|
+
navmenu: () => {
|
|
39
|
+
if (props.disableMenu) return [];
|
|
40
|
+
return h(VcAppMenu, {
|
|
41
|
+
version: props.version,
|
|
42
|
+
"onItem:click": handlers.onMenuItemClick,
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
userDropdown: () => {
|
|
46
|
+
if (props.isEmbedded) return [];
|
|
47
|
+
return h(UserDropdownButton, {
|
|
48
|
+
avatarUrl: props.avatar,
|
|
49
|
+
name: props.name,
|
|
50
|
+
role: props.role,
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
appSwitcher: () => {
|
|
54
|
+
if (props.disableAppSwitcher) return [];
|
|
55
|
+
return (
|
|
56
|
+
slots["app-switcher"]?.() ||
|
|
57
|
+
h(components.VcAppSwitcher, {
|
|
58
|
+
appsList: props.appsList?.value ?? [],
|
|
59
|
+
onClick: handlers.switchApp,
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
provide(APP_SLOTS_KEY, appSlots);
|
|
66
|
+
return appSlots;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Inject app slots in child components
|
|
71
|
+
*/
|
|
72
|
+
export function useAppSlots() {
|
|
73
|
+
const slots = inject(APP_SLOTS_KEY, {});
|
|
74
|
+
return slots;
|
|
75
|
+
}
|
|
@@ -22,38 +22,7 @@
|
|
|
22
22
|
:disable-menu="disableMenu"
|
|
23
23
|
@backlink:click="closeBlade(blades.length - 1)"
|
|
24
24
|
@logo:click="openRoot"
|
|
25
|
-
|
|
26
|
-
<template
|
|
27
|
-
v-if="!disableAppSwitcher"
|
|
28
|
-
#app-switcher
|
|
29
|
-
>
|
|
30
|
-
<slot name="app-switcher">
|
|
31
|
-
<VcAppSwitcher
|
|
32
|
-
:apps-list="appsList"
|
|
33
|
-
@on-click="switchApp($event)"
|
|
34
|
-
/>
|
|
35
|
-
</slot>
|
|
36
|
-
</template>
|
|
37
|
-
|
|
38
|
-
<template #navmenu>
|
|
39
|
-
<VcAppMenu
|
|
40
|
-
v-if="!disableMenu"
|
|
41
|
-
ref="menu"
|
|
42
|
-
class="vc-app__app-menu"
|
|
43
|
-
:version="version"
|
|
44
|
-
@item:click="onMenuItemClick"
|
|
45
|
-
>
|
|
46
|
-
</VcAppMenu>
|
|
47
|
-
</template>
|
|
48
|
-
|
|
49
|
-
<template #user-dropdown>
|
|
50
|
-
<UserDropdownButton
|
|
51
|
-
:avatar-url="avatar"
|
|
52
|
-
:name="name"
|
|
53
|
-
:role="role"
|
|
54
|
-
/>
|
|
55
|
-
</template>
|
|
56
|
-
</VcAppBar>
|
|
25
|
+
/>
|
|
57
26
|
|
|
58
27
|
<!-- Blade navigation -->
|
|
59
28
|
<div
|
|
@@ -70,12 +39,11 @@
|
|
|
70
39
|
</template>
|
|
71
40
|
<!-- eslint-disable @typescript-eslint/no-explicit-any -->
|
|
72
41
|
<script lang="ts" setup>
|
|
73
|
-
import { inject, provide, watch, ref, onUnmounted, computed } from "vue";
|
|
42
|
+
import { inject, provide, watch, ref, onUnmounted, computed, useSlots } from "vue";
|
|
74
43
|
import VcAppBar from "./_internal/vc-app-bar/vc-app-bar.vue";
|
|
75
|
-
import
|
|
44
|
+
import { provideAppSlots } from "./composables/useAppSlots";
|
|
76
45
|
import {
|
|
77
46
|
VcPopupContainer,
|
|
78
|
-
UserDropdownButton,
|
|
79
47
|
useBladeNavigation,
|
|
80
48
|
NotificationDropdown,
|
|
81
49
|
BladeRoutesRecord,
|
|
@@ -90,7 +58,6 @@ import { LanguageSelector } from "../../../../shared/components/language-selecto
|
|
|
90
58
|
import { ThemeSelector } from "../../../../shared/components/theme-selector";
|
|
91
59
|
import { ChangePasswordButton } from "../../../../shared/components/change-password-button";
|
|
92
60
|
import { LogoutButton } from "../../../../shared/components/logout-button";
|
|
93
|
-
import { useI18n } from "vue-i18n";
|
|
94
61
|
import { provideGlobalSearch } from "../../../../core/composables/useGlobalSearch";
|
|
95
62
|
import { provideDashboardService } from "../../../../core/composables/useDashboard";
|
|
96
63
|
import { DynamicModulesKey, EMBEDDED_MODE } from "../../../../injection-keys";
|
|
@@ -110,7 +77,7 @@ export interface Props {
|
|
|
110
77
|
role?: string;
|
|
111
78
|
}
|
|
112
79
|
|
|
113
|
-
|
|
80
|
+
defineEmits<{
|
|
114
81
|
(e: "logo-click", goToRoot: () => void): void;
|
|
115
82
|
}>();
|
|
116
83
|
|
|
@@ -123,6 +90,7 @@ defineSlots<{
|
|
|
123
90
|
}>();
|
|
124
91
|
|
|
125
92
|
const props = defineProps<Props>();
|
|
93
|
+
const slots = useSlots();
|
|
126
94
|
|
|
127
95
|
console.debug("vc-app: Init vc-app");
|
|
128
96
|
|
|
@@ -131,13 +99,16 @@ const dynamicModules = inject(DynamicModulesKey, undefined);
|
|
|
131
99
|
|
|
132
100
|
const isAppReady = ref(props.isReady);
|
|
133
101
|
|
|
102
|
+
const route = useRoute();
|
|
134
103
|
const router = useRouter();
|
|
135
104
|
|
|
105
|
+
const isEmbedded = route.query.EmbeddedMode === "true";
|
|
106
|
+
|
|
136
107
|
const { openBlade, closeBlade, resolveBladeByName, blades, goToRoot } = useBladeNavigation();
|
|
137
108
|
const { appsList, switchApp, getApps } = useAppSwitcher();
|
|
138
109
|
|
|
139
|
-
const { loadFromHistory, notifications
|
|
140
|
-
|
|
110
|
+
const { loadFromHistory, notifications } = useNotifications();
|
|
111
|
+
|
|
141
112
|
const { isAuthenticated } = useUserManagement();
|
|
142
113
|
|
|
143
114
|
const routes = router.getRoutes();
|
|
@@ -149,8 +120,6 @@ const hasUnreadNotifications = computed(() => {
|
|
|
149
120
|
return notifications.value.some((item) => item.isNew);
|
|
150
121
|
});
|
|
151
122
|
|
|
152
|
-
const { t } = useI18n({ useScope: "global" });
|
|
153
|
-
|
|
154
123
|
const { register: registerMobileButton } = provideAppBarMobileButtonsService();
|
|
155
124
|
|
|
156
125
|
registerMenuItem({
|
|
@@ -190,6 +159,7 @@ registerMobileButton({
|
|
|
190
159
|
component: NotificationDropdown,
|
|
191
160
|
icon: "lucide-bell",
|
|
192
161
|
order: 10,
|
|
162
|
+
isVisible: !isEmbedded,
|
|
193
163
|
});
|
|
194
164
|
|
|
195
165
|
const onMenuItemClick = function (item: MenuItem) {
|
|
@@ -247,7 +217,25 @@ provide(DynamicModulesKey, dynamicModules);
|
|
|
247
217
|
provideDashboardService();
|
|
248
218
|
provideMenuService();
|
|
249
219
|
provideGlobalSearch();
|
|
250
|
-
provide(EMBEDDED_MODE,
|
|
220
|
+
provide(EMBEDDED_MODE, isEmbedded);
|
|
221
|
+
// Provide slots to child components with all necessary props and handlers
|
|
222
|
+
provideAppSlots(
|
|
223
|
+
slots,
|
|
224
|
+
{
|
|
225
|
+
disableMenu: props.disableMenu,
|
|
226
|
+
disableAppSwitcher: props.disableAppSwitcher,
|
|
227
|
+
version: props.version,
|
|
228
|
+
avatar: props.avatar,
|
|
229
|
+
name: props.name,
|
|
230
|
+
role: props.role,
|
|
231
|
+
appsList: appsList,
|
|
232
|
+
isEmbedded,
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
onMenuItemClick,
|
|
236
|
+
switchApp,
|
|
237
|
+
},
|
|
238
|
+
);
|
|
251
239
|
|
|
252
240
|
onUnmounted(() => {
|
|
253
241
|
isAppReady.value = false;
|
|
@@ -43,7 +43,11 @@
|
|
|
43
43
|
:key="`${(item && typeof item === 'object' && 'id' in item && item.id) || index}_${cell.id}`"
|
|
44
44
|
class="vc-table-row__cell"
|
|
45
45
|
:class="[cell.class, { 'vc-table-row__cell--fixed-width': !!cell.width }]"
|
|
46
|
-
:style="
|
|
46
|
+
:style="
|
|
47
|
+
cell.width
|
|
48
|
+
? { maxWidth: cell.width, width: cell.width, flex: '0 1 auto', minWidth: '60px' }
|
|
49
|
+
: { flex: '1 1 0', minWidth: '60px' }
|
|
50
|
+
"
|
|
47
51
|
>
|
|
48
52
|
<div class="vc-table-row__cell-content">
|
|
49
53
|
<slot
|
|
@@ -48,7 +48,6 @@ export function useTableColumnResize(
|
|
|
48
48
|
document.body.style.overflow = "hidden";
|
|
49
49
|
document.body.style.userSelect = "none";
|
|
50
50
|
|
|
51
|
-
|
|
52
51
|
// If resizing any column and there are flexible columns, fix all column widths
|
|
53
52
|
if (headerRef.value) {
|
|
54
53
|
const hasFlexibleColumns = internalColumns.value.some((col) => col.visible !== false && !col.width);
|
|
@@ -55,11 +55,11 @@ export function useTableState(options: UseTableStateOptions) {
|
|
|
55
55
|
function mergeColumns(storedCol: TableColPartial, predefinedCol: TableColPartial | undefined) {
|
|
56
56
|
if (predefinedCol) {
|
|
57
57
|
if (predefinedCol.predefined && !storedCol.predefined) {
|
|
58
|
-
return {
|
|
59
|
-
...predefinedCol,
|
|
58
|
+
return {
|
|
59
|
+
...predefinedCol,
|
|
60
60
|
predefined: true,
|
|
61
61
|
width: storedCol.width || predefinedCol.width,
|
|
62
|
-
visible: storedCol.visible !== undefined ? storedCol.visible : predefinedCol.visible
|
|
62
|
+
visible: storedCol.visible !== undefined ? storedCol.visible : predefinedCol.visible,
|
|
63
63
|
};
|
|
64
64
|
} else {
|
|
65
65
|
return {
|
|
@@ -161,37 +161,38 @@ export function useTableState(options: UseTableStateOptions) {
|
|
|
161
161
|
title: item.title || originalColumn?.title || "",
|
|
162
162
|
width: item.width || originalColumn?.width,
|
|
163
163
|
};
|
|
164
|
-
|
|
164
|
+
|
|
165
165
|
// Don't set any width for new columns - they'll take available space
|
|
166
166
|
// The flexbox will handle the distribution
|
|
167
167
|
if (!newCol.width) {
|
|
168
168
|
// Keep it undefined to use flexbox
|
|
169
169
|
newCol.width = undefined;
|
|
170
170
|
}
|
|
171
|
-
|
|
171
|
+
|
|
172
172
|
internalColumns.value.push(newCol);
|
|
173
|
-
|
|
173
|
+
|
|
174
174
|
// When adding a new column, check if we need to adjust widths to prevent overflow
|
|
175
|
-
const visibleColumns = internalColumns.value.filter(col => col.visible !== false);
|
|
176
|
-
const hasFixedWidths = visibleColumns.some(col => col.width);
|
|
177
|
-
|
|
175
|
+
const visibleColumns = internalColumns.value.filter((col) => col.visible !== false);
|
|
176
|
+
const hasFixedWidths = visibleColumns.some((col) => col.width);
|
|
177
|
+
|
|
178
178
|
if (hasFixedWidths) {
|
|
179
179
|
// Calculate total fixed width
|
|
180
180
|
let totalFixedWidth = 0;
|
|
181
|
-
visibleColumns.forEach(col => {
|
|
182
|
-
if (col.width && typeof col.width ===
|
|
181
|
+
visibleColumns.forEach((col) => {
|
|
182
|
+
if (col.width && typeof col.width === "string") {
|
|
183
183
|
const width = parseInt(col.width);
|
|
184
184
|
if (!isNaN(width)) {
|
|
185
185
|
totalFixedWidth += width;
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
});
|
|
189
|
-
|
|
189
|
+
|
|
190
190
|
// If total fixed width is too large, remove fixed widths to allow flex distribution
|
|
191
|
-
if (totalFixedWidth > 800) {
|
|
192
|
-
|
|
191
|
+
if (totalFixedWidth > 800) {
|
|
192
|
+
// Assuming a reasonable container width
|
|
193
|
+
internalColumns.value = internalColumns.value.map((col) => ({
|
|
193
194
|
...col,
|
|
194
|
-
width: undefined // Let flexbox handle it
|
|
195
|
+
width: undefined, // Let flexbox handle it
|
|
195
196
|
}));
|
|
196
197
|
}
|
|
197
198
|
}
|
|
@@ -205,7 +206,7 @@ export function useTableState(options: UseTableStateOptions) {
|
|
|
205
206
|
title: item.title || originalColumn?.title || x.title || "",
|
|
206
207
|
width: item.width || originalColumn?.width || x.width,
|
|
207
208
|
};
|
|
208
|
-
|
|
209
|
+
|
|
209
210
|
return updatedCol;
|
|
210
211
|
}
|
|
211
212
|
return x;
|