Use query param to store page index

This commit is contained in:
Daniel Egger 2023-05-09 07:56:38 +02:00
parent 089d41ee76
commit 7217424fdc
3 changed files with 82 additions and 35 deletions

View File

@ -14,6 +14,7 @@
"@sentry/vue": "^7.20.0", "@sentry/vue": "^7.20.0",
"@urql/vue": "^1.0.2", "@urql/vue": "^1.0.2",
"@vueuse/core": "^9.13.0", "@vueuse/core": "^9.13.0",
"@vueuse/router": "^10.1.2",
"cypress": "^12.9.0", "cypress": "^12.9.0",
"d3": "^7.6.1", "d3": "^7.6.1",
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
@ -25,7 +26,7 @@
"vue": "^3.2.38", "vue": "^3.2.38",
"vue-i18n": "^9.2.2", "vue-i18n": "^9.2.2",
"vue-i18n-extract": "^2.0.7", "vue-i18n-extract": "^2.0.7",
"vue-router": "^4.1.5" "vue-router": "^4.1.6"
}, },
"devDependencies": { "devDependencies": {
"@graphql-codegen/cli": "^2.13.12", "@graphql-codegen/cli": "^2.13.12",
@ -7489,6 +7490,32 @@
"url": "https://github.com/sponsors/antfu" "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": { "node_modules/@vueuse/shared": {
"version": "9.13.0", "version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz",
@ -18979,9 +19006,9 @@
} }
}, },
"node_modules/vue-demi": { "node_modules/vue-demi": {
"version": "0.13.11", "version": "0.14.0",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", "integrity": "sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg==",
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-fix": "bin/vue-demi-fix.js",
@ -25294,6 +25321,25 @@
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==" "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": { "@vueuse/shared": {
"version": "9.13.0", "version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz",
@ -33879,9 +33925,9 @@
} }
}, },
"vue-demi": { "vue-demi": {
"version": "0.13.11", "version": "0.14.0",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==" "integrity": "sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg=="
}, },
"vue-docgen-api": { "vue-docgen-api": {
"version": "4.64.1", "version": "4.64.1",

View File

@ -25,6 +25,7 @@
"@sentry/vue": "^7.20.0", "@sentry/vue": "^7.20.0",
"@urql/vue": "^1.0.2", "@urql/vue": "^1.0.2",
"@vueuse/core": "^9.13.0", "@vueuse/core": "^9.13.0",
"@vueuse/router": "^10.1.2",
"cypress": "^12.9.0", "cypress": "^12.9.0",
"d3": "^7.6.1", "d3": "^7.6.1",
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
@ -36,7 +37,7 @@
"vue": "^3.2.38", "vue": "^3.2.38",
"vue-i18n": "^9.2.2", "vue-i18n": "^9.2.2",
"vue-i18n-extract": "^2.0.7", "vue-i18n-extract": "^2.0.7",
"vue-router": "^4.1.5" "vue-router": "^4.1.6"
}, },
"devDependencies": { "devDependencies": {
"@graphql-codegen/cli": "^2.13.12", "@graphql-codegen/cli": "^2.13.12",

View File

@ -14,6 +14,7 @@ import type {
CourseSessionUser, CourseSessionUser,
LearningContent, LearningContent,
} from "@/types"; } from "@/types";
import { useRouteQuery } from "@vueuse/router";
import dayjs from "dayjs"; import dayjs from "dayjs";
import * as log from "loglevel"; import * as log from "loglevel";
import { computed, onMounted, reactive } from "vue"; import { computed, onMounted, reactive } from "vue";
@ -27,14 +28,11 @@ const userStore = useUserStore();
interface State { interface State {
assignment: Assignment | undefined; assignment: Assignment | undefined;
courseSessionAssignmentDetails: CourseSessionAssignmentDetails | undefined; courseSessionAssignmentDetails: CourseSessionAssignmentDetails | undefined;
pageIndex: number;
} }
const state: State = reactive({ const state: State = reactive({
assignment: undefined, assignment: undefined,
courseSessionAssignmentDetails: undefined, courseSessionAssignmentDetails: undefined,
// 0 = introduction, 1 - n = tasks, n+1 = submission
pageIndex: 0,
}); });
const props = defineProps<{ const props = defineProps<{
@ -42,6 +40,9 @@ const props = defineProps<{
learningContent: LearningContent; 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 assignmentCompletion = computed(() => assignmentStore.assignmentCompletion);
const completionStatus = computed(() => { const completionStatus = computed(() => {
return assignmentCompletion.value?.completion_status ?? "in_progress"; return assignmentCompletion.value?.completion_status ?? "in_progress";
@ -62,10 +63,11 @@ onMounted(async () => {
courseSessionId.value courseSessionId.value
); );
if (completionStatus.value === "in_progress") { if (
state.pageIndex = 0; pageIndex.value === 0 &&
} else { (completionStatus.value ?? "in_progress") !== "in_progress"
state.pageIndex = numPages.value - 1; ) {
pageIndex.value = numPages.value - 1;
} }
} catch (error) { } catch (error) {
log.error(error); log.error(error);
@ -74,9 +76,9 @@ onMounted(async () => {
const numTasks = computed(() => state.assignment?.tasks?.length ?? 0); const numTasks = computed(() => state.assignment?.tasks?.length ?? 0);
const numPages = computed(() => numTasks.value + 2); const numPages = computed(() => numTasks.value + 2);
const showPreviousButton = computed(() => state.pageIndex != 0); const showPreviousButton = computed(() => pageIndex.value != 0);
const showNextButton = computed(() => state.pageIndex + 1 < numPages.value); const showNextButton = computed(() => pageIndex.value + 1 < numPages.value);
const showExitButton = computed(() => numPages.value === state.pageIndex + 1); const showExitButton = computed(() => numPages.value === pageIndex.value + 1);
const dueDate = computed(() => const dueDate = computed(() =>
dayjs(state.courseSessionAssignmentDetails?.submissionDeadlineDateTimeUtc) dayjs(state.courseSessionAssignmentDetails?.submissionDeadlineDateTimeUtc)
); );
@ -84,41 +86,41 @@ const courseSessionId = computed(
() => courseSessionsStore.currentCourseSession?.id ?? 0 () => courseSessionsStore.currentCourseSession?.id ?? 0
); );
const currentTask = computed(() => { const currentTask = computed(() => {
if (state.pageIndex > 0 && state.pageIndex <= numTasks.value) { if (pageIndex.value > 0 && pageIndex.value <= numTasks.value) {
return state.assignment?.tasks[state.pageIndex - 1]; return state.assignment?.tasks[pageIndex.value - 1];
} }
return undefined; return undefined;
}); });
const handleBack = () => { const handleBack = () => {
log.debug("handleBack"); log.debug("handleBack");
if (state.pageIndex > 0) { if (pageIndex.value > 0) {
state.pageIndex -= 1; pageIndex.value -= 1;
} }
log.debug(`pageIndex: ${state.pageIndex}`); log.debug(`pageIndex: ${pageIndex.value}`);
}; };
const handleContinue = () => { const handleContinue = () => {
log.debug("handleContinue"); log.debug("handleContinue");
if (state.pageIndex + 1 < numPages.value) { if (pageIndex.value + 1 < numPages.value) {
state.pageIndex += 1; pageIndex.value += 1;
} }
log.debug(`pageIndex: ${state.pageIndex}`); log.debug(`pageIndex: ${pageIndex.value}`);
}; };
const jumpToTask = (task: AssignmentTask) => { const jumpToTask = (task: AssignmentTask) => {
log.debug("jumpToTask", task); log.debug("jumpToTask", task);
const index = state.assignment?.tasks.findIndex((t) => t.id === task.id); const index = state.assignment?.tasks.findIndex((t) => t.id === task.id);
if (index && index >= 0) { if (index && index >= 0) {
state.pageIndex = index + 1; pageIndex.value = index + 1;
} }
log.debug(`pageIndex: ${state.pageIndex}`); log.debug(`pageIndex: ${pageIndex.value}`);
}; };
const getTitle = () => { const getTitle = () => {
if (0 === state.pageIndex) { if (0 === pageIndex.value) {
return t("general.introduction"); return t("general.introduction");
} else if (state.pageIndex === numPages.value - 1) { } else if (pageIndex.value === numPages.value - 1) {
return t("general.submission"); return t("general.submission");
} }
return currentTask?.value?.value.title ?? "Unknown"; return currentTask?.value?.value.title ?? "Unknown";
@ -135,7 +137,7 @@ const assignmentUser = computed(() => {
<div v-if="state.assignment"> <div v-if="state.assignment">
<div class="flex"> <div class="flex">
<LearningContentMultiLayout <LearningContentMultiLayout
:current-step="state.pageIndex" :current-step="pageIndex"
:subtitle="state.assignment?.title ?? ''" :subtitle="state.assignment?.title ?? ''"
:title="getTitle()" :title="getTitle()"
learning-content-type="assignment" learning-content-type="assignment"
@ -153,7 +155,7 @@ const assignmentUser = computed(() => {
<div class="flex"> <div class="flex">
<div> <div>
<AssignmentIntroductionView <AssignmentIntroductionView
v-if="state.pageIndex === 0 && state.assignment" v-if="pageIndex === 0 && state.assignment"
:due-date="dueDate" :due-date="dueDate"
:assignment="state.assignment!" :assignment="state.assignment!"
></AssignmentIntroductionView> ></AssignmentIntroductionView>
@ -163,9 +165,7 @@ const assignmentUser = computed(() => {
:assignment-id="props.assignmentId" :assignment-id="props.assignmentId"
></AssignmentTaskView> ></AssignmentTaskView>
<AssignmentSubmissionView <AssignmentSubmissionView
v-if=" v-if="pageIndex + 1 === numPages && state.assignment && courseSessionId"
state.pageIndex + 1 === numPages && state.assignment && courseSessionId
"
:due-date="dueDate" :due-date="dueDate"
:assignment="state.assignment!" :assignment="state.assignment!"
:assignment-completion-data="assignmentCompletion?.completion_data ?? {}" :assignment-completion-data="assignmentCompletion?.completion_data ?? {}"