feat(frontend): Functionaliteit om leerobjecten te tonen toegevoegd.
Hiervoor ook de state management geherstructureerd.
This commit is contained in:
parent
07340de2e3
commit
728b04c9d8
12 changed files with 141 additions and 150 deletions
|
@ -1,32 +1,22 @@
|
||||||
<script setup lang="ts" generic="T">
|
<script setup lang="ts" generic="T">
|
||||||
import {type ErrorState, RemoteResource, type RemoteResourceState} from "@/services/api-client/remote-resource.ts";
|
import {RemoteResource} from "@/services/api-client/remote-resource.ts";
|
||||||
import {computed, onMounted, reactive, ref, type UnwrapNestedRefs, watch} from "vue";
|
import {computed} from "vue";
|
||||||
import {useI18n} from "vue-i18n";
|
import {useI18n} from "vue-i18n";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
resource: RemoteResource<T> | (UnwrapNestedRefs<RemoteResource<T>> & {})
|
resource: RemoteResource<T>
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const resource = reactive(props.resource as RemoteResource<T>);
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const isLoading = computed(() => resource.state.type === 'loading');
|
const isLoading = computed(() => props.resource.state.type === 'loading');
|
||||||
const isError = computed(() => resource.state.type === 'error');
|
const isError = computed(() => props.resource.state.type === 'error');
|
||||||
|
const data = computed(() => props.resource.state.type === 'success' ? props.resource.state.data : null);
|
||||||
|
|
||||||
// `data` will be correctly inferred as `T`
|
const error = computed(() => props.resource.state.type === "error" ? props.resource.state : null);
|
||||||
const data = computed(() => resource.data);
|
|
||||||
|
|
||||||
const error = computed(() => resource.state.type === "error" ? resource.state as ErrorState : null);
|
|
||||||
const errorMessage = computed(() =>
|
const errorMessage = computed(() =>
|
||||||
error.value?.message ? error.value.message : JSON.stringify(error.value?.error)
|
error.value?.error.message ? error.value.error.message : JSON.stringify(error.value?.error)
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(data, (newValue, _) => {
|
|
||||||
if (!newValue && resource.state.type !== "loading") {
|
|
||||||
(resource as RemoteResource<T>).startRequestInBackground();
|
|
||||||
}
|
|
||||||
}, {immediate: true});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -46,6 +36,5 @@ import {computed, onMounted, reactive, ref, type UnwrapNestedRefs, watch} from "
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.loading-div {
|
.loading-div {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 10px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
|
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
|
||||||
import {RemoteResource} from "@/services/api-client/remote-resource.ts";
|
|
||||||
|
|
||||||
export class DeleteEndpoint<PP extends Params, QP extends Params, R> extends RestEndpoint<PP, QP, undefined, R> {
|
export class DeleteEndpoint<PP extends Params, QP extends Params, R> extends RestEndpoint<PP, QP, undefined, R> {
|
||||||
readonly method = "GET";
|
readonly method = "GET";
|
||||||
|
|
||||||
public delete(pathParams: PP, queryParams: QP): RemoteResource<R> {
|
public delete(pathParams: PP, queryParams: QP): Promise<R> {
|
||||||
return super.request(pathParams, queryParams, undefined);
|
return super.request(pathParams, queryParams, undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
|
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
|
||||||
import {RemoteResource} from "@/services/api-client/remote-resource.ts";
|
|
||||||
|
|
||||||
export class GetEndpoint<PP extends Params, QP extends Params, R> extends RestEndpoint<PP, QP, undefined, R> {
|
export class GetEndpoint<PP extends Params, QP extends Params, R> extends RestEndpoint<PP, QP, undefined, R> {
|
||||||
readonly method = "GET";
|
readonly method = "GET";
|
||||||
|
|
||||||
public get(pathParams: PP, queryParams: QP): RemoteResource<R> {
|
public get(pathParams: PP, queryParams: QP): Promise<R> {
|
||||||
return super.request(pathParams, queryParams, undefined);
|
return super.request(pathParams, queryParams, undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
|
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
|
||||||
import {RemoteResource} from "@/services/api-client/remote-resource.ts";
|
|
||||||
|
|
||||||
export class GetHtmlEndpoint<PP extends Params, QP extends Params> extends RestEndpoint<PP, QP, undefined, Document> {
|
export class GetHtmlEndpoint<PP extends Params, QP extends Params> extends RestEndpoint<PP, QP, undefined, Document> {
|
||||||
readonly method: "GET" | "POST" | "PUT" | "DELETE" = "GET";
|
readonly method: "GET" | "POST" | "PUT" | "DELETE" = "GET";
|
||||||
|
|
||||||
public get(pathParams: PP, queryParams: QP): RemoteResource<Document> {
|
public get(pathParams: PP, queryParams: QP): Promise<Document> {
|
||||||
return super.request(pathParams, queryParams, undefined, "document");
|
return super.request(pathParams, queryParams, undefined, "document");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
|
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
|
||||||
import {RemoteResource} from "@/services/api-client/remote-resource.ts";
|
|
||||||
|
|
||||||
export class PostEndpoint<PP extends Params, QP extends Params, B, R> extends RestEndpoint<PP, QP, B, R> {
|
export class PostEndpoint<PP extends Params, QP extends Params, B, R> extends RestEndpoint<PP, QP, B, R> {
|
||||||
readonly method = "POST";
|
readonly method = "POST";
|
||||||
|
|
||||||
public post(pathParams: PP, queryParams: QP, body: B): RemoteResource<R> {
|
public post(pathParams: PP, queryParams: QP, body: B): Promise<R> {
|
||||||
return super.request(pathParams, queryParams, body);
|
return super.request(pathParams, queryParams, body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import {RemoteResource} from "@/services/api-client/remote-resource.ts";
|
|
||||||
import apiClient from "@/services/api-client/api-client.ts";
|
import apiClient from "@/services/api-client/api-client.ts";
|
||||||
import {HttpErrorStatusException} from "@/services/api-client/api-exceptions.ts";
|
import {HttpErrorStatusException} from "@/services/api-client/api-exceptions.ts";
|
||||||
import type {ResponseType} from "axios";
|
import type {ResponseType} from "axios";
|
||||||
|
@ -8,15 +7,10 @@ export abstract class RestEndpoint<PP extends Params, QP extends Params, B, R> {
|
||||||
constructor(public readonly url: string) {
|
constructor(public readonly url: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected request(pathParams: PP, queryParams: QP, body: B, responseType?: ResponseType): RemoteResource<R> {
|
protected async request(pathParams: PP, queryParams: QP, body: B, responseType?: ResponseType): Promise<R> {
|
||||||
let urlFilledIn = this.url.replace(/:(\w+)(\/|$)/g, (_, key, after) =>
|
let urlFilledIn = this.url.replace(/:(\w+)(\/|$)/g, (_, key, after) =>
|
||||||
(pathParams[key] ? encodeURIComponent(pathParams[key]) : `:${key}`) + after
|
(pathParams[key] ? encodeURIComponent(pathParams[key]) : `:${key}`) + after
|
||||||
);
|
);
|
||||||
console.log(this.url);
|
|
||||||
console.log(/:(\w+)(\W|$)/g.test(this.url))
|
|
||||||
console.log(pathParams);
|
|
||||||
console.log("--> filled in: " + urlFilledIn);
|
|
||||||
return new RemoteResource(async () => {
|
|
||||||
const response = await apiClient.request<R>({
|
const response = await apiClient.request<R>({
|
||||||
url: urlFilledIn,
|
url: urlFilledIn,
|
||||||
method: this.method,
|
method: this.method,
|
||||||
|
@ -28,7 +22,6 @@ export abstract class RestEndpoint<PP extends Params, QP extends Params, B, R> {
|
||||||
throw new HttpErrorStatusException(response);
|
throw new HttpErrorStatusException(response);
|
||||||
}
|
}
|
||||||
return response.data;
|
return response.data;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,78 +1,4 @@
|
||||||
export class RemoteResource<T> {
|
import {type ShallowReactive, shallowReactive} from "vue";
|
||||||
static NOT_LOADED: NotLoadedState = {type: "notLoaded"};
|
|
||||||
static LOADING: LoadingState = {type: "loading"};
|
|
||||||
|
|
||||||
private _state: RemoteResourceState<T> = RemoteResource.NOT_LOADED;
|
|
||||||
|
|
||||||
constructor(private readonly requestFn: () => Promise<T>) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static join<T>(resources: RemoteResource<T>[]): RemoteResource<T[]> {
|
|
||||||
return new RemoteResource(async () => {
|
|
||||||
console.log("joined fetch");
|
|
||||||
const promises = resources.map(it => it.request());
|
|
||||||
const data = await Promise.all(promises);
|
|
||||||
const failed = resources
|
|
||||||
.filter(it => it.state.type === "error")
|
|
||||||
.map(it => it.state as ErrorState);
|
|
||||||
if (failed.length > 0) {
|
|
||||||
console.log("joined error!");
|
|
||||||
throw failed[0].error;
|
|
||||||
}
|
|
||||||
console.log("succ");
|
|
||||||
console.log(data);
|
|
||||||
return data.map(it => it!);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async request(): Promise<T | undefined> {
|
|
||||||
this._state = RemoteResource.LOADING;
|
|
||||||
try {
|
|
||||||
let resource = await this.requestFn();
|
|
||||||
this._state = {
|
|
||||||
type: "success",
|
|
||||||
data: resource
|
|
||||||
};
|
|
||||||
return resource;
|
|
||||||
} catch (e: any) {
|
|
||||||
this._state = {
|
|
||||||
type: "error",
|
|
||||||
errorCode: e.statusCode,
|
|
||||||
message: e.message,
|
|
||||||
error: e
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public startRequestInBackground(): RemoteResource<T> {
|
|
||||||
this.request().then();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get state(): RemoteResourceState<T> {
|
|
||||||
return this._state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get data(): T | undefined {
|
|
||||||
if (this._state.type === "success") {
|
|
||||||
return this._state.data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public map<U>(mappingFn: (content: T) => U): RemoteResource<U> {
|
|
||||||
return new RemoteResource<U>(async () => {
|
|
||||||
await this.request();
|
|
||||||
if (this._state.type === "success") {
|
|
||||||
return mappingFn(this._state.data);
|
|
||||||
} else if (this._state.type === "error") {
|
|
||||||
throw this._state.error;
|
|
||||||
} else {
|
|
||||||
throw new Error("Fetched resource, but afterwards, it was neither in a success nor in an error state. " +
|
|
||||||
"This should never happen.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type NotLoadedState = {
|
export type NotLoadedState = {
|
||||||
type: "notLoaded"
|
type: "notLoaded"
|
||||||
|
@ -82,8 +8,6 @@ export type LoadingState = {
|
||||||
};
|
};
|
||||||
export type ErrorState = {
|
export type ErrorState = {
|
||||||
type: "error",
|
type: "error",
|
||||||
errorCode?: number,
|
|
||||||
message?: string,
|
|
||||||
error: any
|
error: any
|
||||||
};
|
};
|
||||||
export type SuccessState<T> = {
|
export type SuccessState<T> = {
|
||||||
|
@ -91,3 +15,23 @@ export type SuccessState<T> = {
|
||||||
data: T
|
data: T
|
||||||
};
|
};
|
||||||
export type RemoteResourceState<T> = NotLoadedState | LoadingState | ErrorState | SuccessState<T>;
|
export type RemoteResourceState<T> = NotLoadedState | LoadingState | ErrorState | SuccessState<T>;
|
||||||
|
|
||||||
|
export type RemoteResource<T> = ShallowReactive<{
|
||||||
|
state: RemoteResourceState<T>
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export function remoteResource<T>(): RemoteResource<T> {
|
||||||
|
return shallowReactive({
|
||||||
|
state: {
|
||||||
|
type: "notLoaded"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadResource<T>(resource: RemoteResource<T>, promise: Promise<T>): void {
|
||||||
|
resource.state = { type: "loading" }
|
||||||
|
promise.then(
|
||||||
|
data => resource.state = { type: "success", data },
|
||||||
|
error => resource.state = { type: "error", error }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,28 @@
|
||||||
import {GetEndpoint} from "@/services/api-client/endpoints/get-endpoint.ts";
|
import {GetEndpoint} from "@/services/api-client/endpoints/get-endpoint.ts";
|
||||||
import type {LearningObject} from "@/services/learning-content/learning-object.ts";
|
import type {LearningObject} from "@/services/learning-content/learning-object.ts";
|
||||||
import type {Language} from "@/services/learning-content/language.ts";
|
import type {Language} from "@/services/learning-content/language.ts";
|
||||||
import type {RemoteResource} from "@/services/api-client/remote-resource.ts";
|
import {GetHtmlEndpoint} from "@/services/api-client/endpoints/get-html-endpoint.ts";
|
||||||
|
|
||||||
const getLearningObjectMetadataEndpoint = new GetEndpoint<{hruid: string}, {language: Language, version: number}, LearningObject>(
|
const getLearningObjectMetadataEndpoint = new GetEndpoint<{hruid: string}, {language: Language, version: number}, LearningObject>(
|
||||||
"/learningObject/:hruid"
|
"/learningObject/:hruid"
|
||||||
);
|
);
|
||||||
|
|
||||||
export function getLearningObjectMetadata(hruid: string, language: Language, version: number): RemoteResource<LearningObject> {
|
const getLearningObjectHtmlEndpoint = new GetHtmlEndpoint<{hruid: string}, {language: Language, version: number}>(
|
||||||
return getLearningObjectMetadataEndpoint
|
"/learningObject/:hruid/html"
|
||||||
.get({hruid}, {language, version});
|
);
|
||||||
|
|
||||||
|
export function getLearningObjectMetadata(
|
||||||
|
hruid: string,
|
||||||
|
language: Language,
|
||||||
|
version: number
|
||||||
|
): Promise<LearningObject> {
|
||||||
|
return getLearningObjectMetadataEndpoint.get({hruid}, {language, version});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getLearningObjectHTML(
|
||||||
|
hruid: string,
|
||||||
|
language: Language,
|
||||||
|
version: number
|
||||||
|
): Promise<Document> {
|
||||||
|
return getLearningObjectHtmlEndpoint.get({hruid}, {language, version});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import {GetEndpoint} from "@/services/api-client/endpoints/get-endpoint.ts";
|
import {GetEndpoint} from "@/services/api-client/endpoints/get-endpoint.ts";
|
||||||
import {LearningPath, type LearningPathDTO} from "@/services/learning-content/learning-path.ts";
|
import {LearningPath, type LearningPathDTO} from "@/services/learning-content/learning-path.ts";
|
||||||
import type {RemoteResource} from "@/services/api-client/remote-resource.ts";
|
|
||||||
import type {Language} from "@/services/learning-content/language.ts";
|
import type {Language} from "@/services/learning-content/language.ts";
|
||||||
import {single} from "@/utils/response-assertions.ts";
|
import {single} from "@/utils/response-assertions.ts";
|
||||||
|
|
||||||
|
@ -8,16 +7,12 @@ const learningPathEndpoint = new GetEndpoint<{}, {search?: string, hruid?: strin
|
||||||
"/learningPath"
|
"/learningPath"
|
||||||
);
|
);
|
||||||
|
|
||||||
export function searchLearningPaths(query: string): RemoteResource<LearningPath[]> {
|
export async function searchLearningPaths(query: string): Promise<LearningPath[]> {
|
||||||
return learningPathEndpoint
|
let dtos = await learningPathEndpoint.get({}, {search: query})
|
||||||
.get({}, {search: query})
|
return dtos.map(dto => LearningPath.fromDTO(dto));
|
||||||
.map(dtos => dtos.map(dto => LearningPath.fromDTO(dto)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLearningPath(hruid: string, language: Language): RemoteResource<LearningPath> {
|
export async function getLearningPath(hruid: string, language: Language): Promise<LearningPath> {
|
||||||
console.log({hruid, language})
|
let dtos = await learningPathEndpoint.get({}, {hruid, language});
|
||||||
return learningPathEndpoint
|
return LearningPath.fromDTO(single(dtos));
|
||||||
.get({}, {hruid, language})
|
|
||||||
.map(it => {console.log(it); return it;})
|
|
||||||
.map(dtos => LearningPath.fromDTO(single(dtos)));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import type {Language} from "@/services/learning-content/language.ts";
|
import type {Language} from "@/services/learning-content/language.ts";
|
||||||
import {RemoteResource} from "@/services/api-client/remote-resource.ts";
|
|
||||||
import type {LearningObject} from "@/services/learning-content/learning-object.ts";
|
import type {LearningObject} from "@/services/learning-content/learning-object.ts";
|
||||||
import {getLearningObjectMetadata} from "@/services/learning-content/learning-object-service.ts";
|
import {getLearningObjectMetadata} from "@/services/learning-content/learning-object-service.ts";
|
||||||
|
|
||||||
|
@ -43,7 +42,6 @@ interface LearningPathTransitionDTO {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LearningPathNode {
|
export class LearningPathNode {
|
||||||
public learningObject: RemoteResource<LearningObject>
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly learningobjectHruid: string,
|
public readonly learningobjectHruid: string,
|
||||||
|
@ -53,7 +51,10 @@ export class LearningPathNode {
|
||||||
public readonly createdAt: Date,
|
public readonly createdAt: Date,
|
||||||
public readonly updatedAt: Date
|
public readonly updatedAt: Date
|
||||||
) {
|
) {
|
||||||
this.learningObject = getLearningObjectMetadata(learningobjectHruid, language, version);
|
}
|
||||||
|
|
||||||
|
get learningObject(): Promise<LearningObject> {
|
||||||
|
return getLearningObjectMetadata(this.learningobjectHruid, this.language, this.version);
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromDTOAndOtherNodes(dto: LearningPathNodeDTO, otherNodes: LearningPathNodeDTO[]): LearningPathNode {
|
static fromDTOAndOtherNodes(dto: LearningPathNodeDTO, otherNodes: LearningPathNodeDTO[]): LearningPathNode {
|
||||||
|
@ -109,8 +110,8 @@ export class LearningPath {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get learningObjectsAsList(): RemoteResource<LearningObject[]> {
|
public get learningObjectsAsList(): Promise<LearningObject[]> {
|
||||||
return RemoteResource.join(this.nodesAsList.map(node => node.learningObject));
|
return Promise.all(this.nodesAsList.map(node => node.learningObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromDTO(dto: LearningPathDTO): LearningPath {
|
static fromDTO(dto: LearningPathDTO): LearningPath {
|
||||||
|
|
31
frontend/src/views/learning-paths/LearningObjectView.vue
Normal file
31
frontend/src/views/learning-paths/LearningObjectView.vue
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {Language} from "@/services/learning-content/language.ts";
|
||||||
|
import {watch} from "vue";
|
||||||
|
import {getLearningObjectHTML} from "@/services/learning-content/learning-object-service.ts";
|
||||||
|
import UsingRemoteResource from "@/components/UsingRemoteResource.vue";
|
||||||
|
import {loadResource, remoteResource} from "@/services/api-client/remote-resource.ts";
|
||||||
|
|
||||||
|
const props = defineProps<{hruid: string, language: Language, version: number}>()
|
||||||
|
|
||||||
|
const learningPathHtmlResource = remoteResource<Document>();
|
||||||
|
watch(props, () => {
|
||||||
|
loadResource(learningPathHtmlResource, getLearningObjectHTML(props.hruid, props.language, props.version))
|
||||||
|
}, {immediate: true});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<using-remote-resource :resource="learningPathHtmlResource" v-slot="learningPathHtml : {data: Document}">
|
||||||
|
<div class="learning-object-container" v-html="learningPathHtml.data.body.innerHTML"></div>
|
||||||
|
</using-remote-resource>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.learning-object-container {
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
:deep(hr) {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -2,31 +2,52 @@
|
||||||
import {Language} from "@/services/learning-content/language.ts";
|
import {Language} from "@/services/learning-content/language.ts";
|
||||||
import {getLearningPath} from "@/services/learning-content/learning-path-service.ts";
|
import {getLearningPath} from "@/services/learning-content/learning-path-service.ts";
|
||||||
import UsingRemoteResource from "@/components/UsingRemoteResource.vue";
|
import UsingRemoteResource from "@/components/UsingRemoteResource.vue";
|
||||||
import type {LearningPath} from "@/services/learning-content/learning-path.ts";
|
import {type LearningPath} from "@/services/learning-content/learning-path.ts";
|
||||||
import {onMounted, reactive, watch} from "vue";
|
import {computed, watch, watchEffect} from "vue";
|
||||||
import type {LearningObject} from "@/services/learning-content/learning-object.ts";
|
import type {LearningObject} from "@/services/learning-content/learning-object.ts";
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import type {SuccessState} from "@/services/api-client/remote-resource.ts";
|
import {loadResource, remoteResource, type SuccessState} from "@/services/api-client/remote-resource.ts";
|
||||||
|
import LearningObjectView from "@/views/learning-paths/LearningObjectView.vue";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const props = defineProps<{hruid: string, language: Language, learningObjectHruid?: string}>()
|
const props = defineProps<{hruid: string, language: Language, learningObjectHruid?: string}>()
|
||||||
|
|
||||||
const learningPathResource = reactive(getLearningPath(props.hruid, props.language));
|
const learningPathResource = remoteResource<LearningPath>();
|
||||||
|
watchEffect(() => {
|
||||||
|
loadResource(learningPathResource, getLearningPath(props.hruid, props.language));
|
||||||
|
});
|
||||||
|
|
||||||
|
const learningObjectListResource = remoteResource<LearningObject[]>();
|
||||||
|
watch(learningPathResource, () => {
|
||||||
|
if (learningPathResource.state.type === "success") {
|
||||||
|
loadResource(learningObjectListResource, learningPathResource.state.data.learningObjectsAsList)
|
||||||
|
}
|
||||||
|
}, {immediate: true});
|
||||||
|
|
||||||
|
const currentNode = computed(() => {
|
||||||
|
let currentHruid = props.learningObjectHruid;
|
||||||
|
if (learningPathResource.state.type === "success") {
|
||||||
|
return learningPathResource.state.data.nodesAsList.filter(it => it.learningobjectHruid === currentHruid)[0]
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (!props.learningObjectHruid) {
|
if (!props.learningObjectHruid) {
|
||||||
watch(() => learningPathResource.state, (newValue) => {
|
watch(() => learningPathResource.state, (newValue) => {
|
||||||
console.log("state changed!!");
|
|
||||||
if (newValue.type === "success") {
|
if (newValue.type === "success") {
|
||||||
router.push(router.currentRoute.value.path
|
router.push(router.currentRoute.value.path
|
||||||
+ "/" + (newValue as SuccessState<LearningPath>).data.startNode.learningobjectHruid);
|
+ "/" + (newValue as SuccessState<LearningPath>).data.startNode.learningobjectHruid);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<using-remote-resource :resource="learningPathResource" v-slot="learningPath: {data: LearningPath}">
|
<using-remote-resource
|
||||||
|
:resource="learningPathResource"
|
||||||
|
v-slot="learningPath: {data: LearningPath}"
|
||||||
|
>
|
||||||
<v-navigation-drawer>
|
<v-navigation-drawer>
|
||||||
<v-list-item
|
<v-list-item
|
||||||
:title="learningPath.data.title"
|
:title="learningPath.data.title"
|
||||||
|
@ -36,7 +57,7 @@
|
||||||
|
|
||||||
<div v-if="props.learningObjectHruid">
|
<div v-if="props.learningObjectHruid">
|
||||||
<using-remote-resource
|
<using-remote-resource
|
||||||
:resource="learningPath.data.learningObjectsAsList"
|
:resource="learningObjectListResource"
|
||||||
v-slot="learningObjects: {data: LearningObject[]}"
|
v-slot="learningObjects: {data: LearningObject[]}"
|
||||||
>
|
>
|
||||||
<v-list-item
|
<v-list-item
|
||||||
|
@ -53,6 +74,12 @@
|
||||||
</using-remote-resource>
|
</using-remote-resource>
|
||||||
</div>
|
</div>
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
|
<learning-object-view
|
||||||
|
:hruid="currentNode.learningobjectHruid"
|
||||||
|
:language="currentNode.language"
|
||||||
|
:version="currentNode.version"
|
||||||
|
v-if="currentNode"
|
||||||
|
></learning-object-view>
|
||||||
</using-remote-resource>
|
</using-remote-resource>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue