fix(backend): Diverse bugfixes omtrent LearningPathPage
This commit is contained in:
parent
27b9cdf833
commit
12b9f31f5f
9 changed files with 34 additions and 33 deletions
|
@ -1,6 +1,5 @@
|
|||
<script setup lang="ts" generic="T">
|
||||
import {RemoteResource} from "@/services/api-client/remote-resource.ts";
|
||||
import {computed, type MaybeRefOrGetter} from "vue";
|
||||
import {computed} from "vue";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import type {UseQueryReturnType} from "@tanstack/vue-query";
|
||||
|
||||
|
@ -8,13 +7,12 @@
|
|||
queryResult: UseQueryReturnType<T, Error>
|
||||
}>()
|
||||
|
||||
const { isLoading, isError, isSuccess, data, error } = props.queryResult;
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const isLoading = computed(() => props.queryResult.isFetching);
|
||||
const data = computed(() => props.queryResult.data);
|
||||
const error = computed(() => props.queryResult.error);
|
||||
const errorMessage = computed(() => {
|
||||
let errorWithMessage = (error.value as {message: string}) || null;
|
||||
let errorWithMessage = (error as {message: string}) || null;
|
||||
return errorWithMessage?.message || JSON.stringify(errorWithMessage)
|
||||
});
|
||||
</script>
|
||||
|
@ -23,14 +21,14 @@
|
|||
<div class="loading-div" v-if="isLoading">
|
||||
<v-progress-circular indeterminate></v-progress-circular>
|
||||
</div>
|
||||
<div v-if="error">
|
||||
<div v-if="isError">
|
||||
<v-empty-state
|
||||
icon="mdi-alert-circle-outline"
|
||||
:text="errorMessage"
|
||||
:title="t('error_title')"
|
||||
></v-empty-state>
|
||||
</div>
|
||||
<slot v-if="data" :data="data!"></slot>
|
||||
<slot v-if="isSuccess && data" :data="data"></slot>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -1,41 +1,47 @@
|
|||
import { apiConfig } from "@/config.ts";
|
||||
import apiClient from "@/services/api-client/api-client.ts";
|
||||
import type {AxiosResponse, ResponseType} from "axios";
|
||||
import {HttpErrorResponseException} from "@/exception/http-error-response-exception.ts";
|
||||
|
||||
export abstract class BaseController {
|
||||
protected baseUrl: string;
|
||||
protected basePath: string;
|
||||
|
||||
protected constructor(basePath: string) {
|
||||
this.baseUrl = `${apiConfig.baseUrl}/${basePath}`;
|
||||
this.basePath = basePath;
|
||||
}
|
||||
|
||||
private assertSuccessResponse(response: AxiosResponse<unknown, unknown>) {
|
||||
if (response.status / 200 !== 2) {
|
||||
if (response.status / 100 !== 2) {
|
||||
throw new HttpErrorResponseException(response);
|
||||
}
|
||||
}
|
||||
|
||||
private absolutePathFor(path: string) {
|
||||
return "/" + this.basePath + path;
|
||||
}
|
||||
|
||||
protected async get<T>(path: string, queryParams?: Record<string, any>, responseType?: ResponseType): Promise<T> {
|
||||
let response = await apiClient.get<T>(path, {params: queryParams, responseType});
|
||||
let response = await apiClient.get<T>(
|
||||
this.absolutePathFor(path),
|
||||
{params: queryParams, responseType}
|
||||
);
|
||||
this.assertSuccessResponse(response);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
protected async post<T>(path: string, body: unknown): Promise<T> {
|
||||
let response = await apiClient.post<T>(path, body);
|
||||
let response = await apiClient.post<T>(this.absolutePathFor(path), body);
|
||||
this.assertSuccessResponse(response);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
protected async delete<T>(path: string): Promise<T> {
|
||||
let response = await apiClient.delete<T>(path)
|
||||
let response = await apiClient.delete<T>(this.absolutePathFor(path))
|
||||
this.assertSuccessResponse(response);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
protected async put<T>(path: string, body: unknown): Promise<T> {
|
||||
let response = await apiClient.put<T>(path, body);
|
||||
let response = await apiClient.put<T>(this.absolutePathFor(path), body);
|
||||
this.assertSuccessResponse(response);
|
||||
return response.data;
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@ export class LearningObjectController extends BaseController {
|
|||
}
|
||||
|
||||
async getMetadata(hruid: string, language: Language, version: number): Promise<LearningObject> {
|
||||
return this.get<LearningObject>(`/learningObject/${hruid}`, {language, version});
|
||||
return this.get<LearningObject>(`/${hruid}`, {language, version});
|
||||
}
|
||||
|
||||
async getHTML(hruid: string, language: Language, version: number): Promise<Document> {
|
||||
return this.get<Document>(`/learningObject/${hruid}/html`, {language, version}, "document");
|
||||
return this.get<Document>(`/${hruid}/html`, {language, version}, "document");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import {BaseController} from "@/controllers/base-controller.ts";
|
|||
import {LearningPath} from "@/data-objects/learning-path.ts";
|
||||
import type {LearningPathDTO} from "@/data-objects/learning-path.ts";
|
||||
import type {Language} from "@/data-objects/language.ts";
|
||||
import {single} from "@/utils/response-assertions.ts";
|
||||
|
||||
export class LearningPathController extends BaseController {
|
||||
constructor() {
|
||||
|
@ -18,6 +19,6 @@ export class LearningPathController extends BaseController {
|
|||
forGroup: options?.forGroup,
|
||||
forStudent: options?.forStudent
|
||||
});
|
||||
return dtos.map(dto => LearningPath.fromDTO(dto))
|
||||
return LearningPath.fromDTO(single(dtos));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import type {AxiosResponse} from "axios";
|
||||
|
||||
export class HttpErrorResponseException extends Error {
|
||||
public statusCode: number;
|
||||
constructor(public response: AxiosResponse<unknown, unknown>) {
|
||||
super(response.statusText);
|
||||
super((response.data as {message: string})?.message || JSON.stringify(response.data));
|
||||
this.statusCode = response.status;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,10 +47,10 @@ export function useLearningObjectListForPathQuery(
|
|||
let learningObjects = [];
|
||||
for (let node of toValue(learningPath).nodesAsList) {
|
||||
learningObjects.push(
|
||||
learningObjectController.getHTML(node.learningobjectHruid, node.language, node.version)
|
||||
learningObjectController.getMetadata(node.learningobjectHruid, node.language, node.version)
|
||||
);
|
||||
}
|
||||
return learningObjects;
|
||||
return Promise.all(learningObjects);
|
||||
},
|
||||
enabled: () => Boolean(toValue(learningPath)),
|
||||
});
|
||||
|
|
|
@ -12,7 +12,6 @@ import UserClasses from "@/views/classes/UserClasses.vue";
|
|||
import UserAssignments from "@/views/classes/UserAssignments.vue";
|
||||
import authState from "@/services/auth/auth-service.ts";
|
||||
import LearningPathPage from "@/views/learning-paths/LearningPathPage.vue";
|
||||
import path from "path";
|
||||
import LearningPathSearchPage from "@/views/learning-paths/LearningPathSearchPage.vue";
|
||||
import UserHomePage from "@/views/homepage/UserHomePage.vue";
|
||||
import SingleTheme from "@/views/SingleTheme.vue";
|
||||
|
@ -109,16 +108,15 @@ const router = createRouter({
|
|||
},
|
||||
{
|
||||
path: "/learningPath",
|
||||
component: MenuBar,
|
||||
children: [
|
||||
{
|
||||
path: "/search",
|
||||
path: "search",
|
||||
name: "LearningPathSearchPage",
|
||||
component: LearningPathSearchPage,
|
||||
meta: { requiresAuth: true }
|
||||
},
|
||||
{
|
||||
path: "/:hruid/:language",
|
||||
path: ":hruid/:language",
|
||||
name: "LearningPath",
|
||||
component: LearningPathPage,
|
||||
props: true,
|
||||
|
|
|
@ -6,7 +6,7 @@ import UsingQueryResult from "@/components/UsingQueryResult.vue";
|
|||
|
||||
const props = defineProps<{hruid: string, language: Language, version: number}>()
|
||||
|
||||
const learningObjectHtmlQueryResult: UseQueryReturnType<Document, Error> = useLearningObjectHTMLQuery(props.hruid, props.language, props.version);
|
||||
const learningObjectHtmlQueryResult: UseQueryReturnType<Document, Error> = useLearningObjectHTMLQuery(() => props.hruid, () => props.language, () => props.version);
|
||||
|
||||
</script>
|
||||
|
||||
|
|
|
@ -27,10 +27,10 @@
|
|||
|
||||
const learningPathQueryResult = useGetLearningPathQuery(props.hruid, props.language, typedQuery.value);
|
||||
|
||||
const learningObjectListQueryResult = useLearningObjectListForPathQuery(learningPathQueryResult.data.value);
|
||||
const learningObjectListQueryResult = useLearningObjectListForPathQuery(learningPathQueryResult.data);
|
||||
|
||||
const nodesList: ComputedRef<LearningPathNode[] | null> = computed(() =>
|
||||
(!learningPathQueryResult.isPending && !learningPathQueryResult.isError) ? learningPathQueryResult.data.value?.nodesAsList : null
|
||||
learningPathQueryResult.isSuccess ? learningPathQueryResult.data.value?.nodesAsList : null
|
||||
);
|
||||
|
||||
const currentNode = computed(() => {
|
||||
|
@ -107,7 +107,6 @@
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<v-main>
|
||||
<using-query-result
|
||||
:query-result="learningPathQueryResult"
|
||||
v-slot="learningPath: {data: LearningPath}"
|
||||
|
@ -125,7 +124,6 @@
|
|||
</template>
|
||||
</v-list-item>
|
||||
<v-divider></v-divider>
|
||||
|
||||
<div v-if="props.learningObjectHruid">
|
||||
<using-query-result
|
||||
:query-result="learningObjectListQueryResult"
|
||||
|
@ -160,7 +158,6 @@
|
|||
<learning-path-search-field></learning-path-search-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<learning-object-view
|
||||
:hruid="currentNode.learningobjectHruid"
|
||||
:language="currentNode.language"
|
||||
|
@ -186,7 +183,6 @@
|
|||
</v-btn>
|
||||
</div>
|
||||
</using-query-result>
|
||||
</v-main>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue