refactor: refs #8197 backward compatible #1091

Merged
alexm merged 2 commits from 8197-VnCardMain_backwardCompatibility into 8197-VnCardMain 2024-12-17 11:47:21 +00:00
6 changed files with 128 additions and 25 deletions

View File

@ -92,8 +92,10 @@ function findMatches(search, item) {
}
function addChildren(module, route, parent) {
if (!route?.meta?.menu) return;
const matches = findMatches(route.meta.menu, route);
const menus = route?.meta?.menu ?? route?.menus?.[props.source]; //backwards compatible
if (!menus) return;
const matches = findMatches(menus, route);
for (const child of matches) {
navigation.addMenuItem(module, child, parent);
@ -118,17 +120,28 @@ function getRoutes() {
}
if (props.source === 'card') {
let menuRoute;
let index = route.matched.length - 1;
const currentRoute = route.matched[1];
const currentModule = toLowerCamel(currentRoute.name);
let moduleDef = routes.find(
(route) => toLowerCamel(route.name) === currentModule
);
while (!menuRoute && index > 0) {
if (route.matched[index]?.meta?.menu) menuRoute = route.matched[index];
index--;
}
addChildren('', menuRoute, items.value);
if (!moduleDef) return;
if (!moduleDef?.menus) moduleDef = betaGetRoutes();
addChildren(currentModule, moduleDef, items.value);
}
}
function betaGetRoutes() {
let menuRoute;
let index = route.matched.length - 1;
while (!menuRoute && index > 0) {
if (route.matched[index]?.meta?.menu) menuRoute = route.matched[index];
index--;
}
return menuRoute;
}
async function togglePinned(item, event) {
if (event.defaultPrevented) return;
event.preventDefault();

View File

@ -4,7 +4,10 @@ import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
import { useArrayData } from 'src/composables/useArrayData';
import { useStateStore } from 'stores/useStateStore';
import useCardSize from 'src/composables/useCardSize';
import VnSubToolbar from '../ui/VnSubToolbar.vue';
import VnSearchbar from 'components/ui/VnSearchbar.vue';
import LeftMenu from 'components/LeftMenu.vue';
import RightMenu from 'components/common/RightMenu.vue';
const props = defineProps({
dataKey: { type: String, required: true },
baseUrl: { type: String, default: undefined },
@ -26,7 +29,10 @@ const url = computed(() => {
}
return props.customUrl;
});
const searchRightDataKey = computed(() => {
if (!props.searchDataKey) return route.name;
return props.searchDataKey;
});
const arrayData = useArrayData(props.dataKey, {
url: url.value,
filter: props.filter,
@ -53,13 +59,32 @@ if (props.baseUrl) {
}
</script>
<template>
<Teleport to="#left-panel" v-if="stateStore.isHeaderMounted()">
<component :is="descriptor" />
<QSeparator />
<LeftMenu source="card" />
</Teleport>
<VnSubToolbar />
<div :class="[useCardSize(), $attrs.class]">
<RouterView :key="route.path" />
</div>
<QDrawer
v-model="stateStore.leftDrawer"
show-if-above
:width="256"
v-if="stateStore.isHeaderMounted()"
>
<QScrollArea class="fit">
<component :is="descriptor" />
<QSeparator />
<LeftMenu source="card" />
</QScrollArea>
</QDrawer>
<slot name="searchbar" v-if="props.searchDataKey">
<VnSearchbar :data-key="props.searchDataKey" v-bind="props.searchbarProps" />
</slot>
<RightMenu>
<template #right-panel v-if="props.filterPanel">
<component :is="props.filterPanel" :data-key="searchRightDataKey" />
</template>
</RightMenu>
<QPageContainer>
<QPage>
<VnSubToolbar />
<div :class="[useCardSize(), $attrs.class]">
<RouterView :key="route.path" />
</div>
</QPage>
</QPageContainer>
</template>

View File

@ -0,0 +1,65 @@
<script setup>
import { onBeforeMount, computed } from 'vue';
import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router';
import { useArrayData } from 'src/composables/useArrayData';
import { useStateStore } from 'stores/useStateStore';
import useCardSize from 'src/composables/useCardSize';
import LeftMenu from 'components/LeftMenu.vue';
const props = defineProps({
dataKey: { type: String, required: true },
baseUrl: { type: String, default: undefined },
customUrl: { type: String, default: undefined },
filter: { type: Object, default: () => {} },
descriptor: { type: Object, required: true },
filterPanel: { type: Object, default: undefined },
searchDataKey: { type: String, default: undefined },
searchbarProps: { type: Object, default: undefined },
redirectOnError: { type: Boolean, default: false },
});
const stateStore = useStateStore();
const route = useRoute();
const router = useRouter();
const url = computed(() => {
if (props.baseUrl) {
return `${props.baseUrl}/${route.params.id}`;
}
return props.customUrl;
});
const arrayData = useArrayData(props.dataKey, {
url: url.value,
filter: props.filter,
});
onBeforeMount(async () => {
try {
if (!props.baseUrl) arrayData.store.filter.where = { id: route.params.id };
await arrayData.fetch({ append: false, updateRouter: false });
} catch {
const { matched: matches } = router.currentRoute.value;
const { path } = matches.at(-1);
router.push({ path: path.replace(/:id.*/, '') });
}
});
if (props.baseUrl) {
onBeforeRouteUpdate(async (to, from) => {
if (to.params.id !== from.params.id) {
arrayData.store.url = `${props.baseUrl}/${to.params.id}`;
await arrayData.fetch({ append: false, updateRouter: false });
}
});
}
</script>
<template>
<Teleport to="#left-panel" v-if="stateStore.isHeaderMounted()">
<component :is="descriptor" />
<QSeparator />
<LeftMenu source="card" />
</Teleport>
<VnSubToolbar />
<div :class="[useCardSize(), $attrs.class]">
<RouterView :key="route.path" />
</div>
</template>

View File

@ -1,12 +1,12 @@
<script setup>
import { useI18n } from 'vue-i18n';
import VnCard from 'components/common/VnCard.vue';
import VnCardBeta from 'components/common/VnCardBeta.vue';
import AliasDescriptor from './AliasDescriptor.vue';
const { t } = useI18n();
</script>
<template>
<VnCard
<VnCardBeta
data-key="Alias"
base-url="MailAliases"
:descriptor="AliasDescriptor"

View File

@ -1,8 +1,8 @@
<script setup>
import VnCard from 'components/common/VnCard.vue';
import VnCardBeta from 'components/common/VnCardBeta.vue';
import AccountDescriptor from './AccountDescriptor.vue';
</script>
<template>
<VnCard data-key="AccountId" :descriptor="AccountDescriptor" />
<VnCardBeta data-key="AccountId" :descriptor="AccountDescriptor" />
</template>

View File

@ -1,7 +1,7 @@
<script setup>
import VnCard from 'components/common/VnCard.vue';
import VnCardBeta from 'components/common/VnCardBeta.vue';
import RoleDescriptor from './RoleDescriptor.vue';
</script>
<template>
<VnCard data-key="Role" :descriptor="RoleDescriptor" />
<VnCardBeta data-key="Role" :descriptor="RoleDescriptor" />
</template>