feat(Account & AccountRole): refs #8197 add VnCardMain

This commit is contained in:
Alex Moreno 2024-12-02 11:39:01 +01:00
parent 658551e085
commit 907bf3cf3b
17 changed files with 266 additions and 287 deletions

View File

@ -59,32 +59,16 @@ if (props.baseUrl) {
} }
</script> </script>
<template> <template>
<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"> <slot name="searchbar" v-if="props.searchDataKey">
<VnSearchbar :data-key="props.searchDataKey" v-bind="props.searchbarProps" /> <VnSearchbar :data-key="props.searchDataKey" v-bind="props.searchbarProps" />
</slot> </slot>
<RightMenu> <Teleport to="#left-panel" v-if="stateStore.isHeaderMounted()">
<template #right-panel v-if="props.filterPanel"> <component :is="descriptor" />
<component :is="props.filterPanel" :data-key="searchRightDataKey" /> <QSeparator />
</template> <LeftMenu source="card" />
</RightMenu> </Teleport>
<QPageContainer> <VnSubToolbar />
<QPage> <div :class="[useCardSize(), $attrs.class]">
<VnSubToolbar /> <RouterView :key="route.path" />
<div :class="[useCardSize(), $attrs.class]"> </div>
<RouterView :key="route.path" />
</div>
</QPage>
</QPageContainer>
</template> </template>

View File

@ -0,0 +1,20 @@
<script setup>
import LeftMenu from '../LeftMenu.vue';
import { useStateStore } from 'stores/useStateStore';
const stateStore = useStateStore();
defineProps({
section: {
type: String,
required: true,
},
});
</script>
<template>
<slot name="searchbar" />
<Teleport to="#left-panel" v-if="stateStore.isHeaderMounted()">
<LeftMenu v-if="section == $route.name" />
</Teleport>
<slot name="body" v-if="section == $route.name" />
<RouterView v-else />
</template>

View File

@ -1,6 +1,5 @@
<script setup> <script setup>
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import LeftMenu from 'components/LeftMenu.vue';
import { onMounted } from 'vue'; import { onMounted } from 'vue';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
@ -19,7 +18,7 @@ onMounted(
<template> <template>
<QDrawer v-model="stateStore.leftDrawer" show-if-above :width="256"> <QDrawer v-model="stateStore.leftDrawer" show-if-above :width="256">
<QScrollArea class="fit text-grey-8"> <QScrollArea class="fit text-grey-8">
<LeftMenu /> <div id="left-panel"></div>
</QScrollArea> </QScrollArea>
</QDrawer> </QDrawer>
<QPageContainer> <QPageContainer>

View File

@ -75,18 +75,13 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
limit: store.limit, limit: store.limit,
}; };
let userParams = { ...store.userParams };
Object.assign(filter, store.userFilter); Object.assign(filter, store.userFilter);
let where; delete store.filter.where;
if (filter?.where || store.filter?.where)
where = Object.assign(filter?.where ?? {}, store.filter?.where ?? {});
Object.assign(filter, store.filter); Object.assign(filter, store.filter);
filter.where = where;
const params = { filter }; const params = { filter };
Object.assign(params, userParams); Object.assign(params, store.userParams);
if (params.filter) params.filter.skip = store.skip; if (params.filter) params.filter.skip = store.skip;
if (store?.order && typeof store?.order == 'string') store.order = [store.order]; if (store?.order && typeof store?.order == 'string') store.order = [store.order];
if (store.order?.length) params.filter.order = [...store.order]; if (store.order?.length) params.filter.order = [...store.order];

View File

@ -5,14 +5,15 @@ import VnTable from 'components/VnTable/VnTable.vue';
import VnSearchbar from 'components/ui/VnSearchbar.vue'; import VnSearchbar from 'components/ui/VnSearchbar.vue';
import AccountSummary from './Card/AccountSummary.vue'; import AccountSummary from './Card/AccountSummary.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import AccountFilter from './AccountFilter.vue'; import VnCardMain from 'src/components/common/VnCardMain.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
const { t } = useI18n(); const { t } = useI18n();
const { viewSummary } = useSummaryDialog(); const { viewSummary } = useSummaryDialog();
const tableRef = ref(); const tableRef = ref();
const filter = { const filter = {
include: { relation: 'role', scope: { fields: ['id', 'name'] } }, include: { relation: 'role', scope: { fields: ['id', 'name'] } },
}; };
const dataKey = 'AccountList';
const url = 'VnUsers/preview';
const columns = computed(() => [ const columns = computed(() => [
{ {
align: 'left', align: 'left',
@ -103,31 +104,34 @@ const exprBuilder = (param, value) => {
</script> </script>
<template> <template>
<VnSearchbar <VnCardMain :section="dataKey">
data-key="AccountList" <template #searchbar>
:expr-builder="exprBuilder" <VnSearchbar
:label="t('account.search')" :data-key="dataKey"
:info="t('account.searchInfo')" :expr-builder="exprBuilder"
:filter="filter" :label="t('account.search')"
/> :info="t('account.searchInfo')"
<RightMenu> :filter="filter"
<template #right-panel> :url="url"
<AccountFilter data-key="AccountList" /> />
</template> </template>
</RightMenu> <template #body>
<VnTable <VnTable
ref="tableRef" :style="{ display: !!$route.name.endsWith('List') ? '' : 'none' }"
data-key="AccountList" ref="tableRef"
url="VnUsers/preview" :data-key="dataKey"
:filter="filter" :url="url"
order="id DESC" :filter="filter"
:columns="columns" order="id DESC"
default-mode="table" :columns="columns"
redirect="account" default-mode="table"
:use-model="true" redirect="account"
:right-search="false" :use-model="true"
auto-load :right-search="true"
/> :expr-builder="exprBuilder"
/>
</template>
</VnCardMain>
</template> </template>
<i18n> <i18n>

View File

@ -1,20 +1,8 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n';
import VnCard from 'components/common/VnCard.vue'; import VnCard from 'components/common/VnCard.vue';
import AccountDescriptor from './AccountDescriptor.vue'; import AccountDescriptor from './AccountDescriptor.vue';
const { t } = useI18n();
</script> </script>
<template> <template>
<VnCard <VnCard data-key="Account" :descriptor="AccountDescriptor" />
data-key="Account"
:descriptor="AccountDescriptor"
search-data-key="AccountList"
:searchbar-props="{
url: 'VnUsers/preview',
label: t('account.search'),
info: t('account.searchInfo'),
}"
/>
</template> </template>

View File

@ -6,8 +6,11 @@ import { useRoute } from 'vue-router';
import VnSearchbar from 'components/ui/VnSearchbar.vue'; import VnSearchbar from 'components/ui/VnSearchbar.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import RoleSummary from './Card/RoleSummary.vue'; import RoleSummary from './Card/RoleSummary.vue';
import VnCardMain from 'src/components/common/VnCardMain.vue';
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const { viewSummary } = useSummaryDialog();
const $props = defineProps({ const $props = defineProps({
id: { id: {
type: Number, type: Number,
@ -15,8 +18,10 @@ const $props = defineProps({
}, },
}); });
const tableRef = ref(); const tableRef = ref();
const url = 'VnRoles';
const dataKey = 'AccountRoleList';
const entityId = computed(() => $props.id || route.params.id); const entityId = computed(() => $props.id || route.params.id);
const { viewSummary } = useSummaryDialog();
const columns = computed(() => [ const columns = computed(() => [
{ {
align: 'left', align: 'left',
@ -63,6 +68,7 @@ const columns = computed(() => [
}, },
]); ]);
const exprBuilder = (param, value) => { const exprBuilder = (param, value) => {
console.log('param: ', param);
switch (param) { switch (param) {
case 'search': case 'search':
return /^\d+$/.test(value) return /^\d+$/.test(value)
@ -81,30 +87,37 @@ const exprBuilder = (param, value) => {
</script> </script>
<template> <template>
<VnSearchbar <VnCardMain :section="dataKey">
data-key="AccountRolesList" <template #searchbar>
:expr-builder="exprBuilder" <VnSearchbar
:label="t('role.searchRoles')" :url="url"
:info="t('role.searchInfo')" :data-key="dataKey"
/> :expr-builder="exprBuilder"
<VnTable :label="t('role.searchRoles')"
ref="tableRef" :info="t('role.searchInfo')"
data-key="AccountRolesList" />
:url="`VnRoles`" </template>
:create="{ <template #body>
urlCreate: 'VnRoles', <VnTable
title: t('Create rol'), ref="tableRef"
onDataSaved: ({ id }) => tableRef.redirect(id), :data-key="dataKey"
formInitialData: { :url="url"
editorFk: entityId, :create="{
}, urlCreate: 'VnRoles',
}" title: t('Create rol'),
order="id ASC" onDataSaved: ({ id }) => tableRef.redirect(id),
:disable-option="{ card: true }" formInitialData: {
:columns="columns" editorFk: entityId,
default-mode="table" },
redirect="account/role" }"
/> order="id ASC"
:disable-option="{ card: true }"
:columns="columns"
default-mode="table"
redirect="account/role"
/>
</template>
</VnCardMain>
</template> </template>
<i18n> <i18n>

View File

@ -1,20 +1,7 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n';
import VnCard from 'components/common/VnCard.vue'; import VnCard from 'components/common/VnCard.vue';
import RoleDescriptor from './RoleDescriptor.vue'; import RoleDescriptor from './RoleDescriptor.vue';
const { t } = useI18n();
</script> </script>
<template> <template>
<VnCard <VnCard data-key="Role" :descriptor="RoleDescriptor" />
data-key="Role"
:descriptor="RoleDescriptor"
search-data-key="AccountRolesList"
:searchbar-props="{
url: 'VnRoles',
label: t('role.searchRoles'),
info: t('role.searchInfo'),
searchUrl: 'table',
}"
/>
</template> </template>

View File

@ -43,7 +43,7 @@ const removeRole = async () => {
:filter="filter" :filter="filter"
module="Role" module="Role"
@on-fetch="setData" @on-fetch="setData"
data-key="accountData" data-key="Role"
:title="data.title" :title="data.title"
:subtitle="data.subtitle" :subtitle="data.subtitle"
:summary="$props.summary" :summary="$props.summary"

View File

@ -27,10 +27,10 @@ const filter = {
<template> <template>
<CardSummary <CardSummary
ref="summary" ref="summary"
:url="`VnRoles`" :url="`VnRoles/${entityId}`"
:filter="filter" :filter="filter"
@on-fetch="(data) => (role = data)" @on-fetch="(data) => (role = data)"
data-key="RoleSummary" data-key="Role"
> >
<template #header> {{ role.id }} - {{ role.name }} </template> <template #header> {{ role.id }} - {{ role.name }} </template>
<template #body> <template #body>

View File

@ -1,4 +1,7 @@
import { RouterView } from 'vue-router'; import { RouterView } from 'vue-router';
import accountCard from './account/accountCard';
import roleCard from './account/roleCard';
import getSections from 'src/utils/getSections';
export default { export default {
path: '/account', path: '/account',
@ -22,39 +25,48 @@ export default {
'AccountAcls', 'AccountAcls',
'AccountConnections', 'AccountConnections',
], ],
card: [ card: getSections(accountCard.children),
'AccountBasicData',
'AccountInheritedRoles',
'AccountMailForwarding',
'AccountMailAlias',
'AccountPrivileges',
'AccountLog',
],
}, },
children: [ children: [
{ {
path: '', path: '',
name: 'AccountMain', name: 'AccountMain',
component: () => import('src/components/common/VnSectionMain.vue'), component: () => import('src/components/common/VnSectionMain.vue'),
redirect: { name: 'AccountList' }, redirect: { name: 'AccountIndexMain' },
children: [ children: [
{ {
path: 'list', path: '',
name: 'AccountList', name: 'AccountIndexMain',
meta: { redirect: { name: 'AccountList' },
title: 'list',
icon: 'view_list',
},
component: () => import('src/pages/Account/AccountList.vue'), component: () => import('src/pages/Account/AccountList.vue'),
children: [
{
name: 'AccountList',
path: 'list',
meta: {
title: 'list',
icon: 'view_list',
},
},
accountCard,
],
}, },
{ {
path: 'role-list', path: 'role',
name: 'AccountRoles', name: 'AccountRoles',
redirect: { name: 'AccountRoleList' },
meta: { meta: {
title: 'roles', title: 'roles',
icon: 'group', icon: 'group',
}, },
component: () => import('src/pages/Account/Role/AccountRoles.vue'), component: () => import('src/pages/Account/Role/AccountRoles.vue'),
children: [
{
name: 'AccountRoleList',
path: 'list',
},
roleCard,
],
}, },
{ {
path: 'alias-list', path: 'alias-list',
@ -120,81 +132,5 @@ export default {
}, },
], ],
}, },
{
name: 'AccountCard',
path: ':id',
component: () => import('src/pages/Account/Card/AccountCard.vue'),
redirect: { name: 'AccountSummary' },
children: [
{
name: 'AccountSummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'launch',
},
component: () => import('src/pages/Account/Card/AccountSummary.vue'),
},
{
name: 'AccountBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () =>
import('src/pages/Account/Card/AccountBasicData.vue'),
},
{
name: 'AccountInheritedRoles',
path: 'inherited-roles',
meta: {
title: 'inheritedRoles',
icon: 'group',
},
component: () =>
import('src/pages/Account/Card/AccountInheritedRoles.vue'),
},
{
name: 'AccountMailForwarding',
path: 'mail-forwarding',
meta: {
title: 'mailForwarding',
icon: 'forward',
},
component: () =>
import('src/pages/Account/Card/AccountMailForwarding.vue'),
},
{
name: 'AccountMailAlias',
path: 'mail-alias',
meta: {
title: 'mailAlias',
icon: 'email',
},
component: () =>
import('src/pages/Account/Card/AccountMailAlias.vue'),
},
{
name: 'AccountPrivileges',
path: 'privileges',
meta: {
title: 'privileges',
icon: 'badge',
},
component: () =>
import('src/pages/Account/Card/AccountPrivileges.vue'),
},
{
name: 'AccountLog',
path: 'log',
meta: {
title: 'log',
icon: 'history',
},
component: () => import('src/pages/Account/Card/AccountLog.vue'),
},
],
},
], ],
}; };

View File

@ -0,0 +1,71 @@
export default {
name: 'AccountCard',
path: ':id',
redirect: { name: 'AccountSummary' },
component: () => import('src/pages/Account/Card/AccountCard.vue'),
children: [
{
name: 'AccountSummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'launch',
},
component: () => import('src/pages/Account/Card/AccountSummary.vue'),
},
{
name: 'AccountBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () => import('src/pages/Account/Card/AccountBasicData.vue'),
},
{
name: 'AccountInheritedRoles',
path: 'inherited-roles',
meta: {
title: 'inheritedRoles',
icon: 'group',
},
component: () => import('src/pages/Account/Card/AccountInheritedRoles.vue'),
},
{
name: 'AccountMailForwarding',
path: 'mail-forwarding',
meta: {
title: 'mailForwarding',
icon: 'forward',
},
component: () => import('src/pages/Account/Card/AccountMailForwarding.vue'),
},
{
name: 'AccountMailAlias',
path: 'mail-alias',
meta: {
title: 'mailAlias',
icon: 'email',
},
component: () => import('src/pages/Account/Card/AccountMailAlias.vue'),
},
{
name: 'AccountPrivileges',
path: 'privileges',
meta: {
title: 'privileges',
icon: 'badge',
},
component: () => import('src/pages/Account/Card/AccountPrivileges.vue'),
},
{
name: 'AccountLog',
path: 'log',
meta: {
title: 'log',
icon: 'history',
},
component: () => import('src/pages/Account/Card/AccountLog.vue'),
},
],
};

View File

@ -0,0 +1,54 @@
export default {
name: 'RoleCard',
path: ':id',
component: () => import('src/pages/Account/Role/Card/RoleCard.vue'),
redirect: { name: 'RoleSummary' },
children: [
{
name: 'RoleSummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'launch',
},
component: () => import('src/pages/Account/Role/Card/RoleSummary.vue'),
},
{
name: 'RoleBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () => import('src/pages/Account/Role/Card/RoleBasicData.vue'),
},
{
name: 'SubRoles',
path: 'sub-roles',
meta: {
title: 'subRoles',
icon: 'group',
},
component: () => import('src/pages/Account/Role/Card/SubRoles.vue'),
},
{
name: 'InheritedRoles',
path: 'inherited-roles',
meta: {
title: 'inheritedRoles',
icon: 'account_tree',
},
component: () => import('src/pages/Account/Role/Card/InheritedRoles.vue'),
},
{
name: 'RoleLog',
path: 'log',
meta: {
title: 'log',
icon: 'history',
},
component: () => import('src/pages/Account/Role/Card/RoleLog.vue'),
},
],
};

View File

@ -21,7 +21,6 @@ import Zone from './zone';
import Account from './account'; import Account from './account';
import Monitor from './monitor'; import Monitor from './monitor';
import MailAlias from './mailAlias'; import MailAlias from './mailAlias';
import Role from './role';
export default [ export default [
Item, Item,
@ -47,5 +46,4 @@ export default [
Account, Account,
MailAlias, MailAlias,
Monitor, Monitor,
Role,
]; ];

View File

@ -1,76 +0,0 @@
import { RouterView } from 'vue-router';
export default {
path: 'account/role',
name: 'Role',
meta: {
title: 'role',
icon: 'vn:greuge',
moduleName: 'Role',
},
component: RouterView,
redirect: { name: 'AccountRoles' },
menus: {
main: [],
card: ['RoleBasicData', 'SubRoles', 'InheritedRoles', 'RoleLog'],
},
children: [
{
name: 'RoleCard',
path: ':id',
component: () => import('src/pages/Account/Role/Card/RoleCard.vue'),
redirect: { name: 'RoleSummary' },
children: [
{
name: 'RoleSummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'launch',
},
component: () =>
import('src/pages/Account/Role/Card/RoleSummary.vue'),
},
{
name: 'RoleBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () =>
import('src/pages/Account/Role/Card/RoleBasicData.vue'),
},
{
name: 'SubRoles',
path: 'sub-roles',
meta: {
title: 'subRoles',
icon: 'group',
},
component: () => import('src/pages/Account/Role/Card/SubRoles.vue'),
},
{
name: 'InheritedRoles',
path: 'inherited-roles',
meta: {
title: 'inheritedRoles',
icon: 'account_tree',
},
component: () =>
import('src/pages/Account/Role/Card/InheritedRoles.vue'),
},
{
name: 'RoleLog',
path: 'log',
meta: {
title: 'log',
icon: 'history',
},
component: () => import('src/pages/Account/Role/Card/RoleLog.vue'),
},
],
},
],
};

View File

@ -10,7 +10,6 @@ import wagon from './modules/wagon';
import supplier from './modules/Supplier'; import supplier from './modules/Supplier';
import travel from './modules/travel'; import travel from './modules/travel';
import department from './modules/department'; import department from './modules/department';
import role from './modules/role';
import ItemType from './modules/itemType'; import ItemType from './modules/itemType';
import shelving from 'src/router/modules/shelving'; import shelving from 'src/router/modules/shelving';
import order from 'src/router/modules/order'; import order from 'src/router/modules/order';
@ -95,7 +94,6 @@ const routes = [
ItemType, ItemType,
zone, zone,
account, account,
role,
mailAlias, mailAlias,
{ {
path: '/:catchAll(.*)*', path: '/:catchAll(.*)*',

8
src/utils/getSections.js Normal file
View File

@ -0,0 +1,8 @@
export default (sections) => {
const names = [];
for (const section of sections) {
if (section.path == 'summary') continue;
names.push(section.name);
}
return names;
};