diff --git a/client/package-lock.json b/client/package-lock.json index 83a70117..7b8ede7b 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -14,6 +14,7 @@ "@sentry/vue": "^7.20.0", "@urql/vue": "^1.0.2", "@vueuse/core": "^9.13.0", + "@vueuse/router": "^10.1.2", "cypress": "^12.9.0", "d3": "^7.6.1", "dayjs": "^1.11.7", @@ -25,7 +26,7 @@ "vue": "^3.2.38", "vue-i18n": "^9.2.2", "vue-i18n-extract": "^2.0.7", - "vue-router": "^4.1.5" + "vue-router": "^4.1.6" }, "devDependencies": { "@graphql-codegen/cli": "^2.13.12", @@ -7489,6 +7490,32 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/@vueuse/router": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/router/-/router-10.1.2.tgz", + "integrity": "sha512-99KhTBZliU5gRPHPhi7UO97vArgWIYLomLeCPYJQvbg1gYYa3BVX/uFDcdOaVYhdz5rWDeY/DaeW5CeNYR7zzQ==", + "dependencies": { + "@vueuse/shared": "10.1.2", + "vue-demi": ">=0.14.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue-router": ">=4.0.0-rc.1" + } + }, + "node_modules/@vueuse/router/node_modules/@vueuse/shared": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.1.2.tgz", + "integrity": "sha512-1uoUTPBlgyscK9v6ScGeVYDDzlPSFXBlxuK7SfrDGyUTBiznb3mNceqhwvZHjtDRELZEN79V5uWPTF1VDV8svA==", + "dependencies": { + "vue-demi": ">=0.14.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@vueuse/shared": { "version": "9.13.0", "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", @@ -18979,9 +19006,9 @@ } }, "node_modules/vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz", + "integrity": "sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg==", "hasInstallScript": true, "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", @@ -25294,6 +25321,25 @@ "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==" }, + "@vueuse/router": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/router/-/router-10.1.2.tgz", + "integrity": "sha512-99KhTBZliU5gRPHPhi7UO97vArgWIYLomLeCPYJQvbg1gYYa3BVX/uFDcdOaVYhdz5rWDeY/DaeW5CeNYR7zzQ==", + "requires": { + "@vueuse/shared": "10.1.2", + "vue-demi": ">=0.14.0" + }, + "dependencies": { + "@vueuse/shared": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.1.2.tgz", + "integrity": "sha512-1uoUTPBlgyscK9v6ScGeVYDDzlPSFXBlxuK7SfrDGyUTBiznb3mNceqhwvZHjtDRELZEN79V5uWPTF1VDV8svA==", + "requires": { + "vue-demi": ">=0.14.0" + } + } + } + }, "@vueuse/shared": { "version": "9.13.0", "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", @@ -33879,9 +33925,9 @@ } }, "vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==" + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz", + "integrity": "sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg==" }, "vue-docgen-api": { "version": "4.64.1", diff --git a/client/package.json b/client/package.json index 1a125dd0..d81aca16 100644 --- a/client/package.json +++ b/client/package.json @@ -25,6 +25,7 @@ "@sentry/vue": "^7.20.0", "@urql/vue": "^1.0.2", "@vueuse/core": "^9.13.0", + "@vueuse/router": "^10.1.2", "cypress": "^12.9.0", "d3": "^7.6.1", "dayjs": "^1.11.7", @@ -36,7 +37,7 @@ "vue": "^3.2.38", "vue-i18n": "^9.2.2", "vue-i18n-extract": "^2.0.7", - "vue-router": "^4.1.5" + "vue-router": "^4.1.6" }, "devDependencies": { "@graphql-codegen/cli": "^2.13.12", diff --git a/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue b/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue index 415d14d3..7d8e1c08 100644 --- a/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue +++ b/client/src/pages/learningPath/learningContentPage/assignment/AssignmentView.vue @@ -14,6 +14,7 @@ import type { CourseSessionUser, LearningContent, } from "@/types"; +import { useRouteQuery } from "@vueuse/router"; import dayjs from "dayjs"; import * as log from "loglevel"; import { computed, onMounted, reactive } from "vue"; @@ -27,14 +28,11 @@ const userStore = useUserStore(); interface State { assignment: Assignment | undefined; courseSessionAssignmentDetails: CourseSessionAssignmentDetails | undefined; - pageIndex: number; } const state: State = reactive({ assignment: undefined, courseSessionAssignmentDetails: undefined, - // 0 = introduction, 1 - n = tasks, n+1 = submission - pageIndex: 0, }); const props = defineProps<{ @@ -42,6 +40,9 @@ const props = defineProps<{ learningContent: LearningContent; }>(); +// 0 = introduction, 1 - n = tasks, n+1 = submission +const pageIndex = useRouteQuery("page", "0", { transform: Number, mode: "push" }); + const assignmentCompletion = computed(() => assignmentStore.assignmentCompletion); const completionStatus = computed(() => { return assignmentCompletion.value?.completion_status ?? "in_progress"; @@ -62,10 +63,11 @@ onMounted(async () => { courseSessionId.value ); - if (completionStatus.value === "in_progress") { - state.pageIndex = 0; - } else { - state.pageIndex = numPages.value - 1; + if ( + pageIndex.value === 0 && + (completionStatus.value ?? "in_progress") !== "in_progress" + ) { + pageIndex.value = numPages.value - 1; } } catch (error) { log.error(error); @@ -74,9 +76,9 @@ onMounted(async () => { const numTasks = computed(() => state.assignment?.tasks?.length ?? 0); const numPages = computed(() => numTasks.value + 2); -const showPreviousButton = computed(() => state.pageIndex != 0); -const showNextButton = computed(() => state.pageIndex + 1 < numPages.value); -const showExitButton = computed(() => numPages.value === state.pageIndex + 1); +const showPreviousButton = computed(() => pageIndex.value != 0); +const showNextButton = computed(() => pageIndex.value + 1 < numPages.value); +const showExitButton = computed(() => numPages.value === pageIndex.value + 1); const dueDate = computed(() => dayjs(state.courseSessionAssignmentDetails?.submissionDeadlineDateTimeUtc) ); @@ -84,41 +86,41 @@ const courseSessionId = computed( () => courseSessionsStore.currentCourseSession?.id ?? 0 ); const currentTask = computed(() => { - if (state.pageIndex > 0 && state.pageIndex <= numTasks.value) { - return state.assignment?.tasks[state.pageIndex - 1]; + if (pageIndex.value > 0 && pageIndex.value <= numTasks.value) { + return state.assignment?.tasks[pageIndex.value - 1]; } return undefined; }); const handleBack = () => { log.debug("handleBack"); - if (state.pageIndex > 0) { - state.pageIndex -= 1; + if (pageIndex.value > 0) { + pageIndex.value -= 1; } - log.debug(`pageIndex: ${state.pageIndex}`); + log.debug(`pageIndex: ${pageIndex.value}`); }; const handleContinue = () => { log.debug("handleContinue"); - if (state.pageIndex + 1 < numPages.value) { - state.pageIndex += 1; + if (pageIndex.value + 1 < numPages.value) { + pageIndex.value += 1; } - log.debug(`pageIndex: ${state.pageIndex}`); + log.debug(`pageIndex: ${pageIndex.value}`); }; const jumpToTask = (task: AssignmentTask) => { log.debug("jumpToTask", task); const index = state.assignment?.tasks.findIndex((t) => t.id === task.id); if (index && index >= 0) { - state.pageIndex = index + 1; + pageIndex.value = index + 1; } - log.debug(`pageIndex: ${state.pageIndex}`); + log.debug(`pageIndex: ${pageIndex.value}`); }; const getTitle = () => { - if (0 === state.pageIndex) { + if (0 === pageIndex.value) { return t("general.introduction"); - } else if (state.pageIndex === numPages.value - 1) { + } else if (pageIndex.value === numPages.value - 1) { return t("general.submission"); } return currentTask?.value?.value.title ?? "Unknown"; @@ -135,7 +137,7 @@ const assignmentUser = computed(() => {
{
@@ -163,9 +165,7 @@ const assignmentUser = computed(() => { :assignment-id="props.assignmentId" >