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

Update

parent 26b83250
...@@ -99,7 +99,7 @@ module.exports = configure(function (ctx) { ...@@ -99,7 +99,7 @@ module.exports = configure(function (ctx) {
// directives: [], // directives: [],
// Quasar plugins // Quasar plugins
plugins: ['Notify'], plugins: ['Notify', 'Dialog'],
}, },
animations: 'all', // --- includes all animations animations: 'all', // --- includes all animations
......
...@@ -20,8 +20,10 @@ export const config = { ...@@ -20,8 +20,10 @@ export const config = {
export enum API_PATHS { export enum API_PATHS {
login = '/user/login', login = '/user/login',
getUserGroups = '/group/get_list', getUserGroups = '/group/get_list',
getGroupInfo = '/group/get_info',
getListPages = '/user/page/list', getListPages = '/user/page/list',
getListGroupUsers = '/user/group/list', getListGroupUsers = '/user/group/list',
addNewGroupUser = 'user/group/add', addNewGroupUser = 'user/group/add',
deleteGroupUser = '/user/group/delete',
getUserGroupDetail = '/user/group/detail',
updateUserGroupInfo = '/user/group/update',
} }
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { EditMode } from 'src/assets/enums'; import { EditMode } from 'src/assets/enums';
import { i18n } from 'src/boot/i18n'; import { i18n } from 'src/boot/i18n';
import { useStore } from '../../store/index';
import { Page } from 'src/store/authentication/state';
const groupNameRules = [ const groupNameRules = [
(val?: string) => (val?: string) =>
(val && val.trim().length) || (val && val.trim().length) ||
i18n.global.t('userGroupPage.groupInfo.validateMessages.requireGroupName'), i18n.global.t('userGroupPage.groupInfo.validateMessages.requireGroupName'),
];
const groupDescriptionRules = [
(val?: string) => (val?: string) =>
(val && val.trim().length <= 10) || (val && val.trim().length) ||
i18n.global.t( i18n.global.t(
'userGroupPage.groupInfo.validateMessages.groupNameLengthInvalid' 'userGroupPage.groupInfo.validateMessages.requireGroupDescription'
), ),
]; ];
...@@ -27,14 +32,42 @@ export const GroupInfoScript = defineComponent({ ...@@ -27,14 +32,42 @@ export const GroupInfoScript = defineComponent({
type: String, type: String,
required: true, required: true,
}, },
selectedPageRoles: {
type: Array,
required: true,
},
}, },
emits: [ emits: [
'resetGroupInfo', 'resetGroupInfo',
'update:groupName', 'update:groupName',
'update:groupDescription', 'update:groupDescription',
'saveGroupInfo', 'saveGroupInfo',
'deleteGroup',
'update:selectedPageRoles',
], ],
setup() { setup() {
return { EditMode, groupNameRules }; const $store = useStore();
const pagesRoles = [...$store.state.authentication.pageList].reduce(
(acc: Page[], page) => {
const newPage = { ...page };
newPage.name = newPage.pageName;
newPage.formatted_role_list = newPage.formatted_role_list?.map(
(role) => {
const newRole = { ...role };
newRole.id = `${newRole.id || ''}-${newPage.id}`;
newRole.name = newRole.roleName;
return newRole;
}
);
acc.push(newPage);
return acc;
},
[]
);
console.log(pagesRoles);
return { EditMode, groupNameRules, groupDescriptionRules, pagesRoles };
}, },
}); });
<template> <template>
<q-card flat bordered class="my-card"> <q-card flat bordered class="my-card">
<q-form @submit.prevent="$emit('saveGroupInfo', isDisable)"> <q-form greedy @submit.prevent="$emit('saveGroupInfo', isDisable)">
<q-card-section style="padding-top: 28px"> <q-card-section style="padding-top: 28px">
<div class="row"> <div class="row">
<div class="col-4" style="display: flex"> <div class="col-4" style="display: flex">
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
color="red" color="red"
icon="delete" icon="delete"
:label="$t('crudActions.delete')" :label="$t('crudActions.delete')"
@click="$emit('deleteGroup')"
/> />
<q-btn <q-btn
v-if="isDisable" v-if="isDisable"
...@@ -43,9 +44,10 @@ ...@@ -43,9 +44,10 @@
:model-value="groupName" :model-value="groupName"
:disable="!isDisable ? true : false" :disable="!isDisable ? true : false"
outlined outlined
@update:model-value="$emit('update:groupName', $event)" :label="$t('userGroupPage.groupInfo.fieldLabels.groupName')"
placeholder="Tên nhóm *"
:rules="groupNameRules" :rules="groupNameRules"
hide-bottom-space
@update:model-value="$emit('update:groupName', $event)"
/> />
</q-card-section> </q-card-section>
<q-card-section class="q-pt-none"> <q-card-section class="q-pt-none">
...@@ -53,12 +55,30 @@ ...@@ -53,12 +55,30 @@
:model-value="groupDescription" :model-value="groupDescription"
:disable="!isDisable ? true : false" :disable="!isDisable ? true : false"
outlined outlined
:label="$t('userGroupPage.groupInfo.fieldLabels.groupDescription')"
:rules="groupDescriptionRules"
hide-bottom-space
@update:model-value="$emit('update:groupDescription', $event)" @update:model-value="$emit('update:groupDescription', $event)"
placeholder="Mô tả *"
/> />
</q-card-section> </q-card-section>
</q-form> </q-form>
<q-card-section v-if="isDisable === EditMode.edit"> </q-card-section> <q-card-section v-if="isDisable === EditMode.edit">
<q-scroll-area
class="full-width"
style="height: calc(100vh - 25rem) !important"
>
<q-tree
class="col-12 col-sm-6"
:nodes="pagesRoles"
node-key="id"
tick-strategy="leaf"
label-key="name"
children-key="formatted_role_list"
:ticked="selectedPageRoles"
@update:ticked="$emit('update:selectedPageRoles', $event)"
/>
</q-scroll-area>
</q-card-section>
</q-card> </q-card>
</template> </template>
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
align="left" align="left"
:outline="userItem.id !== selectedGroupId" :outline="userItem.id !== selectedGroupId"
size="large" size="large"
class="full-width my-1" class="full-width q-my-xs"
color="primary" color="primary"
:label="userItem.groupName" :label="userItem.groupName"
no-caps no-caps
......
...@@ -5,7 +5,7 @@ export default { ...@@ -5,7 +5,7 @@ export default {
failed: 'Action failed', failed: 'Action failed',
success: 'Action was successful', success: 'Action was successful',
requestErrorMessage: 'Không thể kết nối đến server', requestErrorMessage: 'Không thể kết nối đến server',
responseErrorMessage: '', responseErrorMessage: 'Xảy ra lỗi trong quá trình kết nối tới server',
tokenInvalidMessage: 'Phiên đăng nhập hết hạn. Vui lòng đăng nhập lại', tokenInvalidMessage: 'Phiên đăng nhập hết hạn. Vui lòng đăng nhập lại',
loginSuccess: 'Đăng nhập thành công', loginSuccess: 'Đăng nhập thành công',
logoutSuccess: 'Đăng xuất thành công', logoutSuccess: 'Đăng xuất thành công',
...@@ -20,6 +20,7 @@ export default { ...@@ -20,6 +20,7 @@ export default {
}, },
responseErrorMsg: { responseErrorMsg: {
'msg-1': 'Lỗi không xác định', 'msg-1': 'Lỗi không xác định',
msg999: 'Lỗi hệ thống',
}, },
emptyData: 'Không tìm thấy dữ liệu', emptyData: 'Không tìm thấy dữ liệu',
crudActions: { crudActions: {
...@@ -37,7 +38,24 @@ export default { ...@@ -37,7 +38,24 @@ export default {
requireGroupName: 'Vui lòng cung cấp tên nhóm người dùng', requireGroupName: 'Vui lòng cung cấp tên nhóm người dùng',
groupNameLengthInvalid: groupNameLengthInvalid:
'Tên nhóm người dùng chỉ có thể dài tối đa 10 ký tự', 'Tên nhóm người dùng chỉ có thể dài tối đa 10 ký tự',
requireGroupDescription: 'Vui lòng cung cấp mô tả nhóm người dùng',
}, },
actionMessages: {
addNewSuccess: 'Thêm mới nhóm người dùng thành công',
deleteSuccess: 'Xoá nhóm người dùng thành công',
updateSuccess: 'Cập nhật nhóm người dùng thành công',
},
fieldLabels: {
groupName: 'Tên nhóm người dùng *',
groupDescription: 'Mô tả *',
},
},
confirmActionsTitle: {
confirmDeleteGroupTitle: 'Xác nhận',
confirmDeleteGroupContent: 'Bạn có chắc chắn muốn xoá {groupName}?',
confirmDeleteGroupCancelBtnLabel: 'Huỷ',
}, },
}, },
}; };
import { defineComponent, onMounted, Ref, ref } from 'vue'; import { defineComponent, onMounted, Ref, ref } from 'vue';
import { useStore } from 'src/store'; import { StateInterface, useStore } from 'src/store';
import UserGroupComponent from '../../components/user-group/index.vue'; import UserGroupComponent from '../../components/user-group/index.vue';
import GroupInfoComponent from '../../components/group-info/index.vue'; import GroupInfoComponent from '../../components/group-info/index.vue';
import { AxiosResponse } from 'axios'; import { AxiosResponse } from 'axios';
import { api, BaseResponseBody } from 'src/boot/axios'; import { api, BaseResponseBody } from 'src/boot/axios';
import { EditMode } from 'src/assets/enums'; import { EditMode } from 'src/assets/enums';
import { API_PATHS } from 'src/assets/configurations'; import { API_PATHS, config } from 'src/assets/configurations';
import { Dialog, Notify } from 'quasar';
import { i18n } from 'src/boot/i18n';
import { Store } from 'vuex';
export type GroupInfoType = { export type GroupInfoType = {
createBy: null | string; createBy: null | string;
...@@ -23,31 +26,216 @@ const isDisable = ref(EditMode.default); ...@@ -23,31 +26,216 @@ const isDisable = ref(EditMode.default);
const groupName = ref(''); const groupName = ref('');
const groupDescription = ref(''); const groupDescription = ref('');
const selectedGroupId = ref(-1); const selectedGroupId = ref(-1);
const selectedPageRoles: Ref<string[]> = ref([]);
const saveGroupInfo = async () => { const addNewGroupInfo = async ($store: Store<StateInterface>) => {
//... try {
const response = (await api({
url: API_PATHS.addNewGroupUser,
method: 'POST',
data: {
group: {
groupName: groupName.value,
description: groupDescription.value,
},
users: [],
pageRoles: [],
},
})) as AxiosResponse<BaseResponseBody<unknown>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
Notify.create({
type: 'positive',
message: i18n.global.t(
'userGroupPage.groupInfo.actionMessages.addNewSuccess'
),
});
if (isDisable.value === EditMode.add) { changeValueIsDisable(EditMode.default);
try { void getListUserGroup($store);
const response = (await api({ }
url: API_PATHS.addNewGroupUser, } catch (error) {}
method: 'POST', };
data: {
group: { const updateGroupInfo = async ($store: Store<StateInterface>) => {
groupName: groupName.value, try {
description: groupDescription.value, const pages = selectedPageRoles.value
}, .map((role) => {
const page = role.split('-')[1];
return Number(page);
})
.reduce((acc: number[], id) => {
if (!acc.includes(id)) {
acc.push(id);
}
return acc;
}, []);
console.log(pages);
const pageRoles = pages.reduce(
(acc: { id: number; roles: string }[], page) => {
const parsedPage = {
...$store.state.authentication.pageList.find((p) => p.id === page),
roles: '',
};
parsedPage.roles = selectedPageRoles.value
.reduce((a: number[], pageRole) => {
const splittedRoles = pageRole.split('-');
if (Number(splittedRoles[1]) === page) {
a.push(Number(splittedRoles[0]));
}
return a;
}, [])
.join(',');
acc.push({
id: parsedPage.id || -1,
roles: parsedPage.roles,
});
return acc;
},
[]
);
console.log(pageRoles);
const response = (await api({
url: API_PATHS.updateUserGroupInfo,
method: 'POST',
data: {
group: {
id: selectedGroupId.value,
groupName: groupName.value,
description: groupDescription.value,
}, },
})) as AxiosResponse<BaseResponseBody<unknown>>; pageRoles,
return response; },
} catch (error) {} })) as AxiosResponse<BaseResponseBody<unknown>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
Notify.create({
type: 'positive',
message: i18n.global.t(
'userGroupPage.groupInfo.actionMessages.updateSuccess'
),
});
changeValueIsDisable(EditMode.default);
void getListUserGroup($store);
}
} catch (error) {}
};
const changeValueIsDisable = (value: number) => {
isDisable.value = value;
groupName.value = '';
groupDescription.value = '';
selectedGroupId.value = -1;
};
const saveGroupInfo = ($store: Store<StateInterface>) => {
//...
if (isDisable.value === EditMode.add) {
void addNewGroupInfo($store);
} else { } else {
console.log('editGroupInfo'); void updateGroupInfo($store);
} }
}; };
const getListUserGroup = async ($store: Store<StateInterface>) => {
await $store.dispatch('authentication/getListUsers').then((response) => {
const res = response as AxiosResponse<BaseResponseBody<GroupInfoType[]>>;
if (!res.data.error.code) {
userList.value = res.data.data;
}
});
};
const confirmDeleteGroup = ($store: Store<StateInterface>) => {
Dialog.create({
title: i18n.global.t(
'userGroupPage.confirmActionsTitle.confirmDeleteGroupTitle'
),
message: i18n.global
.t('userGroupPage.confirmActionsTitle.confirmDeleteGroupContent')
.replace('{groupName}', groupName.value),
cancel: i18n.global.t(
'userGroupPage.confirmActionsTitle.confirmDeleteGroupCancelBtnLabel'
),
color: 'negative',
}).onOk(() => {
void deleteGroup($store);
});
};
const deleteGroup = async ($store: Store<StateInterface>) => {
try {
const deleteResult = (await api({
url: API_PATHS.deleteGroupUser,
method: 'GET',
params: {
groupId: selectedGroupId.value,
},
})) as AxiosResponse<BaseResponseBody<unknown>>;
if (deleteResult.data.error.code === config.API_RES_CODE.OK.code) {
Notify.create({
type: 'positive',
message: i18n.global.t(
'userGroupPage.groupInfo.actionMessages.deleteSuccess'
),
});
changeValueIsDisable(EditMode.default);
void getListUserGroup($store);
}
} catch (error) {}
};
const getGroupDetail = async () => {
try {
const groupDetailRes = (await api({
url: API_PATHS.getUserGroupDetail,
method: 'GET',
params: {
groupId: selectedGroupId.value,
},
})) as AxiosResponse<BaseResponseBody<unknown>>;
if (groupDetailRes.data.error.code === config.API_RES_CODE.OK.code) {
// selectedPageRoles.value
const groupDetail = groupDetailRes.data.data as {
pageRoles: {
id: number;
roles: string;
}[];
};
selectedPageRoles.value = groupDetail.pageRoles.reduce(
(acc: string[], pageRole) => {
const splittedRoles = pageRole.roles.split(',');
splittedRoles.forEach((role) => {
acc.push(`${role}-${pageRole.id}`);
});
return acc;
},
[]
);
}
} catch (error) {}
};
export default defineComponent({ export default defineComponent({
components: { UserGroupComponent, GroupInfoComponent }, components: { UserGroupComponent, GroupInfoComponent },
watch: {
selectedPageRoles(value) {
console.log(value);
},
},
setup() { setup() {
const $store = useStore(); const $store = useStore();
const getGroupInfo = (groupInfo: GroupInfoType) => { const getGroupInfo = (groupInfo: GroupInfoType) => {
...@@ -55,23 +243,11 @@ export default defineComponent({ ...@@ -55,23 +243,11 @@ export default defineComponent({
selectedGroupId.value = groupInfo.id; selectedGroupId.value = groupInfo.id;
groupName.value = groupInfo.groupName; groupName.value = groupInfo.groupName;
groupDescription.value = groupInfo.description; groupDescription.value = groupInfo.description;
}; void getGroupDetail();
const changeValueIsDisable = (value: number) => {
isDisable.value = value;
groupName.value = '';
groupDescription.value = '';
selectedGroupId.value = -1;
}; };
onMounted(async () => { onMounted(() => {
await $store.dispatch('authentication/getListUsers').then((response) => { void getListUserGroup($store);
const res = response as AxiosResponse<
BaseResponseBody<GroupInfoType[]>
>;
if (!res.data.error.code) {
userList.value = res.data.data;
}
});
}); });
return { return {
userList, userList,
...@@ -82,6 +258,8 @@ export default defineComponent({ ...@@ -82,6 +258,8 @@ export default defineComponent({
groupDescription, groupDescription,
selectedGroupId, selectedGroupId,
saveGroupInfo, saveGroupInfo,
confirmDeleteGroup,
selectedPageRoles,
}; };
}, },
}); });
...@@ -14,8 +14,10 @@ ...@@ -14,8 +14,10 @@
:is-disable="isDisable" :is-disable="isDisable"
v-model:group-name="groupName" v-model:group-name="groupName"
v-model:group-description="groupDescription" v-model:group-description="groupDescription"
v-model:selectedPageRoles="selectedPageRoles"
@resetGroupInfo="changeValueIsDisable" @resetGroupInfo="changeValueIsDisable"
@saveGroupInfo="saveGroupInfo" @saveGroupInfo="saveGroupInfo($store)"
@deleteGroup="confirmDeleteGroup($store)"
></GroupInfoComponent> ></GroupInfoComponent>
</div> </div>
</div> </div>
......
...@@ -20,6 +20,8 @@ export type Page = { ...@@ -20,6 +20,8 @@ export type Page = {
parentId: number; parentId: number;
roleList?: string | null; roleList?: string | null;
formatted_role_list?: PageRole[]; formatted_role_list?: PageRole[];
name?: string;
roles?: string;
}; };
export type PageRole = { export type PageRole = {
...@@ -29,6 +31,8 @@ export type PageRole = { ...@@ -29,6 +31,8 @@ export type PageRole = {
roleId: number; roleId: number;
roleName: string; roleName: string;
status: number; status: number;
id?: number | string;
name?: string;
}; };
export type MenuItem = { export type MenuItem = {
......
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