Commit 94394d0e authored by Nguyễn Hải Sơn's avatar Nguyễn Hải Sơn

Update user group

parent 7e019e8a
...@@ -102,9 +102,9 @@ module.exports = configure(function (ctx) { ...@@ -102,9 +102,9 @@ module.exports = configure(function (ctx) {
plugins: ['Notify'], plugins: ['Notify'],
}, },
// animations: 'all', // --- includes all animations animations: 'all', // --- includes all animations
// https://v2.quasar.dev/options/animations // https://v2.quasar.dev/options/animations
animations: [], // animations: [],
// https://v2.quasar.dev/quasar-cli/developing-ssr/configuring-ssr // https://v2.quasar.dev/quasar-cli/developing-ssr/configuring-ssr
ssr: { ssr: {
......
...@@ -23,4 +23,5 @@ export enum API_PATHS { ...@@ -23,4 +23,5 @@ export enum API_PATHS {
getGroupInfo = '/group/get_info', getGroupInfo = '/group/get_info',
getListPages = '/user/page/list', getListPages = '/user/page/list',
getListGroupUsers = '/user/group/list', getListGroupUsers = '/user/group/list',
addNewGroupUser = 'user/group/add',
} }
import { defineComponent, ref } from 'vue'; import { defineComponent } from 'vue';
import { EditMode } from 'src/assets/enums'; import { EditMode } from 'src/assets/enums';
import { i18n } from 'src/boot/i18n';
const check = ref(false); const groupNameRules = [
const check1 = ref(false); (val?: string) =>
const check2 = ref(false); (val && val.trim().length) ||
const check3 = ref(false); i18n.global.t('userGroupPage.groupInfo.validateMessages.requireGroupName'),
(val?: string) =>
(val && val.trim().length <= 10) ||
i18n.global.t(
'userGroupPage.groupInfo.validateMessages.groupNameLengthInvalid'
),
];
export const GroupInfoScript = defineComponent({ export const GroupInfoScript = defineComponent({
props: { props: {
...@@ -21,8 +28,13 @@ export const GroupInfoScript = defineComponent({ ...@@ -21,8 +28,13 @@ export const GroupInfoScript = defineComponent({
requite: true, requite: true,
}, },
}, },
emits: ['resetGroupInfo'], emits: [
'resetGroupInfo',
'update:groupName',
'update:groupDescription',
'saveGroupInfo',
],
setup() { setup() {
return { check, check1, check2, check3, EditMode }; return { EditMode, groupNameRules };
}, },
}); });
<template> <template>
<q-card flat bordered class="my-card"> <q-card flat bordered class="my-card">
<q-card-section style="padding-top: 28px"> <q-form @submit.prevent="$emit('saveGroupInfo')">
<div class="row"> <q-card-section style="padding-top: 28px">
<div class="col-4" style="display: flex"> <div class="row">
<div class="text-h6">Thông tin nhóm</div> <div class="col-4" style="display: flex">
<div class="text-h6">{{ $t('userGroupPage.groupInfo.title') }}</div>
</div>
<div class="col-8" style="display: flex; justify-content: flex-end">
<q-btn
v-if="isDisable === EditMode.edit"
style="margin-right: 8px"
color="red"
icon="delete"
:label="$t('crudActions.delete')"
/>
<q-btn
v-if="isDisable"
color="primary"
icon="update"
:label="
isDisable === EditMode.edit
? $t('crudActions.update')
: $t('crudActions.add')
"
type="submit"
/>
</div>
<div v-if="isDisable" style="position: absolute; top: 0; right: 0">
<q-btn
@click="$emit('resetGroupInfo', EditMode.default)"
size="x-small"
flat
round
color="primary"
icon="close"
/>
</div>
</div> </div>
<div class="col-8" style="display: flex; justify-content: flex-end"> </q-card-section>
<q-btn <q-card-section class="q-pt-none">
v-if="isDisable === EditMode.edit" <q-input
style="margin-right: 8px" :model-value="groupName"
color="red" :disable="!isDisable ? true : false"
icon="delete" outlined
label="Xoá" @update:model-value="$emit('update:groupName', $event)"
/> placeholder="Tên nhóm *"
<q-btn :rules="groupNameRules"
v-if="isDisable" />
color="primary" </q-card-section>
icon="update" <q-card-section class="q-pt-none">
label="Cập nhật" <q-input
/> :model-value="groupDescription"
</div> :disable="!isDisable ? true : false"
<div v-if="isDisable" style="position: absolute; top: 0; right: 0"> outlined
<q-btn @update:model-value="$emit('update:groupDescription', $event)"
@click="$emit('resetGroupInfo', EditMode.default)" placeholder="Mô tả *"
size="x-small" />
flat </q-card-section>
round </q-form>
color="primary" <q-card-section v-if="isDisable === EditMode.edit"> </q-card-section>
icon="close"
/>
</div>
</div>
</q-card-section>
<q-card-section class="q-pt-none">
<q-input
v-model="groupName"
:disable="!isDisable ? true : false"
outlined
placeholder="Tên nhóm *"
/>
</q-card-section>
<q-card-section class="q-pt-none">
<q-input
v-model="groupDescription"
:disable="!isDisable ? true : false"
outlined
placeholder="Mô tả *"
/>
</q-card-section>
<q-card-section v-if="isDisable === EditMode.edit">
<div class="row">
<div class="col-6">
<q-list bordered padding>
<q-item tag="label" v-ripple>
<q-item-section side top>
<q-checkbox v-model="check" />
</q-item-section>
<q-item-section>
<q-item-label class="text-h5">Trang</q-item-label>
</q-item-section>
</q-item>
<q-item tag="label" v-ripple>
<q-item-section side top>
<q-checkbox v-model="check1" />
</q-item-section>
<q-item-section>
<q-item-label class="text-subtitle1" style="display: flex"
>Trang chủ</q-item-label
>
</q-item-section>
</q-item>
<q-item tag="label" v-ripple>
<q-item-section side top>
<q-checkbox v-model="check2" />
</q-item-section>
<q-item-section>
<q-item-label style="display: flex" class="text-subtitle1"
>Người dùng</q-item-label
>
</q-item-section>
</q-item>
<q-item tag="label" v-ripple>
<q-item-section side top>
<q-checkbox v-model="check3" />
</q-item-section>
<q-item-section>
<q-item-label style="display: flex" class="text-subtitle1"
>Nhóm người dùng</q-item-label
>
</q-item-section>
</q-item>
</q-list>
</div>
<div class="col-6"></div>
</div>
</q-card-section>
</q-card> </q-card>
</template> </template>
......
import { MenuItem } from 'src/store/authentication/state'; import { MenuItem } from 'src/store/authentication/state';
import { defineComponent, PropType } from 'vue'; import { computed, defineComponent, PropType } from 'vue';
import { useRoute } from 'vue-router';
export const MenuItemScript = defineComponent({ export const MenuItemScript = defineComponent({
name: 'MenuItemComponent', name: 'MenuItemComponent',
props: { props: {
...@@ -8,4 +9,16 @@ export const MenuItemScript = defineComponent({ ...@@ -8,4 +9,16 @@ export const MenuItemScript = defineComponent({
required: true, required: true,
}, },
}, },
setup(props) {
const $route = useRoute();
const isActive = computed(() => {
return (
props.item.children &&
props.item.children?.findIndex((item) => item.pageUrl === $route.path) >
-1
);
});
return { isActive };
},
}); });
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
:label="item.pageName" :label="item.pageName"
:icon="item.pageIcon" :icon="item.pageIcon"
:header-inset-level="item.level - 1" :header-inset-level="item.level - 1"
:header-style="`margin-left: -${(item.level - 1) * 1.8}rem`"
:model-value="isActive"
> >
<MenuItemComponent <MenuItemComponent
v-for="(menuItem, menuItemIdx) in item.children" v-for="(menuItem, menuItemIdx) in item.children"
...@@ -17,7 +19,10 @@ ...@@ -17,7 +19,10 @@
:label="item.pageName" :label="item.pageName"
:icon="item.pageIcon" :icon="item.pageIcon"
:header-inset-level="item.level - 1" :header-inset-level="item.level - 1"
:to="item.pageUrl" :header-style="`margin-left: -${(item.level - 1) * 1.8}rem`"
:to="item.pageUrl || '/'"
exact
active-class="bg-primary text-white"
></q-expansion-item> ></q-expansion-item>
</template> </template>
......
...@@ -3,12 +3,16 @@ import { computed, defineComponent, PropType, ref } from 'vue'; ...@@ -3,12 +3,16 @@ import { computed, defineComponent, PropType, ref } from 'vue';
import { EditMode } from 'src/assets/enums'; import { EditMode } from 'src/assets/enums';
// import { useStore } from 'src/store'; // import { useStore } from 'src/store';
export const UserGroupScript = defineComponent({ export default defineComponent({
props: { props: {
listUsers: { listUsers: {
type: Array as PropType<GroupInfoType[]>, type: Array as PropType<GroupInfoType[]>,
required: true, required: true,
}, },
selectedGroupId: {
type: Number,
required: true,
},
}, },
emits: ['click:groupName', 'click:addNewGroupUsers'], emits: ['click:groupName', 'click:addNewGroupUsers'],
setup(props) { setup(props) {
......
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
<q-card-section style="padding-top: 28px"> <q-card-section style="padding-top: 28px">
<div class="row"> <div class="row">
<div class="col-8 text-h6" style="display: flex"> <div class="col-8 text-h6" style="display: flex">
<div>Nhóm người dùng</div> <div>{{ $t('userGroupPage.title') }}</div>
</div> </div>
<div class="col-4" style="display: flex; justify-content: flex-end"> <div class="col-4" style="display: flex; justify-content: flex-end">
<q-btn <q-btn
@click="$emit('click:addNewGroupUsers', EditMode.add)" @click="$emit('click:addNewGroupUsers', EditMode.add)"
color="primary" color="primary"
label="Thêm mới" :label="$t('crudActions.add')"
no-caps no-caps
/> />
</div> </div>
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
v-for="(userItem, userItemIdx) in filteredListUsers" v-for="(userItem, userItemIdx) in filteredListUsers"
:key="`userItem-${userItemIdx}`" :key="`userItem-${userItemIdx}`"
align="left" align="left"
outline :outline="userItem.id !== selectedGroupId"
size="large" size="large"
class="full-width my-1" class="full-width my-1"
color="primary" color="primary"
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
</q-card> </q-card>
</template> </template>
<script lang="ts"> <script lang="ts" src="./UserGroup.ts">
import { UserGroupScript } from './UserGroup'; // import { UserGroupScript } from './UserGroup';
export default UserGroupScript; // export default UserGroupScript;
</script> </script>
...@@ -22,4 +22,22 @@ export default { ...@@ -22,4 +22,22 @@ export default {
'msg-1': 'Lỗi không xác định', 'msg-1': 'Lỗi không xác định',
}, },
emptyData: 'Không tìm thấy dữ liệu', emptyData: 'Không tìm thấy dữ liệu',
crudActions: {
add: 'Thêm mới',
update: 'Cập nhật',
delete: 'Xoá',
details: 'Chi tiết',
},
userGroupPage: {
title: 'Nhóm người dùng',
groupInfo: {
title: 'Thông tin nhóm',
validateMessages: {
requireGroupName: 'Vui lòng cung cấp tên nhóm người dùng',
groupNameLengthInvalid:
'Tên nhóm người dùng chỉ có thể dài tối đa 10 ký tự',
},
},
},
}; };
<template> <template>
<q-layout view="lHh Lpr lFf"> <q-layout view="hHh Lpr lFf">
<q-header v-if="showHeader" elevated> <q-header v-if="showHeader" elevated>
<q-toolbar> <q-toolbar>
<q-btn <q-btn
...@@ -11,9 +11,7 @@ ...@@ -11,9 +11,7 @@
@click="toggleLeftDrawer" @click="toggleLeftDrawer"
/> />
<q-toolbar-title> Quasar App </q-toolbar-title> <q-toolbar-title> VAB CMS Logo </q-toolbar-title>
<div>Quasar v{{ $q.version }}</div>
</q-toolbar> </q-toolbar>
</q-header> </q-header>
...@@ -24,11 +22,33 @@ ...@@ -24,11 +22,33 @@
bordered bordered
class="bg-grey-1" class="bg-grey-1"
> >
<MenuListComponent /> <q-scroll-area class="fit">
<MenuListComponent />
</q-scroll-area>
</q-drawer> </q-drawer>
<q-page-container> <q-page-container>
<router-view /> <q-page>
<q-scroll-area
class="full-width"
style="height: calc(100vh - 4rem) !important"
>
<div
class="relative-position q-pa-sm"
style="min-height: calc(100vh - 4rem)"
>
<router-view v-slot="{ Component }">
<transition
appear
enter-active-class="animated slideInUp"
leave-active-class="animated fadeOut absolute full-width"
>
<component :is="Component" />
</transition>
</router-view>
</div>
</q-scroll-area>
</q-page>
</q-page-container> </q-page-container>
</q-layout> </q-layout>
</template> </template>
......
...@@ -21,12 +21,19 @@ const userList: Ref<GroupInfoType[]> = ref([]); ...@@ -21,12 +21,19 @@ const userList: Ref<GroupInfoType[]> = ref([]);
const isDisable = ref(EditMode.default); const isDisable = ref(EditMode.default);
const groupName = ref(''); const groupName = ref('');
const groupDescription = ref(''); const groupDescription = ref('');
export const UserGroup = defineComponent({ const selectedGroupId = ref(-1);
const saveGroupInfo = () => {
//...
};
export default defineComponent({
components: { UserGroupComponent, GroupInfoComponent }, components: { UserGroupComponent, GroupInfoComponent },
setup() { setup() {
const $store = useStore(); const $store = useStore();
const getGroupInfo = (groupInfo: GroupInfoType) => { const getGroupInfo = (groupInfo: GroupInfoType) => {
isDisable.value = EditMode.edit; isDisable.value = EditMode.edit;
selectedGroupId.value = groupInfo.id;
groupName.value = groupInfo.groupName; groupName.value = groupInfo.groupName;
groupDescription.value = groupInfo.description; groupDescription.value = groupInfo.description;
}; };
...@@ -34,6 +41,7 @@ export const UserGroup = defineComponent({ ...@@ -34,6 +41,7 @@ export const UserGroup = defineComponent({
isDisable.value = value; isDisable.value = value;
groupName.value = ''; groupName.value = '';
groupDescription.value = ''; groupDescription.value = '';
selectedGroupId.value = -1;
}; };
onMounted(async () => { onMounted(async () => {
await $store.dispatch('authentication/getListUsers').then((response) => { await $store.dispatch('authentication/getListUsers').then((response) => {
...@@ -52,6 +60,8 @@ export const UserGroup = defineComponent({ ...@@ -52,6 +60,8 @@ export const UserGroup = defineComponent({
changeValueIsDisable, changeValueIsDisable,
groupName, groupName,
groupDescription, groupDescription,
selectedGroupId,
saveGroupInfo,
}; };
}, },
}); });
<template> <template>
<q-page padding> <div class="row q-col-gutter-sm q-pa-sm" align="center" justify="center">
<div class="row q-col-gutter-sm" align="center" justify="center"> <div class="col-4">
<div class="col-4"> <UserGroupComponent
<UserGroupComponent :list-users="userList"
:list-users="userList" :is-disable="isDisable"
:is-disable="isDisable" :selected-group-id="selectedGroupId"
@click:groupName="getGroupInfo" @click:groupName="getGroupInfo"
@click:addNewGroupUsers="changeValueIsDisable" @click:addNewGroupUsers="changeValueIsDisable"
></UserGroupComponent> ></UserGroupComponent>
</div>
<div class="col-8">
<GroupInfoComponent
:is-disable="isDisable"
:group-name="groupName"
:group-description="groupDescription"
@resetGroupInfo="changeValueIsDisable"
></GroupInfoComponent>
</div>
</div> </div>
</q-page> <div class="col-8">
<GroupInfoComponent
:is-disable="isDisable"
v-model:group-name="groupName"
v-model:group-description="groupDescription"
@resetGroupInfo="changeValueIsDisable"
@saveGroupInfo="saveGroupInfo"
></GroupInfoComponent>
</div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts" src="./UserGroup.ts">
import { UserGroup } from './UserGroup'; // import { UserGroup } from './UserGroup';
export default UserGroup; // export default UserGroup;
</script> </script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment