diff --git a/frontend/src/assets/lang/en.json b/frontend/src/assets/lang/en.json index 4e2398ab..c11be7c7 100644 --- a/frontend/src/assets/lang/en.json +++ b/frontend/src/assets/lang/en.json @@ -113,6 +113,34 @@ "required": "This field is required", "deadline": "The deadline must be after the start date" }, + "admin": { + "title": "Admin", + "keyword": "Keyword", + "search": "Search", + "edit": "Edit", + "cancel": "Cancel", + "save": "Save", + "users": { + "title": "Users", + "id": "ID", + "username": "Username", + "email": "Email", + "roles": "Roles" + }, + "user": "User", + "assistants": { + "title": "Assistants" + }, + "assistant": "Assistant", + "students": { + "title": "Students" + }, + "student": "Student", + "teachers": { + "title": "Teachers" + }, + "teacher": "Teacher" + }, "primevue": { "startsWith": "Starts with", "contains": "Contains", diff --git a/frontend/src/assets/lang/nl.json b/frontend/src/assets/lang/nl.json index 95ecced5..7652fc5a 100644 --- a/frontend/src/assets/lang/nl.json +++ b/frontend/src/assets/lang/nl.json @@ -141,37 +141,31 @@ }, "admin": { "title": "Beheerder", + "keyword": "Trefwoord", + "search": "Zoektocht", + "edit": "Bewerken", + "cancel": "Annuleer", + "save": "Sla op", "users": { "title": "Gebruikers", - "create": "Gebruiker aanmaken", - "edit": "Gebruiker bewerken" + "id": "ID", + "username": "Gebruikersnaam", + "email": "E-mail", + "roles": "Functies" }, + "user": "Gebruiker", "assistants": { "title": "Assistenten" }, + "assistant": "Assistent", "students": { "title": "Studenten" }, + "student": "Student", "teachers": { "title": "Leerkrachten" - } - }, - "admin": { - "title": "Beheerder", - "users": { - "title": "Gebruikers", - "create": "Gebruiker aanmaken", - "edit": "Gebruiker bewerken" - }, - "assistants": { - "title": "Assistenten" - }, - "students": { - "title": "Studenten" }, - "teachers": { - "title": "Leerkrachten" - } + "teacher": "Leerkracht" }, "primevue": { "accept": "Ja", diff --git a/frontend/src/components/layout/admin/AdminHeader.vue b/frontend/src/components/layout/admin/AdminHeader.vue index 0affd42b..9c894acb 100644 --- a/frontend/src/components/layout/admin/AdminHeader.vue +++ b/frontend/src/components/layout/admin/AdminHeader.vue @@ -1,5 +1,9 @@ - + - + + + diff --git a/frontend/src/components/layout/admin/AdminSidebar.vue b/frontend/src/components/layout/admin/AdminSidebar.vue index 1bee50c7..e2d74f9d 100644 --- a/frontend/src/components/layout/admin/AdminSidebar.vue +++ b/frontend/src/components/layout/admin/AdminSidebar.vue @@ -7,20 +7,20 @@ const { t } = useI18n(); const items = ref([ { - label: t('admin.users.title'), + label: 'admin.users.title', items: [ { - label: t('admin.users.title'), + label: 'admin.users.title', route: 'admin-users', }, { - label: t('admin.assistants.title'), + label: 'admin.assistants.title', }, { - label: t('admin.students.title'), + label: 'admin.students.title', }, { - label: t('admin.teachers.title'), + label: 'admin.teachers.title', }, ], }, @@ -53,7 +53,7 @@ const items = ref([ - {{ item.label }} + {{ t(item.label) }} import DataTable, { - DataTableFilterEvent, - DataTableSelectAllChangeEvent, DataTableSortEvent, + type DataTableFilterEvent, + type DataTableSelectAllChangeEvent, + type DataTableSortEvent, } from 'primevue/datatable'; import Column from 'primevue/column'; import Dialog from 'primevue/dialog'; @@ -15,19 +16,26 @@ import Title from '@/components/layout/Title.vue'; import { ref, onMounted, watch } from 'vue'; import { useI18n } from 'vue-i18n'; import { useUser } from '@/composables/services/users.service.ts'; +import { useStudents } from '@/composables/services/students.service.ts'; +import { useAssistant } from '@/composables/services/assistant.service.ts'; +import { useTeacher } from '@/composables/services/teachers.service.ts'; import { useFilter } from '@/composables/filters/filter.ts'; import { usePaginator } from '@/composables/filters/paginator.ts'; -import { roles, Role, User } from '@/types/users/User.ts'; +import { roles, type Role, User } from '@/types/users/User.ts'; import { USER_FILTER } from '@/types/filter/Filter.ts'; /* Composable injections */ const { t } = useI18n(); const { pagination, users, getUsers, searchUsers } = useUser(); +const { createStudent } = useStudents(); +const { createAssistant } = useAssistant(); +const { createTeacher } = useTeacher(); const { filter } = useFilter(USER_FILTER); const { paginate, page, first, pageSize } = usePaginator(); onMounted(async () => { + fillCreators(); await loadLazyData(); watch( @@ -40,104 +48,108 @@ onMounted(async () => { }, { deep: true }, ); - - watch( - page, - async () => { - await loadLazyData(); - } - ) }); -const dt = ref(); +const creators = ref Promise>>({}); +const createFunctions = ref([createStudent, createAssistant, createTeacher]); + const loading = ref(false); const totalRecords = ref(0); -const selectedStudents = ref(); +const selectedUsers = ref(); const selectAll = ref(false); const editItem = ref(User.blankUser()); const popupEdit = ref(false); - const columns = ref([ - {field: 'id', header: 'ID', width: '5rem'}, - {field: 'username', header: 'Username', width: '6rem'}, - {field: 'email', header: 'Email', width: '10rem'}, - {field: 'roles', header: 'Roles', width: '5rem'}, + { field: 'id', header: 'admin.users.id' }, + { field: 'username', header: 'admin.users.username' }, + { field: 'email', header: 'admin.users.email' }, + { field: 'roles', header: 'admin.users.roles' }, ]); -const loadLazyData = async () => { +const fillCreators = (): void => { + for (let i = 1; i < roles.length; i++) { + const role: Role = roles[i]; + creators.value[role] = createFunctions.value[i - 1]; + } +}; +const loadLazyData = async (): Promise => { loading.value = true; - setTimeout(async () => { - await searchUsers(filter.value, page.value, pageSize.value).then(() => { - loading.value = false; - }) - }, - 500 - ) + setTimeout((): void => { + searchUsers(filter.value, page.value, pageSize.value); + loading.value = false; + }, 500); }; -const onFilter = async (event: DataTableFilterEvent) => { +const onFilter = async (event: DataTableFilterEvent): Promise => { await paginate(event.first); await loadLazyData(); }; -const onSort = async (event: DataTableSortEvent) => { +const onSort = async (event: DataTableSortEvent): Promise => { await paginate(event.first); await loadLazyData(); -} -const onSelectAllChange = (event: DataTableSelectAllChangeEvent) => { +}; +const onSelectAllChange = (event: DataTableSelectAllChangeEvent): void => { selectAll.value = event.checked; if (selectAll.value) { getUsers().then(() => { selectAll.value = true; - selectedStudents.value = users.value; + selectedUsers.value = users.value; }); } else { selectAll.value = false; - selectedStudents.value = []; + selectedUsers.value = []; } }; -const onRowSelect = () => { - selectAll.value = selectedStudents.value.length === totalRecords.value; +const onRowSelect = (): void => { + selectAll.value = selectedUsers.value.length === totalRecords.value; }; -const onRowUnselect = () => { +const onRowUnselect = (): void => { selectAll.value = false; }; -const showPopup = (data: any) => { +const showPopup = (data: any): void => { editItem.value = JSON.parse(JSON.stringify(data)); // I do this to get a deep copy of the role array popupEdit.value = true; }; -const updateRole = (role: Role) => { - const index = editItem.value.roles.findIndex((role2: string) => role == role2); - if (index != -1) { // if role is in role list of user +const updateRole = (role: Role): void => { + const index = editItem.value.roles.findIndex((role2: string) => role === role2); + if (index !== -1) { + // if role is in role list of user editItem.value.roles.splice(index, 1); - } else { // role is NOT in role list of user + } else { + // role is NOT in role list of user editItem.value.roles.push(role); } }; -const saveItem = () => { +const saveItem = (): void => { if (pagination.value != null) { - if (editItem.value.roles.includes("student") && editItem.value.roles.includes("teacher")) { + if (editItem.value.roles.includes('student') && editItem.value.roles.includes('teacher')) { // this is not allowed TODO } else { - // update locally - const index = pagination.value.results.findIndex((row: User) => row.id == editItem.value.id); - pagination.value.results.splice(index, 1, {...editItem.value}); + const index = pagination.value.results.findIndex((row: User) => row.id === editItem.value.id); // update remotely TODO + const paginationItem = pagination.value.results[index]; + for (let i = 1; i < roles.length; i++) { + const role = roles[i]; + if (!paginationItem.roles.includes(role) && editItem.value.roles.includes(role)) { + // const func = creators.value[role]; + // Normally the create function requires an object of the specific role that it creates something of. + // But they always just extract the email, the first name and the last name, which the User object has. + // func(editItem.value); + } + } + // update locally + pagination.value.results.splice(index, 1, { ...editItem.value }); } } else { // raise error TODO } popupEdit.value = false; }; - -const searchText = (header: string) => { - return `${header} search` -} - @@ -145,35 +157,64 @@ const searchText = (header: string) => { {{ t('admin.users.title') }} - + - + No matching data. Loading data. Please wait. - + - + - + @@ -182,34 +223,31 @@ const searchText = (header: string) => { - showPopup(data)">Edit + showPopup(data)">{{ t('admin.edit') }} - - - {{ columns[0].header }} - {{ editItem.id }} - - - {{ data.header }} + + + {{ t(data.header) }} {{ editItem[data.field] }} - - {{ role }} - updateRole(role)"/> + + {{ t('admin.' + role) }} + updateRole(role)" /> - - + + - \ No newline at end of file +