From 3e95438086911dc5bf670c9c2a844c95f7743ae3 Mon Sep 17 00:00:00 2001 From: francis Date: Sat, 23 Mar 2024 09:59:43 +0100 Subject: [PATCH 1/8] chore: placeholder component --- frontend/src/components/Dummy.vue | 8 ++++++ frontend/src/router/routes.ts | 48 +++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 frontend/src/components/Dummy.vue diff --git a/frontend/src/components/Dummy.vue b/frontend/src/components/Dummy.vue new file mode 100644 index 00000000..dfb42325 --- /dev/null +++ b/frontend/src/components/Dummy.vue @@ -0,0 +1,8 @@ + + + diff --git a/frontend/src/router/routes.ts b/frontend/src/router/routes.ts index 7fe9ace7..f3b99c0b 100644 --- a/frontend/src/router/routes.ts +++ b/frontend/src/router/routes.ts @@ -1,10 +1,52 @@ +import { RouteRecordRaw } from 'vue-router'; import DashboardView from '@/views/dashboard/DashboardView.vue'; -import {RouteRecordRaw} from 'vue-router'; import CourseView from '@/views/courses/CourseView.vue'; +import Dummy from '@/components/Dummy.vue'; export const routes: RouteRecordRaw[] = [ { path: '/', component: DashboardView, name: 'dashboard' }, { path: '/courses', name: 'courses', children: [ { path: ':id', component: CourseView, name: 'view' } - ]} -]; \ No newline at end of file + ]}, + { path: '/login', component: Dummy, name: 'login' } +]; + + +/** + * Routes: + * + * ### COURSES ### + * /courses + * /courses/create (teacher / admin) + * /courses/id + * /courses/id/edit + * /courses/id/projects + * /courses/id/projects/id + * /courses/id/projects/create + * /courses/id/projects/id/edit + * /courses/id/projects/id/groups + * /courses/id/projects/id/submit + * + * ### USERS ### + * /users (teacher /admin) + * /users/students/ + * /users/students/id + * /users/admins + * /users/admins/id + * /users/teachers + * /users/teachers/id + * /users/assistants + * /users/assistants/id + * /users/id (teacher / admin) + * + * ### FACULTIES ### + * /faculties (teacher / admin) + * /faculties/create (teacher / admin) + * + * ### NOTIFICATIONS ### + * /notifications + * /notifications/id + * + * ### AUTHENTICATION ### + * /login + */ \ No newline at end of file From 098b4f8dac053bbedbaedb8f811bd29faab48590 Mon Sep 17 00:00:00 2001 From: francis Date: Sat, 23 Mar 2024 10:11:48 +0100 Subject: [PATCH 2/8] chore: router abstraction --- frontend/src/main.ts | 7 ++----- frontend/src/router/{routes.ts => router.ts} | 12 ++++++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) rename frontend/src/router/{routes.ts => router.ts} (81%) diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 6dc752d2..3bf9720f 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -5,9 +5,8 @@ import PrimeVue from 'primevue/config'; import Ripple from 'primevue/ripple'; import {createApp} from 'vue'; import {createI18n} from 'vue-i18n'; -import {routes} from '@/router/routes.ts'; +import router from './router/router'; import {createPinia} from 'pinia'; -import {createRouter, createWebHistory} from 'vue-router'; const app = createApp(App); @@ -22,9 +21,7 @@ app.use(createI18n({ messages: { en, nl } })); -app.use(createRouter({ - history: createWebHistory(), routes -})); +app.use(router) app.use(PrimeVue, { ripple: true diff --git a/frontend/src/router/routes.ts b/frontend/src/router/router.ts similarity index 81% rename from frontend/src/router/routes.ts rename to frontend/src/router/router.ts index f3b99c0b..679aef31 100644 --- a/frontend/src/router/routes.ts +++ b/frontend/src/router/router.ts @@ -1,9 +1,10 @@ -import { RouteRecordRaw } from 'vue-router'; +import { RouteRecordRaw, createWebHistory, createRouter } from 'vue-router'; + import DashboardView from '@/views/dashboard/DashboardView.vue'; import CourseView from '@/views/courses/CourseView.vue'; import Dummy from '@/components/Dummy.vue'; -export const routes: RouteRecordRaw[] = [ +const routes: RouteRecordRaw[] = [ { path: '/', component: DashboardView, name: 'dashboard' }, { path: '/courses', name: 'courses', children: [ { path: ':id', component: CourseView, name: 'view' } @@ -11,6 +12,13 @@ export const routes: RouteRecordRaw[] = [ { path: '/login', component: Dummy, name: 'login' } ]; +const router = createRouter({ + history: createWebHistory(), + routes, +}) + +export default router + /** * Routes: From f7f25c18a38f677d064462fb9943b1e3cdd3a38f Mon Sep 17 00:00:00 2001 From: francis Date: Sat, 23 Mar 2024 10:19:14 +0100 Subject: [PATCH 3/8] chore: page not found --- frontend/src/components/PageNotFound.vue | 13 +++++++++++++ frontend/src/router/router.ts | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/PageNotFound.vue diff --git a/frontend/src/components/PageNotFound.vue b/frontend/src/components/PageNotFound.vue new file mode 100644 index 00000000..f1c8ca5b --- /dev/null +++ b/frontend/src/components/PageNotFound.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/router/router.ts b/frontend/src/router/router.ts index 679aef31..b51f542d 100644 --- a/frontend/src/router/router.ts +++ b/frontend/src/router/router.ts @@ -3,13 +3,15 @@ import { RouteRecordRaw, createWebHistory, createRouter } from 'vue-router'; import DashboardView from '@/views/dashboard/DashboardView.vue'; import CourseView from '@/views/courses/CourseView.vue'; import Dummy from '@/components/Dummy.vue'; +import PageNotFound from '@/components/PageNotFound.vue'; const routes: RouteRecordRaw[] = [ { path: '/', component: DashboardView, name: 'dashboard' }, { path: '/courses', name: 'courses', children: [ { path: ':id', component: CourseView, name: 'view' } ]}, - { path: '/login', component: Dummy, name: 'login' } + { path: '/login', component: Dummy, name: 'login' }, + { path: '/:pathMatch(.*)*', name: 'PageNotFound', component: PageNotFound }, ]; const router = createRouter({ From a25462ae73855196f8bfe3ea85d814cfc8d820aa Mon Sep 17 00:00:00 2001 From: francis Date: Sat, 23 Mar 2024 11:07:22 +0100 Subject: [PATCH 4/8] chore: routes structure --- frontend/src/router/router.ts | 61 ++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/frontend/src/router/router.ts b/frontend/src/router/router.ts index b51f542d..17af7ae2 100644 --- a/frontend/src/router/router.ts +++ b/frontend/src/router/router.ts @@ -7,11 +7,64 @@ import PageNotFound from '@/components/PageNotFound.vue'; const routes: RouteRecordRaw[] = [ { path: '/', component: DashboardView, name: 'dashboard' }, - { path: '/courses', name: 'courses', children: [ - { path: ':id', component: CourseView, name: 'view' } + + // Courses + { path: '/courses', children: [ + { path: '', component: Dummy, name: 'courses' }, + { path: 'create', component: Dummy, name: 'course-create' }, + // Single course + { path: ':id', children: [ + { path: '', component: CourseView, name: 'course' }, + { path: 'edit', component: Dummy, name: 'course-edit' }, + // Projects + { path: 'projects', children: [ + { path: '', component: Dummy, name: 'projects' }, + { path: 'create', component: Dummy, name: 'project-create' }, + // Single project + { path: ':id', children: [ + { path: '', component: Dummy, name: 'project' }, + { path: 'edit', component: Dummy, name: 'project-edit' }, + { path: 'groups', component: Dummy, name: 'project-groups' }, + { path: 'submit', component: Dummy, name: 'project-submit' }, + ]} + ]}, + ]} + ]}, + + // Users + { path: '/users', children: [ + { path: ':id', component: Dummy, name: 'user' }, + { path: 'students', children: [ + { path: '', component: Dummy, name: 'students' }, + { path: ':id', component: Dummy, name: 'student' }, + ]}, + { path: 'admins', children: [ + { path: '', component: Dummy, name: 'admins' }, + { path: ':id', component: Dummy, name: 'admin' }, + ]}, + { path: 'teachers', children: [ + { path: '', component: Dummy, name: 'teachers' }, + { path: ':id', component: Dummy, name: 'teacher' }, + ]}, + { path: 'assistants', children: [ + { path: '', component: Dummy, name: 'assistants' }, + { path: ':id', component: Dummy, name: 'assistant' }, + ]}, ]}, + + // Faculties + { path: '/faculties', component: Dummy, name: 'faculties' }, + { path: '/faculties/create', component: Dummy, name: 'faculty-create' }, + + // Notifications + { path: '/notifications', component: Dummy, name: 'notifications' }, + { path: '/notifications/:id', component: Dummy, name: 'notification' }, + + // Authentication { path: '/login', component: Dummy, name: 'login' }, - { path: '/:pathMatch(.*)*', name: 'PageNotFound', component: PageNotFound }, + + // Page not found + { path: '/:pathMatch(.*)*', name: 'page-not-found', component: PageNotFound }, ]; const router = createRouter({ @@ -31,8 +84,8 @@ export default router * /courses/id * /courses/id/edit * /courses/id/projects - * /courses/id/projects/id * /courses/id/projects/create + * /courses/id/projects/id * /courses/id/projects/id/edit * /courses/id/projects/id/groups * /courses/id/projects/id/submit From 1866c0165427d7fe2752017ceca0fa5269b19f42 Mon Sep 17 00:00:00 2001 From: francis Date: Sat, 23 Mar 2024 13:11:57 +0100 Subject: [PATCH 5/8] fix: typo --- backend/api/views/project_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/api/views/project_view.py b/backend/api/views/project_view.py index 583b812f..43248234 100644 --- a/backend/api/views/project_view.py +++ b/backend/api/views/project_view.py @@ -97,7 +97,7 @@ def structure_checks(self, request, **_): @structure_checks.mapping.post @structure_checks.mapping.put def _add_structure_check(self, request: Request, **_): - """Add an structure_check to the project""" + """Add a structure_check to the project""" project: Project = self.get_object() From 2699998804eeb9e98526e03a82caeb52ed8c58f3 Mon Sep 17 00:00:00 2001 From: francis Date: Sat, 23 Mar 2024 14:46:16 +0100 Subject: [PATCH 6/8] chore: remove page not found component --- frontend/src/components/PageNotFound.vue | 13 ------------- frontend/src/router/router.ts | 1 - 2 files changed, 14 deletions(-) delete mode 100644 frontend/src/components/PageNotFound.vue diff --git a/frontend/src/components/PageNotFound.vue b/frontend/src/components/PageNotFound.vue deleted file mode 100644 index f1c8ca5b..00000000 --- a/frontend/src/components/PageNotFound.vue +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file diff --git a/frontend/src/router/router.ts b/frontend/src/router/router.ts index d8acf525..f67b36a5 100644 --- a/frontend/src/router/router.ts +++ b/frontend/src/router/router.ts @@ -4,7 +4,6 @@ import DashboardView from '@/views/dashboard/DashboardView.vue'; import CourseView from '@/views/courses/CourseView.vue'; import Dummy from '@/components/Dummy.vue'; import LoginView from '@/views/authentication/LoginView.vue'; -import PageNotFound from '@/components/PageNotFound.vue'; const routes: RouteRecordRaw[] = [ { path: '/', component: DashboardView, name: 'dashboard' }, From 987c1a2d248af4c31d9919031953ea41e2f71c3d Mon Sep 17 00:00:00 2001 From: francis Date: Sat, 23 Mar 2024 17:11:05 +0100 Subject: [PATCH 7/8] chore: navigation guard --- .../src/components/error/NotAuthorized.vue | 7 +++ frontend/src/router/router.ts | 63 +++++++------------ frontend/src/router/routes.ts | 15 ----- 3 files changed, 29 insertions(+), 56 deletions(-) create mode 100644 frontend/src/components/error/NotAuthorized.vue delete mode 100644 frontend/src/router/routes.ts diff --git a/frontend/src/components/error/NotAuthorized.vue b/frontend/src/components/error/NotAuthorized.vue new file mode 100644 index 00000000..8d7ed66e --- /dev/null +++ b/frontend/src/components/error/NotAuthorized.vue @@ -0,0 +1,7 @@ + + + diff --git a/frontend/src/router/router.ts b/frontend/src/router/router.ts index f67b36a5..daf18b7d 100644 --- a/frontend/src/router/router.ts +++ b/frontend/src/router/router.ts @@ -1,9 +1,13 @@ import { RouteRecordRaw, createWebHistory, createRouter } from 'vue-router'; +// import { useUserStore } from '@/stores/userStore'; +// TODO: after pinia setup is done + import DashboardView from '@/views/dashboard/DashboardView.vue'; import CourseView from '@/views/courses/CourseView.vue'; import Dummy from '@/components/Dummy.vue'; import LoginView from '@/views/authentication/LoginView.vue'; +import NotAuthorized from '@/components/error/NotAuthorized.vue'; const routes: RouteRecordRaw[] = [ { path: '/', component: DashboardView, name: 'dashboard' }, @@ -28,7 +32,7 @@ const routes: RouteRecordRaw[] = [ { path: 'submit', component: Dummy, name: 'project-submit' }, ]} ]}, - ]} + ]}, ]}, // Users @@ -65,7 +69,12 @@ const routes: RouteRecordRaw[] = [ { path: 'login', component: LoginView, name: 'login' }, ]}, - // Page not found + // Errors + { path: '/error', children: [ + { path: '/403', component: NotAuthorized, name: 'not-authorized' }, + ]}, + + // Page not found: redirect to dashboard { path: '/:pathMatch(.*)*', redirect: { name: 'dashboard' } } ]; @@ -74,44 +83,16 @@ const router = createRouter({ routes, }) -export default router +// TODO: once pinia store is setup, implement navigation guards +// Navigation guard example: +router.beforeEach((to, _) => { + const isAdmin: boolean = false + if (to.name === 'faculty-create') { + if (!isAdmin) { + return { name: 'not-authorized' } + } + } +}) -/** - * Routes: - * - * ### COURSES ### - * /courses - * /courses/create (teacher / admin) - * /courses/id - * /courses/id/edit - * /courses/id/projects - * /courses/id/projects/create - * /courses/id/projects/id - * /courses/id/projects/id/edit - * /courses/id/projects/id/groups - * /courses/id/projects/id/submit - * - * ### USERS ### - * /users (teacher /admin) - * /users/students/ - * /users/students/id - * /users/admins - * /users/admins/id - * /users/teachers - * /users/teachers/id - * /users/assistants - * /users/assistants/id - * /users/id (teacher / admin) - * - * ### FACULTIES ### - * /faculties (teacher / admin) - * /faculties/create (teacher / admin) - * - * ### NOTIFICATIONS ### - * /notifications - * /notifications/id - * - * ### AUTHENTICATION ### - * /login - */ \ No newline at end of file +export default router diff --git a/frontend/src/router/routes.ts b/frontend/src/router/routes.ts deleted file mode 100644 index 2d406745..00000000 --- a/frontend/src/router/routes.ts +++ /dev/null @@ -1,15 +0,0 @@ -import DashboardView from '@/views/dashboard/DashboardView.vue'; -import CourseView from '@/views/courses/CourseView.vue'; -import LoginView from '@/views/authentication/LoginView.vue'; -import {RouteRecordRaw} from 'vue-router'; - -export const routes: RouteRecordRaw[] = [ - { path: '/auth/', children: [ - { path: 'login', component: LoginView, name: 'login' }, - ]}, - { path: '/', component: DashboardView, name: 'dashboard' }, - { path: '/courses/', children: [ - { path: ':id', component: CourseView, name: 'course-view' } - ]}, - { path: '/:pathMatch(.*)*', redirect: { name: 'dashboard' } } -]; \ No newline at end of file From 72a0b905981d70656822d0dcfea6554a6688d8a7 Mon Sep 17 00:00:00 2001 From: francis Date: Sat, 23 Mar 2024 17:30:49 +0100 Subject: [PATCH 8/8] chore: undo redirect from navigation guard --- frontend/src/components/error/NotAuthorized.vue | 7 ------- frontend/src/router/router.ts | 8 +------- 2 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 frontend/src/components/error/NotAuthorized.vue diff --git a/frontend/src/components/error/NotAuthorized.vue b/frontend/src/components/error/NotAuthorized.vue deleted file mode 100644 index 8d7ed66e..00000000 --- a/frontend/src/components/error/NotAuthorized.vue +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/frontend/src/router/router.ts b/frontend/src/router/router.ts index daf18b7d..a776084f 100644 --- a/frontend/src/router/router.ts +++ b/frontend/src/router/router.ts @@ -7,7 +7,6 @@ import DashboardView from '@/views/dashboard/DashboardView.vue'; import CourseView from '@/views/courses/CourseView.vue'; import Dummy from '@/components/Dummy.vue'; import LoginView from '@/views/authentication/LoginView.vue'; -import NotAuthorized from '@/components/error/NotAuthorized.vue'; const routes: RouteRecordRaw[] = [ { path: '/', component: DashboardView, name: 'dashboard' }, @@ -69,11 +68,6 @@ const routes: RouteRecordRaw[] = [ { path: 'login', component: LoginView, name: 'login' }, ]}, - // Errors - { path: '/error', children: [ - { path: '/403', component: NotAuthorized, name: 'not-authorized' }, - ]}, - // Page not found: redirect to dashboard { path: '/:pathMatch(.*)*', redirect: { name: 'dashboard' } } ]; @@ -89,7 +83,7 @@ router.beforeEach((to, _) => { const isAdmin: boolean = false if (to.name === 'faculty-create') { if (!isAdmin) { - return { name: 'not-authorized' } + return false } } })