Refactor loading of course sessions

This commit is contained in:
Daniel Egger 2023-05-16 14:16:39 +02:00
parent c0407803fc
commit 44131f1d8b
5 changed files with 36 additions and 48 deletions

View File

@ -0,0 +1,16 @@
import { useCourseSessionsStore } from "@/stores/courseSessions";
import type { CourseSession } from "@/types";
import { computed } from "vue";
export function useCurrentCourseSession(): CourseSession {
const store = useCourseSessionsStore();
const currentCourseSession = computed(() => store.currentCourseSession);
// This will always return a defined value, but you should still handle the case where currentCourseSession is undefined in the store.
if (!currentCourseSession.value) {
throw new Error("currentCourseSession is not defined in the store");
} else {
// return a non-reactive copy of the value
return currentCourseSession.value;
}
}

View File

@ -1,7 +1,6 @@
import DashboardPage from "@/pages/DashboardPage.vue"; import DashboardPage from "@/pages/DashboardPage.vue";
import LoginPage from "@/pages/LoginPage.vue"; import LoginPage from "@/pages/LoginPage.vue";
import { redirectToLoginIfRequired, updateLoggedIn } from "@/router/guards"; import { redirectToLoginIfRequired, updateLoggedIn } from "@/router/guards";
import { useAppStore } from "@/stores/app";
import { useCourseSessionsStore } from "@/stores/courseSessions"; import { useCourseSessionsStore } from "@/stores/courseSessions";
import { createRouter, createWebHistory } from "vue-router"; import { createRouter, createWebHistory } from "vue-router";
@ -182,18 +181,19 @@ const router = createRouter({
router.beforeEach(updateLoggedIn); router.beforeEach(updateLoggedIn);
router.beforeEach(redirectToLoginIfRequired); router.beforeEach(redirectToLoginIfRequired);
router.beforeEach((to) => { router.beforeEach(async (to) => {
// register after login hooks
const courseSessionsStore = useCourseSessionsStore(); const courseSessionsStore = useCourseSessionsStore();
if (to.params.courseSlug) { if (to.params.courseSlug) {
courseSessionsStore._currentCourseSlug = to.params.courseSlug as string; courseSessionsStore._currentCourseSlug = to.params.courseSlug as string;
if (!courseSessionsStore.loaded) {
await courseSessionsStore.loadCourseSessionsData();
}
} else { } else {
courseSessionsStore._currentCourseSlug = ""; courseSessionsStore._currentCourseSlug = "";
// load async
courseSessionsStore.loadCourseSessionsData();
} }
}); });
router.afterEach(() => {
const appStore = useAppStore();
appStore.routingFinished = true;
});
export default router; export default router;

View File

@ -1,17 +0,0 @@
import { defineStore } from "pinia";
export type AppState = {
userLoaded: boolean;
routingFinished: boolean;
};
export const useAppStore = defineStore({
id: "app",
state: () =>
({
userLoaded: false,
routingFinished: false,
} as AppState),
getters: {},
actions: {},
});

View File

@ -25,12 +25,14 @@ export type LearningSequenceCircleDocument = {
const SELECTED_COURSE_SESSIONS_KEY = "selectedCourseSessionMap"; const SELECTED_COURSE_SESSIONS_KEY = "selectedCourseSessionMap";
function loadCourseSessionsData(reload = false) { export const useCourseSessionsStore = defineStore("courseSessions", () => {
log.debug("loadCourseSessionsData called"); const loaded = ref(false);
const courseSessions = ref<CourseSession[]>([]); const allCourseSessions = ref<CourseSession[]>([]);
async function loadAndUpdate() { async function loadCourseSessionsData(reload = false) {
courseSessions.value = await itGetCached(`/api/course/sessions/`, { log.debug("loadCourseSessionsData called");
allCourseSessions.value = await itGetCached(`/api/course/sessions/`, {
reload: reload, reload: reload,
}); });
@ -38,7 +40,7 @@ function loadCourseSessionsData(reload = false) {
if (userStore.loggedIn) { if (userStore.loggedIn) {
// TODO: refactor after implementing of Klassenkonzept // TODO: refactor after implementing of Klassenkonzept
await Promise.all( await Promise.all(
courseSessions.value.map(async (cs) => { allCourseSessions.value.map(async (cs) => {
const users = (await itGetCached(`/api/course/sessions/${cs.id}/users/`, { const users = (await itGetCached(`/api/course/sessions/${cs.id}/users/`, {
reload: reload, reload: reload,
})) as CourseSessionUser[]; })) as CourseSessionUser[];
@ -46,26 +48,14 @@ function loadCourseSessionsData(reload = false) {
}) })
); );
if (!courseSessions.value) { if (!allCourseSessions.value) {
throw `No courseSessionData found for user`; throw `No courseSessionData found for user`;
} }
} }
loaded.value = true;
} }
loadAndUpdate(); // this will be called asynchronously, but does not block
// returns the empty sessions array at first, then after loading populates the ref
return { allCourseSessions: courseSessions };
}
export const useCourseSessionsStore = defineStore("courseSessions", () => {
// using setup function seems cleaner, see https://pinia.vuejs.org/core-concepts/#setup-stores
// this will become a state variable (like each other `ref()`
// store should do own setup, we don't want to have each component initialize it
// that's why we call the load function in here
const { allCourseSessions } = loadCourseSessionsData();
const selectedCourseSessionMap = useLocalStorage( const selectedCourseSessionMap = useLocalStorage(
SELECTED_COURSE_SESSIONS_KEY, SELECTED_COURSE_SESSIONS_KEY,
new Map<string, number>() new Map<string, number>()
@ -259,6 +249,8 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
findAssignmentDetails, findAssignmentDetails,
// only used so that `router.afterEach` can switch it // only used so that `router.afterEach` can switch it
loadCourseSessionsData,
loaded,
_currentCourseSlug, _currentCourseSlug,
// only used for unit testing // only used for unit testing

View File

@ -2,7 +2,6 @@ import log from "loglevel";
import { bustItGetCache, itGetCached, itPost } from "@/fetchHelpers"; import { bustItGetCache, itGetCached, itPost } from "@/fetchHelpers";
import { loadLocaleMessages, setI18nLanguage } from "@/i18n"; import { loadLocaleMessages, setI18nLanguage } from "@/i18n";
import { useAppStore } from "@/stores/app";
import { defineStore } from "pinia"; import { defineStore } from "pinia";
const logoutRedirectUrl = import.meta.env.VITE_LOGOUT_REDIRECT || "/"; const logoutRedirectUrl = import.meta.env.VITE_LOGOUT_REDIRECT || "/";
@ -85,11 +84,9 @@ export const useUserStore = defineStore({
}); });
}, },
async fetchUser() { async fetchUser() {
const appStore = useAppStore();
const data = await itGetCached("/api/core/me/"); const data = await itGetCached("/api/core/me/");
this.$state = data; this.$state = data;
this.loggedIn = true; this.loggedIn = true;
appStore.userLoaded = true;
await setLocale(data.language); await setLocale(data.language);
}, },
async setUserLanguages(language: AvailableLanguages) { async setUserLanguages(language: AvailableLanguages) {