diff --git a/frontend/src/components/UsingRemoteResource.vue b/frontend/src/components/UsingRemoteResource.vue
index 96654ce9..5248d7a9 100644
--- a/frontend/src/components/UsingRemoteResource.vue
+++ b/frontend/src/components/UsingRemoteResource.vue
@@ -1,32 +1,22 @@
@@ -46,6 +36,5 @@ import {computed, onMounted, reactive, ref, type UnwrapNestedRefs, watch} from "
diff --git a/frontend/src/services/api-client/endpoints/delete-endpoint.ts b/frontend/src/services/api-client/endpoints/delete-endpoint.ts
index 554e1855..0c01e55a 100644
--- a/frontend/src/services/api-client/endpoints/delete-endpoint.ts
+++ b/frontend/src/services/api-client/endpoints/delete-endpoint.ts
@@ -1,10 +1,9 @@
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
-import {RemoteResource} from "@/services/api-client/remote-resource.ts";
export class DeleteEndpoint extends RestEndpoint {
readonly method = "GET";
- public delete(pathParams: PP, queryParams: QP): RemoteResource {
+ public delete(pathParams: PP, queryParams: QP): Promise {
return super.request(pathParams, queryParams, undefined);
}
}
diff --git a/frontend/src/services/api-client/endpoints/get-endpoint.ts b/frontend/src/services/api-client/endpoints/get-endpoint.ts
index 1d9a086f..4393e288 100644
--- a/frontend/src/services/api-client/endpoints/get-endpoint.ts
+++ b/frontend/src/services/api-client/endpoints/get-endpoint.ts
@@ -1,10 +1,9 @@
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
-import {RemoteResource} from "@/services/api-client/remote-resource.ts";
export class GetEndpoint extends RestEndpoint {
readonly method = "GET";
- public get(pathParams: PP, queryParams: QP): RemoteResource {
+ public get(pathParams: PP, queryParams: QP): Promise {
return super.request(pathParams, queryParams, undefined);
}
}
diff --git a/frontend/src/services/api-client/endpoints/get-html-endpoint.ts b/frontend/src/services/api-client/endpoints/get-html-endpoint.ts
index 2b646c16..9bb2e523 100644
--- a/frontend/src/services/api-client/endpoints/get-html-endpoint.ts
+++ b/frontend/src/services/api-client/endpoints/get-html-endpoint.ts
@@ -1,10 +1,9 @@
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
-import {RemoteResource} from "@/services/api-client/remote-resource.ts";
export class GetHtmlEndpoint extends RestEndpoint {
readonly method: "GET" | "POST" | "PUT" | "DELETE" = "GET";
- public get(pathParams: PP, queryParams: QP): RemoteResource {
+ public get(pathParams: PP, queryParams: QP): Promise {
return super.request(pathParams, queryParams, undefined, "document");
}
}
diff --git a/frontend/src/services/api-client/endpoints/post-endpoint.ts b/frontend/src/services/api-client/endpoints/post-endpoint.ts
index 6fde53e8..9b5fd96f 100644
--- a/frontend/src/services/api-client/endpoints/post-endpoint.ts
+++ b/frontend/src/services/api-client/endpoints/post-endpoint.ts
@@ -1,10 +1,9 @@
import {type Params, RestEndpoint} from "@/services/api-client/endpoints/rest-endpoint.ts";
-import {RemoteResource} from "@/services/api-client/remote-resource.ts";
export class PostEndpoint extends RestEndpoint {
readonly method = "POST";
- public post(pathParams: PP, queryParams: QP, body: B): RemoteResource {
+ public post(pathParams: PP, queryParams: QP, body: B): Promise {
return super.request(pathParams, queryParams, body);
}
}
diff --git a/frontend/src/services/api-client/endpoints/rest-endpoint.ts b/frontend/src/services/api-client/endpoints/rest-endpoint.ts
index cbe18aa0..4438214f 100644
--- a/frontend/src/services/api-client/endpoints/rest-endpoint.ts
+++ b/frontend/src/services/api-client/endpoints/rest-endpoint.ts
@@ -1,4 +1,3 @@
-import {RemoteResource} from "@/services/api-client/remote-resource.ts";
import apiClient from "@/services/api-client/api-client.ts";
import {HttpErrorStatusException} from "@/services/api-client/api-exceptions.ts";
import type {ResponseType} from "axios";
@@ -8,27 +7,21 @@ export abstract class RestEndpoint {
constructor(public readonly url: string) {
}
- protected request(pathParams: PP, queryParams: QP, body: B, responseType?: ResponseType): RemoteResource {
+ protected async request(pathParams: PP, queryParams: QP, body: B, responseType?: ResponseType): Promise {
let urlFilledIn = this.url.replace(/:(\w+)(\/|$)/g, (_, 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({
- url: urlFilledIn,
- method: this.method,
- params: queryParams,
- data: body,
- responseType: responseType || 'json'
- });
- if (response.status / 100 !== 2) {
- throw new HttpErrorStatusException(response);
- }
- return response.data;
+ const response = await apiClient.request({
+ url: urlFilledIn,
+ method: this.method,
+ params: queryParams,
+ data: body,
+ responseType: responseType || 'json'
});
+ if (response.status / 100 !== 2) {
+ throw new HttpErrorStatusException(response);
+ }
+ return response.data;
}
}
diff --git a/frontend/src/services/api-client/remote-resource.ts b/frontend/src/services/api-client/remote-resource.ts
index 4e3cbdfb..24982135 100644
--- a/frontend/src/services/api-client/remote-resource.ts
+++ b/frontend/src/services/api-client/remote-resource.ts
@@ -1,78 +1,4 @@
-export class RemoteResource {
- static NOT_LOADED: NotLoadedState = {type: "notLoaded"};
- static LOADING: LoadingState = {type: "loading"};
-
- private _state: RemoteResourceState = RemoteResource.NOT_LOADED;
-
- constructor(private readonly requestFn: () => Promise) {
- }
-
- public static join(resources: RemoteResource[]): RemoteResource {
- 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 {
- 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 {
- this.request().then();
- return this;
- }
-
- public get state(): RemoteResourceState {
- return this._state;
- }
-
- public get data(): T | undefined {
- if (this._state.type === "success") {
- return this._state.data;
- }
- }
-
- public map(mappingFn: (content: T) => U): RemoteResource {
- return new RemoteResource(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.");
- }
- });
- }
-}
+import {type ShallowReactive, shallowReactive} from "vue";
export type NotLoadedState = {
type: "notLoaded"
@@ -82,8 +8,6 @@ export type LoadingState = {
};
export type ErrorState = {
type: "error",
- errorCode?: number,
- message?: string,
error: any
};
export type SuccessState = {
@@ -91,3 +15,23 @@ export type SuccessState = {
data: T
};
export type RemoteResourceState = NotLoadedState | LoadingState | ErrorState | SuccessState;
+
+export type RemoteResource = ShallowReactive<{
+ state: RemoteResourceState
+}>;
+
+export function remoteResource(): RemoteResource {
+ return shallowReactive({
+ state: {
+ type: "notLoaded"
+ }
+ });
+}
+
+export function loadResource(resource: RemoteResource, promise: Promise): void {
+ resource.state = { type: "loading" }
+ promise.then(
+ data => resource.state = { type: "success", data },
+ error => resource.state = { type: "error", error }
+ );
+}
diff --git a/frontend/src/services/learning-content/learning-object-service.ts b/frontend/src/services/learning-content/learning-object-service.ts
index 076a662e..c6148025 100644
--- a/frontend/src/services/learning-content/learning-object-service.ts
+++ b/frontend/src/services/learning-content/learning-object-service.ts
@@ -1,13 +1,28 @@
import {GetEndpoint} from "@/services/api-client/endpoints/get-endpoint.ts";
import type {LearningObject} from "@/services/learning-content/learning-object.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>(
"/learningObject/:hruid"
);
-export function getLearningObjectMetadata(hruid: string, language: Language, version: number): RemoteResource {
- return getLearningObjectMetadataEndpoint
- .get({hruid}, {language, version});
+const getLearningObjectHtmlEndpoint = new GetHtmlEndpoint<{hruid: string}, {language: Language, version: number}>(
+ "/learningObject/:hruid/html"
+);
+
+export function getLearningObjectMetadata(
+ hruid: string,
+ language: Language,
+ version: number
+): Promise {
+ return getLearningObjectMetadataEndpoint.get({hruid}, {language, version});
+}
+
+export function getLearningObjectHTML(
+ hruid: string,
+ language: Language,
+ version: number
+): Promise {
+ return getLearningObjectHtmlEndpoint.get({hruid}, {language, version});
}
diff --git a/frontend/src/services/learning-content/learning-path-service.ts b/frontend/src/services/learning-content/learning-path-service.ts
index c1af58c9..6c0043ad 100644
--- a/frontend/src/services/learning-content/learning-path-service.ts
+++ b/frontend/src/services/learning-content/learning-path-service.ts
@@ -1,6 +1,5 @@
import {GetEndpoint} from "@/services/api-client/endpoints/get-endpoint.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 {single} from "@/utils/response-assertions.ts";
@@ -8,16 +7,12 @@ const learningPathEndpoint = new GetEndpoint<{}, {search?: string, hruid?: strin
"/learningPath"
);
-export function searchLearningPaths(query: string): RemoteResource {
- return learningPathEndpoint
- .get({}, {search: query})
- .map(dtos => dtos.map(dto => LearningPath.fromDTO(dto)));
+export async function searchLearningPaths(query: string): Promise {
+ let dtos = await learningPathEndpoint.get({}, {search: query})
+ return dtos.map(dto => LearningPath.fromDTO(dto));
}
-export function getLearningPath(hruid: string, language: Language): RemoteResource {
- console.log({hruid, language})
- return learningPathEndpoint
- .get({}, {hruid, language})
- .map(it => {console.log(it); return it;})
- .map(dtos => LearningPath.fromDTO(single(dtos)));
+export async function getLearningPath(hruid: string, language: Language): Promise {
+ let dtos = await learningPathEndpoint.get({}, {hruid, language});
+ return LearningPath.fromDTO(single(dtos));
}
diff --git a/frontend/src/services/learning-content/learning-path.ts b/frontend/src/services/learning-content/learning-path.ts
index 19a94339..a07faf9c 100644
--- a/frontend/src/services/learning-content/learning-path.ts
+++ b/frontend/src/services/learning-content/learning-path.ts
@@ -1,5 +1,4 @@
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 {getLearningObjectMetadata} from "@/services/learning-content/learning-object-service.ts";
@@ -43,7 +42,6 @@ interface LearningPathTransitionDTO {
}
export class LearningPathNode {
- public learningObject: RemoteResource
constructor(
public readonly learningobjectHruid: string,
@@ -53,7 +51,10 @@ export class LearningPathNode {
public readonly createdAt: Date,
public readonly updatedAt: Date
) {
- this.learningObject = getLearningObjectMetadata(learningobjectHruid, language, version);
+ }
+
+ get learningObject(): Promise {
+ return getLearningObjectMetadata(this.learningobjectHruid, this.language, this.version);
}
static fromDTOAndOtherNodes(dto: LearningPathNodeDTO, otherNodes: LearningPathNodeDTO[]): LearningPathNode {
@@ -109,8 +110,8 @@ export class LearningPath {
return list;
}
- public get learningObjectsAsList(): RemoteResource {
- return RemoteResource.join(this.nodesAsList.map(node => node.learningObject));
+ public get learningObjectsAsList(): Promise {
+ return Promise.all(this.nodesAsList.map(node => node.learningObject));
}
static fromDTO(dto: LearningPathDTO): LearningPath {
diff --git a/frontend/src/views/learning-paths/LearningObjectView.vue b/frontend/src/views/learning-paths/LearningObjectView.vue
new file mode 100644
index 00000000..064965ce
--- /dev/null
+++ b/frontend/src/views/learning-paths/LearningObjectView.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/learning-paths/LearningPathPage.vue b/frontend/src/views/learning-paths/LearningPathPage.vue
index 541f0fbe..cadc02c0 100644
--- a/frontend/src/views/learning-paths/LearningPathPage.vue
+++ b/frontend/src/views/learning-paths/LearningPathPage.vue
@@ -2,31 +2,52 @@
import {Language} from "@/services/learning-content/language.ts";
import {getLearningPath} from "@/services/learning-content/learning-path-service.ts";
import UsingRemoteResource from "@/components/UsingRemoteResource.vue";
- import type {LearningPath} from "@/services/learning-content/learning-path.ts";
- import {onMounted, reactive, watch} from "vue";
+ import {type LearningPath} from "@/services/learning-content/learning-path.ts";
+ import {computed, watch, watchEffect} from "vue";
import type {LearningObject} from "@/services/learning-content/learning-object.ts";
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 props = defineProps<{hruid: string, language: Language, learningObjectHruid?: string}>()
- const learningPathResource = reactive(getLearningPath(props.hruid, props.language));
+ const learningPathResource = remoteResource();
+ watchEffect(() => {
+ loadResource(learningPathResource, getLearningPath(props.hruid, props.language));
+ });
+
+ const learningObjectListResource = remoteResource();
+ 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) {
watch(() => learningPathResource.state, (newValue) => {
- console.log("state changed!!");
if (newValue.type === "success") {
router.push(router.currentRoute.value.path
+ "/" + (newValue as SuccessState).data.startNode.learningobjectHruid);
}
});
}
-
-
+
+