From 322252514955e90a9b3b2ec895e8a5bc53dcc57f Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 15 Oct 2024 14:53:00 +0200 Subject: [PATCH 01/47] ew-1009: update readme.md in common cartridge --- .../modules/common-cartridge/common-cartridge-client/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/README.md b/apps/server/src/modules/common-cartridge/common-cartridge-client/README.md index 136b6686d6c..f1f5a586a7b 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/README.md +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/README.md @@ -4,7 +4,7 @@ You can run the script with a parameter, which is the path to the controller you For example: ```bash -node ./scripts/filter-spec.js /courses +node ./scripts/filter_spec-apis.js /courses ``` The execution of the script will generate a new file in the script folder called **filtered-spec.json** with the filtered specification to the controller, you have passed as a parameter. This file should be used to generate the client code for the controller you want to use and should be **deleted** after that. This script is also able to just select used models and operations from the swagger specification. Unused models will be ignored. From f9e04c7abadb71cb7a531ce2b9d2da9087ea004e Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 15 Oct 2024 14:54:58 +0200 Subject: [PATCH 02/47] ew-1009: added generated API code --- .../card-client/cards-api-client/.gitignore | 4 + .../card-client/cards-api-client/.npmignore | 1 + .../.openapi-generator-ignore | 23 +++ .../cards-api-client/.openapi-generator/FILES | 37 ++++ .../card-client/cards-api-client/api.ts | 18 ++ .../cards-api-client/api/board-card-api.ts | 158 ++++++++++++++++++ .../card-client/cards-api-client/base.ts | 86 ++++++++++ .../card-client/cards-api-client/common.ts | 150 +++++++++++++++++ .../cards-api-client/configuration.ts | 110 ++++++++++++ .../card-client/cards-api-client/git_push.sh | 57 +++++++ .../card-client/cards-api-client/index.ts | 18 ++ .../models/api-validation-error.ts | 54 ++++++ ...d-controller-create-element201-response.ts | 53 ++++++ .../models/card-list-response.ts | 33 ++++ .../models/card-response-elements-inner.ts | 56 +++++++ .../cards-api-client/models/card-response.ts | 69 ++++++++ ...laborative-text-editor-element-response.ts | 56 +++++++ .../models/content-element-type.ts | 37 ++++ .../create-content-element-body-params.ts | 41 +++++ .../models/deleted-element-content.ts | 47 ++++++ .../models/deleted-element-response.ts | 59 +++++++ .../models/drawing-element-content.ts | 30 ++++ .../models/drawing-element-response.ts | 59 +++++++ .../models/external-tool-element-content.ts | 30 ++++ .../models/external-tool-element-response.ts | 59 +++++++ .../models/file-element-content.ts | 36 ++++ .../models/file-element-response.ts | 59 +++++++ .../cards-api-client/models/index.ts | 27 +++ .../models/link-element-content.ts | 48 ++++++ .../models/link-element-response.ts | 59 +++++++ .../models/move-card-body-params.ts | 36 ++++ .../models/rename-body-params.ts | 30 ++++ .../models/rich-text-element-content.ts | 36 ++++ .../models/rich-text-element-response.ts | 59 +++++++ .../models/set-height-body-params.ts | 30 ++++ .../submission-container-element-content.ts | 30 ++++ .../submission-container-element-response.ts | 59 +++++++ .../models/timestamps-response.ts | 42 +++++ .../models/visibility-settings-response.ts | 30 ++++ 39 files changed, 1926 insertions(+) create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.gitignore create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.npmignore create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.openapi-generator-ignore create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.openapi-generator/FILES create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/api.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/api/board-card-api.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/base.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/common.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/configuration.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/git_push.sh create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/index.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/api-validation-error.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-controller-create-element201-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-list-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-response-elements-inner.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/collaborative-text-editor-element-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/content-element-type.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/create-content-element-body-params.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/deleted-element-content.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/deleted-element-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/drawing-element-content.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/drawing-element-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/external-tool-element-content.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/external-tool-element-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/file-element-content.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/file-element-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/index.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/link-element-content.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/link-element-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/move-card-body-params.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rename-body-params.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rich-text-element-content.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rich-text-element-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/set-height-body-params.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/submission-container-element-content.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/submission-container-element-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/timestamps-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/visibility-settings-response.ts diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.gitignore b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.gitignore new file mode 100644 index 00000000000..149b5765472 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.gitignore @@ -0,0 +1,4 @@ +wwwroot/*.js +node_modules +typings +dist diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.npmignore b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.npmignore new file mode 100644 index 00000000000..999d88df693 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.npmignore @@ -0,0 +1 @@ +# empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm \ No newline at end of file diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.openapi-generator-ignore b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.openapi-generator-ignore new file mode 100644 index 00000000000..7484ee590a3 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.openapi-generator/FILES b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.openapi-generator/FILES new file mode 100644 index 00000000000..87cd4d4af4d --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/.openapi-generator/FILES @@ -0,0 +1,37 @@ +.gitignore +.npmignore +api.ts +api/board-card-api.ts +base.ts +common.ts +configuration.ts +git_push.sh +index.ts +models/api-validation-error.ts +models/card-controller-create-element201-response.ts +models/card-list-response.ts +models/card-response-elements-inner.ts +models/card-response.ts +models/collaborative-text-editor-element-response.ts +models/content-element-type.ts +models/create-content-element-body-params.ts +models/deleted-element-content.ts +models/deleted-element-response.ts +models/drawing-element-content.ts +models/drawing-element-response.ts +models/external-tool-element-content.ts +models/external-tool-element-response.ts +models/file-element-content.ts +models/file-element-response.ts +models/index.ts +models/link-element-content.ts +models/link-element-response.ts +models/move-card-body-params.ts +models/rename-body-params.ts +models/rich-text-element-content.ts +models/rich-text-element-response.ts +models/set-height-body-params.ts +models/submission-container-element-content.ts +models/submission-container-element-response.ts +models/timestamps-response.ts +models/visibility-settings-response.ts diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/api.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/api.ts new file mode 100644 index 00000000000..3d36f53648d --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/api.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +export * from './api/board-card-api'; + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/api/board-card-api.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/api/board-card-api.ts new file mode 100644 index 00000000000..71fc8373be5 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/api/board-card-api.ts @@ -0,0 +1,158 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from '../configuration'; +import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios'; +import globalAxios from 'axios'; +// Some imports not used depending on template conditions +// @ts-ignore +import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '../common'; +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, type RequestArgs, BaseAPI, RequiredError, operationServerMap } from '../base'; +// @ts-ignore +import type { ApiValidationError } from '../models'; +// @ts-ignore +import type { CardListResponse } from '../models'; +/** + * BoardCardApi - axios parameter creator + * @export + */ +export const BoardCardApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Get a list of cards by their ids. + * @param {Array} ids Array of Ids to be loaded + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + cardControllerGetCards: async (ids: Array, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'ids' is not null or undefined + assertParamExists('cardControllerGetCards', 'ids', ids) + const localVarPath = `/cards`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + if (ids) { + localVarQueryParameter['ids'] = ids; + } + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * BoardCardApi - functional programming interface + * @export + */ +export const BoardCardApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = BoardCardApiAxiosParamCreator(configuration) + return { + /** + * + * @summary Get a list of cards by their ids. + * @param {Array} ids Array of Ids to be loaded + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async cardControllerGetCards(ids: Array, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.cardControllerGetCards(ids, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['BoardCardApi.cardControllerGetCards']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * BoardCardApi - factory interface + * @export + */ +export const BoardCardApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = BoardCardApiFp(configuration) + return { + /** + * + * @summary Get a list of cards by their ids. + * @param {Array} ids Array of Ids to be loaded + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + cardControllerGetCards(ids: Array, options?: any): AxiosPromise { + return localVarFp.cardControllerGetCards(ids, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * BoardCardApi - interface + * @export + * @interface BoardCardApi + */ +export interface BoardCardApiInterface { + /** + * + * @summary Get a list of cards by their ids. + * @param {Array} ids Array of Ids to be loaded + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof BoardCardApiInterface + */ + cardControllerGetCards(ids: Array, options?: RawAxiosRequestConfig): AxiosPromise; + +} + +/** + * BoardCardApi - object-oriented interface + * @export + * @class BoardCardApi + * @extends {BaseAPI} + */ +export class BoardCardApi extends BaseAPI implements BoardCardApiInterface { + /** + * + * @summary Get a list of cards by their ids. + * @param {Array} ids Array of Ids to be loaded + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof BoardCardApi + */ + public cardControllerGetCards(ids: Array, options?: RawAxiosRequestConfig) { + return BoardCardApiFp(this.configuration).cardControllerGetCards(ids, options).then((request) => request(this.axios, this.basePath)); + } +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/base.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/base.ts new file mode 100644 index 00000000000..82686c7b81b --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/base.ts @@ -0,0 +1,86 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from './configuration'; +// Some imports not used depending on template conditions +// @ts-ignore +import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios'; +import globalAxios from 'axios'; + +export const BASE_PATH = "http://localhost/api/v3".replace(/\/+$/, ""); + +/** + * + * @export + */ +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + +/** + * + * @export + * @interface RequestArgs + */ +export interface RequestArgs { + url: string; + options: RawAxiosRequestConfig; +} + +/** + * + * @export + * @class BaseAPI + */ +export class BaseAPI { + protected configuration: Configuration | undefined; + + constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) { + if (configuration) { + this.configuration = configuration; + this.basePath = configuration.basePath ?? basePath; + } + } +}; + +/** + * + * @export + * @class RequiredError + * @extends {Error} + */ +export class RequiredError extends Error { + constructor(public field: string, msg?: string) { + super(msg); + this.name = "RequiredError" + } +} + +interface ServerMap { + [key: string]: { + url: string, + description: string, + }[]; +} + +/** + * + * @export + */ +export const operationServerMap: ServerMap = { +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/common.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/common.ts new file mode 100644 index 00000000000..6c119efb60d --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/common.ts @@ -0,0 +1,150 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from "./configuration"; +import type { RequestArgs } from "./base"; +import type { AxiosInstance, AxiosResponse } from 'axios'; +import { RequiredError } from "./base"; + +/** + * + * @export + */ +export const DUMMY_BASE_URL = 'https://example.com' + +/** + * + * @throws {RequiredError} + * @export + */ +export const assertParamExists = function (functionName: string, paramName: string, paramValue: unknown) { + if (paramValue === null || paramValue === undefined) { + throw new RequiredError(paramName, `Required parameter ${paramName} was null or undefined when calling ${functionName}.`); + } +} + +/** + * + * @export + */ +export const setApiKeyToObject = async function (object: any, keyParamName: string, configuration?: Configuration) { + if (configuration && configuration.apiKey) { + const localVarApiKeyValue = typeof configuration.apiKey === 'function' + ? await configuration.apiKey(keyParamName) + : await configuration.apiKey; + object[keyParamName] = localVarApiKeyValue; + } +} + +/** + * + * @export + */ +export const setBasicAuthToObject = function (object: any, configuration?: Configuration) { + if (configuration && (configuration.username || configuration.password)) { + object["auth"] = { username: configuration.username, password: configuration.password }; + } +} + +/** + * + * @export + */ +export const setBearerAuthToObject = async function (object: any, configuration?: Configuration) { + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + object["Authorization"] = "Bearer " + accessToken; + } +} + +/** + * + * @export + */ +export const setOAuthToObject = async function (object: any, name: string, scopes: string[], configuration?: Configuration) { + if (configuration && configuration.accessToken) { + const localVarAccessTokenValue = typeof configuration.accessToken === 'function' + ? await configuration.accessToken(name, scopes) + : await configuration.accessToken; + object["Authorization"] = "Bearer " + localVarAccessTokenValue; + } +} + +function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: any, key: string = ""): void { + if (parameter == null) return; + if (typeof parameter === "object") { + if (Array.isArray(parameter)) { + (parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key)); + } + else { + Object.keys(parameter).forEach(currentKey => + setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`) + ); + } + } + else { + if (urlSearchParams.has(key)) { + urlSearchParams.append(key, parameter); + } + else { + urlSearchParams.set(key, parameter); + } + } +} + +/** + * + * @export + */ +export const setSearchParams = function (url: URL, ...objects: any[]) { + const searchParams = new URLSearchParams(url.search); + setFlattenedQueryParams(searchParams, objects); + url.search = searchParams.toString(); +} + +/** + * + * @export + */ +export const serializeDataIfNeeded = function (value: any, requestOptions: any, configuration?: Configuration) { + const nonString = typeof value !== 'string'; + const needsSerialization = nonString && configuration && configuration.isJsonMime + ? configuration.isJsonMime(requestOptions.headers['Content-Type']) + : nonString; + return needsSerialization + ? JSON.stringify(value !== undefined ? value : {}) + : (value || ""); +} + +/** + * + * @export + */ +export const toPathString = function (url: URL) { + return url.pathname + url.search + url.hash +} + +/** + * + * @export + */ +export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) { + return >(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...axiosArgs.options, url: (axios.defaults.baseURL ? '' : configuration?.basePath ?? basePath) + axiosArgs.url}; + return axios.request(axiosRequestArgs); + }; +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/configuration.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/configuration.ts new file mode 100644 index 00000000000..8c97d307cf4 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/configuration.ts @@ -0,0 +1,110 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface ConfigurationParameters { + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + username?: string; + password?: string; + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + basePath?: string; + serverIndex?: number; + baseOptions?: any; + formDataCtor?: new () => any; +} + +export class Configuration { + /** + * parameter for apiKey security + * @param name security name + * @memberof Configuration + */ + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + username?: string; + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + password?: string; + /** + * parameter for oauth2 security + * @param name security name + * @param scopes oauth2 scope + * @memberof Configuration + */ + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + /** + * override base path + * + * @type {string} + * @memberof Configuration + */ + basePath?: string; + /** + * override server index + * + * @type {number} + * @memberof Configuration + */ + serverIndex?: number; + /** + * base options for axios calls + * + * @type {any} + * @memberof Configuration + */ + baseOptions?: any; + /** + * The FormData constructor that will be used to create multipart form data + * requests. You can inject this here so that execution environments that + * do not support the FormData class can still run the generated client. + * + * @type {new () => FormData} + */ + formDataCtor?: new () => any; + + constructor(param: ConfigurationParameters = {}) { + this.apiKey = param.apiKey; + this.username = param.username; + this.password = param.password; + this.accessToken = param.accessToken; + this.basePath = param.basePath; + this.serverIndex = param.serverIndex; + this.baseOptions = param.baseOptions; + this.formDataCtor = param.formDataCtor; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime - MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public isJsonMime(mime: string): boolean { + const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i'); + return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json'); + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/git_push.sh b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/git_push.sh new file mode 100644 index 00000000000..f53a75d4fab --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/git_push.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 +git_host=$4 + +if [ "$git_host" = "" ]; then + git_host="github.com" + echo "[INFO] No command line input provided. Set \$git_host to $git_host" +fi + +if [ "$git_user_id" = "" ]; then + git_user_id="GIT_USER_ID" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="GIT_REPO_ID" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="Minor update" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=$(git remote) +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/index.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/index.ts new file mode 100644 index 00000000000..8b762df664e --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/index.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export * from "./api"; +export * from "./configuration"; +export * from "./models"; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/api-validation-error.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/api-validation-error.ts new file mode 100644 index 00000000000..3f49cf86f0d --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/api-validation-error.ts @@ -0,0 +1,54 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface ApiValidationError + */ +export interface ApiValidationError { + /** + * The response status code. + * @type {number} + * @memberof ApiValidationError + */ + 'code': number; + /** + * The error type. + * @type {string} + * @memberof ApiValidationError + */ + 'type': string; + /** + * The error title. + * @type {string} + * @memberof ApiValidationError + */ + 'title': string; + /** + * The error message. + * @type {string} + * @memberof ApiValidationError + */ + 'message': string; + /** + * The error details. + * @type {object} + * @memberof ApiValidationError + */ + 'details'?: object; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-controller-create-element201-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-controller-create-element201-response.ts new file mode 100644 index 00000000000..8d5e118691e --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-controller-create-element201-response.ts @@ -0,0 +1,53 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; +// May contain unused imports in some cases +// @ts-ignore +import type { DeletedElementContent } from './deleted-element-content'; +// May contain unused imports in some cases +// @ts-ignore +import type { DeletedElementResponse } from './deleted-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { DrawingElementResponse } from './drawing-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { ExternalToolElementResponse } from './external-tool-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { FileElementResponse } from './file-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { LinkElementResponse } from './link-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { RichTextElementResponse } from './rich-text-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { SubmissionContainerElementResponse } from './submission-container-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; + +/** + * @type CardControllerCreateElement201Response + * @export + */ +export type CardControllerCreateElement201Response = DeletedElementResponse | DrawingElementResponse | ExternalToolElementResponse | FileElementResponse | LinkElementResponse | RichTextElementResponse | SubmissionContainerElementResponse; + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-list-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-list-response.ts new file mode 100644 index 00000000000..d3127c46646 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-list-response.ts @@ -0,0 +1,33 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { CardResponse } from './card-response'; + +/** + * + * @export + * @interface CardListResponse + */ +export interface CardListResponse { + /** + * + * @type {Array} + * @memberof CardListResponse + */ + 'data': Array; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-response-elements-inner.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-response-elements-inner.ts new file mode 100644 index 00000000000..5111cd49e11 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-response-elements-inner.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { CollaborativeTextEditorElementResponse } from './collaborative-text-editor-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; +// May contain unused imports in some cases +// @ts-ignore +import type { DeletedElementContent } from './deleted-element-content'; +// May contain unused imports in some cases +// @ts-ignore +import type { DeletedElementResponse } from './deleted-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { DrawingElementResponse } from './drawing-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { ExternalToolElementResponse } from './external-tool-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { FileElementResponse } from './file-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { LinkElementResponse } from './link-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { RichTextElementResponse } from './rich-text-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { SubmissionContainerElementResponse } from './submission-container-element-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; + +/** + * @type CardResponseElementsInner + * @export + */ +export type CardResponseElementsInner = CollaborativeTextEditorElementResponse | DeletedElementResponse | DrawingElementResponse | ExternalToolElementResponse | FileElementResponse | LinkElementResponse | RichTextElementResponse | SubmissionContainerElementResponse; + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-response.ts new file mode 100644 index 00000000000..93f03bf3e78 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/card-response.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { CardResponseElementsInner } from './card-response-elements-inner'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { VisibilitySettingsResponse } from './visibility-settings-response'; + +/** + * + * @export + * @interface CardResponse + */ +export interface CardResponse { + /** + * + * @type {string} + * @memberof CardResponse + */ + 'id': string; + /** + * + * @type {string} + * @memberof CardResponse + */ + 'title'?: string; + /** + * + * @type {number} + * @memberof CardResponse + */ + 'height': number; + /** + * + * @type {Array} + * @memberof CardResponse + */ + 'elements': Array; + /** + * + * @type {VisibilitySettingsResponse} + * @memberof CardResponse + */ + 'visibilitySettings': VisibilitySettingsResponse; + /** + * + * @type {TimestampsResponse} + * @memberof CardResponse + */ + 'timestamps': TimestampsResponse; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/collaborative-text-editor-element-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/collaborative-text-editor-element-response.ts new file mode 100644 index 00000000000..83f02148bea --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/collaborative-text-editor-element-response.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; + +/** + * + * @export + * @interface CollaborativeTextEditorElementResponse + */ +export interface CollaborativeTextEditorElementResponse { + /** + * + * @type {string} + * @memberof CollaborativeTextEditorElementResponse + */ + 'id': string; + /** + * + * @type {ContentElementType} + * @memberof CollaborativeTextEditorElementResponse + */ + 'type': ContentElementType; + /** + * + * @type {TimestampsResponse} + * @memberof CollaborativeTextEditorElementResponse + */ + 'timestamps': TimestampsResponse; + /** + * + * @type {object} + * @memberof CollaborativeTextEditorElementResponse + */ + 'content': object; +} + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/content-element-type.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/content-element-type.ts new file mode 100644 index 00000000000..391ec522db3 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/content-element-type.ts @@ -0,0 +1,37 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @enum {string} + */ + +export const ContentElementType = { + FILE: 'file', + DRAWING: 'drawing', + LINK: 'link', + RICH_TEXT: 'richText', + SUBMISSION_CONTAINER: 'submissionContainer', + EXTERNAL_TOOL: 'externalTool', + COLLABORATIVE_TEXT_EDITOR: 'collaborativeTextEditor', + DELETED: 'deleted' +} as const; + +export type ContentElementType = typeof ContentElementType[keyof typeof ContentElementType]; + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/create-content-element-body-params.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/create-content-element-body-params.ts new file mode 100644 index 00000000000..d3dc356aebf --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/create-content-element-body-params.ts @@ -0,0 +1,41 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; + +/** + * + * @export + * @interface CreateContentElementBodyParams + */ +export interface CreateContentElementBodyParams { + /** + * + * @type {ContentElementType} + * @memberof CreateContentElementBodyParams + */ + 'type': ContentElementType; + /** + * to bring element to a specific position, default is last position + * @type {number} + * @memberof CreateContentElementBodyParams + */ + 'toPosition'?: number; +} + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/deleted-element-content.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/deleted-element-content.ts new file mode 100644 index 00000000000..a5837dcbef9 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/deleted-element-content.ts @@ -0,0 +1,47 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; + +/** + * + * @export + * @interface DeletedElementContent + */ +export interface DeletedElementContent { + /** + * + * @type {string} + * @memberof DeletedElementContent + */ + 'title': string; + /** + * + * @type {ContentElementType} + * @memberof DeletedElementContent + */ + 'deletedElementType': ContentElementType; + /** + * + * @type {string} + * @memberof DeletedElementContent + */ + 'description': string; +} + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/deleted-element-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/deleted-element-response.ts new file mode 100644 index 00000000000..271ee47be8a --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/deleted-element-response.ts @@ -0,0 +1,59 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; +// May contain unused imports in some cases +// @ts-ignore +import type { DeletedElementContent } from './deleted-element-content'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; + +/** + * + * @export + * @interface DeletedElementResponse + */ +export interface DeletedElementResponse { + /** + * + * @type {string} + * @memberof DeletedElementResponse + */ + 'id': string; + /** + * + * @type {ContentElementType} + * @memberof DeletedElementResponse + */ + 'type': ContentElementType; + /** + * + * @type {DeletedElementContent} + * @memberof DeletedElementResponse + */ + 'content': DeletedElementContent; + /** + * + * @type {TimestampsResponse} + * @memberof DeletedElementResponse + */ + 'timestamps': TimestampsResponse; +} + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/drawing-element-content.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/drawing-element-content.ts new file mode 100644 index 00000000000..dda7fca8f5d --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/drawing-element-content.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface DrawingElementContent + */ +export interface DrawingElementContent { + /** + * + * @type {string} + * @memberof DrawingElementContent + */ + 'description': string; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/drawing-element-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/drawing-element-response.ts new file mode 100644 index 00000000000..b65f9714169 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/drawing-element-response.ts @@ -0,0 +1,59 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; +// May contain unused imports in some cases +// @ts-ignore +import type { DrawingElementContent } from './drawing-element-content'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; + +/** + * + * @export + * @interface DrawingElementResponse + */ +export interface DrawingElementResponse { + /** + * + * @type {string} + * @memberof DrawingElementResponse + */ + 'id': string; + /** + * + * @type {ContentElementType} + * @memberof DrawingElementResponse + */ + 'type': ContentElementType; + /** + * + * @type {TimestampsResponse} + * @memberof DrawingElementResponse + */ + 'timestamps': TimestampsResponse; + /** + * + * @type {DrawingElementContent} + * @memberof DrawingElementResponse + */ + 'content': DrawingElementContent; +} + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/external-tool-element-content.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/external-tool-element-content.ts new file mode 100644 index 00000000000..357ab4ae07e --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/external-tool-element-content.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface ExternalToolElementContent + */ +export interface ExternalToolElementContent { + /** + * + * @type {string} + * @memberof ExternalToolElementContent + */ + 'contextExternalToolId': string | null; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/external-tool-element-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/external-tool-element-response.ts new file mode 100644 index 00000000000..fb6f4b60fd0 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/external-tool-element-response.ts @@ -0,0 +1,59 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; +// May contain unused imports in some cases +// @ts-ignore +import type { ExternalToolElementContent } from './external-tool-element-content'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; + +/** + * + * @export + * @interface ExternalToolElementResponse + */ +export interface ExternalToolElementResponse { + /** + * + * @type {string} + * @memberof ExternalToolElementResponse + */ + 'id': string; + /** + * + * @type {ContentElementType} + * @memberof ExternalToolElementResponse + */ + 'type': ContentElementType; + /** + * + * @type {ExternalToolElementContent} + * @memberof ExternalToolElementResponse + */ + 'content': ExternalToolElementContent; + /** + * + * @type {TimestampsResponse} + * @memberof ExternalToolElementResponse + */ + 'timestamps': TimestampsResponse; +} + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/file-element-content.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/file-element-content.ts new file mode 100644 index 00000000000..fd8c90b8352 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/file-element-content.ts @@ -0,0 +1,36 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface FileElementContent + */ +export interface FileElementContent { + /** + * + * @type {string} + * @memberof FileElementContent + */ + 'caption': string; + /** + * + * @type {string} + * @memberof FileElementContent + */ + 'alternativeText': string; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/file-element-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/file-element-response.ts new file mode 100644 index 00000000000..8e3c2b8ffff --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/file-element-response.ts @@ -0,0 +1,59 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; +// May contain unused imports in some cases +// @ts-ignore +import type { FileElementContent } from './file-element-content'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; + +/** + * + * @export + * @interface FileElementResponse + */ +export interface FileElementResponse { + /** + * + * @type {string} + * @memberof FileElementResponse + */ + 'id': string; + /** + * + * @type {ContentElementType} + * @memberof FileElementResponse + */ + 'type': ContentElementType; + /** + * + * @type {FileElementContent} + * @memberof FileElementResponse + */ + 'content': FileElementContent; + /** + * + * @type {TimestampsResponse} + * @memberof FileElementResponse + */ + 'timestamps': TimestampsResponse; +} + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/index.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/index.ts new file mode 100644 index 00000000000..c68fe9f28ba --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/index.ts @@ -0,0 +1,27 @@ +export * from './api-validation-error'; +export * from './card-controller-create-element201-response'; +export * from './card-list-response'; +export * from './card-response'; +export * from './card-response-elements-inner'; +export * from './collaborative-text-editor-element-response'; +export * from './content-element-type'; +export * from './create-content-element-body-params'; +export * from './deleted-element-content'; +export * from './deleted-element-response'; +export * from './drawing-element-content'; +export * from './drawing-element-response'; +export * from './external-tool-element-content'; +export * from './external-tool-element-response'; +export * from './file-element-content'; +export * from './file-element-response'; +export * from './link-element-content'; +export * from './link-element-response'; +export * from './move-card-body-params'; +export * from './rename-body-params'; +export * from './rich-text-element-content'; +export * from './rich-text-element-response'; +export * from './set-height-body-params'; +export * from './submission-container-element-content'; +export * from './submission-container-element-response'; +export * from './timestamps-response'; +export * from './visibility-settings-response'; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/link-element-content.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/link-element-content.ts new file mode 100644 index 00000000000..298c02b7a88 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/link-element-content.ts @@ -0,0 +1,48 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface LinkElementContent + */ +export interface LinkElementContent { + /** + * + * @type {string} + * @memberof LinkElementContent + */ + 'url': string; + /** + * + * @type {string} + * @memberof LinkElementContent + */ + 'title': string; + /** + * + * @type {string} + * @memberof LinkElementContent + */ + 'description'?: string; + /** + * + * @type {string} + * @memberof LinkElementContent + */ + 'imageUrl'?: string; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/link-element-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/link-element-response.ts new file mode 100644 index 00000000000..9ce6c6958e0 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/link-element-response.ts @@ -0,0 +1,59 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; +// May contain unused imports in some cases +// @ts-ignore +import type { LinkElementContent } from './link-element-content'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; + +/** + * + * @export + * @interface LinkElementResponse + */ +export interface LinkElementResponse { + /** + * + * @type {string} + * @memberof LinkElementResponse + */ + 'id': string; + /** + * + * @type {ContentElementType} + * @memberof LinkElementResponse + */ + 'type': ContentElementType; + /** + * + * @type {LinkElementContent} + * @memberof LinkElementResponse + */ + 'content': LinkElementContent; + /** + * + * @type {TimestampsResponse} + * @memberof LinkElementResponse + */ + 'timestamps': TimestampsResponse; +} + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/move-card-body-params.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/move-card-body-params.ts new file mode 100644 index 00000000000..56c4bdac0f6 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/move-card-body-params.ts @@ -0,0 +1,36 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface MoveCardBodyParams + */ +export interface MoveCardBodyParams { + /** + * + * @type {string} + * @memberof MoveCardBodyParams + */ + 'toColumnId': string; + /** + * + * @type {number} + * @memberof MoveCardBodyParams + */ + 'toPosition': number; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rename-body-params.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rename-body-params.ts new file mode 100644 index 00000000000..1c52e3f08f9 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rename-body-params.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface RenameBodyParams + */ +export interface RenameBodyParams { + /** + * + * @type {string} + * @memberof RenameBodyParams + */ + 'title': string; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rich-text-element-content.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rich-text-element-content.ts new file mode 100644 index 00000000000..c1c1deec6c4 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rich-text-element-content.ts @@ -0,0 +1,36 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface RichTextElementContent + */ +export interface RichTextElementContent { + /** + * + * @type {string} + * @memberof RichTextElementContent + */ + 'text': string; + /** + * + * @type {string} + * @memberof RichTextElementContent + */ + 'inputFormat': string; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rich-text-element-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rich-text-element-response.ts new file mode 100644 index 00000000000..b46c3b623e2 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/rich-text-element-response.ts @@ -0,0 +1,59 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; +// May contain unused imports in some cases +// @ts-ignore +import type { RichTextElementContent } from './rich-text-element-content'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; + +/** + * + * @export + * @interface RichTextElementResponse + */ +export interface RichTextElementResponse { + /** + * + * @type {string} + * @memberof RichTextElementResponse + */ + 'id': string; + /** + * + * @type {ContentElementType} + * @memberof RichTextElementResponse + */ + 'type': ContentElementType; + /** + * + * @type {RichTextElementContent} + * @memberof RichTextElementResponse + */ + 'content': RichTextElementContent; + /** + * + * @type {TimestampsResponse} + * @memberof RichTextElementResponse + */ + 'timestamps': TimestampsResponse; +} + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/set-height-body-params.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/set-height-body-params.ts new file mode 100644 index 00000000000..c74c7e490bf --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/set-height-body-params.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface SetHeightBodyParams + */ +export interface SetHeightBodyParams { + /** + * + * @type {number} + * @memberof SetHeightBodyParams + */ + 'height': number; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/submission-container-element-content.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/submission-container-element-content.ts new file mode 100644 index 00000000000..dd0b9a949f6 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/submission-container-element-content.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface SubmissionContainerElementContent + */ +export interface SubmissionContainerElementContent { + /** + * The dueDate as date string or null of not set + * @type {string} + * @memberof SubmissionContainerElementContent + */ + 'dueDate': string; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/submission-container-element-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/submission-container-element-response.ts new file mode 100644 index 00000000000..4c3001c303b --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/submission-container-element-response.ts @@ -0,0 +1,59 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { ContentElementType } from './content-element-type'; +// May contain unused imports in some cases +// @ts-ignore +import type { SubmissionContainerElementContent } from './submission-container-element-content'; +// May contain unused imports in some cases +// @ts-ignore +import type { TimestampsResponse } from './timestamps-response'; + +/** + * + * @export + * @interface SubmissionContainerElementResponse + */ +export interface SubmissionContainerElementResponse { + /** + * + * @type {string} + * @memberof SubmissionContainerElementResponse + */ + 'id': string; + /** + * + * @type {ContentElementType} + * @memberof SubmissionContainerElementResponse + */ + 'type': ContentElementType; + /** + * + * @type {SubmissionContainerElementContent} + * @memberof SubmissionContainerElementResponse + */ + 'content': SubmissionContainerElementContent; + /** + * + * @type {TimestampsResponse} + * @memberof SubmissionContainerElementResponse + */ + 'timestamps': TimestampsResponse; +} + + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/timestamps-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/timestamps-response.ts new file mode 100644 index 00000000000..2da93bfa411 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/timestamps-response.ts @@ -0,0 +1,42 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface TimestampsResponse + */ +export interface TimestampsResponse { + /** + * + * @type {string} + * @memberof TimestampsResponse + */ + 'lastUpdatedAt': string; + /** + * + * @type {string} + * @memberof TimestampsResponse + */ + 'createdAt': string; + /** + * + * @type {string} + * @memberof TimestampsResponse + */ + 'deletedAt'?: string; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/visibility-settings-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/visibility-settings-response.ts new file mode 100644 index 00000000000..91baa51c30b --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/cards-api-client/models/visibility-settings-response.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface VisibilitySettingsResponse + */ +export interface VisibilitySettingsResponse { + /** + * + * @type {string} + * @memberof VisibilitySettingsResponse + */ + 'publishedAt'?: string; +} + From 8c89ad5d3d0a55272b25f27f301fa669403d2723 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 15 Oct 2024 14:55:56 +0200 Subject: [PATCH 03/47] ew-1009: created adapter, request config and module wrapper --- .../card-client/card-client.adapter.ts | 38 +++++++++++++++++++ .../card-client/card-client.config.ts | 5 +++ .../card-client/card-client.module.ts | 25 ++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.config.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.ts diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts new file mode 100644 index 00000000000..3afb98693f6 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts @@ -0,0 +1,38 @@ +import { Inject, Injectable, UnauthorizedException } from '@nestjs/common'; +import { extractJwtFromHeader } from '@shared/common'; +import { RawAxiosRequestConfig } from 'axios'; +import { Request } from 'express'; +import { REQUEST } from '@nestjs/core'; +import { CardListResponse } from '@src/modules/board/controller/dto'; +import { BoardCardApi, CardResponse } from './cards-api-client'; + +@Injectable() +export class CardClientAdapter { + constructor(private readonly boardCardApi: BoardCardApi, @Inject(REQUEST) private request: Request) {} + + public async getAllBoardCardsbyIds(cardsIds: Array): Promise { + const options = this.createOptionParams(); + const getBoardCardsResponse = await this.boardCardApi + .cardControllerGetCards(cardsIds, options) + .then((response) => response.data); + + return getBoardCardsResponse; + } + + private createOptionParams(): RawAxiosRequestConfig { + const jwt = this.getJwt(); + const options: RawAxiosRequestConfig = { headers: { authorization: `Bearer ${jwt}` } }; + + return options; + } + + private getJwt(): string { + const jwt = extractJwtFromHeader(this.request) ?? this.request.headers.authorization; + + if (!jwt) { + throw new UnauthorizedException('No JWT found in request'); + } + + return jwt; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.config.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.config.ts new file mode 100644 index 00000000000..62c9df75dc2 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.config.ts @@ -0,0 +1,5 @@ +import { ConfigurationParameters } from './cards-api-client'; + +export interface CardClientConfig extends ConfigurationParameters { + basePath?: string; +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.ts new file mode 100644 index 00000000000..b7e81f8fb4b --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.ts @@ -0,0 +1,25 @@ +import { DynamicModule, Module } from '@nestjs/common'; +import { CardClientConfig } from './card-client.config'; +import { CardClientAdapter } from './card-client.adapter'; +import { BoardCardApi, Configuration } from './cards-api-client'; + +@Module({}) +export class CardClientModule { + static register(config: CardClientConfig): DynamicModule { + const providers = [ + CardClientAdapter, + { + provide: BoardCardApi, + useFactory: () => { + const configuration = new Configuration(config); + return new BoardCardApi(configuration); + }, + }, + ]; + return { + module: CardClientModule, + providers, + exports: [CardClientAdapter], + }; + } +} From b37a85f27af3b241ea98ecb1f428da27e53c9fd9 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 15 Oct 2024 15:51:55 +0200 Subject: [PATCH 04/47] ew-1009: modified return type of get request and extracted array of response --- .../card-client/card-client.adapter.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts index 3afb98693f6..944e24881bb 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts @@ -3,20 +3,19 @@ import { extractJwtFromHeader } from '@shared/common'; import { RawAxiosRequestConfig } from 'axios'; import { Request } from 'express'; import { REQUEST } from '@nestjs/core'; -import { CardListResponse } from '@src/modules/board/controller/dto'; import { BoardCardApi, CardResponse } from './cards-api-client'; @Injectable() export class CardClientAdapter { constructor(private readonly boardCardApi: BoardCardApi, @Inject(REQUEST) private request: Request) {} - public async getAllBoardCardsbyIds(cardsIds: Array): Promise { + public async getAllBoardCardsbyIds(cardsIds: Array): Promise> { const options = this.createOptionParams(); const getBoardCardsResponse = await this.boardCardApi .cardControllerGetCards(cardsIds, options) .then((response) => response.data); - return getBoardCardsResponse; + return getBoardCardsResponse.data; } private createOptionParams(): RawAxiosRequestConfig { From fb0bafa05719574ce92afbe5450b48648fd43a32 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 18 Oct 2024 08:06:52 +0200 Subject: [PATCH 05/47] ew-1009: added all required DTOs for uc usage --- .../card-client/card-client.adapter.spec.ts | 0 .../card-client/card-client.module.spec.ts | 0 .../dto/card-response-elements-inner.dto.ts | 18 + .../card-client/dto/card-response.dto.ts | 33 + ...rative-text-editor-element-response.dto.ts | 19 + .../dto/deleted-element-content.dto.ts | 15 + .../dto/deleted-element-response.dto.ts | 25 + .../dto/drawing-element-content.dto.ts | 7 + .../dto/drawing-element-response.dto.ts | 25 + .../dto/external-tool-element-content.dto.ts | 7 + .../dto/external-tool-element-response.dto.ts | 25 + .../dto/file-element-content.dto.ts | 10 + .../dto/file-element-response.dto.ts | 20 + .../dto/link-element-content.dto.ts | 16 + .../dto/link-element-response.dto.ts | 20 + .../dto/rich-text-element-content.dto.ts | 10 + .../dto/rich-text-element-response.dto.ts | 25 + ...ubmission-container-element-content.dto.ts | 7 + ...bmission-container-element-response.dto.ts | 25 + .../card-client/dto/timestamp-response.dto.ts | 13 + .../dto/visibility-settings-response.dto.ts | 7 + .../enums/content-element-type.enum.ts | 10 + .../mapper/card-response.mapper.ts | 17 + scripts/filtered-spec.json | 973 ++++++++++++++++++ scripts/openapitools.json | 7 + 25 files changed, 1334 insertions(+) create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.spec.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response-elements-inner.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/collaborative-text-editor-element-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/deleted-element-content.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/deleted-element-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-content.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/external-tool-element-content.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/external-tool-element-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/file-element-content.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/file-element-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/link-element-content.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/link-element-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/rich-text-element-content.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/rich-text-element-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-content.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/enums/content-element-type.enum.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts create mode 100644 scripts/filtered-spec.json create mode 100644 scripts/openapitools.json diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.spec.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response-elements-inner.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response-elements-inner.dto.ts new file mode 100644 index 00000000000..525d7dea612 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response-elements-inner.dto.ts @@ -0,0 +1,18 @@ +import { CollaborativeTextEditorElementResponseDto } from './collaborative-text-editor-element-response.dto'; +import { DeletedElementResponseDto } from './deleted-element-response.dto'; +import { DrawingElementResponseDto } from './drawing-element-response.dto'; +import { ExternalToolElementResponseDto } from './external-tool-element-response.dto'; +import { FileElementResponseDto } from './file-element-response.dto'; +import { LinkElementResponseDto } from './link-element-response.dto'; +import { RichTextElementResponseDto } from './rich-text-element-response.dto'; +import { SubmissionContainerElementResponseDto } from './submission-container-element-response.dto'; + +export type CardResponseElementsInnerDto = + | CollaborativeTextEditorElementResponseDto + | DeletedElementResponseDto + | DrawingElementResponseDto + | ExternalToolElementResponseDto + | FileElementResponseDto + | LinkElementResponseDto + | RichTextElementResponseDto + | SubmissionContainerElementResponseDto; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts new file mode 100644 index 00000000000..5220b4ff7f1 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts @@ -0,0 +1,33 @@ +import { CardResponseElementsInnerDto } from './card-response-elements-inner.dto'; +import { TimestampResponseDto } from './timestamp-response.dto'; +import { VisibilitySettingsResponseDto } from './visibility-settings-response.dto'; + +export class CardResponseDto { + id: string; + + title?: string; + + height: number; + + elements: Array; + + visibilitySettings: VisibilitySettingsResponseDto; + + timeStamps: TimestampResponseDto; + + constructor( + id: string, + title: string, + height: number, + elements: Array, + visibilitySettings: VisibilitySettingsResponseDto, + timeStamps: TimestampResponseDto + ) { + this.id = id; + this.title = title; + this.height = height; + this.elements = elements; + this.visibilitySettings = visibilitySettings; + this.timeStamps = timeStamps; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/collaborative-text-editor-element-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/collaborative-text-editor-element-response.dto.ts new file mode 100644 index 00000000000..fdb80af6a70 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/collaborative-text-editor-element-response.dto.ts @@ -0,0 +1,19 @@ +import { ContentElementType } from '../cards-api-client'; +import { TimestampResponseDto } from './timestamp-response.dto'; + +export class CollaborativeTextEditorElementResponseDto { + id: string; + + type: ContentElementType; + + timestamps: TimestampResponseDto; + + content: object; + + constructor(id: string, type: ContentElementType, timestamps: TimestampResponseDto, content: object) { + this.id = id; + this.type = type; + this.timestamps = timestamps; + this.content = content; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/deleted-element-content.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/deleted-element-content.dto.ts new file mode 100644 index 00000000000..3bd24f9967f --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/deleted-element-content.dto.ts @@ -0,0 +1,15 @@ +import { ContentElementType } from '../enums/content-element-type.enum'; + +export class DeletedElementContentDto { + title: string; + + deletedElementType: ContentElementType; + + description: string; + + constructor(title: string, deletedElementType: ContentElementType, description: string) { + this.title = title; + this.deletedElementType = deletedElementType; + this.description = description; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/deleted-element-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/deleted-element-response.dto.ts new file mode 100644 index 00000000000..74eee786bc6 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/deleted-element-response.dto.ts @@ -0,0 +1,25 @@ +import { ContentElementType } from '../cards-api-client'; +import { DeletedElementContentDto } from './deleted-element-content.dto'; +import { TimestampResponseDto } from './timestamp-response.dto'; + +export class DeletedElementResponseDto { + id: string; + + type: ContentElementType; + + content: DeletedElementContentDto; + + timestamps: TimestampResponseDto; + + constructor( + id: string, + type: ContentElementType, + content: DeletedElementContentDto, + timestamps: TimestampResponseDto + ) { + this.id = id; + this.type = type; + this.content = content; + this.timestamps = timestamps; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-content.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-content.dto.ts new file mode 100644 index 00000000000..4291bf7d44a --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-content.dto.ts @@ -0,0 +1,7 @@ +export class DrawingElementContentDto { + descritpion: string; + + constructor(descritpion: string) { + this.descritpion = descritpion; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-response.dto.ts new file mode 100644 index 00000000000..7faeab24465 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-response.dto.ts @@ -0,0 +1,25 @@ +import { ContentElementType } from '../enums/content-element-type.enum'; +import { DrawingElementContentDto } from './drawing-element-content.dto'; +import { TimestampResponseDto } from './timestamp-response.dto'; + +export class DrawingElementResponseDto { + id: string; + + type: ContentElementType; + + timestamps: TimestampResponseDto; + + content: DrawingElementContentDto; + + constructor( + id: string, + type: ContentElementType, + timestamps: TimestampResponseDto, + content: DrawingElementContentDto + ) { + this.id = id; + this.type = type; + this.timestamps = timestamps; + this.content = content; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/external-tool-element-content.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/external-tool-element-content.dto.ts new file mode 100644 index 00000000000..a820a16701f --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/external-tool-element-content.dto.ts @@ -0,0 +1,7 @@ +export class ExternalToolElementContentDto { + contentExternalToolId: string | null; + + constructor(contentExternalToolId: string | null) { + this.contentExternalToolId = contentExternalToolId; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/external-tool-element-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/external-tool-element-response.dto.ts new file mode 100644 index 00000000000..054b0be68f5 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/external-tool-element-response.dto.ts @@ -0,0 +1,25 @@ +import { ContentElementType } from '../enums/content-element-type.enum'; +import { ExternalToolElementContentDto } from './external-tool-element-content.dto'; +import { TimestampResponseDto } from './timestamp-response.dto'; + +export class ExternalToolElementResponseDto { + id: string; + + type: ContentElementType; + + content: ExternalToolElementContentDto; + + timestamps: TimestampResponseDto; + + constructor( + id: string, + type: ContentElementType, + content: ExternalToolElementContentDto, + timestamps: TimestampResponseDto + ) { + this.id = id; + this.type = type; + this.content = content; + this.timestamps = timestamps; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/file-element-content.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/file-element-content.dto.ts new file mode 100644 index 00000000000..58d16071444 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/file-element-content.dto.ts @@ -0,0 +1,10 @@ +export class FileElementContentDto { + caption: string; + + alternativeText: string; + + constructor(caption: string, alternativeText: string) { + this.caption = caption; + this.alternativeText = alternativeText; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/file-element-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/file-element-response.dto.ts new file mode 100644 index 00000000000..66dc3b44579 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/file-element-response.dto.ts @@ -0,0 +1,20 @@ +import { ContentElementType } from '../enums/content-element-type.enum'; +import { FileElementContentDto } from './file-element-content.dto'; +import { TimestampResponseDto } from './timestamp-response.dto'; + +export class FileElementResponseDto { + id: string; + + type: ContentElementType; + + content: FileElementContentDto; + + timestamps: TimestampResponseDto; + + constructor(id: string, type: ContentElementType, content: FileElementContentDto, timestamps: TimestampResponseDto) { + this.id = id; + this.type = type; + this.content = content; + this.timestamps = timestamps; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/link-element-content.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/link-element-content.dto.ts new file mode 100644 index 00000000000..6b257248f30 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/link-element-content.dto.ts @@ -0,0 +1,16 @@ +export class LinkElementContentDto { + url: string; + + title: string; + + description?: string; + + imageUrl?: string; + + constructor(url: string, title: string, description: string, imageUrl: string) { + this.url = url; + this.title = title; + this.description = description; + this.imageUrl = imageUrl; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/link-element-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/link-element-response.dto.ts new file mode 100644 index 00000000000..4c4fa40a48a --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/link-element-response.dto.ts @@ -0,0 +1,20 @@ +import { ContentElementType } from '../enums/content-element-type.enum'; +import { LinkElementContentDto } from './link-element-content.dto'; +import { TimestampResponseDto } from './timestamp-response.dto'; + +export class LinkElementResponseDto { + id: string; + + type: ContentElementType; + + content: LinkElementContentDto; + + timestamps: TimestampResponseDto; + + constructor(id: string, type: ContentElementType, content: LinkElementContentDto, timestamps: TimestampResponseDto) { + this.id = id; + this.type = type; + this.content = content; + this.timestamps = timestamps; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/rich-text-element-content.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/rich-text-element-content.dto.ts new file mode 100644 index 00000000000..7726852b1dd --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/rich-text-element-content.dto.ts @@ -0,0 +1,10 @@ +export class RichTextElementContentDto { + text: string; + + inputFormat: string; + + constructor(text: string, inputFormat: string) { + this.text = text; + this.inputFormat = inputFormat; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/rich-text-element-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/rich-text-element-response.dto.ts new file mode 100644 index 00000000000..b8e5c3811b5 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/rich-text-element-response.dto.ts @@ -0,0 +1,25 @@ +import { ContentElementType } from '../enums/content-element-type.enum'; +import { RichTextElementContentDto } from './rich-text-element-content.dto'; +import { TimestampResponseDto } from './timestamp-response.dto'; + +export class RichTextElementResponseDto { + id: string; + + type: ContentElementType; + + content: RichTextElementContentDto; + + timestamps: TimestampResponseDto; + + constructor( + id: string, + type: ContentElementType, + content: RichTextElementContentDto, + timestamps: TimestampResponseDto + ) { + this.id = id; + this.type = type; + this.content = content; + this.timestamps = timestamps; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-content.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-content.dto.ts new file mode 100644 index 00000000000..4efa4db70db --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-content.dto.ts @@ -0,0 +1,7 @@ +export class SubmissionContainerElementContentDto { + dueDate: string; + + constructor(dueDate: string) { + this.dueDate = dueDate; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-response.dto.ts new file mode 100644 index 00000000000..8b208ab5a12 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-response.dto.ts @@ -0,0 +1,25 @@ +import { ContentElementType } from '../cards-api-client'; +import { SubmissionContainerElementContentDto } from './submission-container-element-content.dto'; +import { TimestampResponseDto } from './timestamp-response.dto'; + +export class SubmissionContainerElementResponseDto { + id: string; + + type: ContentElementType; + + content: SubmissionContainerElementContentDto; + + timestamps: TimestampResponseDto; + + constructor( + id: string, + type: ContentElementType, + content: SubmissionContainerElementContentDto, + timestamps: TimestampResponseDto + ) { + this.id = id; + this.type = type; + this.content = content; + this.timestamps = timestamps; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts new file mode 100644 index 00000000000..f1bc251bb3a --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts @@ -0,0 +1,13 @@ +export class TimestampResponseDto { + lastUpdatedAt: string; + + createdAt: string; + + deletedAt: string; + + constructor(lastUpdatedAt: string, createdAt: string, deletedAt: string) { + this.lastUpdatedAt = lastUpdatedAt; + this.createdAt = createdAt; + this.deletedAt = deletedAt; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts new file mode 100644 index 00000000000..44268af3204 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts @@ -0,0 +1,7 @@ +export class VisibilitySettingsResponseDto { + publishedAt: string; + + constructor(publishedAt: string) { + this.publishedAt = publishedAt; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/enums/content-element-type.enum.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/enums/content-element-type.enum.ts new file mode 100644 index 00000000000..773c63fdbe9 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/enums/content-element-type.enum.ts @@ -0,0 +1,10 @@ +export enum ContentElementType { + FILE = 'file', + DRAWING = 'drawing', + LINK = 'link', + RICH_TEXT = 'richText', + SUBMISSION_CONTAINER = 'submissionContainer', + EXTERNAL_TOOL = 'externalTool', + COLLABORATIVE_TEXT_EDITOR = 'collaborativeTextEditor', + DELETED = 'deleted', +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts new file mode 100644 index 00000000000..b8b02d08621 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts @@ -0,0 +1,17 @@ +import { CardResponse } from '../cards-api-client'; +import { CardResponseDto } from '../dto/card-response.dto'; + +export class CardResponseMapper { + public static mapToCardResponseDto(cardResponse: CardResponse) { + return new CardResponseDto( + cardResponse.id, + cardResponse.title!, + cardResponse.height, + cardResponse.elements, + cardResponse.visibilitySettings, + cardResponse.timestamps + ); + } + + private static mapTo +} diff --git a/scripts/filtered-spec.json b/scripts/filtered-spec.json new file mode 100644 index 00000000000..9b6a4b8a0d6 --- /dev/null +++ b/scripts/filtered-spec.json @@ -0,0 +1,973 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Schulcloud-Verbund-Software Server API", + "description": "This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1.", + "version": "3.0", + "contact": {} + }, + "servers": [ + { + "url": "/api/v3/" + } + ], + "paths": { + "/cards": { + "get": { + "operationId": "CardController_getCards", + "summary": "Get a list of cards by their ids.", + "parameters": [ + { + "name": "ids", + "required": true, + "in": "query", + "description": "Array of Ids to be loaded", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CardListResponse" + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiValidationError" + } + } + } + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenException" + } + } + } + } + }, + "tags": [ + "Board Card" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/cards/{cardId}/position": { + "put": { + "operationId": "CardController_moveCard", + "summary": "Move a single card.", + "parameters": [ + { + "name": "cardId", + "required": true, + "in": "path", + "description": "The id of the card.", + "schema": { + "nullable": false, + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MoveCardBodyParams" + } + } + } + }, + "responses": { + "204": { + "description": "" + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiValidationError" + } + } + } + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenException" + } + } + } + }, + "404": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundException" + } + } + } + } + }, + "tags": [ + "Board Card" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/cards/{cardId}/height": { + "patch": { + "operationId": "CardController_updateCardHeight", + "summary": "Update the height of a single card.", + "parameters": [ + { + "name": "cardId", + "required": true, + "in": "path", + "description": "The id of the card.", + "schema": { + "nullable": false, + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetHeightBodyParams" + } + } + } + }, + "responses": { + "204": { + "description": "" + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiValidationError" + } + } + } + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenException" + } + } + } + }, + "404": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundException" + } + } + } + } + }, + "tags": [ + "Board Card" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/cards/{cardId}/title": { + "patch": { + "operationId": "CardController_updateCardTitle", + "summary": "Update the title of a single card.", + "parameters": [ + { + "name": "cardId", + "required": true, + "in": "path", + "description": "The id of the card.", + "schema": { + "nullable": false, + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RenameBodyParams" + } + } + } + }, + "responses": { + "204": { + "description": "" + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiValidationError" + } + } + } + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenException" + } + } + } + }, + "404": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundException" + } + } + } + } + }, + "tags": [ + "Board Card" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/cards/{cardId}": { + "delete": { + "operationId": "CardController_deleteCard", + "summary": "Delete a single card.", + "parameters": [ + { + "name": "cardId", + "required": true, + "in": "path", + "description": "The id of the card.", + "schema": { + "nullable": false, + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "" + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiValidationError" + } + } + } + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenException" + } + } + } + }, + "404": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundException" + } + } + } + } + }, + "tags": [ + "Board Card" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/cards/{cardId}/elements": { + "post": { + "operationId": "CardController_createElement", + "summary": "Create a new element on a card.", + "parameters": [ + { + "name": "cardId", + "required": true, + "in": "path", + "description": "The id of the card.", + "schema": { + "nullable": false, + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateContentElementBodyParams" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/ExternalToolElementResponse" + }, + { + "$ref": "#/components/schemas/FileElementResponse" + }, + { + "$ref": "#/components/schemas/LinkElementResponse" + }, + { + "$ref": "#/components/schemas/RichTextElementResponse" + }, + { + "$ref": "#/components/schemas/SubmissionContainerElementResponse" + }, + { + "$ref": "#/components/schemas/DrawingElementResponse" + }, + { + "$ref": "#/components/schemas/DeletedElementResponse" + } + ] + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiValidationError" + } + } + } + }, + "403": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ForbiddenException" + } + } + } + }, + "404": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundException" + } + } + } + } + }, + "tags": [ + "Board Card" + ], + "security": [ + { + "bearer": [] + } + ] + } + } + }, + "components": { + "securitySchemes": { + "bearer": { + "scheme": "bearer", + "bearerFormat": "JWT", + "type": "http" + } + }, + "schemas": { + "ApiValidationError": { + "type": "object", + "properties": { + "code": { + "type": "number", + "description": "The response status code." + }, + "type": { + "type": "string", + "description": "The error type." + }, + "title": { + "type": "string", + "description": "The error title." + }, + "message": { + "type": "string", + "description": "The error message." + }, + "details": { + "type": "object", + "description": "The error details." + } + }, + "required": [ + "code", + "type", + "title", + "message" + ] + }, + "ForbiddenException": { + "type": "object", + "properties": {} + }, + "NotFoundException": { + "type": "object", + "properties": {} + }, + "TimestampsResponse": { + "type": "object", + "properties": { + "lastUpdatedAt": { + "format": "date-time", + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "deletedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "lastUpdatedAt", + "createdAt" + ] + }, + "RenameBodyParams": { + "type": "object", + "properties": { + "title": { + "type": "string", + "nullable": false + } + }, + "required": [ + "title" + ] + }, + "ContentElementType": { + "type": "string", + "enum": [ + "file", + "drawing", + "link", + "richText", + "submissionContainer", + "externalTool", + "collaborativeTextEditor", + "deleted" + ] + }, + "ExternalToolElementContent": { + "type": "object", + "properties": { + "contextExternalToolId": { + "type": "string", + "nullable": true + } + }, + "required": [ + "contextExternalToolId" + ] + }, + "ExternalToolElementResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "[a-f0-9]{24}" + }, + "type": { + "$ref": "#/components/schemas/ContentElementType" + }, + "content": { + "$ref": "#/components/schemas/ExternalToolElementContent" + }, + "timestamps": { + "$ref": "#/components/schemas/TimestampsResponse" + } + }, + "required": [ + "id", + "type", + "content", + "timestamps" + ] + }, + "FileElementContent": { + "type": "object", + "properties": { + "caption": { + "type": "string" + }, + "alternativeText": { + "type": "string" + } + }, + "required": [ + "caption", + "alternativeText" + ] + }, + "FileElementResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "[a-f0-9]{24}" + }, + "type": { + "$ref": "#/components/schemas/ContentElementType" + }, + "content": { + "$ref": "#/components/schemas/FileElementContent" + }, + "timestamps": { + "$ref": "#/components/schemas/TimestampsResponse" + } + }, + "required": [ + "id", + "type", + "content", + "timestamps" + ] + }, + "LinkElementContent": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "imageUrl": { + "type": "string" + } + }, + "required": [ + "url", + "title" + ] + }, + "LinkElementResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "[a-f0-9]{24}" + }, + "type": { + "$ref": "#/components/schemas/ContentElementType" + }, + "content": { + "$ref": "#/components/schemas/LinkElementContent" + }, + "timestamps": { + "$ref": "#/components/schemas/TimestampsResponse" + } + }, + "required": [ + "id", + "type", + "content", + "timestamps" + ] + }, + "RichTextElementContent": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "inputFormat": { + "type": "string" + } + }, + "required": [ + "text", + "inputFormat" + ] + }, + "RichTextElementResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "[a-f0-9]{24}" + }, + "type": { + "$ref": "#/components/schemas/ContentElementType" + }, + "content": { + "$ref": "#/components/schemas/RichTextElementContent" + }, + "timestamps": { + "$ref": "#/components/schemas/TimestampsResponse" + } + }, + "required": [ + "id", + "type", + "content", + "timestamps" + ] + }, + "DrawingElementContent": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + }, + "required": [ + "description" + ] + }, + "DrawingElementResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "[a-f0-9]{24}" + }, + "type": { + "$ref": "#/components/schemas/ContentElementType" + }, + "timestamps": { + "$ref": "#/components/schemas/TimestampsResponse" + }, + "content": { + "$ref": "#/components/schemas/DrawingElementContent" + } + }, + "required": [ + "id", + "type", + "timestamps", + "content" + ] + }, + "SubmissionContainerElementContent": { + "type": "object", + "properties": { + "dueDate": { + "format": "date-time", + "type": "string", + "description": "The dueDate as date string or null of not set", + "example": "2023-08-17T14:17:51.958+00:00" + } + }, + "required": [ + "dueDate" + ] + }, + "SubmissionContainerElementResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "[a-f0-9]{24}" + }, + "type": { + "$ref": "#/components/schemas/ContentElementType" + }, + "content": { + "$ref": "#/components/schemas/SubmissionContainerElementContent" + }, + "timestamps": { + "$ref": "#/components/schemas/TimestampsResponse" + } + }, + "required": [ + "id", + "type", + "content", + "timestamps" + ] + }, + "CollaborativeTextEditorElementResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "[a-f0-9]{24}" + }, + "type": { + "$ref": "#/components/schemas/ContentElementType" + }, + "timestamps": { + "$ref": "#/components/schemas/TimestampsResponse" + }, + "content": { + "type": "object" + } + }, + "required": [ + "id", + "type", + "timestamps", + "content" + ] + }, + "DeletedElementContent": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "deletedElementType": { + "$ref": "#/components/schemas/ContentElementType" + }, + "description": { + "type": "string" + } + }, + "required": [ + "title", + "deletedElementType", + "description" + ] + }, + "DeletedElementResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "[a-f0-9]{24}" + }, + "type": { + "$ref": "#/components/schemas/ContentElementType" + }, + "content": { + "$ref": "#/components/schemas/DeletedElementContent" + }, + "timestamps": { + "$ref": "#/components/schemas/TimestampsResponse" + } + }, + "required": [ + "id", + "type", + "content", + "timestamps" + ] + }, + "VisibilitySettingsResponse": { + "type": "object", + "properties": { + "publishedAt": { + "type": "string" + } + } + }, + "CardResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "[a-f0-9]{24}" + }, + "title": { + "type": "string" + }, + "height": { + "type": "number" + }, + "elements": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ExternalToolElementResponse" + }, + { + "$ref": "#/components/schemas/FileElementResponse" + }, + { + "$ref": "#/components/schemas/LinkElementResponse" + }, + { + "$ref": "#/components/schemas/RichTextElementResponse" + }, + { + "$ref": "#/components/schemas/SubmissionContainerElementResponse" + }, + { + "$ref": "#/components/schemas/DrawingElementResponse" + }, + { + "$ref": "#/components/schemas/CollaborativeTextEditorElementResponse" + }, + { + "$ref": "#/components/schemas/DeletedElementResponse" + } + ] + } + }, + "visibilitySettings": { + "$ref": "#/components/schemas/VisibilitySettingsResponse" + }, + "timestamps": { + "$ref": "#/components/schemas/TimestampsResponse" + } + }, + "required": [ + "id", + "height", + "elements", + "visibilitySettings", + "timestamps" + ] + }, + "CardListResponse": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CardResponse" + } + } + }, + "required": [ + "data" + ] + }, + "MoveCardBodyParams": { + "type": "object", + "properties": { + "toColumnId": { + "type": "string", + "nullable": false + }, + "toPosition": { + "type": "number", + "nullable": false + } + }, + "required": [ + "toColumnId", + "toPosition" + ] + }, + "SetHeightBodyParams": { + "type": "object", + "properties": { + "height": { + "type": "number", + "nullable": false + } + }, + "required": [ + "height" + ] + }, + "CreateContentElementBodyParams": { + "type": "object", + "properties": { + "type": { + "description": "The type of element", + "nullable": false, + "$ref": "#/components/schemas/ContentElementType" + }, + "toPosition": { + "type": "number", + "description": "to bring element to a specific position, default is last position", + "nullable": false + } + }, + "required": [ + "type" + ] + } + } + } +} \ No newline at end of file diff --git a/scripts/openapitools.json b/scripts/openapitools.json new file mode 100644 index 00000000000..f80faaa6d18 --- /dev/null +++ b/scripts/openapitools.json @@ -0,0 +1,7 @@ +{ + "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json", + "spaces": 2, + "generator-cli": { + "version": "7.9.0" + } +} From 5b88b9dc9e3655ceefd6a2a972cc38013d5da6b2 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 18 Oct 2024 13:09:05 +0200 Subject: [PATCH 06/47] ew-1009: proper mapping for all DTOs implemented --- .../card-client/dto/card-response.dto.ts | 2 +- ...rative-text-editor-element-response.dto.ts | 2 +- .../dto/drawing-element-response.dto.ts | 4 +- .../mapper/card-response.mapper.ts | 200 +++++++++++++++++- .../types/card-content-elements-inner.type.ts | 17 ++ 5 files changed, 215 insertions(+), 10 deletions(-) create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/types/card-content-elements-inner.type.ts diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts index 5220b4ff7f1..43e20b43b9e 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts @@ -19,7 +19,7 @@ export class CardResponseDto { id: string, title: string, height: number, - elements: Array, + elements: CardResponseElementsInnerDto[], visibilitySettings: VisibilitySettingsResponseDto, timeStamps: TimestampResponseDto ) { diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/collaborative-text-editor-element-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/collaborative-text-editor-element-response.dto.ts index fdb80af6a70..7d864480759 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/collaborative-text-editor-element-response.dto.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/collaborative-text-editor-element-response.dto.ts @@ -10,7 +10,7 @@ export class CollaborativeTextEditorElementResponseDto { content: object; - constructor(id: string, type: ContentElementType, timestamps: TimestampResponseDto, content: object) { + constructor(id: string, type: ContentElementType, content: object, timestamps: TimestampResponseDto) { this.id = id; this.type = type; this.timestamps = timestamps; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-response.dto.ts index 7faeab24465..a658f9de525 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-response.dto.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/drawing-element-response.dto.ts @@ -14,8 +14,8 @@ export class DrawingElementResponseDto { constructor( id: string, type: ContentElementType, - timestamps: TimestampResponseDto, - content: DrawingElementContentDto + content: DrawingElementContentDto, + timestamps: TimestampResponseDto ) { this.id = id; this.type = type; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts index b8b02d08621..0e9edde6f31 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts @@ -1,17 +1,205 @@ -import { CardResponse } from '../cards-api-client'; +import { + CardResponse, + CardResponseElementsInner, + VisibilitySettingsResponse, + TimestampsResponse, + DeletedElementResponse, + SubmissionContainerElementResponse, + DrawingElementResponse, + ExternalToolElementResponse, + FileElementResponse, + LinkElementResponse, + RichTextElementResponse, +} from '../cards-api-client'; +import { CardResponseElementsInnerDto } from '../dto/card-response-elements-inner.dto'; import { CardResponseDto } from '../dto/card-response.dto'; +import { CollaborativeTextEditorElementResponseDto } from '../dto/collaborative-text-editor-element-response.dto'; +import { DeletedElementResponseDto } from '../dto/deleted-element-response.dto'; +import { DrawingElementContentDto } from '../dto/drawing-element-content.dto'; +import { DrawingElementResponseDto } from '../dto/drawing-element-response.dto'; +import { ExternalToolElementContentDto } from '../dto/external-tool-element-content.dto'; +import { ExternalToolElementResponseDto } from '../dto/external-tool-element-response.dto'; +import { FileElementContentDto } from '../dto/file-element-content.dto'; +import { FileElementResponseDto } from '../dto/file-element-response.dto'; +import { LinkElementContentDto } from '../dto/link-element-content.dto'; +import { LinkElementResponseDto } from '../dto/link-element-response.dto'; +import { RichTextElementContentDto } from '../dto/rich-text-element-content.dto'; +import { RichTextElementResponseDto } from '../dto/rich-text-element-response.dto'; +import { SubmissionContainerElementResponseDto } from '../dto/submission-container-element-response.dto'; +import { ContentElementType } from '../enums/content-element-type.enum'; +import { SubmissionContainerElementContentDto } from '../dto/submission-container-element-content.dto'; +import { DeletedElementContentDto } from '../dto/deleted-element-content.dto'; +import { VisibilitySettingsResponseDto } from '../dto/visibility-settings-response.dto'; +import { TimestampResponseDto } from '../dto/timestamp-response.dto'; +import { CardContentElementInner } from '../types/card-content-elements-inner.type'; export class CardResponseMapper { - public static mapToCardResponseDto(cardResponse: CardResponse) { + public static mapToCardResponseDto(cardResponse: CardResponse): CardResponseDto { return new CardResponseDto( cardResponse.id, cardResponse.title!, cardResponse.height, - cardResponse.elements, - cardResponse.visibilitySettings, - cardResponse.timestamps + this.mapToCardResponseElementsInnerDto(cardResponse.elements), + this.mapToVisibilitySettingsDto(cardResponse.visibilitySettings), + this.mapToTimestampDto(cardResponse.timestamps) ); } - private static mapTo + private static mapToCardResponseElementsInnerDto( + cardResponseElementsInner: CardResponseElementsInner[] + ): CardResponseElementsInnerDto[] { + const elements: CardResponseElementsInnerDto[] = []; + + cardResponseElementsInner.forEach((element) => { + switch (element.type) { + case ContentElementType.COLLABORATIVE_TEXT_EDITOR: + elements.push( + new CollaborativeTextEditorElementResponseDto( + element.id, + ContentElementType.COLLABORATIVE_TEXT_EDITOR, + this.mapToElementsContent(element, ContentElementType.COLLABORATIVE_TEXT_EDITOR), + this.mapToTimestampDto(element.timestamps) + ) + ); + break; + case ContentElementType.DELETED: + elements.push( + new DeletedElementResponseDto( + element.id, + ContentElementType.DELETED, + this.mapToElementsContent(element, ContentElementType.DELETED) as DeletedElementContentDto, + this.mapToTimestampDto(element.timestamps) + ) + ); + break; + case ContentElementType.SUBMISSION_CONTAINER: + elements.push( + new SubmissionContainerElementResponseDto( + element.id, + ContentElementType.SUBMISSION_CONTAINER, + this.mapToElementsContent( + element, + ContentElementType.SUBMISSION_CONTAINER + ) as SubmissionContainerElementContentDto, + this.mapToTimestampDto(element.timestamps) + ) + ); + break; + case ContentElementType.DRAWING: + elements.push( + new DrawingElementResponseDto( + element.id, + ContentElementType.DRAWING, + this.mapToElementsContent(element, ContentElementType.DRAWING) as DrawingElementContentDto, + this.mapToTimestampDto(element.timestamps) + ) + ); + break; + case ContentElementType.EXTERNAL_TOOL: + elements.push( + new ExternalToolElementResponseDto( + element.id, + ContentElementType.EXTERNAL_TOOL, + this.mapToElementsContent(element, ContentElementType.EXTERNAL_TOOL) as ExternalToolElementContentDto, + this.mapToTimestampDto(element.timestamps) + ) + ); + break; + case ContentElementType.FILE: + elements.push( + new FileElementResponseDto( + element.id, + ContentElementType.FILE, + this.mapToElementsContent(element, ContentElementType.FILE) as FileElementContentDto, + this.mapToTimestampDto(element.timestamps) + ) + ); + break; + case ContentElementType.LINK: + elements.push( + new LinkElementResponseDto( + element.id, + ContentElementType.LINK, + this.mapToElementsContent(element, ContentElementType.LINK) as LinkElementContentDto, + this.mapToTimestampDto(element.timestamps) + ) + ); + break; + case ContentElementType.RICH_TEXT: + elements.push( + new RichTextElementResponseDto( + element.id, + ContentElementType.RICH_TEXT, + this.mapToElementsContent(element, ContentElementType.RICH_TEXT) as RichTextElementContentDto, + this.mapToTimestampDto(element.timestamps) + ) + ); + break; + default: + break; + } + }); + return elements; + } + + private static mapToElementsContent( + response: CardResponseElementsInner, + elementType: ContentElementType + ): CardContentElementInner { + switch (elementType) { + case ContentElementType.COLLABORATIVE_TEXT_EDITOR: + return {}; + case ContentElementType.DELETED: { + const deletedElementContent: DeletedElementResponse = response as DeletedElementResponse; + return new DeletedElementContentDto( + deletedElementContent.content.title, + ContentElementType.DELETED, + deletedElementContent.content.description + ); + } + case ContentElementType.SUBMISSION_CONTAINER: { + const submissionContainerResponse: SubmissionContainerElementResponse = + response as SubmissionContainerElementResponse; + return new SubmissionContainerElementContentDto(submissionContainerResponse.content.dueDate); + } + case ContentElementType.DRAWING: { + const drawingResponse: DrawingElementResponse = response as DrawingElementResponse; + return new DrawingElementContentDto(drawingResponse.content.description); + } + case ContentElementType.EXTERNAL_TOOL: { + const externalToolResponse: ExternalToolElementResponse = response as ExternalToolElementResponse; + return new ExternalToolElementContentDto(externalToolResponse.content.contextExternalToolId); + } + case ContentElementType.FILE: { + const fileResponse: FileElementResponse = response as FileElementResponse; + return new FileElementContentDto(fileResponse.content.caption, fileResponse.content.alternativeText); + } + case ContentElementType.LINK: { + const linkElementResponse: LinkElementResponse = response as LinkElementResponse; + return new LinkElementContentDto( + linkElementResponse.content.url, + linkElementResponse.content.title, + linkElementResponse.content.description!, + linkElementResponse.content.imageUrl as string + ); + } + case ContentElementType.RICH_TEXT: { + const richTextResponse: RichTextElementResponse = response as RichTextElementResponse; + return new RichTextElementContentDto(richTextResponse.content.text, richTextResponse.content.inputFormat); + } + default: + break; + } + return {}; + } + + private static mapToVisibilitySettingsDto( + visibilitySettings: VisibilitySettingsResponse + ): VisibilitySettingsResponseDto { + return new VisibilitySettingsResponseDto(visibilitySettings.publishedAt as string); + } + + private static mapToTimestampDto(timestamp: TimestampsResponse): TimestampResponseDto { + return new TimestampResponseDto(timestamp.lastUpdatedAt, timestamp.createdAt, timestamp.deletedAt!); + } } diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/types/card-content-elements-inner.type.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/types/card-content-elements-inner.type.ts new file mode 100644 index 00000000000..b8a32bc9479 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/types/card-content-elements-inner.type.ts @@ -0,0 +1,17 @@ +import { DeletedElementContentDto } from '../dto/deleted-element-content.dto'; +import { DrawingElementContentDto } from '../dto/drawing-element-content.dto'; +import { ExternalToolElementContentDto } from '../dto/external-tool-element-content.dto'; +import { FileElementContentDto } from '../dto/file-element-content.dto'; +import { LinkElementContentDto } from '../dto/link-element-content.dto'; +import { RichTextElementContentDto } from '../dto/rich-text-element-content.dto'; +import { SubmissionContainerElementContentDto } from '../dto/submission-container-element-content.dto'; + +export type CardContentElementInner = + | LinkElementContentDto + | DeletedElementContentDto + | DrawingElementContentDto + | ExternalToolElementContentDto + | FileElementContentDto + | RichTextElementContentDto + | SubmissionContainerElementContentDto + | object; From 2fbdf112e2d6ea166433b0b0c1c47d02222f7643 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 22 Oct 2024 12:44:47 +0200 Subject: [PATCH 07/47] ew-1009: tests setup --- .../card-client/card-client.adapter.spec.ts | 65 +++++++++++++++++++ .../card-client/card-client.adapter.ts | 2 +- .../card-client/dto/card-list-response.dto.ts | 9 +++ .../dto/card-response-elements-inner.dto.ts | 18 ----- .../card-client/dto/card-response.dto.ts | 2 +- .../mapper/card-response.mapper.spec.ts | 0 .../mapper/card-response.mapper.ts | 20 ++++-- .../card-response-elements-inner.type.ts | 18 +++++ 8 files changed, 109 insertions(+), 25 deletions(-) create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-list-response.dto.ts delete mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response-elements-inner.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/types/card-response-elements-inner.type.ts diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts index e69de29bb2d..f8376d44214 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts @@ -0,0 +1,65 @@ +import { faker } from '@faker-js/faker'; +import { createMock, DeepMocked } from '@golevelup/ts-jest'; +import { REQUEST } from '@nestjs/core'; +import { Test, TestingModule } from '@nestjs/testing'; +import { AxiosResponse } from 'axios'; +import { Request } from 'express'; +import { CardListResponse, CardResponse } from './cards-api-client/models'; +import { CardClientAdapter } from './card-client.adapter'; +import { BoardCardApi } from './cards-api-client'; + +const jwtToken = 'someJwtToken'; + +describe(CardClientAdapter.name, () => { + let module: TestingModule; + let adapterUnderTest: CardClientAdapter; + let cardApiMock: DeepMocked; + + beforeAll(async () => { + module = await Test.createTestingModule({ + providers: [ + CardClientAdapter, + { + provide: BoardCardApi, + useValue: createMock(), + }, + { + provide: REQUEST, + useValue: createMock({ + headers: { + authorization: `Bearer ${jwtToken}`, + }, + }), + }, + ], + }).compile(); + adapterUnderTest = module.get(CardClientAdapter); + cardApiMock = module.get(BoardCardApi); + }); + + afterAll(async () => { + await module.close(); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it('CardClientAdapter Properly Defined', () => { + expect(adapterUnderTest).toBeDefined(); + }); + + describe('getAllBoardCardsByIds', () => { + const setup = () => { + const cardResponseData: CardResponse[] = []; + const data: CardListResponse = { data: cardResponseData }; + const response = createMock>({ + data, + }); + + cardApiMock.cardControllerGetCards.mockResolvedValue(response); + + return { response }; + }; + }); +}); diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts index 944e24881bb..4d24daf59ab 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts @@ -9,7 +9,7 @@ import { BoardCardApi, CardResponse } from './cards-api-client'; export class CardClientAdapter { constructor(private readonly boardCardApi: BoardCardApi, @Inject(REQUEST) private request: Request) {} - public async getAllBoardCardsbyIds(cardsIds: Array): Promise> { + public async getAllBoardCardsByIds(cardsIds: Array): Promise { const options = this.createOptionParams(); const getBoardCardsResponse = await this.boardCardApi .cardControllerGetCards(cardsIds, options) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-list-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-list-response.dto.ts new file mode 100644 index 00000000000..ce011649d1b --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-list-response.dto.ts @@ -0,0 +1,9 @@ +import { CardResponseDto } from './card-response.dto'; + +export class CardListResponseDto { + data: CardResponseDto[]; + + constructor(data: CardResponseDto[]) { + this.data = data; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response-elements-inner.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response-elements-inner.dto.ts deleted file mode 100644 index 525d7dea612..00000000000 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response-elements-inner.dto.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { CollaborativeTextEditorElementResponseDto } from './collaborative-text-editor-element-response.dto'; -import { DeletedElementResponseDto } from './deleted-element-response.dto'; -import { DrawingElementResponseDto } from './drawing-element-response.dto'; -import { ExternalToolElementResponseDto } from './external-tool-element-response.dto'; -import { FileElementResponseDto } from './file-element-response.dto'; -import { LinkElementResponseDto } from './link-element-response.dto'; -import { RichTextElementResponseDto } from './rich-text-element-response.dto'; -import { SubmissionContainerElementResponseDto } from './submission-container-element-response.dto'; - -export type CardResponseElementsInnerDto = - | CollaborativeTextEditorElementResponseDto - | DeletedElementResponseDto - | DrawingElementResponseDto - | ExternalToolElementResponseDto - | FileElementResponseDto - | LinkElementResponseDto - | RichTextElementResponseDto - | SubmissionContainerElementResponseDto; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts index 43e20b43b9e..9e597cfd85c 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts @@ -1,4 +1,4 @@ -import { CardResponseElementsInnerDto } from './card-response-elements-inner.dto'; +import { CardResponseElementsInnerDto } from '../types/card-response-elements-inner.type'; import { TimestampResponseDto } from './timestamp-response.dto'; import { VisibilitySettingsResponseDto } from './visibility-settings-response.dto'; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts index 0e9edde6f31..55f369e79f8 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts @@ -1,4 +1,5 @@ import { + CardListResponse, CardResponse, CardResponseElementsInner, VisibilitySettingsResponse, @@ -11,7 +12,6 @@ import { LinkElementResponse, RichTextElementResponse, } from '../cards-api-client'; -import { CardResponseElementsInnerDto } from '../dto/card-response-elements-inner.dto'; import { CardResponseDto } from '../dto/card-response.dto'; import { CollaborativeTextEditorElementResponseDto } from '../dto/collaborative-text-editor-element-response.dto'; import { DeletedElementResponseDto } from '../dto/deleted-element-response.dto'; @@ -32,12 +32,22 @@ import { DeletedElementContentDto } from '../dto/deleted-element-content.dto'; import { VisibilitySettingsResponseDto } from '../dto/visibility-settings-response.dto'; import { TimestampResponseDto } from '../dto/timestamp-response.dto'; import { CardContentElementInner } from '../types/card-content-elements-inner.type'; +import { CardResponseElementsInnerDto } from '../types/card-response-elements-inner.type'; +import { CardListResponseDto } from '../dto/card-list-response.dto'; export class CardResponseMapper { - public static mapToCardResponseDto(cardResponse: CardResponse): CardResponseDto { + public static mapToCardListResponseDto(cardListResponse: CardListResponse) { + const cardListResponseDto: CardListResponseDto = new CardListResponseDto([]); + + cardListResponse.data.forEach((cardResponse) => { + cardListResponseDto.data.push(this.mapToCardResponseDto(cardResponse)); + }); + } + + private static mapToCardResponseDto(cardResponse: CardResponse): CardResponseDto { return new CardResponseDto( cardResponse.id, - cardResponse.title!, + cardResponse.title as string, cardResponse.height, this.mapToCardResponseElementsInnerDto(cardResponse.elements), this.mapToVisibilitySettingsDto(cardResponse.visibilitySettings), @@ -179,7 +189,7 @@ export class CardResponseMapper { return new LinkElementContentDto( linkElementResponse.content.url, linkElementResponse.content.title, - linkElementResponse.content.description!, + linkElementResponse.content.description as string, linkElementResponse.content.imageUrl as string ); } @@ -200,6 +210,6 @@ export class CardResponseMapper { } private static mapToTimestampDto(timestamp: TimestampsResponse): TimestampResponseDto { - return new TimestampResponseDto(timestamp.lastUpdatedAt, timestamp.createdAt, timestamp.deletedAt!); + return new TimestampResponseDto(timestamp.lastUpdatedAt, timestamp.createdAt, timestamp.deletedAt as string); } } diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/types/card-response-elements-inner.type.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/types/card-response-elements-inner.type.ts new file mode 100644 index 00000000000..7b4c77dafd8 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/types/card-response-elements-inner.type.ts @@ -0,0 +1,18 @@ +import { CollaborativeTextEditorElementResponseDto } from '../dto/collaborative-text-editor-element-response.dto'; +import { DeletedElementResponseDto } from '../dto/deleted-element-response.dto'; +import { DrawingElementResponseDto } from '../dto/drawing-element-response.dto'; +import { ExternalToolElementResponseDto } from '../dto/external-tool-element-response.dto'; +import { FileElementResponseDto } from '../dto/file-element-response.dto'; +import { LinkElementResponseDto } from '../dto/link-element-response.dto'; +import { RichTextElementResponseDto } from '../dto/rich-text-element-response.dto'; +import { SubmissionContainerElementResponseDto } from '../dto/submission-container-element-response.dto'; + +export type CardResponseElementsInnerDto = + | CollaborativeTextEditorElementResponseDto + | DeletedElementResponseDto + | DrawingElementResponseDto + | ExternalToolElementResponseDto + | FileElementResponseDto + | LinkElementResponseDto + | RichTextElementResponseDto + | SubmissionContainerElementResponseDto; From abb9c5fad93eeda19cac650f95df70f117c5b7f1 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 22 Oct 2024 14:53:03 +0200 Subject: [PATCH 08/47] ew-1009: adapter tests implemented --- .../card-client/card-client.adapter.spec.ts | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts index f8376d44214..0b666dfee09 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts @@ -4,6 +4,7 @@ import { REQUEST } from '@nestjs/core'; import { Test, TestingModule } from '@nestjs/testing'; import { AxiosResponse } from 'axios'; import { Request } from 'express'; +import { UnauthorizedException } from '@nestjs/common'; import { CardListResponse, CardResponse } from './cards-api-client/models'; import { CardClientAdapter } from './card-client.adapter'; import { BoardCardApi } from './cards-api-client'; @@ -45,7 +46,7 @@ describe(CardClientAdapter.name, () => { jest.resetAllMocks(); }); - it('CardClientAdapter Properly Defined', () => { + it('CardClientAdapter should be defind', () => { expect(adapterUnderTest).toBeDefined(); }); @@ -59,7 +60,30 @@ describe(CardClientAdapter.name, () => { cardApiMock.cardControllerGetCards.mockResolvedValue(response); - return { response }; + return faker.string.uuid(); }; + it('it should return a list of card response', async () => { + const ids: Array = new Array(setup()); + await adapterUnderTest.getAllBoardCardsByIds(ids); + expect(cardApiMock.cardControllerGetCards).toHaveBeenCalled(); + }); + }); + describe('When no JWT token is found', () => { + const setup = () => { + const ids: Array = new Array(faker.string.uuid()); + const request = createMock({ + headers: {}, + }); + + const adapter: CardClientAdapter = new CardClientAdapter(cardApiMock, request); + + return { ids, adapter }; + }; + + it('should throw an UnauthorizedError', async () => { + const { ids, adapter } = setup(); + + await expect(adapter.getAllBoardCardsByIds(ids)).rejects.toThrowError(UnauthorizedException); + }); }); }); From 0cd05620bb0010283e52ecd8c77856da0a3b52e8 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 22 Oct 2024 15:23:02 +0200 Subject: [PATCH 09/47] ew-1009: usecase implemented --- .../card-client/card-client.adapter.ts | 8 +++++--- .../card-client/mapper/card-response.mapper.ts | 3 ++- .../controller/common-cartridge.controller.ts | 7 +++++++ .../modules/common-cartridge/uc/common-cartridge.uc.ts | 7 +++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts index 4d24daf59ab..4861ec0f241 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts @@ -3,19 +3,21 @@ import { extractJwtFromHeader } from '@shared/common'; import { RawAxiosRequestConfig } from 'axios'; import { Request } from 'express'; import { REQUEST } from '@nestjs/core'; -import { BoardCardApi, CardResponse } from './cards-api-client'; +import { BoardCardApi } from './cards-api-client'; +import { CardListResponseDto } from './dto/card-list-response.dto'; +import { CardResponseMapper } from './mapper/card-response.mapper'; @Injectable() export class CardClientAdapter { constructor(private readonly boardCardApi: BoardCardApi, @Inject(REQUEST) private request: Request) {} - public async getAllBoardCardsByIds(cardsIds: Array): Promise { + public async getAllBoardCardsByIds(cardsIds: Array): Promise { const options = this.createOptionParams(); const getBoardCardsResponse = await this.boardCardApi .cardControllerGetCards(cardsIds, options) .then((response) => response.data); - return getBoardCardsResponse.data; + return CardResponseMapper.mapToCardListResponseDto(getBoardCardsResponse); } private createOptionParams(): RawAxiosRequestConfig { diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts index 55f369e79f8..c4f7a07d61a 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts @@ -36,12 +36,13 @@ import { CardResponseElementsInnerDto } from '../types/card-response-elements-in import { CardListResponseDto } from '../dto/card-list-response.dto'; export class CardResponseMapper { - public static mapToCardListResponseDto(cardListResponse: CardListResponse) { + public static mapToCardListResponseDto(cardListResponse: CardListResponse): CardListResponseDto { const cardListResponseDto: CardListResponseDto = new CardListResponseDto([]); cardListResponse.data.forEach((cardResponse) => { cardListResponseDto.data.push(this.mapToCardResponseDto(cardResponse)); }); + return cardListResponseDto; } private static mapToCardResponseDto(cardResponse: CardResponse): CardResponseDto { diff --git a/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts b/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts index bd609c4ff88..cccc5656977 100644 --- a/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts +++ b/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts @@ -3,6 +3,7 @@ import { ApiTags } from '@nestjs/swagger'; import { CommonCartridgeUc } from '../uc/common-cartridge.uc'; import { ExportCourseParams } from './dto'; import { CourseExportBodyResponse } from './dto/course-export-body.response'; +import { CardListResponseDto } from '../common-cartridge-client/card-client/dto/card-list-response.dto'; @ApiTags('common-cartridge') @Controller('common-cartridge') @@ -13,4 +14,10 @@ export class CommonCartridgeController { public async exportCourse(@Param() exportCourseParams: ExportCourseParams): Promise { return this.commonCartridgeUC.exportCourse(exportCourseParams.parentId); } + + @Get('export/cards/:parentId') + public async exportCards(@Param() exportCourseParams: ExportCourseParams): Promise { + const ids: Array = new Array(exportCourseParams.parentId); + return this.commonCartridgeUC.exportCardList(ids); + } } diff --git a/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts b/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts index 8caa9381633..2190c44ead5 100644 --- a/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts +++ b/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts @@ -4,6 +4,7 @@ import { CourseFileIdsResponse } from '../controller/dto'; import { CommonCartridgeExportService } from '../service/common-cartridge-export.service'; import { CourseExportBodyResponse } from '../controller/dto/course-export-body.response'; import { CourseCommonCartridgeMetadataDto } from '../common-cartridge-client/course-client'; +import { CardListResponseDto } from '../common-cartridge-client/card-client/dto/card-list-response.dto'; @Injectable() export class CommonCartridgeUc { @@ -22,4 +23,10 @@ export class CommonCartridgeUc { return response; } + + public async exportCardList(cardIds: Array): Promise { + const lesson = await this.exportService.getAllCardsByIds(cardIds); + + return lesson; + } } From 5e1e7dbe9b167780ed8c632b40c05bca0f103076 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 22 Oct 2024 16:12:13 +0200 Subject: [PATCH 10/47] ew-1009: mapper tests implemented --- .../mapper/card-response.mapper.spec.ts | 57 +++++++++++++++++++ .../common-cartridge-export.service.ts | 9 +++ 2 files changed, 66 insertions(+) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index e69de29bb2d..d72fe86633e 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -0,0 +1,57 @@ +import { faker } from '@faker-js/faker'; +import { CardResponseMapper } from './card-response.mapper'; +import { CardListResponse } from '../cards-api-client'; +import { ContentElementType } from '../enums/content-element-type.enum'; +import { CardResponseDto } from '../dto/card-response.dto'; + +describe('CardResponseMapper', () => { + describe('mapToCardListResponseDto', () => { + it('should map CardListResponse to CardListResponseDto correctly', () => { + // Mock data for CardListResponse + const mockCardListResponse: CardListResponse = { + data: [ + { + id: 'card-1', + title: 'Card 1', + height: 200, + elements: [ + { + id: 'element-1', + type: ContentElementType.RICH_TEXT, + content: { + text: faker.string.alphanumeric.toString(), + inputFormat: 'HTML', + }, + timestamps: { + lastUpdatedAt: faker.date.anytime.toString(), + createdAt: faker.date.anytime.toString(), + deletedAt: '', + }, + }, + ], + visibilitySettings: { + publishedAt: '2024-10-01T12:00:00Z', + }, + timestamps: { + lastUpdatedAt: '2024-10-01T11:00:00Z', + createdAt: faker.date.anytime.toString(), + deletedAt: faker.date.anytime.toString(), + }, + }, + ], + }; + + const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); + expect(result).toBeDefined(); + expect(result.data).toHaveLength(1); + + const cardResponseDto: CardResponseDto = result.data[0]; + expect(cardResponseDto.id).toBe('card-1'); + expect(cardResponseDto.title).toBe('Card 1'); + expect(cardResponseDto.height).toBe(200); + expect(cardResponseDto.elements).toHaveLength(1); + expect(cardResponseDto.visibilitySettings.publishedAt).toBe('2024-10-01T12:00:00Z'); + expect(cardResponseDto.timeStamps.lastUpdatedAt).toBe('2024-10-01T11:00:00Z'); + }); + }); +}); diff --git a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts index 9d358dba255..d68b8bb8195 100644 --- a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts +++ b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts @@ -4,12 +4,15 @@ import { BoardClientAdapter } from '../common-cartridge-client/board-client'; import { CourseCommonCartridgeMetadataDto, CoursesClientAdapter } from '../common-cartridge-client/course-client'; import { CourseRoomsClientAdapter } from '../common-cartridge-client/room-client'; import { RoomBoardDto } from '../common-cartridge-client/room-client/dto/room-board.dto'; +import { CardClientAdapter } from '../common-cartridge-client/card-client/card-client.adapter'; +import { CardListResponseDto } from '../common-cartridge-client/card-client/dto/card-list-response.dto'; @Injectable() export class CommonCartridgeExportService { constructor( private readonly filesService: FilesStorageClientAdapterService, private readonly boardClientAdapter: BoardClientAdapter, + private readonly cardClientAdapter: CardClientAdapter, private readonly coursesClientAdapter: CoursesClientAdapter, private readonly courseRoomsClientAdapter: CourseRoomsClientAdapter ) {} @@ -31,4 +34,10 @@ export class CommonCartridgeExportService { return courseRooms; } + + public async getAllCardsByIds(ids: Array): Promise { + const cards: CardListResponseDto = await this.cardClientAdapter.getAllBoardCardsByIds(ids); + + return cards; + } } From def768afaa23271a1a933c50731b16039dc61bed Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 22 Oct 2024 16:17:05 +0200 Subject: [PATCH 11/47] ew-1009: CardClientModule tests implemented --- .../card-client/card-client.module.spec.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.spec.ts index e69de29bb2d..badf66780f8 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.module.spec.ts @@ -0,0 +1,28 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { CardClientModule } from './card-client.module'; +import { CardClientAdapter } from './card-client.adapter'; + +describe('CardClientModule', () => { + let module: TestingModule; + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [ + CardClientModule.register({ + basePath: 'http://localhost:3030/api/v3', + }), + ], + }).compile(); + }); + + afterAll(async () => { + await module.close(); + }); + + describe('when module is initialized', () => { + it('should have the CardClientAdapter defined', () => { + const cardClientAdapter = module.get(CardClientAdapter); + expect(cardClientAdapter).toBeDefined(); + }); + }); +}); From 2a117d301161666fd90a0b61a449fe7cdf875f8b Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 22 Oct 2024 16:44:37 +0200 Subject: [PATCH 12/47] ew-1009: review comments fixed --- .../card-client/dto/timestamp-response.dto.ts | 2 +- .../card-client/dto/visibility-settings-response.dto.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts index f1bc251bb3a..3c6b49c14ac 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts @@ -3,7 +3,7 @@ export class TimestampResponseDto { createdAt: string; - deletedAt: string; + deletedAt: string | undefined; constructor(lastUpdatedAt: string, createdAt: string, deletedAt: string) { this.lastUpdatedAt = lastUpdatedAt; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts index 44268af3204..c0efba4e1af 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts @@ -1,5 +1,5 @@ export class VisibilitySettingsResponseDto { - publishedAt: string; + publishedAt: string | undefined; constructor(publishedAt: string) { this.publishedAt = publishedAt; From 63b323f74cf1a5b1c4cfdb4a0445222eefe406ba Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Wed, 23 Oct 2024 18:09:24 +0200 Subject: [PATCH 13/47] ew-1009: few changes for unit tests is export service --- .../common-cartridge.module.ts | 4 ++ .../common-cartridge-export.service.spec.ts | 51 +++++++++++++++++++ .../common-cartridge-export.service.ts | 2 +- .../uc/common-cartridge.uc.ts | 2 +- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge.module.ts b/apps/server/src/modules/common-cartridge/common-cartridge.module.ts index 9f54ce75802..b5490aa3cbc 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge.module.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge.module.ts @@ -11,6 +11,7 @@ import { CoursesClientModule } from './common-cartridge-client/course-client'; import { CommonCartridgeExportService } from './service/common-cartridge-export.service'; import { CommonCartridgeUc } from './uc/common-cartridge.uc'; import { CourseRoomsModule } from './common-cartridge-client/room-client'; +import { CardClientModule } from './common-cartridge-client/card-client/card-client.module'; @Module({ imports: [ @@ -33,6 +34,9 @@ import { CourseRoomsModule } from './common-cartridge-client/room-client'; CourseRoomsModule.register({ basePath: `${Configuration.get('API_HOST') as string}/v3/`, }), + CardClientModule.register({ + basePath: `${Configuration.get('API_HOST') as string}/v3/`, + }), ], providers: [CommonCartridgeUc, CommonCartridgeExportService], exports: [CommonCartridgeUc], diff --git a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts index 4a1b4b53066..42a55321b12 100644 --- a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts +++ b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts @@ -6,6 +6,7 @@ import { BoardClientAdapter } from '../common-cartridge-client/board-client'; import { CommonCartridgeExportService } from './common-cartridge-export.service'; import { CoursesClientAdapter } from '../common-cartridge-client/course-client'; import { CourseRoomsClientAdapter } from '../common-cartridge-client/room-client'; +import { CardClientAdapter } from '../common-cartridge-client/card-client/card-client.adapter'; describe('CommonCartridgeExportService', () => { let module: TestingModule; @@ -13,6 +14,7 @@ describe('CommonCartridgeExportService', () => { let filesStorageServiceMock: DeepMocked; let coursesClientAdapterMock: DeepMocked; let courseRoomsClientAdapterMock: DeepMocked; + let cardClientAdapterMock: DeepMocked; beforeAll(async () => { module = await Test.createTestingModule({ @@ -34,6 +36,10 @@ describe('CommonCartridgeExportService', () => { provide: CourseRoomsClientAdapter, useValue: createMock(), }, + { + provide: CardClientAdapter, + useValue: createMock(), + }, ], }).compile(); @@ -41,6 +47,7 @@ describe('CommonCartridgeExportService', () => { filesStorageServiceMock = module.get(FilesStorageClientAdapterService); coursesClientAdapterMock = module.get(CoursesClientAdapter); courseRoomsClientAdapterMock = module.get(CourseRoomsClientAdapter); + cardClientAdapterMock = module.get(CardClientAdapter); }); afterAll(async () => { @@ -118,4 +125,48 @@ describe('CommonCartridgeExportService', () => { expect(result).toEqual(expected); }); }); + + // describe('findAllCardsByIds', () => { + // const setup = () => { + // const cardsIds: Array = new Array(faker.string.uuid()); + // const mockCard: CardResponseDto = { + // id: cardsIds[0], + // title: faker.lorem.word(), + // height: faker.number.int(), + // elements: [ + // { + // id: 'element-1', + // type: ContentElementType.RICH_TEXT, + // content: { + // text: faker.string.alphanumeric.toString(), + // inputFormat: 'HTML', + // }, + // timestamps: { + // lastUpdatedAt: faker.date.anytime.toString(), + // createdAt: faker.date.anytime.toString(), + // deletedAt: '', + // }, + // }, + // ], + // visibilitySettings: { + // publishedAt: '2024-10-01T12:00:00Z', + // }, + // timeStamps: { + // lastUpdatedAt: '2024-10-01T11:00:00Z', + // createdAt: faker.date.anytime.toString(), + // deletedAt: faker.date.anytime.toString(), + // }, + // }; + // const expected: CardListResponseDto = new CardListResponseDto(new Array(mockCard)); + // cardClientAdapterMock.getAllBoardCardsByIds.mockResolvedValue(expected); + + // return { cardsIds, expected }; + // }; + // it('should return a card', () => { + // const { cardsIds, expected } = setup(); + // const result = sut.findAllCardsByIds(cardsIds); + + // expect(result).toEqual(expected); + // }); + // }); }); diff --git a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts index d68b8bb8195..59990bd08ac 100644 --- a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts +++ b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts @@ -35,7 +35,7 @@ export class CommonCartridgeExportService { return courseRooms; } - public async getAllCardsByIds(ids: Array): Promise { + public async findAllCardsByIds(ids: Array): Promise { const cards: CardListResponseDto = await this.cardClientAdapter.getAllBoardCardsByIds(ids); return cards; diff --git a/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts b/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts index 2190c44ead5..00e370dcc40 100644 --- a/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts +++ b/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts @@ -25,7 +25,7 @@ export class CommonCartridgeUc { } public async exportCardList(cardIds: Array): Promise { - const lesson = await this.exportService.getAllCardsByIds(cardIds); + const lesson = await this.exportService.findAllCardsByIds(cardIds); return lesson; } From e6ee88f5057b69124cceba482713074fd1139a91 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Thu, 24 Oct 2024 13:18:56 +0200 Subject: [PATCH 14/47] ew-1009: nullable types added to DTOs --- .../card-client/dto/card-response.dto.ts | 4 ++-- .../card-client/dto/timestamp-response.dto.ts | 2 +- .../card-client/dto/visibility-settings-response.dto.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts index 9e597cfd85c..2139dfcbd1e 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/card-response.dto.ts @@ -21,13 +21,13 @@ export class CardResponseDto { height: number, elements: CardResponseElementsInnerDto[], visibilitySettings: VisibilitySettingsResponseDto, - timeStamps: TimestampResponseDto + timestamps: TimestampResponseDto ) { this.id = id; this.title = title; this.height = height; this.elements = elements; this.visibilitySettings = visibilitySettings; - this.timeStamps = timeStamps; + this.timeStamps = timestamps; } } diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts index 3c6b49c14ac..a75998154b1 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/timestamp-response.dto.ts @@ -3,7 +3,7 @@ export class TimestampResponseDto { createdAt: string; - deletedAt: string | undefined; + deletedAt?: string; constructor(lastUpdatedAt: string, createdAt: string, deletedAt: string) { this.lastUpdatedAt = lastUpdatedAt; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts index c0efba4e1af..8497fe79a4e 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/visibility-settings-response.dto.ts @@ -1,5 +1,5 @@ export class VisibilitySettingsResponseDto { - publishedAt: string | undefined; + publishedAt?: string; constructor(publishedAt: string) { this.publishedAt = publishedAt; From 0c2af993e22cb19185c033a8470e8c5818a65dd5 Mon Sep 17 00:00:00 2001 From: Patrick Sachmann <20001160+psachmann@users.noreply.github.com> Date: Thu, 24 Oct 2024 09:31:55 +0200 Subject: [PATCH 15/47] EW-1029 adding additional information for HTTP error logs (#5305) * Adding more information to HTTP error logs --- .../core/error/domain/domainErrorHandler.ts | 28 ++++++++++++++++--- .../error/filter/global-error.filter.spec.ts | 26 +++++++++++------ .../core/error/filter/global-error.filter.ts | 12 ++++---- .../src/core/error/loggable/error.loggable.ts | 7 +++-- .../src/core/logger/types/logging.types.ts | 2 +- 5 files changed, 53 insertions(+), 22 deletions(-) diff --git a/apps/server/src/core/error/domain/domainErrorHandler.ts b/apps/server/src/core/error/domain/domainErrorHandler.ts index e61daf094df..778dd48026b 100644 --- a/apps/server/src/core/error/domain/domainErrorHandler.ts +++ b/apps/server/src/core/error/domain/domainErrorHandler.ts @@ -1,6 +1,9 @@ import { Injectable } from '@nestjs/common'; +import { HttpArgumentsHost } from '@nestjs/common/interfaces'; +import { ErrorLogger, Loggable, LoggingUtils, LogMessageDataObject } from '@src/core/logger'; +import { ICurrentUser } from '@src/infra/auth-guard'; +import { Request } from 'express'; import util from 'util'; -import { ErrorLogger, Loggable, LoggingUtils } from '@src/core/logger'; import { ErrorLoggable } from '../loggable'; @Injectable() @@ -12,16 +15,33 @@ export class DomainErrorHandler { this.logger.error(loggable); } - private createErrorLoggable(error: unknown): Loggable { + public execHttpContext(error: unknown, context: HttpArgumentsHost): void { + const request: Request = context.getRequest(); + const user = request.user as ICurrentUser | undefined; + const requestInfo = { + userId: user?.userId, + request: { + method: request.method, + endpoint: request.url, + params: JSON.stringify(request.params), + query: JSON.stringify(request.query), + }, + }; + const loggable = this.createErrorLoggable(error, requestInfo); + + this.logger.error(loggable); + } + + private createErrorLoggable(error: unknown, data?: LogMessageDataObject): Loggable { let loggable: Loggable; if (LoggingUtils.isInstanceOfLoggable(error)) { loggable = error; } else if (error instanceof Error) { - loggable = new ErrorLoggable(error); + loggable = new ErrorLoggable(error, data); } else { const unknownError = new Error(util.inspect(error)); - loggable = new ErrorLoggable(unknownError); + loggable = new ErrorLoggable(unknownError, data); } return loggable; diff --git a/apps/server/src/core/error/filter/global-error.filter.spec.ts b/apps/server/src/core/error/filter/global-error.filter.spec.ts index 8773c0bb5f3..31ce2b9f04f 100644 --- a/apps/server/src/core/error/filter/global-error.filter.spec.ts +++ b/apps/server/src/core/error/filter/global-error.filter.spec.ts @@ -3,14 +3,14 @@ import { NotFound } from '@feathersjs/errors'; import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { ArgumentsHost, BadRequestException, HttpStatus, InternalServerErrorException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; +import { WsException } from '@nestjs/websockets'; import { BusinessError } from '@shared/common'; import { ErrorLogMessage, Loggable } from '@src/core/logger'; import { Response } from 'express'; -import { WsException } from '@nestjs/websockets'; +import { DomainErrorHandler } from '../domain'; import { ErrorResponse } from '../dto'; import { ErrorUtils } from '../utils'; -import { GlobalErrorFilter } from './global-error.filter'; -import { DomainErrorHandler } from '../domain'; +import { GlobalErrorFilter, UseableContextType } from './global-error.filter'; class SampleBusinessError extends BusinessError { constructor() { @@ -78,19 +78,27 @@ describe('GlobalErrorFilter', () => { describe('catch', () => { describe('when any error is passed as parameter', () => { const setup = () => { - const argumentsHost = createMock(); - argumentsHost.getType.mockReturnValueOnce('http'); + const allContextTypes = Object.keys(UseableContextType); + const contextTypes = [...allContextTypes]; + const argumentsHost = createMock({ + getType: () => contextTypes.pop() || '', + }); const error = new Error('test'); - return { error, argumentsHost }; + return { allContextTypes, argumentsHost, error }; }; - it('should be pass the error to domain error handler', () => { - const { error, argumentsHost } = setup(); + it('should call exec on domain error handler', () => { + const { allContextTypes, argumentsHost, error } = setup(); - service.catch(error, argumentsHost); + allContextTypes.forEach(() => { + service.catch(error, argumentsHost); + }); expect(domainErrorHandler.exec).toBeCalledWith(error); + expect(domainErrorHandler.exec).toBeCalledTimes(allContextTypes.length - 1); + expect(domainErrorHandler.execHttpContext).toBeCalledWith(error, {}); + expect(domainErrorHandler.execHttpContext).toBeCalledTimes(1); }); }); diff --git a/apps/server/src/core/error/filter/global-error.filter.ts b/apps/server/src/core/error/filter/global-error.filter.ts index a658d0115a7..7098b49a78b 100644 --- a/apps/server/src/core/error/filter/global-error.filter.ts +++ b/apps/server/src/core/error/filter/global-error.filter.ts @@ -1,17 +1,17 @@ import { IError, RpcMessage } from '@infra/rabbitmq'; import { ArgumentsHost, Catch, ExceptionFilter, HttpException, InternalServerErrorException } from '@nestjs/common'; +import { WsException } from '@nestjs/websockets'; import { ApiValidationError, BusinessError } from '@shared/common'; import { Response } from 'express'; import _ from 'lodash'; -import { WsException } from '@nestjs/websockets'; +import { DomainErrorHandler } from '../domain'; import { ApiValidationErrorResponse, ErrorResponse } from '../dto'; import { FeathersError } from '../interface'; import { ErrorUtils } from '../utils'; -import { DomainErrorHandler } from '../domain'; // We are receiving rmq instead of rpc and rmq is missing in context type. // @nestjs/common export type ContextType = 'http' | 'ws' | 'rpc'; -enum UseableContextType { +export enum UseableContextType { http = 'http', rpc = 'rpc', ws = 'ws', @@ -23,18 +23,20 @@ export class GlobalErrorFilter implements ExceptionFilter { constructor(private readonly domainErrorHandler: DomainErrorHandler) {} catch(error: E, host: ArgumentsHost): void | RpcMessage | WsException { - this.domainErrorHandler.exec(error); - const contextType = host.getType(); switch (contextType) { case UseableContextType.http: + this.domainErrorHandler.execHttpContext(error, host.switchToHttp()); return this.sendHttpResponse(error, host); case UseableContextType.rpc: case UseableContextType.rmq: + this.domainErrorHandler.exec(error); return this.sendRpcResponse(error); case UseableContextType.ws: + this.domainErrorHandler.exec(error); return this.sendWsResponse(error); default: + this.domainErrorHandler.exec(error); return undefined; } } diff --git a/apps/server/src/core/error/loggable/error.loggable.ts b/apps/server/src/core/error/loggable/error.loggable.ts index 518c738e8f9..b13f100a1f9 100644 --- a/apps/server/src/core/error/loggable/error.loggable.ts +++ b/apps/server/src/core/error/loggable/error.loggable.ts @@ -1,12 +1,12 @@ +import { ValidationError } from '@nestjs/common'; import { ApiValidationError } from '@shared/common'; import { getMetadataStorage } from 'class-validator'; -import { ValidationError } from '@nestjs/common'; import { Loggable } from '../../logger/interfaces'; -import { ErrorLogMessage, ValidationErrorLogMessage } from '../../logger/types'; +import { ErrorLogMessage, LogMessageDataObject, ValidationErrorLogMessage } from '../../logger/types'; import { ErrorUtils } from '../utils/error.utils'; export class ErrorLoggable implements Loggable { - constructor(private readonly error: Error) {} + constructor(private readonly error: Error, private readonly data?: LogMessageDataObject) {} private readonly classValidatorMetadataStorage = getMetadataStorage(); @@ -14,6 +14,7 @@ export class ErrorLoggable implements Loggable { let logMessage: ErrorLogMessage | ValidationErrorLogMessage = { error: this.error, type: '', + data: this.data, }; if (this.error instanceof ApiValidationError) { diff --git a/apps/server/src/core/logger/types/logging.types.ts b/apps/server/src/core/logger/types/logging.types.ts index 3bd1839fd8b..97f5699fdd1 100644 --- a/apps/server/src/core/logger/types/logging.types.ts +++ b/apps/server/src/core/logger/types/logging.types.ts @@ -26,6 +26,6 @@ export type LogMessageWithContext = { export type LogMessageData = LogMessageDataObject | string | number | boolean | undefined; -type LogMessageDataObject = { +export type LogMessageDataObject = { [key: string]: LogMessageData; }; From e9a18b88813e66714f57a65f2222ac7444101851 Mon Sep 17 00:00:00 2001 From: Sergej Hoffmann <97111299+SevenWaysDP@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:09:45 +0200 Subject: [PATCH 16/47] BC-8311 - fix circular dependency between modules (#5311) --- apps/server/src/modules/group/group.module.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/server/src/modules/group/group.module.ts b/apps/server/src/modules/group/group.module.ts index 252132b7ef0..9d0ff151a95 100644 --- a/apps/server/src/modules/group/group.module.ts +++ b/apps/server/src/modules/group/group.module.ts @@ -1,12 +1,12 @@ -import { Module } from '@nestjs/common'; +import { forwardRef, Module } from '@nestjs/common'; import { CqrsModule } from '@nestjs/cqrs'; +import { RoleModule } from '../role'; +import { UserModule } from '../user'; import { GroupRepo } from './repo'; import { GroupService } from './service'; -import { UserModule } from '../user'; -import { RoleModule } from '../role'; @Module({ - imports: [UserModule, RoleModule, CqrsModule], + imports: [forwardRef(() => UserModule), RoleModule, CqrsModule], providers: [GroupRepo, GroupService], exports: [GroupService], }) From 4968b040f6e64e720b2671199e1f3f1248e5508d Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Thu, 24 Oct 2024 18:37:44 +0200 Subject: [PATCH 17/47] ew-1009: mapper unit tests added --- .../mapper/card-response.mapper.spec.ts | 142 +++++++++++++++--- 1 file changed, 118 insertions(+), 24 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index d72fe86633e..ab2c74e1564 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -1,13 +1,40 @@ import { faker } from '@faker-js/faker'; import { CardResponseMapper } from './card-response.mapper'; -import { CardListResponse } from '../cards-api-client'; +import { + CardListResponse, + DeletedElementResponse, + SubmissionContainerElementResponse, + DrawingElementResponse, + ExternalToolElementResponse, + FileElementResponse, + LinkElementResponse, + RichTextElementResponse, + CollaborativeTextEditorElementResponse, + CardResponseElementsInner, +} from '../cards-api-client'; import { ContentElementType } from '../enums/content-element-type.enum'; -import { CardResponseDto } from '../dto/card-response.dto'; +import { CardContentElementInner } from '../types/card-content-elements-inner.type'; describe('CardResponseMapper', () => { describe('mapToCardListResponseDto', () => { - it('should map CardListResponse to CardListResponseDto correctly', () => { - // Mock data for CardListResponse + const createMockElement = ( + id: string, + type: ContentElementType, + content: CardContentElementInner + ): CardContentElementInner => { + return { + id, + type, + content, + timestamps: { + lastUpdatedAt: '2024-10-01T10:00:00Z', + createdAt: '2024-10-01T09:00:00Z', + deletedAt: null, + }, + }; + }; + + it('should map CardListResponse to CardListResponseDto with all types of elements', () => { const mockCardListResponse: CardListResponse = { data: [ { @@ -15,27 +42,49 @@ describe('CardResponseMapper', () => { title: 'Card 1', height: 200, elements: [ - { - id: 'element-1', - type: ContentElementType.RICH_TEXT, - content: { - text: faker.string.alphanumeric.toString(), - inputFormat: 'HTML', - }, - timestamps: { - lastUpdatedAt: faker.date.anytime.toString(), - createdAt: faker.date.anytime.toString(), - deletedAt: '', - }, - }, + createMockElement( + 'element-1', + ContentElementType.COLLABORATIVE_TEXT_EDITOR, + {} + ) as CollaborativeTextEditorElementResponse, + createMockElement('element-2', ContentElementType.DELETED, { + title: 'Deleted Title', + description: 'Deleted Description', + }) as DeletedElementResponse, + createMockElement('element-3', ContentElementType.SUBMISSION_CONTAINER, { + dueDate: '2024-10-10', + }) as SubmissionContainerElementResponse, + createMockElement('element-4', ContentElementType.DRAWING, { + description: 'Sample Drawing', + }) as DrawingElementResponse, + createMockElement('element-5', ContentElementType.EXTERNAL_TOOL, { + contextExternalToolId: 'external-tool-1', + }) as ExternalToolElementResponse, + createMockElement('element-6', ContentElementType.FILE, { + caption: 'Sample Caption', + alternativeText: 'Sample Alt Text', + }) as FileElementResponse, + createMockElement('element-7', ContentElementType.LINK, { + url: 'https://example.com', + title: 'Example Title', + description: 'Sample Description', + imageUrl: 'https://example.com/image.png', + }) as LinkElementResponse, + createMockElement('element-8', ContentElementType.RICH_TEXT, { + text: 'Rich text content', + inputFormat: 'Markdown', + }) as RichTextElementResponse, + createMockElement( + 'element-unknown', + 'UNKNOWN_TYPE' as ContentElementType, + {} + ) as CardResponseElementsInner, ], - visibilitySettings: { - publishedAt: '2024-10-01T12:00:00Z', - }, + visibilitySettings: { publishedAt: '2024-10-01T12:00:00Z' }, timestamps: { lastUpdatedAt: '2024-10-01T11:00:00Z', - createdAt: faker.date.anytime.toString(), - deletedAt: faker.date.anytime.toString(), + createdAt: '2024-10-01T10:00:00Z', + deletedAt: faker.date.recent().toString(), }, }, ], @@ -45,13 +94,58 @@ describe('CardResponseMapper', () => { expect(result).toBeDefined(); expect(result.data).toHaveLength(1); - const cardResponseDto: CardResponseDto = result.data[0]; + const cardResponseDto = result.data[0]; expect(cardResponseDto.id).toBe('card-1'); expect(cardResponseDto.title).toBe('Card 1'); expect(cardResponseDto.height).toBe(200); - expect(cardResponseDto.elements).toHaveLength(1); expect(cardResponseDto.visibilitySettings.publishedAt).toBe('2024-10-01T12:00:00Z'); expect(cardResponseDto.timeStamps.lastUpdatedAt).toBe('2024-10-01T11:00:00Z'); + + // Check elements + expect(cardResponseDto.elements).toHaveLength(8); // Should include all valid elements + expect(cardResponseDto.elements[0].type).toBe(ContentElementType.COLLABORATIVE_TEXT_EDITOR); + expect(cardResponseDto.elements[1].type).toBe(ContentElementType.DELETED); + expect(cardResponseDto.elements[2].type).toBe(ContentElementType.SUBMISSION_CONTAINER); + expect(cardResponseDto.elements[3].type).toBe(ContentElementType.DRAWING); + expect(cardResponseDto.elements[4].type).toBe(ContentElementType.EXTERNAL_TOOL); + expect(cardResponseDto.elements[5].type).toBe(ContentElementType.FILE); + expect(cardResponseDto.elements[6].type).toBe(ContentElementType.LINK); + expect(cardResponseDto.elements[7].type).toBe(ContentElementType.RICH_TEXT); + }); + + it('should handle unknown element types without breaking', () => { + const mockCardListResponse: CardListResponse = { + data: [ + { + id: 'card-2', + title: 'Card 2', + height: 150, + elements: [ + createMockElement( + 'element-unknown', + 'UNKNOWN_TYPE' as ContentElementType, + {} + ) as CardResponseElementsInner, + ], + visibilitySettings: { publishedAt: '2024-10-02T12:00:00Z' }, + timestamps: { + lastUpdatedAt: '2024-10-02T11:00:00Z', + createdAt: '2024-10-02T10:00:00Z', + deletedAt: faker.date.recent().toString(), + }, + }, + ], + }; + + const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); + expect(result).toBeDefined(); + expect(result.data).toHaveLength(1); + + const cardResponseDto = result.data[0]; + expect(cardResponseDto.id).toBe('card-2'); + expect(cardResponseDto.title).toBe('Card 2'); + expect(cardResponseDto.height).toBe(150); + expect(cardResponseDto.elements).toHaveLength(0); }); }); }); From 43e43a00fe9a1dfef509fc07ea29ec0a140764ed Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Thu, 24 Oct 2024 19:01:29 +0200 Subject: [PATCH 18/47] ew-1009: removed comments --- .../card-client/mapper/card-response.mapper.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index ab2c74e1564..232af6f6afb 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -101,8 +101,7 @@ describe('CardResponseMapper', () => { expect(cardResponseDto.visibilitySettings.publishedAt).toBe('2024-10-01T12:00:00Z'); expect(cardResponseDto.timeStamps.lastUpdatedAt).toBe('2024-10-01T11:00:00Z'); - // Check elements - expect(cardResponseDto.elements).toHaveLength(8); // Should include all valid elements + expect(cardResponseDto.elements).toHaveLength(8); expect(cardResponseDto.elements[0].type).toBe(ContentElementType.COLLABORATIVE_TEXT_EDITOR); expect(cardResponseDto.elements[1].type).toBe(ContentElementType.DELETED); expect(cardResponseDto.elements[2].type).toBe(ContentElementType.SUBMISSION_CONTAINER); From 2981b2f69cf02819ccbf3104af5f0157a5e19dc8 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Thu, 24 Oct 2024 19:25:39 +0200 Subject: [PATCH 19/47] ew-1009: test added for empty elements --- .../mapper/card-response.mapper.spec.ts | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index 232af6f6afb..201f797191c 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -14,6 +14,7 @@ import { } from '../cards-api-client'; import { ContentElementType } from '../enums/content-element-type.enum'; import { CardContentElementInner } from '../types/card-content-elements-inner.type'; +import { CardResponseDto } from '../dto/card-response.dto'; describe('CardResponseMapper', () => { describe('mapToCardListResponseDto', () => { @@ -146,5 +147,35 @@ describe('CardResponseMapper', () => { expect(cardResponseDto.height).toBe(150); expect(cardResponseDto.elements).toHaveLength(0); }); + it('should return an empty list of elements when CardResponse has no elements', () => { + const mockCardListResponse: CardListResponse = { + data: [ + { + id: 'card-3', + title: 'Card 3', + height: 100, + elements: [], + visibilitySettings: { publishedAt: '2024-10-03T12:00:00Z' }, + timestamps: { + lastUpdatedAt: '2024-10-03T11:00:00Z', + createdAt: '2024-10-03T10:00:00Z', + deletedAt: faker.date.recent().toString(), + }, + }, + ], + }; + + const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); + expect(result).toBeDefined(); + expect(result.data).toHaveLength(1); + + const cardResponse: CardResponseDto = result.data[0]; + expect(cardResponse.id).toBe('card-3'); + expect(cardResponse.title).toBe('Card 3'); + expect(cardResponse.height).toBe(100); + expect(cardResponse.elements).toHaveLength(0); + expect(cardResponse.visibilitySettings.publishedAt).toBe('2024-10-03T12:00:00Z'); + expect(cardResponse.timeStamps.lastUpdatedAt).toBe('2024-10-03T11:00:00Z'); + }); }); }); From 375279b45aa73b496b0f721c82fd2b3c02184a0d Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Thu, 24 Oct 2024 19:43:10 +0200 Subject: [PATCH 20/47] ew-1009: removed hard coded string --- .../card-client/card-client.adapter.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts index 0b666dfee09..a15bbccf8b7 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts @@ -9,7 +9,7 @@ import { CardListResponse, CardResponse } from './cards-api-client/models'; import { CardClientAdapter } from './card-client.adapter'; import { BoardCardApi } from './cards-api-client'; -const jwtToken = 'someJwtToken'; +const jwtToken = faker.string.uuid(); describe(CardClientAdapter.name, () => { let module: TestingModule; From 29aeb7a2ba5203ba437476abfa7164970f24b619 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Thu, 24 Oct 2024 19:44:18 +0200 Subject: [PATCH 21/47] ew-1009: modified variable name --- .../src/modules/common-cartridge/uc/common-cartridge.uc.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts b/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts index 00e370dcc40..86b372b2d9c 100644 --- a/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts +++ b/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts @@ -25,8 +25,8 @@ export class CommonCartridgeUc { } public async exportCardList(cardIds: Array): Promise { - const lesson = await this.exportService.findAllCardsByIds(cardIds); + const cardList = await this.exportService.findAllCardsByIds(cardIds); - return lesson; + return cardList; } } From 76d28aa1943e7d2c157bbc5cbd1c9b5a8a2d6fe8 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 25 Oct 2024 06:17:53 +0200 Subject: [PATCH 22/47] ew-1009: sonar coverage exclusion added --- sonar-project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonar-project.properties b/sonar-project.properties index 79aa1797c82..ff67c5c84dc 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.projectKey=hpi-schul-cloud_schulcloud-server sonar.sources=. sonar.tests=. sonar.test.inclusions=**/*.spec.ts -sonar.exclusions=**/*.js,jest.config.ts,globalSetup.ts,globalTeardown.ts,**/*.app.ts,**/seed-data/*.ts,**/migrations/mikro-orm/*.ts,**/etherpad-api-client/**/*.ts,**/authorization-api-client/**/*.ts, **/course-api-client/**/*.ts,**/board-api-client/**/*.ts,**/generated/**/*.ts,**/room-api-client/**/*.ts +sonar.exclusions=**/*.js,jest.config.ts,globalSetup.ts,globalTeardown.ts,**/*.app.ts,**/seed-data/*.ts,**/migrations/mikro-orm/*.ts,**/etherpad-api-client/**/*.ts,**/authorization-api-client/**/*.ts, **/course-api-client/**/*.ts,**/board-api-client/**/*.ts,**/generated/**/*.ts,**/room-api-client/**/*.ts, **/cards-api-client/**/*.ts sonar.coverage.exclusions=**/board-management.uc.ts,**/*.module.ts,**/*.factory.ts,**/migrations/mikro-orm/*.ts,**/globalSetup.ts,**/globalTeardown.ts,**/etherpad-api-client/**/*.ts,**/authorization-api-client/**/*.ts, **/course-api-client/**/*.ts,**/board-api-client/**/*.ts,**/generated/**/*.ts,**/room-api-client/**/*.ts sonar.cpd.exclusions=**/controller/dto/**/*.ts,**/api/dto/**/*.ts,**/shared/testing/factory/*.factory.ts sonar.javascript.lcov.reportPaths=merged-lcov.info From de69e736b678182feee2eac6c18c576e88d30c72 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 25 Oct 2024 06:38:33 +0200 Subject: [PATCH 23/47] ew-1009: added handling default case for switch statement --- .../mapper/card-response.mapper.spec.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index 201f797191c..95007a7a27a 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -177,5 +177,40 @@ describe('CardResponseMapper', () => { expect(cardResponse.visibilitySettings.publishedAt).toBe('2024-10-03T12:00:00Z'); expect(cardResponse.timeStamps.lastUpdatedAt).toBe('2024-10-03T11:00:00Z'); }); + + it('should cover default switch case and return an empty object', () => { + const mockCardListResponse: CardListResponse = { + data: [ + { + id: faker.datatype.uuid(), + title: faker.lorem.sentence(), + height: faker.datatype.number({ min: 100, max: 500 }), + elements: [ + createMockElement( + faker.datatype.uuid(), + 'UNKNOWN_TYPE' as ContentElementType, + {} + ) as CardResponseElementsInner, + ], + visibilitySettings: { publishedAt: faker.date.past().toISOString() }, + timestamps: { + lastUpdatedAt: faker.date.recent().toISOString(), + createdAt: faker.date.past().toISOString(), + deletedAt: faker.date.future().toISOString(), + }, + }, + ], + }; + + const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); + expect(result).toBeDefined(); + expect(result.data).toHaveLength(1); + + const cardResponseDto = result.data[0]; + expect(cardResponseDto.id).toBe(mockCardListResponse.data[0].id); + expect(cardResponseDto.title).toBe(mockCardListResponse.data[0].title); + expect(cardResponseDto.height).toBe(mockCardListResponse.data[0].height); + expect(cardResponseDto.elements).toHaveLength(0); + }); }); }); From 7979094ba1c2780f23d94d6ef358b0857132eba1 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 25 Oct 2024 07:05:02 +0200 Subject: [PATCH 24/47] ew-1009: removed unneeded comments and added solution for unreachable code --- .../mapper/card-response.mapper.ts | 9 +++- .../common-cartridge-export.service.spec.ts | 44 ------------------- 2 files changed, 7 insertions(+), 46 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts index c4f7a07d61a..75c76d742c9 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts @@ -157,6 +157,7 @@ export class CardResponseMapper { response: CardResponseElementsInner, elementType: ContentElementType ): CardContentElementInner { + // eslint-disable-next-line default-case switch (elementType) { case ContentElementType.COLLABORATIVE_TEXT_EDITOR: return {}; @@ -199,9 +200,8 @@ export class CardResponseMapper { return new RichTextElementContentDto(richTextResponse.content.text, richTextResponse.content.inputFormat); } default: - break; + return this.assertUnreachableCode(elementType); } - return {}; } private static mapToVisibilitySettingsDto( @@ -213,4 +213,9 @@ export class CardResponseMapper { private static mapToTimestampDto(timestamp: TimestampsResponse): TimestampResponseDto { return new TimestampResponseDto(timestamp.lastUpdatedAt, timestamp.createdAt, timestamp.deletedAt as string); } + + private static assertUnreachableCode(anyObject: never): never { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + throw new Error(`Unexpected object: ${anyObject}`); + } } diff --git a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts index 42a55321b12..651de6ae4d8 100644 --- a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts +++ b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts @@ -125,48 +125,4 @@ describe('CommonCartridgeExportService', () => { expect(result).toEqual(expected); }); }); - - // describe('findAllCardsByIds', () => { - // const setup = () => { - // const cardsIds: Array = new Array(faker.string.uuid()); - // const mockCard: CardResponseDto = { - // id: cardsIds[0], - // title: faker.lorem.word(), - // height: faker.number.int(), - // elements: [ - // { - // id: 'element-1', - // type: ContentElementType.RICH_TEXT, - // content: { - // text: faker.string.alphanumeric.toString(), - // inputFormat: 'HTML', - // }, - // timestamps: { - // lastUpdatedAt: faker.date.anytime.toString(), - // createdAt: faker.date.anytime.toString(), - // deletedAt: '', - // }, - // }, - // ], - // visibilitySettings: { - // publishedAt: '2024-10-01T12:00:00Z', - // }, - // timeStamps: { - // lastUpdatedAt: '2024-10-01T11:00:00Z', - // createdAt: faker.date.anytime.toString(), - // deletedAt: faker.date.anytime.toString(), - // }, - // }; - // const expected: CardListResponseDto = new CardListResponseDto(new Array(mockCard)); - // cardClientAdapterMock.getAllBoardCardsByIds.mockResolvedValue(expected); - - // return { cardsIds, expected }; - // }; - // it('should return a card', () => { - // const { cardsIds, expected } = setup(); - // const result = sut.findAllCardsByIds(cardsIds); - - // expect(result).toEqual(expected); - // }); - // }); }); From 8485ce412519abf3229641707ae7df2e0019702d Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 25 Oct 2024 07:26:16 +0200 Subject: [PATCH 25/47] ew-1009: trial 1, removing return --- .../card-client/mapper/card-response.mapper.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts index 75c76d742c9..11c7588522b 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts @@ -156,7 +156,7 @@ export class CardResponseMapper { private static mapToElementsContent( response: CardResponseElementsInner, elementType: ContentElementType - ): CardContentElementInner { + ): CardContentElementInner | undefined { // eslint-disable-next-line default-case switch (elementType) { case ContentElementType.COLLABORATIVE_TEXT_EDITOR: @@ -199,8 +199,6 @@ export class CardResponseMapper { const richTextResponse: RichTextElementResponse = response as RichTextElementResponse; return new RichTextElementContentDto(richTextResponse.content.text, richTextResponse.content.inputFormat); } - default: - return this.assertUnreachableCode(elementType); } } @@ -213,9 +211,4 @@ export class CardResponseMapper { private static mapToTimestampDto(timestamp: TimestampsResponse): TimestampResponseDto { return new TimestampResponseDto(timestamp.lastUpdatedAt, timestamp.createdAt, timestamp.deletedAt as string); } - - private static assertUnreachableCode(anyObject: never): never { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - throw new Error(`Unexpected object: ${anyObject}`); - } } From 39898421bf9811bd0992fc53c3646eae2cbbdde1 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 25 Oct 2024 07:26:53 +0200 Subject: [PATCH 26/47] ew-1009: trial 1 removing return --- .../card-client/mapper/card-response.mapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts index 11c7588522b..7a49a61e0cc 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts @@ -156,7 +156,7 @@ export class CardResponseMapper { private static mapToElementsContent( response: CardResponseElementsInner, elementType: ContentElementType - ): CardContentElementInner | undefined { + ): CardContentElementInner { // eslint-disable-next-line default-case switch (elementType) { case ContentElementType.COLLABORATIVE_TEXT_EDITOR: From 9e602c6084ab5addb71dbdb02ca9802fe5264440 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 25 Oct 2024 07:43:41 +0200 Subject: [PATCH 27/47] ew-1009: modified mapper to include only one switch statement --- .../mapper/card-response.mapper.ts | 116 +++++++----------- 1 file changed, 41 insertions(+), 75 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts index 7a49a61e0cc..54cf32a2436 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts @@ -4,13 +4,13 @@ import { CardResponseElementsInner, VisibilitySettingsResponse, TimestampsResponse, - DeletedElementResponse, - SubmissionContainerElementResponse, - DrawingElementResponse, - ExternalToolElementResponse, - FileElementResponse, - LinkElementResponse, - RichTextElementResponse, + DeletedElementContent, + SubmissionContainerElementContent, + DrawingElementContent, + ExternalToolElementContent, + FileElementContent, + LinkElementContent, + RichTextElementContent, } from '../cards-api-client'; import { CardResponseDto } from '../dto/card-response.dto'; import { CollaborativeTextEditorElementResponseDto } from '../dto/collaborative-text-editor-element-response.dto'; @@ -31,7 +31,6 @@ import { SubmissionContainerElementContentDto } from '../dto/submission-containe import { DeletedElementContentDto } from '../dto/deleted-element-content.dto'; import { VisibilitySettingsResponseDto } from '../dto/visibility-settings-response.dto'; import { TimestampResponseDto } from '../dto/timestamp-response.dto'; -import { CardContentElementInner } from '../types/card-content-elements-inner.type'; import { CardResponseElementsInnerDto } from '../types/card-response-elements-inner.type'; import { CardListResponseDto } from '../dto/card-list-response.dto'; @@ -68,84 +67,100 @@ export class CardResponseMapper { new CollaborativeTextEditorElementResponseDto( element.id, ContentElementType.COLLABORATIVE_TEXT_EDITOR, - this.mapToElementsContent(element, ContentElementType.COLLABORATIVE_TEXT_EDITOR), + {}, this.mapToTimestampDto(element.timestamps) ) ); break; - case ContentElementType.DELETED: + case ContentElementType.DELETED: { + const content: DeletedElementContent = element.content as DeletedElementContent; elements.push( new DeletedElementResponseDto( element.id, ContentElementType.DELETED, - this.mapToElementsContent(element, ContentElementType.DELETED) as DeletedElementContentDto, + new DeletedElementContentDto(content.title, ContentElementType.DELETED, content.description), this.mapToTimestampDto(element.timestamps) ) ); break; - case ContentElementType.SUBMISSION_CONTAINER: + } + case ContentElementType.SUBMISSION_CONTAINER: { + const content: SubmissionContainerElementContent = element.content as SubmissionContainerElementContent; elements.push( new SubmissionContainerElementResponseDto( element.id, ContentElementType.SUBMISSION_CONTAINER, - this.mapToElementsContent( - element, - ContentElementType.SUBMISSION_CONTAINER - ) as SubmissionContainerElementContentDto, + new SubmissionContainerElementContentDto(content.dueDate), this.mapToTimestampDto(element.timestamps) ) ); break; - case ContentElementType.DRAWING: + } + case ContentElementType.DRAWING: { + const content: DrawingElementContent = element.content as DrawingElementContent; elements.push( new DrawingElementResponseDto( element.id, ContentElementType.DRAWING, - this.mapToElementsContent(element, ContentElementType.DRAWING) as DrawingElementContentDto, + new DrawingElementContentDto(content.description), this.mapToTimestampDto(element.timestamps) ) ); break; - case ContentElementType.EXTERNAL_TOOL: + } + case ContentElementType.EXTERNAL_TOOL: { + const content: ExternalToolElementContent = element.content as ExternalToolElementContent; elements.push( new ExternalToolElementResponseDto( element.id, ContentElementType.EXTERNAL_TOOL, - this.mapToElementsContent(element, ContentElementType.EXTERNAL_TOOL) as ExternalToolElementContentDto, + new ExternalToolElementContentDto(content.contextExternalToolId), this.mapToTimestampDto(element.timestamps) ) ); break; - case ContentElementType.FILE: + } + case ContentElementType.FILE: { + const content: FileElementContent = element.content as FileElementContent; elements.push( new FileElementResponseDto( element.id, ContentElementType.FILE, - this.mapToElementsContent(element, ContentElementType.FILE) as FileElementContentDto, + new FileElementContentDto(content.caption, content.alternativeText), this.mapToTimestampDto(element.timestamps) ) ); break; - case ContentElementType.LINK: + } + case ContentElementType.LINK: { + const content: LinkElementContent = element.content as LinkElementContent; elements.push( new LinkElementResponseDto( element.id, ContentElementType.LINK, - this.mapToElementsContent(element, ContentElementType.LINK) as LinkElementContentDto, + new LinkElementContentDto( + content.url, + content.title, + content.description as string, + content.imageUrl as string + ), this.mapToTimestampDto(element.timestamps) ) ); break; - case ContentElementType.RICH_TEXT: + } + case ContentElementType.RICH_TEXT: { + const content: RichTextElementContent = element.content as RichTextElementContent; elements.push( new RichTextElementResponseDto( element.id, ContentElementType.RICH_TEXT, - this.mapToElementsContent(element, ContentElementType.RICH_TEXT) as RichTextElementContentDto, + new RichTextElementContentDto(content.text, content.inputFormat), this.mapToTimestampDto(element.timestamps) ) ); break; + } default: break; } @@ -153,55 +168,6 @@ export class CardResponseMapper { return elements; } - private static mapToElementsContent( - response: CardResponseElementsInner, - elementType: ContentElementType - ): CardContentElementInner { - // eslint-disable-next-line default-case - switch (elementType) { - case ContentElementType.COLLABORATIVE_TEXT_EDITOR: - return {}; - case ContentElementType.DELETED: { - const deletedElementContent: DeletedElementResponse = response as DeletedElementResponse; - return new DeletedElementContentDto( - deletedElementContent.content.title, - ContentElementType.DELETED, - deletedElementContent.content.description - ); - } - case ContentElementType.SUBMISSION_CONTAINER: { - const submissionContainerResponse: SubmissionContainerElementResponse = - response as SubmissionContainerElementResponse; - return new SubmissionContainerElementContentDto(submissionContainerResponse.content.dueDate); - } - case ContentElementType.DRAWING: { - const drawingResponse: DrawingElementResponse = response as DrawingElementResponse; - return new DrawingElementContentDto(drawingResponse.content.description); - } - case ContentElementType.EXTERNAL_TOOL: { - const externalToolResponse: ExternalToolElementResponse = response as ExternalToolElementResponse; - return new ExternalToolElementContentDto(externalToolResponse.content.contextExternalToolId); - } - case ContentElementType.FILE: { - const fileResponse: FileElementResponse = response as FileElementResponse; - return new FileElementContentDto(fileResponse.content.caption, fileResponse.content.alternativeText); - } - case ContentElementType.LINK: { - const linkElementResponse: LinkElementResponse = response as LinkElementResponse; - return new LinkElementContentDto( - linkElementResponse.content.url, - linkElementResponse.content.title, - linkElementResponse.content.description as string, - linkElementResponse.content.imageUrl as string - ); - } - case ContentElementType.RICH_TEXT: { - const richTextResponse: RichTextElementResponse = response as RichTextElementResponse; - return new RichTextElementContentDto(richTextResponse.content.text, richTextResponse.content.inputFormat); - } - } - } - private static mapToVisibilitySettingsDto( visibilitySettings: VisibilitySettingsResponse ): VisibilitySettingsResponseDto { From 7a36b3633ccbee62b3e0eb58d1037c30d7a251b5 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 25 Oct 2024 08:00:21 +0200 Subject: [PATCH 28/47] ew-1009: removed unneeded hardcoded strings --- .../mapper/card-response.mapper.spec.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index 95007a7a27a..57ae29ed549 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -81,7 +81,7 @@ describe('CardResponseMapper', () => { {} ) as CardResponseElementsInner, ], - visibilitySettings: { publishedAt: '2024-10-01T12:00:00Z' }, + visibilitySettings: { publishedAt: faker.date.past().toISOString() }, timestamps: { lastUpdatedAt: '2024-10-01T11:00:00Z', createdAt: '2024-10-01T10:00:00Z', @@ -127,10 +127,10 @@ describe('CardResponseMapper', () => { {} ) as CardResponseElementsInner, ], - visibilitySettings: { publishedAt: '2024-10-02T12:00:00Z' }, + visibilitySettings: { publishedAt: faker.date.past().toISOString() }, timestamps: { - lastUpdatedAt: '2024-10-02T11:00:00Z', - createdAt: '2024-10-02T10:00:00Z', + lastUpdatedAt: faker.date.past().toISOString(), + createdAt: faker.date.past().toISOString(), deletedAt: faker.date.recent().toString(), }, }, @@ -182,12 +182,12 @@ describe('CardResponseMapper', () => { const mockCardListResponse: CardListResponse = { data: [ { - id: faker.datatype.uuid(), + id: faker.string.uuid(), title: faker.lorem.sentence(), - height: faker.datatype.number({ min: 100, max: 500 }), + height: faker.number.int(), elements: [ createMockElement( - faker.datatype.uuid(), + faker.string.uuid(), 'UNKNOWN_TYPE' as ContentElementType, {} ) as CardResponseElementsInner, From d7d338cd1d302eadd6b9000dd484284a3281b5f5 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 25 Oct 2024 08:03:22 +0200 Subject: [PATCH 29/47] ew-1009: test issue solved --- .../card-client/mapper/card-response.mapper.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index 57ae29ed549..6615ab579dc 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -81,7 +81,7 @@ describe('CardResponseMapper', () => { {} ) as CardResponseElementsInner, ], - visibilitySettings: { publishedAt: faker.date.past().toISOString() }, + visibilitySettings: { publishedAt: '2024-10-01T12:00:00Z' }, timestamps: { lastUpdatedAt: '2024-10-01T11:00:00Z', createdAt: '2024-10-01T10:00:00Z', From 5017ddbdec3d47150937c27ef42fe3299e584551 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 25 Oct 2024 09:12:59 +0200 Subject: [PATCH 30/47] ew-1009: property type changed --- .../card-client/dto/submission-container-element-content.dto.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-content.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-content.dto.ts index 4efa4db70db..75742befce9 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-content.dto.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/dto/submission-container-element-content.dto.ts @@ -1,5 +1,5 @@ export class SubmissionContainerElementContentDto { - dueDate: string; + dueDate?: string; constructor(dueDate: string) { this.dueDate = dueDate; From df45278b4a8cbbfe3aacdc02f4ac3c809c3af7fe Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Fri, 25 Oct 2024 11:17:09 +0200 Subject: [PATCH 31/47] ew-1009: review comments --- .../common-cartridge-export.service.spec.ts | 47 + .../common-cartridge-export.service.ts | 2 +- scripts/filtered-spec.json | 973 ------------------ scripts/openapitools.json | 7 - 4 files changed, 48 insertions(+), 981 deletions(-) delete mode 100644 scripts/filtered-spec.json delete mode 100644 scripts/openapitools.json diff --git a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts index 651de6ae4d8..f6d1066f5b0 100644 --- a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts +++ b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.spec.ts @@ -7,6 +7,9 @@ import { CommonCartridgeExportService } from './common-cartridge-export.service' import { CoursesClientAdapter } from '../common-cartridge-client/course-client'; import { CourseRoomsClientAdapter } from '../common-cartridge-client/room-client'; import { CardClientAdapter } from '../common-cartridge-client/card-client/card-client.adapter'; +import { CardListResponseDto } from '../common-cartridge-client/card-client/dto/card-list-response.dto'; +import { CardResponseDto } from '../common-cartridge-client/card-client/dto/card-response.dto'; +import { ContentElementType } from '../common-cartridge-client/card-client/enums/content-element-type.enum'; describe('CommonCartridgeExportService', () => { let module: TestingModule; @@ -125,4 +128,48 @@ describe('CommonCartridgeExportService', () => { expect(result).toEqual(expected); }); }); + + describe('findAllCardsByIds', () => { + const setup = () => { + const cardsIds: Array = new Array(faker.string.uuid()); + const mockCard: CardResponseDto = { + id: cardsIds[0], + title: faker.lorem.word(), + height: faker.number.int(), + elements: [ + { + id: 'element-1', + type: ContentElementType.RICH_TEXT, + content: { + text: faker.string.alphanumeric.toString(), + inputFormat: 'HTML', + }, + timestamps: { + lastUpdatedAt: faker.date.anytime.toString(), + createdAt: faker.date.anytime.toString(), + deletedAt: '', + }, + }, + ], + visibilitySettings: { + publishedAt: '2024-10-01T12:00:00Z', + }, + timeStamps: { + lastUpdatedAt: '2024-10-01T11:00:00Z', + createdAt: faker.date.anytime.toString(), + deletedAt: faker.date.anytime.toString(), + }, + }; + const expected: CardListResponseDto = new CardListResponseDto(new Array(mockCard)); + cardClientAdapterMock.getAllBoardCardsByIds.mockResolvedValue(expected); + + return { cardsIds, expected }; + }; + it('should return a card', async () => { + const { cardsIds, expected } = setup(); + const result = await sut.findAllCardsByIds(cardsIds); + + expect(result).toEqual(expected); + }); + }); }); diff --git a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts index 59990bd08ac..05895643bf1 100644 --- a/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts +++ b/apps/server/src/modules/common-cartridge/service/common-cartridge-export.service.ts @@ -36,7 +36,7 @@ export class CommonCartridgeExportService { } public async findAllCardsByIds(ids: Array): Promise { - const cards: CardListResponseDto = await this.cardClientAdapter.getAllBoardCardsByIds(ids); + const cards = await this.cardClientAdapter.getAllBoardCardsByIds(ids); return cards; } diff --git a/scripts/filtered-spec.json b/scripts/filtered-spec.json deleted file mode 100644 index 9b6a4b8a0d6..00000000000 --- a/scripts/filtered-spec.json +++ /dev/null @@ -1,973 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Schulcloud-Verbund-Software Server API", - "description": "This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1.", - "version": "3.0", - "contact": {} - }, - "servers": [ - { - "url": "/api/v3/" - } - ], - "paths": { - "/cards": { - "get": { - "operationId": "CardController_getCards", - "summary": "Get a list of cards by their ids.", - "parameters": [ - { - "name": "ids", - "required": true, - "in": "query", - "description": "Array of Ids to be loaded", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CardListResponse" - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiValidationError" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenException" - } - } - } - } - }, - "tags": [ - "Board Card" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/cards/{cardId}/position": { - "put": { - "operationId": "CardController_moveCard", - "summary": "Move a single card.", - "parameters": [ - { - "name": "cardId", - "required": true, - "in": "path", - "description": "The id of the card.", - "schema": { - "nullable": false, - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MoveCardBodyParams" - } - } - } - }, - "responses": { - "204": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiValidationError" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenException" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotFoundException" - } - } - } - } - }, - "tags": [ - "Board Card" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/cards/{cardId}/height": { - "patch": { - "operationId": "CardController_updateCardHeight", - "summary": "Update the height of a single card.", - "parameters": [ - { - "name": "cardId", - "required": true, - "in": "path", - "description": "The id of the card.", - "schema": { - "nullable": false, - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetHeightBodyParams" - } - } - } - }, - "responses": { - "204": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiValidationError" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenException" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotFoundException" - } - } - } - } - }, - "tags": [ - "Board Card" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/cards/{cardId}/title": { - "patch": { - "operationId": "CardController_updateCardTitle", - "summary": "Update the title of a single card.", - "parameters": [ - { - "name": "cardId", - "required": true, - "in": "path", - "description": "The id of the card.", - "schema": { - "nullable": false, - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RenameBodyParams" - } - } - } - }, - "responses": { - "204": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiValidationError" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenException" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotFoundException" - } - } - } - } - }, - "tags": [ - "Board Card" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/cards/{cardId}": { - "delete": { - "operationId": "CardController_deleteCard", - "summary": "Delete a single card.", - "parameters": [ - { - "name": "cardId", - "required": true, - "in": "path", - "description": "The id of the card.", - "schema": { - "nullable": false, - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "" - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiValidationError" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenException" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotFoundException" - } - } - } - } - }, - "tags": [ - "Board Card" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/cards/{cardId}/elements": { - "post": { - "operationId": "CardController_createElement", - "summary": "Create a new element on a card.", - "parameters": [ - { - "name": "cardId", - "required": true, - "in": "path", - "description": "The id of the card.", - "schema": { - "nullable": false, - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateContentElementBodyParams" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/ExternalToolElementResponse" - }, - { - "$ref": "#/components/schemas/FileElementResponse" - }, - { - "$ref": "#/components/schemas/LinkElementResponse" - }, - { - "$ref": "#/components/schemas/RichTextElementResponse" - }, - { - "$ref": "#/components/schemas/SubmissionContainerElementResponse" - }, - { - "$ref": "#/components/schemas/DrawingElementResponse" - }, - { - "$ref": "#/components/schemas/DeletedElementResponse" - } - ] - } - } - } - }, - "400": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiValidationError" - } - } - } - }, - "403": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ForbiddenException" - } - } - } - }, - "404": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotFoundException" - } - } - } - } - }, - "tags": [ - "Board Card" - ], - "security": [ - { - "bearer": [] - } - ] - } - } - }, - "components": { - "securitySchemes": { - "bearer": { - "scheme": "bearer", - "bearerFormat": "JWT", - "type": "http" - } - }, - "schemas": { - "ApiValidationError": { - "type": "object", - "properties": { - "code": { - "type": "number", - "description": "The response status code." - }, - "type": { - "type": "string", - "description": "The error type." - }, - "title": { - "type": "string", - "description": "The error title." - }, - "message": { - "type": "string", - "description": "The error message." - }, - "details": { - "type": "object", - "description": "The error details." - } - }, - "required": [ - "code", - "type", - "title", - "message" - ] - }, - "ForbiddenException": { - "type": "object", - "properties": {} - }, - "NotFoundException": { - "type": "object", - "properties": {} - }, - "TimestampsResponse": { - "type": "object", - "properties": { - "lastUpdatedAt": { - "format": "date-time", - "type": "string" - }, - "createdAt": { - "format": "date-time", - "type": "string" - }, - "deletedAt": { - "format": "date-time", - "type": "string" - } - }, - "required": [ - "lastUpdatedAt", - "createdAt" - ] - }, - "RenameBodyParams": { - "type": "object", - "properties": { - "title": { - "type": "string", - "nullable": false - } - }, - "required": [ - "title" - ] - }, - "ContentElementType": { - "type": "string", - "enum": [ - "file", - "drawing", - "link", - "richText", - "submissionContainer", - "externalTool", - "collaborativeTextEditor", - "deleted" - ] - }, - "ExternalToolElementContent": { - "type": "object", - "properties": { - "contextExternalToolId": { - "type": "string", - "nullable": true - } - }, - "required": [ - "contextExternalToolId" - ] - }, - "ExternalToolElementResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "[a-f0-9]{24}" - }, - "type": { - "$ref": "#/components/schemas/ContentElementType" - }, - "content": { - "$ref": "#/components/schemas/ExternalToolElementContent" - }, - "timestamps": { - "$ref": "#/components/schemas/TimestampsResponse" - } - }, - "required": [ - "id", - "type", - "content", - "timestamps" - ] - }, - "FileElementContent": { - "type": "object", - "properties": { - "caption": { - "type": "string" - }, - "alternativeText": { - "type": "string" - } - }, - "required": [ - "caption", - "alternativeText" - ] - }, - "FileElementResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "[a-f0-9]{24}" - }, - "type": { - "$ref": "#/components/schemas/ContentElementType" - }, - "content": { - "$ref": "#/components/schemas/FileElementContent" - }, - "timestamps": { - "$ref": "#/components/schemas/TimestampsResponse" - } - }, - "required": [ - "id", - "type", - "content", - "timestamps" - ] - }, - "LinkElementContent": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "imageUrl": { - "type": "string" - } - }, - "required": [ - "url", - "title" - ] - }, - "LinkElementResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "[a-f0-9]{24}" - }, - "type": { - "$ref": "#/components/schemas/ContentElementType" - }, - "content": { - "$ref": "#/components/schemas/LinkElementContent" - }, - "timestamps": { - "$ref": "#/components/schemas/TimestampsResponse" - } - }, - "required": [ - "id", - "type", - "content", - "timestamps" - ] - }, - "RichTextElementContent": { - "type": "object", - "properties": { - "text": { - "type": "string" - }, - "inputFormat": { - "type": "string" - } - }, - "required": [ - "text", - "inputFormat" - ] - }, - "RichTextElementResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "[a-f0-9]{24}" - }, - "type": { - "$ref": "#/components/schemas/ContentElementType" - }, - "content": { - "$ref": "#/components/schemas/RichTextElementContent" - }, - "timestamps": { - "$ref": "#/components/schemas/TimestampsResponse" - } - }, - "required": [ - "id", - "type", - "content", - "timestamps" - ] - }, - "DrawingElementContent": { - "type": "object", - "properties": { - "description": { - "type": "string" - } - }, - "required": [ - "description" - ] - }, - "DrawingElementResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "[a-f0-9]{24}" - }, - "type": { - "$ref": "#/components/schemas/ContentElementType" - }, - "timestamps": { - "$ref": "#/components/schemas/TimestampsResponse" - }, - "content": { - "$ref": "#/components/schemas/DrawingElementContent" - } - }, - "required": [ - "id", - "type", - "timestamps", - "content" - ] - }, - "SubmissionContainerElementContent": { - "type": "object", - "properties": { - "dueDate": { - "format": "date-time", - "type": "string", - "description": "The dueDate as date string or null of not set", - "example": "2023-08-17T14:17:51.958+00:00" - } - }, - "required": [ - "dueDate" - ] - }, - "SubmissionContainerElementResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "[a-f0-9]{24}" - }, - "type": { - "$ref": "#/components/schemas/ContentElementType" - }, - "content": { - "$ref": "#/components/schemas/SubmissionContainerElementContent" - }, - "timestamps": { - "$ref": "#/components/schemas/TimestampsResponse" - } - }, - "required": [ - "id", - "type", - "content", - "timestamps" - ] - }, - "CollaborativeTextEditorElementResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "[a-f0-9]{24}" - }, - "type": { - "$ref": "#/components/schemas/ContentElementType" - }, - "timestamps": { - "$ref": "#/components/schemas/TimestampsResponse" - }, - "content": { - "type": "object" - } - }, - "required": [ - "id", - "type", - "timestamps", - "content" - ] - }, - "DeletedElementContent": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "deletedElementType": { - "$ref": "#/components/schemas/ContentElementType" - }, - "description": { - "type": "string" - } - }, - "required": [ - "title", - "deletedElementType", - "description" - ] - }, - "DeletedElementResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "[a-f0-9]{24}" - }, - "type": { - "$ref": "#/components/schemas/ContentElementType" - }, - "content": { - "$ref": "#/components/schemas/DeletedElementContent" - }, - "timestamps": { - "$ref": "#/components/schemas/TimestampsResponse" - } - }, - "required": [ - "id", - "type", - "content", - "timestamps" - ] - }, - "VisibilitySettingsResponse": { - "type": "object", - "properties": { - "publishedAt": { - "type": "string" - } - } - }, - "CardResponse": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "[a-f0-9]{24}" - }, - "title": { - "type": "string" - }, - "height": { - "type": "number" - }, - "elements": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ExternalToolElementResponse" - }, - { - "$ref": "#/components/schemas/FileElementResponse" - }, - { - "$ref": "#/components/schemas/LinkElementResponse" - }, - { - "$ref": "#/components/schemas/RichTextElementResponse" - }, - { - "$ref": "#/components/schemas/SubmissionContainerElementResponse" - }, - { - "$ref": "#/components/schemas/DrawingElementResponse" - }, - { - "$ref": "#/components/schemas/CollaborativeTextEditorElementResponse" - }, - { - "$ref": "#/components/schemas/DeletedElementResponse" - } - ] - } - }, - "visibilitySettings": { - "$ref": "#/components/schemas/VisibilitySettingsResponse" - }, - "timestamps": { - "$ref": "#/components/schemas/TimestampsResponse" - } - }, - "required": [ - "id", - "height", - "elements", - "visibilitySettings", - "timestamps" - ] - }, - "CardListResponse": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CardResponse" - } - } - }, - "required": [ - "data" - ] - }, - "MoveCardBodyParams": { - "type": "object", - "properties": { - "toColumnId": { - "type": "string", - "nullable": false - }, - "toPosition": { - "type": "number", - "nullable": false - } - }, - "required": [ - "toColumnId", - "toPosition" - ] - }, - "SetHeightBodyParams": { - "type": "object", - "properties": { - "height": { - "type": "number", - "nullable": false - } - }, - "required": [ - "height" - ] - }, - "CreateContentElementBodyParams": { - "type": "object", - "properties": { - "type": { - "description": "The type of element", - "nullable": false, - "$ref": "#/components/schemas/ContentElementType" - }, - "toPosition": { - "type": "number", - "description": "to bring element to a specific position, default is last position", - "nullable": false - } - }, - "required": [ - "type" - ] - } - } - } -} \ No newline at end of file diff --git a/scripts/openapitools.json b/scripts/openapitools.json deleted file mode 100644 index f80faaa6d18..00000000000 --- a/scripts/openapitools.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json", - "spaces": 2, - "generator-cli": { - "version": "7.9.0" - } -} From c417e475867451ad6a16b44fd5d5a6117b36e980 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Mon, 28 Oct 2024 06:06:15 +0100 Subject: [PATCH 32/47] ew-1009: unnecessary space removed --- sonar-project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonar-project.properties b/sonar-project.properties index ff67c5c84dc..79cbc0385fe 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.projectKey=hpi-schul-cloud_schulcloud-server sonar.sources=. sonar.tests=. sonar.test.inclusions=**/*.spec.ts -sonar.exclusions=**/*.js,jest.config.ts,globalSetup.ts,globalTeardown.ts,**/*.app.ts,**/seed-data/*.ts,**/migrations/mikro-orm/*.ts,**/etherpad-api-client/**/*.ts,**/authorization-api-client/**/*.ts, **/course-api-client/**/*.ts,**/board-api-client/**/*.ts,**/generated/**/*.ts,**/room-api-client/**/*.ts, **/cards-api-client/**/*.ts +sonar.exclusions=**/*.js,jest.config.ts,globalSetup.ts,globalTeardown.ts,**/*.app.ts,**/seed-data/*.ts,**/migrations/mikro-orm/*.ts,**/etherpad-api-client/**/*.ts,**/authorization-api-client/**/*.ts, **/course-api-client/**/*.ts,**/board-api-client/**/*.ts,**/generated/**/*.ts,**/room-api-client/**/*.ts,**/cards-api-client/**/*.ts sonar.coverage.exclusions=**/board-management.uc.ts,**/*.module.ts,**/*.factory.ts,**/migrations/mikro-orm/*.ts,**/globalSetup.ts,**/globalTeardown.ts,**/etherpad-api-client/**/*.ts,**/authorization-api-client/**/*.ts, **/course-api-client/**/*.ts,**/board-api-client/**/*.ts,**/generated/**/*.ts,**/room-api-client/**/*.ts sonar.cpd.exclusions=**/controller/dto/**/*.ts,**/api/dto/**/*.ts,**/shared/testing/factory/*.factory.ts sonar.javascript.lcov.reportPaths=merged-lcov.info From 548fdf825661cd6fe65f19ede11fa60d04b1b496 Mon Sep 17 00:00:00 2001 From: mamutmk5 <3045922+mamutmk5@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:55:59 +0200 Subject: [PATCH 33/47] BC-8312 - fix state for External Secret for TLDraw server (#5312) --- ansible/roles/schulcloud-server-core/tasks/main.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ansible/roles/schulcloud-server-core/tasks/main.yml b/ansible/roles/schulcloud-server-core/tasks/main.yml index 89f5e60f84c..28c8a15460b 100644 --- a/ansible/roles/schulcloud-server-core/tasks/main.yml +++ b/ansible/roles/schulcloud-server-core/tasks/main.yml @@ -376,12 +376,10 @@ kubeconfig: ~/.kube/config namespace: "{{ NAMESPACE }}" template: tldraw-server-external-secret.yml.j2 - state: "{{ 'present' if - WITH_BRANCH_MONGO_DB_MANAGEMENT is defined and WITH_BRANCH_MONGO_DB_MANAGEMENT|bool and - WITH_TLDRAW is defined and WITH_TLDRAW|bool - else 'absent'}}" + state: "{{ 'present' if WITH_BRANCH_MONGO_DB_MANAGEMENT is defined and WITH_BRANCH_MONGO_DB_MANAGEMENT|bool else 'absent'}}" when: - - EXTERNAL_SECRETS_OPERATOR is defined and EXTERNAL_SECRETS_OPERATOR|bool + - EXTERNAL_SECRETS_OPERATOR is defined and EXTERNAL_SECRETS_OPERATOR|bool + - WITH_TLDRAW is defined and WITH_TLDRAW|bool tags: - 1password From 9b20e7085701f409dcbf66bcaeca3db7604cf75e Mon Sep 17 00:00:00 2001 From: Majed Mak <132336669+MajedAlaitwniCap@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:20:28 +0200 Subject: [PATCH 34/47] EW-1008 Decouple lesson dependency from common-cartridge module (#5300) Add generated API for Lesson to decouple common cartridge module --- .../lesson-client/dto/index.ts | 4 + .../lesson-client/dto/lesson-contents.dto.ts | 28 +++ .../dto/lesson-linked-task.dto.ts | 50 ++++ .../lesson-client/dto/lesson-materials.dto.ts | 25 ++ .../lesson-client/dto/lesson.dto.ts | 31 +++ .../lesson-client.adapter.spec.ts | 211 ++++++++++++++++ .../lesson-client/lesson-client.adapter.ts | 47 ++++ .../lesson-client/lesson-client.config.ts | 5 + .../lesson-client.module.spec.ts | 29 +++ .../lesson-client/lesson-client.module.ts | 26 ++ .../lessons-api-client/.gitignore | 4 + .../lessons-api-client/.npmignore | 1 + .../.openapi-generator-ignore | 23 ++ .../.openapi-generator/FILES | 17 ++ .../.openapi-generator/VERSION | 1 + .../lesson-client/lessons-api-client/api.ts | 18 ++ .../lessons-api-client/api/lesson-api.ts | 228 ++++++++++++++++++ .../lesson-client/lessons-api-client/base.ts | 86 +++++++ .../lessons-api-client/common.ts | 150 ++++++++++++ .../lessons-api-client/configuration.ts | 110 +++++++++ .../lessons-api-client/git_push.sh | 57 +++++ .../lesson-client/lessons-api-client/index.ts | 18 ++ .../lessons-api-client/models/index.ts | 6 + .../models/lesson-content-response.ts | 73 ++++++ .../models/lesson-linked-task-response.ts | 106 ++++++++ .../models/lesson-metadata-list-response.ts | 51 ++++ .../models/lesson-metadata-response.ts | 36 +++ .../models/lesson-response.ts | 85 +++++++ .../models/material-response.ts | 72 ++++++ .../mapper/lesson-dto.mapper.spec.ts | 129 ++++++++++ .../lesson-client/mapper/lesson-dto.mapper.ts | 68 ++++++ .../common-cartridge.module.ts | 10 +- sonar-project.properties | 2 +- 33 files changed, 1803 insertions(+), 4 deletions(-) create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/index.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-contents.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-linked-task.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-materials.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson.dto.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.adapter.spec.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.adapter.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.config.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.module.spec.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.module.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.gitignore create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.npmignore create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator-ignore create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator/FILES create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator/VERSION create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/api.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/api/lesson-api.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/base.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/common.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/configuration.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/git_push.sh create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/index.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/index.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-content-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-linked-task-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-metadata-list-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-metadata-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/material-response.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/mapper/lesson-dto.mapper.spec.ts create mode 100644 apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/mapper/lesson-dto.mapper.ts diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/index.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/index.ts new file mode 100644 index 00000000000..08e0eea5cf6 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/index.ts @@ -0,0 +1,4 @@ +export * from './lesson.dto'; +export * from './lesson-materials.dto'; +export * from './lesson-contents.dto'; +export * from './lesson-linked-task.dto'; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-contents.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-contents.dto.ts new file mode 100644 index 00000000000..e9f00a471d4 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-contents.dto.ts @@ -0,0 +1,28 @@ +export class LessonContentDto { + content: object; + + title: string; + + component: LessonContentDtoComponent; + + hidden: boolean; + + constructor(props: LessonContentDto) { + this.content = props.content; + this.title = props.title; + this.component = props.component; + this.hidden = props.hidden; + } +} + +export const LessonContentDtoComponentValues = { + ETHERPAD: 'Etherpad', + GEO_GEBRA: 'geoGebra', + INTERNAL: 'internal', + RESOURCES: 'resources', + TEXT: 'text', + NE_XBOARD: 'neXboard', +} as const; + +export type LessonContentDtoComponent = + typeof LessonContentDtoComponentValues[keyof typeof LessonContentDtoComponentValues]; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-linked-task.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-linked-task.dto.ts new file mode 100644 index 00000000000..f2b5344b4ac --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-linked-task.dto.ts @@ -0,0 +1,50 @@ +export class LessonLinkedTaskDto { + name: string; + + description: string; + + descriptionInputFormat: LessonLinkedTaskDescriptionInputFormatType; + + availableDate: string | null; + + dueDate: string | null; + + private: boolean; + + publicSubmissions: boolean | null; + + teamSubmissions: boolean | null; + + creator: string | null; + + courseId: string | null; + + submissionIds: string[]; + + finishedIds: string[]; + + constructor(props: LessonLinkedTaskDto) { + this.name = props.name; + this.description = props.description; + this.descriptionInputFormat = props.descriptionInputFormat; + this.availableDate = props.availableDate; + this.dueDate = props.dueDate; + this.private = props.private; + this.creator = props.creator; + this.courseId = props.courseId; + this.publicSubmissions = props.publicSubmissions; + this.teamSubmissions = props.teamSubmissions; + this.submissionIds = props.submissionIds; + this.finishedIds = props.finishedIds; + } +} + +export const LessonLinkedTaskDescriptionInputFormat = { + PLAIN_TEXT: 'plainText', + RICH_TEXT_CK5_SIMPLE: 'richTextCk5Simple', + RICH_TEXT_CK4: 'richTextCk4', + RICH_TEXT_CK5: 'richTextCk5', +} as const; + +export type LessonLinkedTaskDescriptionInputFormatType = + typeof LessonLinkedTaskDescriptionInputFormat[keyof typeof LessonLinkedTaskDescriptionInputFormat]; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-materials.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-materials.dto.ts new file mode 100644 index 00000000000..daec368ce49 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson-materials.dto.ts @@ -0,0 +1,25 @@ +export class LessonMaterialsDto { + materialsId: string; + + title: string; + + relatedResources: string[]; + + url: string; + + client: string; + + license: string[]; + + merlinReference: string; + + constructor(props: LessonMaterialsDto) { + this.materialsId = props.materialsId; + this.title = props.title; + this.relatedResources = props.relatedResources; + this.url = props.url; + this.client = props.client; + this.license = props.license; + this.merlinReference = props.merlinReference; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson.dto.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson.dto.ts new file mode 100644 index 00000000000..864b6502f19 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/dto/lesson.dto.ts @@ -0,0 +1,31 @@ +import { LessonContentDto } from './lesson-contents.dto'; +import { LessonMaterialsDto } from './lesson-materials.dto'; + +export class LessonDto { + lessonId: string; + + name: string; + + courseId?: string; + + courseGroupId?: string; + + hidden: boolean; + + position: number; + + contents: LessonContentDto[]; + + materials: LessonMaterialsDto[]; + + constructor(props: LessonDto) { + this.lessonId = props.lessonId; + this.name = props.name; + this.courseId = props.courseId; + this.courseGroupId = props.courseGroupId; + this.hidden = props.hidden; + this.position = props.position; + this.contents = props.contents; + this.materials = props.materials; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.adapter.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.adapter.spec.ts new file mode 100644 index 00000000000..fef7a941220 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.adapter.spec.ts @@ -0,0 +1,211 @@ +import { faker } from '@faker-js/faker'; +import { createMock, DeepMocked } from '@golevelup/ts-jest'; +import { UnauthorizedException } from '@nestjs/common'; +import { REQUEST } from '@nestjs/core'; +import { Test, TestingModule } from '@nestjs/testing'; +import { AxiosResponse } from 'axios'; +import { Request } from 'express'; +import { LessonClientAdapter } from './lesson-client.adapter'; +import { LessonApi, LessonLinkedTaskResponse, LessonResponse } from './lessons-api-client'; + +describe(LessonClientAdapter.name, () => { + let module: TestingModule; + let sut: LessonClientAdapter; + let lessonApiMock: DeepMocked; + const jwtToken = faker.string.alphanumeric(20); + + beforeAll(async () => { + module = await Test.createTestingModule({ + providers: [ + LessonClientAdapter, + { + provide: LessonApi, + useValue: createMock(), + }, + { + provide: REQUEST, + useValue: createMock({ + headers: { + authorization: `Bearer ${jwtToken}`, + }, + }), + }, + ], + }).compile(); + + sut = module.get(LessonClientAdapter); + lessonApiMock = module.get(LessonApi); + }); + + afterAll(async () => { + await module.close(); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it('should be defined', () => { + expect(sut).toBeDefined(); + }); + + describe('getLessonById', () => { + describe('When getLessonById is called', () => { + const setup = () => { + const response = createMock>({ + data: { + _id: faker.string.uuid(), + id: faker.string.uuid(), + name: faker.lorem.sentence(), + courseId: faker.string.uuid(), + courseGroupId: faker.string.uuid(), + hidden: faker.datatype.boolean(), + position: faker.number.int(), + contents: [ + { + content: { text: faker.lorem.sentence() }, + _id: faker.string.uuid(), + id: faker.string.uuid(), + title: faker.lorem.sentence(), + component: faker.helpers.arrayElement(['Etherpad', 'geoGebra', 'neXboard']), + hidden: faker.datatype.boolean(), + }, + ], + materials: [ + { + _id: faker.string.uuid(), + id: faker.string.uuid(), + title: faker.lorem.sentence(), + relatedResources: [faker.lorem.sentence()], + url: faker.internet.url(), + client: faker.lorem.sentence(), + license: [faker.lorem.sentence()], + merlinReference: faker.lorem.sentence(), + }, + ], + }, + }); + + lessonApiMock.lessonControllerGetLesson.mockResolvedValue(response); + + return { lessonId: response.data.id }; + }; + + it('should call lessonControllerGetLesson', async () => { + const { lessonId } = setup(); + + await sut.getLessonById(lessonId); + + expect(lessonApiMock.lessonControllerGetLesson).toHaveBeenCalled(); + }); + }); + + describe('When getLessonById is called with invalid id', () => { + const setup = () => { + const lessonResponseId = faker.string.uuid(); + + lessonApiMock.lessonControllerGetLesson.mockRejectedValueOnce(new Error('error')); + + return { lessonResponseId }; + }; + + it('should throw an error', async () => { + const { lessonResponseId } = setup(); + + const result = sut.getLessonById(lessonResponseId); + + await expect(result).rejects.toThrowError('error'); + }); + }); + + describe('When no JWT token is found', () => { + const setup = () => { + const lessonResponseId = faker.string.uuid(); + const request = createMock({ + headers: {}, + }) as Request; + + const adapter: LessonClientAdapter = new LessonClientAdapter(lessonApiMock, request); + + return { lessonResponseId, adapter }; + }; + + it('should throw an UnauthorizedError', async () => { + const { lessonResponseId, adapter } = setup(); + + await expect(adapter.getLessonById(lessonResponseId)).rejects.toThrowError(UnauthorizedException); + }); + }); + }); + + describe('getLessonTasks', () => { + describe('When getLessonTasks is called', () => { + const setup = () => { + const lessonId = faker.string.uuid(); + const response = createMock>({ + data: [ + { + name: faker.lorem.sentence(), + description: faker.lorem.sentence(), + descriptionInputFormat: faker.helpers.arrayElement(['plainText', 'richTextCk4', 'richTextCk5Simple']), + availableDate: faker.date.recent().toString(), + dueDate: faker.date.future().toString(), + private: faker.datatype.boolean(), + publicSubmissions: faker.datatype.boolean(), + teamSubmissions: faker.datatype.boolean(), + }, + ], + }); + + lessonApiMock.lessonControllerGetLessonTasks.mockResolvedValue(response); + + return { lessonId }; + }; + + it('should call lessonControllerGetLessonTasks', async () => { + const { lessonId } = setup(); + + await sut.getLessonTasks(lessonId); + + expect(lessonApiMock.lessonControllerGetLessonTasks).toHaveBeenCalled(); + }); + }); + + describe('When getLessonTasks is called with invalid id', () => { + const setup = () => { + const lessonResponseId = faker.string.uuid(); + + lessonApiMock.lessonControllerGetLessonTasks.mockRejectedValueOnce(new Error('error')); + + return { lessonResponseId }; + }; + + it('should throw an error', async () => { + const { lessonResponseId } = setup(); + + const result = sut.getLessonTasks(lessonResponseId); + + await expect(result).rejects.toThrowError('error'); + }); + }); + + describe('When no JWT token is found', () => { + const setup = () => { + const lessonResponseId = faker.string.uuid(); + const request = createMock({ + headers: {}, + }) as Request; + + const adapter: LessonClientAdapter = new LessonClientAdapter(lessonApiMock, request); + + return { lessonResponseId, adapter }; + }; + + it('should throw an UnauthorizedError', async () => { + const { lessonResponseId, adapter } = setup(); + + await expect(adapter.getLessonTasks(lessonResponseId)).rejects.toThrowError(UnauthorizedException); + }); + }); + }); +}); diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.adapter.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.adapter.ts new file mode 100644 index 00000000000..22e8abf7eec --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.adapter.ts @@ -0,0 +1,47 @@ +import { Inject, Injectable, UnauthorizedException } from '@nestjs/common'; +import { REQUEST } from '@nestjs/core'; +import { extractJwtFromHeader } from '@shared/common'; +import { RawAxiosRequestConfig } from 'axios'; +import { Request } from 'express'; +import { LessonDto, LessonLinkedTaskDto } from './dto'; +import { LessonApi } from './lessons-api-client'; +import { LessonDtoMapper } from './mapper/lesson-dto.mapper'; + +@Injectable() +export class LessonClientAdapter { + constructor(private readonly lessonApi: LessonApi, @Inject(REQUEST) private request: Request) {} + + public async getLessonById(lessonId: string): Promise { + const options = this.createOptionParams(); + const response = await this.lessonApi.lessonControllerGetLesson(lessonId, options); + const lessonDto = LessonDtoMapper.mapToLessonDto(response.data); + + return lessonDto; + } + + public async getLessonTasks(lessonId: string): Promise { + const options = this.createOptionParams(); + const response = await this.lessonApi.lessonControllerGetLessonTasks(lessonId, options); + + const lessonTasksDtoList = response.data.map((task) => LessonDtoMapper.mapToLessonLinkedTaskDto(task)); + + return lessonTasksDtoList; + } + + private createOptionParams(): RawAxiosRequestConfig { + const jwt = this.getJwt(); + const options: RawAxiosRequestConfig = { headers: { authorization: `Bearer ${jwt}` } }; + + return options; + } + + private getJwt(): string { + const jwt = extractJwtFromHeader(this.request) ?? this.request.headers.authorization; + + if (!jwt) { + throw new UnauthorizedException('No JWT found in request'); + } + + return jwt; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.config.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.config.ts new file mode 100644 index 00000000000..2ffb2218be3 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.config.ts @@ -0,0 +1,5 @@ +import { ConfigurationParameters } from './lessons-api-client'; + +export interface LessonClientConfig extends ConfigurationParameters { + basePath: string; +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.module.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.module.spec.ts new file mode 100644 index 00000000000..4761ca36add --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.module.spec.ts @@ -0,0 +1,29 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { LessonClientModule } from './lesson-client.module'; +import { LessonClientAdapter } from './lesson-client.adapter'; + +describe('LessonClientModule', () => { + let module: TestingModule; + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [ + LessonClientModule.register({ + basePath: 'http://localhost:3030/api/v3', + }), + ], + }).compile(); + }); + + afterAll(async () => { + await module.close(); + }); + + describe('when module is initialized', () => { + it('should have the LessonClientAdapter defined', () => { + const lessonClientAdapter = module.get(LessonClientAdapter); + + expect(lessonClientAdapter).toBeDefined(); + }); + }); +}); diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.module.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.module.ts new file mode 100644 index 00000000000..08fdac95d4e --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lesson-client.module.ts @@ -0,0 +1,26 @@ +import { DynamicModule, Module } from '@nestjs/common'; +import { LessonClientConfig } from './lesson-client.config'; +import { LessonClientAdapter } from './lesson-client.adapter'; +import { LessonApi, Configuration } from './lessons-api-client'; + +@Module({}) +export class LessonClientModule { + static register(config: LessonClientConfig): DynamicModule { + const providers = [ + LessonClientAdapter, + { + provide: LessonApi, + useFactory: () => { + const configuration = new Configuration(config); + return new LessonApi(configuration); + }, + }, + ]; + + return { + module: LessonClientModule, + providers, + exports: [LessonClientAdapter], + }; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.gitignore b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.gitignore new file mode 100644 index 00000000000..149b5765472 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.gitignore @@ -0,0 +1,4 @@ +wwwroot/*.js +node_modules +typings +dist diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.npmignore b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.npmignore new file mode 100644 index 00000000000..999d88df693 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.npmignore @@ -0,0 +1 @@ +# empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm \ No newline at end of file diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator-ignore b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator-ignore new file mode 100644 index 00000000000..7484ee590a3 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator/FILES b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator/FILES new file mode 100644 index 00000000000..96db8953479 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator/FILES @@ -0,0 +1,17 @@ +.gitignore +.npmignore +.openapi-generator-ignore +api.ts +api/lesson-api.ts +base.ts +common.ts +configuration.ts +git_push.sh +index.ts +models/index.ts +models/lesson-content-response.ts +models/lesson-linked-task-response.ts +models/lesson-metadata-list-response.ts +models/lesson-metadata-response.ts +models/lesson-response.ts +models/material-response.ts diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator/VERSION b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator/VERSION new file mode 100644 index 00000000000..93c8ddab9fe --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.6.0 diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/api.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/api.ts new file mode 100644 index 00000000000..e2267d5e672 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/api.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +export * from './api/lesson-api'; + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/api/lesson-api.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/api/lesson-api.ts new file mode 100644 index 00000000000..7adc931634b --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/api/lesson-api.ts @@ -0,0 +1,228 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from '../configuration'; +import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios'; +import globalAxios from 'axios'; +// Some imports not used depending on template conditions +// @ts-ignore +import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '../common'; +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, type RequestArgs, BaseAPI, RequiredError, operationServerMap } from '../base'; +// @ts-ignore +import type { LessonLinkedTaskResponse } from '../models'; +// @ts-ignore +import type { LessonResponse } from '../models'; +/** + * LessonApi - axios parameter creator + * @export + */ +export const LessonApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @param {string} lessonId The id of the lesson. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + lessonControllerGetLesson: async (lessonId: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'lessonId' is not null or undefined + assertParamExists('lessonControllerGetLesson', 'lessonId', lessonId) + const localVarPath = `/lessons/{lessonId}` + .replace(`{${"lessonId"}}`, encodeURIComponent(String(lessonId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @param {string} lessonId The id of the lesson. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + lessonControllerGetLessonTasks: async (lessonId: string, options: RawAxiosRequestConfig = {}): Promise => { + // verify required parameter 'lessonId' is not null or undefined + assertParamExists('lessonControllerGetLessonTasks', 'lessonId', lessonId) + const localVarPath = `/lessons/{lessonId}/tasks` + .replace(`{${"lessonId"}}`, encodeURIComponent(String(lessonId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * LessonApi - functional programming interface + * @export + */ +export const LessonApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = LessonApiAxiosParamCreator(configuration) + return { + /** + * + * @param {string} lessonId The id of the lesson. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async lessonControllerGetLesson(lessonId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.lessonControllerGetLesson(lessonId, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['LessonApi.lessonControllerGetLesson']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + /** + * + * @param {string} lessonId The id of the lesson. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async lessonControllerGetLessonTasks(lessonId: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + const localVarAxiosArgs = await localVarAxiosParamCreator.lessonControllerGetLessonTasks(lessonId, options); + const localVarOperationServerIndex = configuration?.serverIndex ?? 0; + const localVarOperationServerBasePath = operationServerMap['LessonApi.lessonControllerGetLessonTasks']?.[localVarOperationServerIndex]?.url; + return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); + }, + } +}; + +/** + * LessonApi - factory interface + * @export + */ +export const LessonApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = LessonApiFp(configuration) + return { + /** + * + * @param {string} lessonId The id of the lesson. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + lessonControllerGetLesson(lessonId: string, options?: any): AxiosPromise { + return localVarFp.lessonControllerGetLesson(lessonId, options).then((request) => request(axios, basePath)); + }, + /** + * + * @param {string} lessonId The id of the lesson. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + lessonControllerGetLessonTasks(lessonId: string, options?: any): AxiosPromise> { + return localVarFp.lessonControllerGetLessonTasks(lessonId, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * LessonApi - interface + * @export + * @interface LessonApi + */ +export interface LessonApiInterface { + /** + * + * @param {string} lessonId The id of the lesson. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof LessonApiInterface + */ + lessonControllerGetLesson(lessonId: string, options?: RawAxiosRequestConfig): AxiosPromise; + + /** + * + * @param {string} lessonId The id of the lesson. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof LessonApiInterface + */ + lessonControllerGetLessonTasks(lessonId: string, options?: RawAxiosRequestConfig): AxiosPromise>; + +} + +/** + * LessonApi - object-oriented interface + * @export + * @class LessonApi + * @extends {BaseAPI} + */ +export class LessonApi extends BaseAPI implements LessonApiInterface { + /** + * + * @param {string} lessonId The id of the lesson. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof LessonApi + */ + public lessonControllerGetLesson(lessonId: string, options?: RawAxiosRequestConfig) { + return LessonApiFp(this.configuration).lessonControllerGetLesson(lessonId, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @param {string} lessonId The id of the lesson. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof LessonApi + */ + public lessonControllerGetLessonTasks(lessonId: string, options?: RawAxiosRequestConfig) { + return LessonApiFp(this.configuration).lessonControllerGetLessonTasks(lessonId, options).then((request) => request(this.axios, this.basePath)); + } +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/base.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/base.ts new file mode 100644 index 00000000000..82686c7b81b --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/base.ts @@ -0,0 +1,86 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from './configuration'; +// Some imports not used depending on template conditions +// @ts-ignore +import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios'; +import globalAxios from 'axios'; + +export const BASE_PATH = "http://localhost/api/v3".replace(/\/+$/, ""); + +/** + * + * @export + */ +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + +/** + * + * @export + * @interface RequestArgs + */ +export interface RequestArgs { + url: string; + options: RawAxiosRequestConfig; +} + +/** + * + * @export + * @class BaseAPI + */ +export class BaseAPI { + protected configuration: Configuration | undefined; + + constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) { + if (configuration) { + this.configuration = configuration; + this.basePath = configuration.basePath ?? basePath; + } + } +}; + +/** + * + * @export + * @class RequiredError + * @extends {Error} + */ +export class RequiredError extends Error { + constructor(public field: string, msg?: string) { + super(msg); + this.name = "RequiredError" + } +} + +interface ServerMap { + [key: string]: { + url: string, + description: string, + }[]; +} + +/** + * + * @export + */ +export const operationServerMap: ServerMap = { +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/common.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/common.ts new file mode 100644 index 00000000000..6c119efb60d --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/common.ts @@ -0,0 +1,150 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from "./configuration"; +import type { RequestArgs } from "./base"; +import type { AxiosInstance, AxiosResponse } from 'axios'; +import { RequiredError } from "./base"; + +/** + * + * @export + */ +export const DUMMY_BASE_URL = 'https://example.com' + +/** + * + * @throws {RequiredError} + * @export + */ +export const assertParamExists = function (functionName: string, paramName: string, paramValue: unknown) { + if (paramValue === null || paramValue === undefined) { + throw new RequiredError(paramName, `Required parameter ${paramName} was null or undefined when calling ${functionName}.`); + } +} + +/** + * + * @export + */ +export const setApiKeyToObject = async function (object: any, keyParamName: string, configuration?: Configuration) { + if (configuration && configuration.apiKey) { + const localVarApiKeyValue = typeof configuration.apiKey === 'function' + ? await configuration.apiKey(keyParamName) + : await configuration.apiKey; + object[keyParamName] = localVarApiKeyValue; + } +} + +/** + * + * @export + */ +export const setBasicAuthToObject = function (object: any, configuration?: Configuration) { + if (configuration && (configuration.username || configuration.password)) { + object["auth"] = { username: configuration.username, password: configuration.password }; + } +} + +/** + * + * @export + */ +export const setBearerAuthToObject = async function (object: any, configuration?: Configuration) { + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + object["Authorization"] = "Bearer " + accessToken; + } +} + +/** + * + * @export + */ +export const setOAuthToObject = async function (object: any, name: string, scopes: string[], configuration?: Configuration) { + if (configuration && configuration.accessToken) { + const localVarAccessTokenValue = typeof configuration.accessToken === 'function' + ? await configuration.accessToken(name, scopes) + : await configuration.accessToken; + object["Authorization"] = "Bearer " + localVarAccessTokenValue; + } +} + +function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: any, key: string = ""): void { + if (parameter == null) return; + if (typeof parameter === "object") { + if (Array.isArray(parameter)) { + (parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key)); + } + else { + Object.keys(parameter).forEach(currentKey => + setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`) + ); + } + } + else { + if (urlSearchParams.has(key)) { + urlSearchParams.append(key, parameter); + } + else { + urlSearchParams.set(key, parameter); + } + } +} + +/** + * + * @export + */ +export const setSearchParams = function (url: URL, ...objects: any[]) { + const searchParams = new URLSearchParams(url.search); + setFlattenedQueryParams(searchParams, objects); + url.search = searchParams.toString(); +} + +/** + * + * @export + */ +export const serializeDataIfNeeded = function (value: any, requestOptions: any, configuration?: Configuration) { + const nonString = typeof value !== 'string'; + const needsSerialization = nonString && configuration && configuration.isJsonMime + ? configuration.isJsonMime(requestOptions.headers['Content-Type']) + : nonString; + return needsSerialization + ? JSON.stringify(value !== undefined ? value : {}) + : (value || ""); +} + +/** + * + * @export + */ +export const toPathString = function (url: URL) { + return url.pathname + url.search + url.hash +} + +/** + * + * @export + */ +export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) { + return >(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...axiosArgs.options, url: (axios.defaults.baseURL ? '' : configuration?.basePath ?? basePath) + axiosArgs.url}; + return axios.request(axiosRequestArgs); + }; +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/configuration.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/configuration.ts new file mode 100644 index 00000000000..8c97d307cf4 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/configuration.ts @@ -0,0 +1,110 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface ConfigurationParameters { + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + username?: string; + password?: string; + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + basePath?: string; + serverIndex?: number; + baseOptions?: any; + formDataCtor?: new () => any; +} + +export class Configuration { + /** + * parameter for apiKey security + * @param name security name + * @memberof Configuration + */ + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + username?: string; + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + password?: string; + /** + * parameter for oauth2 security + * @param name security name + * @param scopes oauth2 scope + * @memberof Configuration + */ + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + /** + * override base path + * + * @type {string} + * @memberof Configuration + */ + basePath?: string; + /** + * override server index + * + * @type {number} + * @memberof Configuration + */ + serverIndex?: number; + /** + * base options for axios calls + * + * @type {any} + * @memberof Configuration + */ + baseOptions?: any; + /** + * The FormData constructor that will be used to create multipart form data + * requests. You can inject this here so that execution environments that + * do not support the FormData class can still run the generated client. + * + * @type {new () => FormData} + */ + formDataCtor?: new () => any; + + constructor(param: ConfigurationParameters = {}) { + this.apiKey = param.apiKey; + this.username = param.username; + this.password = param.password; + this.accessToken = param.accessToken; + this.basePath = param.basePath; + this.serverIndex = param.serverIndex; + this.baseOptions = param.baseOptions; + this.formDataCtor = param.formDataCtor; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime - MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public isJsonMime(mime: string): boolean { + const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i'); + return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json'); + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/git_push.sh b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/git_push.sh new file mode 100644 index 00000000000..f53a75d4fab --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/git_push.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 +git_host=$4 + +if [ "$git_host" = "" ]; then + git_host="github.com" + echo "[INFO] No command line input provided. Set \$git_host to $git_host" +fi + +if [ "$git_user_id" = "" ]; then + git_user_id="GIT_USER_ID" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="GIT_REPO_ID" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="Minor update" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=$(git remote) +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/index.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/index.ts new file mode 100644 index 00000000000..8b762df664e --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/index.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export * from "./api"; +export * from "./configuration"; +export * from "./models"; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/index.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/index.ts new file mode 100644 index 00000000000..9abd938430d --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/index.ts @@ -0,0 +1,6 @@ +export * from './lesson-content-response'; +export * from './lesson-linked-task-response'; +export * from './lesson-metadata-list-response'; +export * from './lesson-metadata-response'; +export * from './lesson-response'; +export * from './material-response'; diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-content-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-content-response.ts new file mode 100644 index 00000000000..da12106638f --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-content-response.ts @@ -0,0 +1,73 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface LessonContentResponse + */ +export interface LessonContentResponse { + /** + * + * @type {object} + * @memberof LessonContentResponse + */ + 'content': object; + /** + * The id of the Material entity + * @type {string} + * @memberof LessonContentResponse + * @deprecated + */ + '_id': string; + /** + * The id of the Material entity + * @type {string} + * @memberof LessonContentResponse + */ + 'id': string; + /** + * Title of the Material entity + * @type {string} + * @memberof LessonContentResponse + */ + 'title': string; + /** + * + * @type {string} + * @memberof LessonContentResponse + */ + 'component': LessonContentResponseComponent; + /** + * + * @type {boolean} + * @memberof LessonContentResponse + */ + 'hidden': boolean; +} + +export const LessonContentResponseComponent = { + ETHERPAD: 'Etherpad', + GEO_GEBRA: 'geoGebra', + INTERNAL: 'internal', + RESOURCES: 'resources', + TEXT: 'text', + NE_XBOARD: 'neXboard' +} as const; + +export type LessonContentResponseComponent = typeof LessonContentResponseComponent[keyof typeof LessonContentResponseComponent]; + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-linked-task-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-linked-task-response.ts new file mode 100644 index 00000000000..58cc71d2d39 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-linked-task-response.ts @@ -0,0 +1,106 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface LessonLinkedTaskResponse + */ +export interface LessonLinkedTaskResponse { + /** + * + * @type {string} + * @memberof LessonLinkedTaskResponse + */ + 'name': string; + /** + * + * @type {string} + * @memberof LessonLinkedTaskResponse + */ + 'description': string; + /** + * + * @type {string} + * @memberof LessonLinkedTaskResponse + */ + 'descriptionInputFormat': LessonLinkedTaskResponseDescriptionInputFormat; + /** + * + * @type {string} + * @memberof LessonLinkedTaskResponse + */ + 'availableDate': string | null; + /** + * + * @type {string} + * @memberof LessonLinkedTaskResponse + */ + 'dueDate': string | null; + /** + * + * @type {boolean} + * @memberof LessonLinkedTaskResponse + */ + 'private': boolean; + /** + * + * @type {boolean} + * @memberof LessonLinkedTaskResponse + */ + 'publicSubmissions': boolean | null; + /** + * + * @type {boolean} + * @memberof LessonLinkedTaskResponse + */ + 'teamSubmissions': boolean | null; + /** + * + * @type {string} + * @memberof LessonLinkedTaskResponse + */ + 'creator': string | null; + /** + * + * @type {string} + * @memberof LessonLinkedTaskResponse + */ + 'courseId': string | null; + /** + * + * @type {Array} + * @memberof LessonLinkedTaskResponse + */ + 'submissionIds': Array; + /** + * + * @type {Array} + * @memberof LessonLinkedTaskResponse + */ + 'finishedIds': Array; +} + +export const LessonLinkedTaskResponseDescriptionInputFormat = { + PLAIN_TEXT: 'plainText', + RICH_TEXT_CK5_SIMPLE: 'richTextCk5Simple', + RICH_TEXT_CK4: 'richTextCk4', + RICH_TEXT_CK5: 'richTextCk5' +} as const; + +export type LessonLinkedTaskResponseDescriptionInputFormat = typeof LessonLinkedTaskResponseDescriptionInputFormat[keyof typeof LessonLinkedTaskResponseDescriptionInputFormat]; + + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-metadata-list-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-metadata-list-response.ts new file mode 100644 index 00000000000..4a528b10ead --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-metadata-list-response.ts @@ -0,0 +1,51 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { LessonMetadataResponse } from './lesson-metadata-response'; + +/** + * + * @export + * @interface LessonMetadataListResponse + */ +export interface LessonMetadataListResponse { + /** + * The items for the current page. + * @type {Array} + * @memberof LessonMetadataListResponse + */ + 'data': Array; + /** + * The total amount of items. + * @type {number} + * @memberof LessonMetadataListResponse + */ + 'total': number; + /** + * The amount of items skipped from the start. + * @type {number} + * @memberof LessonMetadataListResponse + */ + 'skip': number; + /** + * The page size of the response. + * @type {number} + * @memberof LessonMetadataListResponse + */ + 'limit': number; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-metadata-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-metadata-response.ts new file mode 100644 index 00000000000..c9e144139a1 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-metadata-response.ts @@ -0,0 +1,36 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface LessonMetadataResponse + */ +export interface LessonMetadataResponse { + /** + * The id of the Lesson entity + * @type {string} + * @memberof LessonMetadataResponse + */ + '_id': string; + /** + * Name of the Lesson entity + * @type {string} + * @memberof LessonMetadataResponse + */ + 'name': string; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-response.ts new file mode 100644 index 00000000000..ac2a0c697ba --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/lesson-response.ts @@ -0,0 +1,85 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +// May contain unused imports in some cases +// @ts-ignore +import type { LessonContentResponse } from './lesson-content-response'; +// May contain unused imports in some cases +// @ts-ignore +import type { MaterialResponse } from './material-response'; + +/** + * + * @export + * @interface LessonResponse + */ +export interface LessonResponse { + /** + * The id of the Lesson entity + * @type {string} + * @memberof LessonResponse + * @deprecated + */ + '_id': string; + /** + * The id of the Lesson entity + * @type {string} + * @memberof LessonResponse + */ + 'id': string; + /** + * Name of the Lesson entity + * @type {string} + * @memberof LessonResponse + */ + 'name': string; + /** + * The id of the Course entity + * @type {string} + * @memberof LessonResponse + */ + 'courseId'?: string; + /** + * The id of the Course-group entity + * @type {string} + * @memberof LessonResponse + */ + 'courseGroupId'?: string; + /** + * Hidden status of the Lesson entity + * @type {boolean} + * @memberof LessonResponse + */ + 'hidden': boolean; + /** + * Position of the Lesson entity + * @type {number} + * @memberof LessonResponse + */ + 'position': number; + /** + * Contents of the Lesson entity + * @type {Array} + * @memberof LessonResponse + */ + 'contents': Array; + /** + * Materials of the Lesson entity + * @type {Array} + * @memberof LessonResponse + */ + 'materials': Array; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/material-response.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/material-response.ts new file mode 100644 index 00000000000..6b427cb511f --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/lessons-api-client/models/material-response.ts @@ -0,0 +1,72 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schulcloud-Verbund-Software Server API + * This is v3 of Schulcloud-Verbund-Software Server. Checkout /docs for v1. + * + * The version of the OpenAPI document: 3.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + + +/** + * + * @export + * @interface MaterialResponse + */ +export interface MaterialResponse { + /** + * The id of the Material entity + * @type {string} + * @memberof MaterialResponse + */ + '_id': string; + /** + * The id of the Material entity + * @type {string} + * @memberof MaterialResponse + */ + 'id': string; + /** + * Title of the Material entity + * @type {string} + * @memberof MaterialResponse + */ + 'title': string; + /** + * ? + * @type {Array} + * @memberof MaterialResponse + */ + 'relatedResources': Array; + /** + * Url of the material + * @type {string} + * @memberof MaterialResponse + */ + 'url': string; + /** + * Position of the Lesson entity + * @type {string} + * @memberof MaterialResponse + */ + 'client': string; + /** + * Description of the material license + * @type {Array} + * @memberof MaterialResponse + */ + 'license': Array; + /** + * For material from Merlin, the Merlin reference + * @type {string} + * @memberof MaterialResponse + */ + 'merlinReference': string; +} + diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/mapper/lesson-dto.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/mapper/lesson-dto.mapper.spec.ts new file mode 100644 index 00000000000..3b294527520 --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/mapper/lesson-dto.mapper.spec.ts @@ -0,0 +1,129 @@ +import { faker } from '@faker-js/faker'; +import { + MaterialResponse, + LessonContentResponse, + LessonResponse, + LessonLinkedTaskResponse, + LessonLinkedTaskResponseDescriptionInputFormat, +} from '../lessons-api-client'; +import { LessonDtoMapper } from './lesson-dto.mapper'; + +describe('LessonDtoMapper', () => { + describe('mapToLessonDto', () => { + describe('when mapping to LessonResponse', () => { + const setup = () => { + const materialResponse: MaterialResponse = { + _id: faker.string.uuid(), + id: faker.string.uuid(), + title: faker.lorem.sentence(), + relatedResources: [faker.lorem.sentence()], + url: faker.internet.url(), + client: faker.lorem.sentence(), + license: [faker.lorem.sentence()], + merlinReference: faker.lorem.sentence(), + }; + + const lessonContentResponse: LessonContentResponse = { + content: { text: faker.lorem.sentence() }, + _id: faker.string.uuid(), + id: faker.string.uuid(), + title: faker.lorem.sentence(), + component: faker.helpers.arrayElement(['Etherpad', 'neXboard', 'geoGebra']), + hidden: faker.datatype.boolean(), + }; + + const lessonResponse: LessonResponse = { + _id: faker.string.uuid(), + id: faker.string.uuid(), + name: faker.lorem.sentence(), + courseId: faker.string.uuid(), + courseGroupId: faker.string.uuid(), + hidden: faker.datatype.boolean(), + position: faker.number.int(), + contents: [lessonContentResponse], + materials: [materialResponse], + }; + + return { lessonResponse }; + }; + + it('should return LessonDto', () => { + const { lessonResponse } = setup(); + + const result = LessonDtoMapper.mapToLessonDto(lessonResponse); + + expect(result).toEqual({ + lessonId: lessonResponse.id, + name: lessonResponse.name, + courseId: lessonResponse.courseId, + courseGroupId: lessonResponse.courseGroupId, + hidden: lessonResponse.hidden, + position: lessonResponse.position, + contents: [ + { + content: lessonResponse.contents[0].content, + title: lessonResponse.contents[0].title, + component: lessonResponse.contents[0].component, + hidden: lessonResponse.contents[0].hidden, + }, + ], + materials: [ + { + materialsId: lessonResponse.materials[0].id, + title: lessonResponse.materials[0].title, + relatedResources: [lessonResponse.materials[0].relatedResources[0]], + url: lessonResponse.materials[0].url, + client: lessonResponse.materials[0].client, + license: lessonResponse.materials[0].license, + merlinReference: lessonResponse.materials[0].merlinReference, + }, + ], + }); + }); + }); + }); + + describe('mapToLessonLinkedTaskDto', () => { + describe('when mapping to LessonLinkedTaskResponse', () => { + const setup = () => { + const lessonLinkedTaskResponse: LessonLinkedTaskResponse = { + name: faker.lorem.sentence(), + description: faker.lorem.sentence(), + descriptionInputFormat: LessonLinkedTaskResponseDescriptionInputFormat.PLAIN_TEXT, + availableDate: faker.date.recent().toString(), + dueDate: faker.date.future().toString(), + private: faker.datatype.boolean(), + publicSubmissions: faker.datatype.boolean(), + teamSubmissions: faker.datatype.boolean(), + creator: faker.internet.email(), + courseId: faker.string.uuid(), + submissionIds: [faker.string.uuid()], + finishedIds: [faker.string.uuid()], + }; + + return { lessonLinkedTaskResponse }; + }; + + it('should return LessonLinkedTaskDto', () => { + const { lessonLinkedTaskResponse } = setup(); + + const result = LessonDtoMapper.mapToLessonLinkedTaskDto(lessonLinkedTaskResponse); + + expect(result).toEqual({ + name: lessonLinkedTaskResponse.name, + description: lessonLinkedTaskResponse.description, + descriptionInputFormat: lessonLinkedTaskResponse.descriptionInputFormat, + availableDate: lessonLinkedTaskResponse.availableDate, + dueDate: lessonLinkedTaskResponse.dueDate, + private: lessonLinkedTaskResponse.private, + publicSubmissions: lessonLinkedTaskResponse.publicSubmissions, + teamSubmissions: lessonLinkedTaskResponse.teamSubmissions, + creator: lessonLinkedTaskResponse.creator, + courseId: lessonLinkedTaskResponse.courseId, + submissionIds: lessonLinkedTaskResponse.submissionIds, + finishedIds: lessonLinkedTaskResponse.finishedIds, + }); + }); + }); + }); +}); diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/mapper/lesson-dto.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/mapper/lesson-dto.mapper.ts new file mode 100644 index 00000000000..150037ddaee --- /dev/null +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/lesson-client/mapper/lesson-dto.mapper.ts @@ -0,0 +1,68 @@ +import { LessonContentDto, LessonDto, LessonLinkedTaskDto, LessonMaterialsDto } from '../dto'; +import { + LessonContentResponse, + LessonLinkedTaskResponse, + LessonResponse, + MaterialResponse, +} from '../lessons-api-client'; + +export class LessonDtoMapper { + public static mapToLessonLinkedTaskDto(task: LessonLinkedTaskResponse): LessonLinkedTaskDto { + const lessonLinkedTaskDto = new LessonLinkedTaskDto({ + name: task.name, + description: task.description, + descriptionInputFormat: task.descriptionInputFormat, + availableDate: task.availableDate, + dueDate: task.dueDate, + private: task.private, + publicSubmissions: task.publicSubmissions, + teamSubmissions: task.teamSubmissions, + courseId: task.courseId, + creator: task.creator, + submissionIds: task.submissionIds, + finishedIds: task.finishedIds, + }); + + return lessonLinkedTaskDto; + } + + public static mapToLessonDto(lessonResponse: LessonResponse): LessonDto { + const lessonDto = new LessonDto({ + lessonId: lessonResponse.id, + name: lessonResponse.name, + courseId: lessonResponse.courseId, + courseGroupId: lessonResponse.courseGroupId, + hidden: lessonResponse.hidden, + position: lessonResponse.position, + contents: lessonResponse.contents.map((content) => this.mapToLessenContentDto(content)), + materials: lessonResponse.materials.map((material) => this.mapToLessonMaterialDto(material)), + }); + + return lessonDto; + } + + private static mapToLessonMaterialDto(materialResponse: MaterialResponse): LessonMaterialsDto { + const lessonMaterialsDto = new LessonMaterialsDto({ + materialsId: materialResponse.id, + title: materialResponse.title, + relatedResources: materialResponse.relatedResources.map((resource) => resource), + url: materialResponse.url, + client: materialResponse.client, + license: materialResponse.license, + merlinReference: materialResponse.merlinReference, + }); + + return lessonMaterialsDto; + } + + private static mapToLessenContentDto(lessonContentResponse: LessonContentResponse): LessonContentDto { + const lessonContentDto = new LessonContentDto({ + content: lessonContentResponse.content, + title: lessonContentResponse.title, + component: lessonContentResponse.component, + hidden: lessonContentResponse.hidden, + }); + + return lessonContentDto; + } +} diff --git a/apps/server/src/modules/common-cartridge/common-cartridge.module.ts b/apps/server/src/modules/common-cartridge/common-cartridge.module.ts index b5490aa3cbc..8c75f15b688 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge.module.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge.module.ts @@ -12,13 +12,11 @@ import { CommonCartridgeExportService } from './service/common-cartridge-export. import { CommonCartridgeUc } from './uc/common-cartridge.uc'; import { CourseRoomsModule } from './common-cartridge-client/room-client'; import { CardClientModule } from './common-cartridge-client/card-client/card-client.module'; +import { LessonClientModule } from './common-cartridge-client/lesson-client/lesson-client.module'; @Module({ imports: [ RabbitMQWrapperModule, - CoursesClientModule.register({ - basePath: `${Configuration.get('API_HOST') as string}/v3/`, - }), FilesStorageClientModule, MikroOrmModule.forRoot({ ...defaultMikroOrmOptions, @@ -37,6 +35,12 @@ import { CardClientModule } from './common-cartridge-client/card-client/card-cli CardClientModule.register({ basePath: `${Configuration.get('API_HOST') as string}/v3/`, }), + CoursesClientModule.register({ + basePath: `${Configuration.get('API_HOST') as string}/v3/`, + }), + LessonClientModule.register({ + basePath: `${Configuration.get('API_HOST') as string}/v3/`, + }), ], providers: [CommonCartridgeUc, CommonCartridgeExportService], exports: [CommonCartridgeUc], diff --git a/sonar-project.properties b/sonar-project.properties index 79cbc0385fe..0501516afc7 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -3,7 +3,7 @@ sonar.projectKey=hpi-schul-cloud_schulcloud-server sonar.sources=. sonar.tests=. sonar.test.inclusions=**/*.spec.ts -sonar.exclusions=**/*.js,jest.config.ts,globalSetup.ts,globalTeardown.ts,**/*.app.ts,**/seed-data/*.ts,**/migrations/mikro-orm/*.ts,**/etherpad-api-client/**/*.ts,**/authorization-api-client/**/*.ts, **/course-api-client/**/*.ts,**/board-api-client/**/*.ts,**/generated/**/*.ts,**/room-api-client/**/*.ts,**/cards-api-client/**/*.ts +sonar.exclusions=**/*.js,jest.config.ts,globalSetup.ts,globalTeardown.ts,**/*.app.ts,**/seed-data/*.ts,**/migrations/mikro-orm/*.ts,**/etherpad-api-client/**/*.ts,**/authorization-api-client/**/*.ts, **/course-api-client/**/*.ts,**/board-api-client/**/*.ts,**/generated/**/*.ts,**/room-api-client/**/*.ts,**/cards-api-client/**/*.ts,**/lessons-api-client/**/*.ts sonar.coverage.exclusions=**/board-management.uc.ts,**/*.module.ts,**/*.factory.ts,**/migrations/mikro-orm/*.ts,**/globalSetup.ts,**/globalTeardown.ts,**/etherpad-api-client/**/*.ts,**/authorization-api-client/**/*.ts, **/course-api-client/**/*.ts,**/board-api-client/**/*.ts,**/generated/**/*.ts,**/room-api-client/**/*.ts sonar.cpd.exclusions=**/controller/dto/**/*.ts,**/api/dto/**/*.ts,**/shared/testing/factory/*.factory.ts sonar.javascript.lcov.reportPaths=merged-lcov.info From 012a2858a20c2270d7766079877fcd3b7f868f75 Mon Sep 17 00:00:00 2001 From: MBergCap <111343628+MBergCap@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:07:59 +0200 Subject: [PATCH 35/47] N21-2167 preferred tools for boards (#5282) * add preferred tool endpoint * add preferred tool uc * add apiProperty description * add seed data * add feature flag FEATURE_PREFERRED_CTL_TOOLS_ENABLED --------- Co-authored-by: Steliyan Dinkov <133751031+sdinkov@users.noreply.github.com> Co-authored-by: Igor Richter --- .../board-node-copy-specific.service.spec.ts | 1 + .../modules/server/admin-api-server.config.ts | 1 + .../modules/server/api/dto/config.response.ts | 4 + .../server/api/test/server.api.spec.ts | 1 + .../src/modules/server/server.config.ts | 1 + .../api-test/tool-configuration.api.spec.ts | 172 ++++++++++++++++++ .../controller/dto/request/index.ts | 1 + .../dto/request/tool-context-type.params.ts | 14 ++ .../controller/dto/response/index.ts | 2 + .../response/preferred-tool-list.response.ts | 11 ++ .../dto/response/preferred-tool.response.ts | 21 +++ .../tool-configuration.controller.ts | 27 ++- .../mapper/tool-configuration.mapper.ts | 22 +++ .../testing/external-tool.factory.ts | 1 + .../uc/external-tool-configuration.uc.spec.ts | 150 ++++++++++++++- .../uc/external-tool-configuration.uc.ts | 75 ++++++-- apps/server/src/modules/tool/tool-config.ts | 1 + backup/setup/external-tools.json | 103 +++++++++++ config/default.schema.json | 5 + 19 files changed, 594 insertions(+), 19 deletions(-) create mode 100644 apps/server/src/modules/tool/external-tool/controller/dto/request/tool-context-type.params.ts create mode 100644 apps/server/src/modules/tool/external-tool/controller/dto/response/preferred-tool-list.response.ts create mode 100644 apps/server/src/modules/tool/external-tool/controller/dto/response/preferred-tool.response.ts diff --git a/apps/server/src/modules/board/service/internal/board-node-copy-specific.service.spec.ts b/apps/server/src/modules/board/service/internal/board-node-copy-specific.service.spec.ts index 3db0d06fa2a..1a82f545a59 100644 --- a/apps/server/src/modules/board/service/internal/board-node-copy-specific.service.spec.ts +++ b/apps/server/src/modules/board/service/internal/board-node-copy-specific.service.spec.ts @@ -55,6 +55,7 @@ describe(BoardNodeCopyService.name, () => { CTL_TOOLS_RELOAD_TIME_MS: 0, FILES_STORAGE__SERVICE_BASE_URL: '', CTL_TOOLS__PREFERRED_TOOLS_LIMIT: 10, + FEATURE_PREFERRED_CTL_TOOLS_ENABLED: false, }; let contextExternalToolService: DeepMocked; let copyHelperService: DeepMocked; diff --git a/apps/server/src/modules/server/admin-api-server.config.ts b/apps/server/src/modules/server/admin-api-server.config.ts index 1d954ab8062..93b855541c9 100644 --- a/apps/server/src/modules/server/admin-api-server.config.ts +++ b/apps/server/src/modules/server/admin-api-server.config.ts @@ -66,6 +66,7 @@ const config: AdminApiServerConfig = { FEATURE_IDENTITY_MANAGEMENT_LOGIN_ENABLED: Configuration.get('FEATURE_IDENTITY_MANAGEMENT_LOGIN_ENABLED') as boolean, FEATURE_IDENTITY_MANAGEMENT_STORE_ENABLED: Configuration.get('FEATURE_IDENTITY_MANAGEMENT_STORE_ENABLED') as boolean, CTL_TOOLS__PREFERRED_TOOLS_LIMIT: Configuration.get('CTL_TOOLS__PREFERRED_TOOLS_LIMIT') as number, + FEATURE_PREFERRED_CTL_TOOLS_ENABLED: Configuration.get('FEATURE_PREFERRED_CTL_TOOLS_ENABLED') as boolean, TEACHER_VISIBILITY_FOR_EXTERNAL_TEAM_INVITATION: Configuration.get( 'TEACHER_VISIBILITY_FOR_EXTERNAL_TEAM_INVITATION' ) as string, diff --git a/apps/server/src/modules/server/api/dto/config.response.ts b/apps/server/src/modules/server/api/dto/config.response.ts index e0a40450526..07d619da715 100644 --- a/apps/server/src/modules/server/api/dto/config.response.ts +++ b/apps/server/src/modules/server/api/dto/config.response.ts @@ -38,6 +38,9 @@ export class ConfigResponse { @ApiProperty() FEATURE_CTL_TOOLS_COPY_ENABLED: boolean; + @ApiProperty() + FEATURE_PREFERRED_CTL_TOOLS_ENABLED: boolean; + @ApiProperty() FEATURE_SHOW_MIGRATION_WIZARD: boolean; @@ -291,6 +294,7 @@ export class ConfigResponse { this.FEATURE_SHOW_NEW_CLASS_VIEW_ENABLED = config.FEATURE_SHOW_NEW_CLASS_VIEW_ENABLED; this.FEATURE_SHOW_NEW_ROOMS_VIEW_ENABLED = config.FEATURE_SHOW_NEW_ROOMS_VIEW_ENABLED; this.FEATURE_CTL_TOOLS_COPY_ENABLED = config.FEATURE_CTL_TOOLS_COPY_ENABLED; + this.FEATURE_PREFERRED_CTL_TOOLS_ENABLED = config.FEATURE_PREFERRED_CTL_TOOLS_ENABLED; this.FEATURE_SHOW_MIGRATION_WIZARD = config.FEATURE_SHOW_MIGRATION_WIZARD; this.MIGRATION_WIZARD_DOCUMENTATION_LINK = config.MIGRATION_WIZARD_DOCUMENTATION_LINK; this.FEATURE_TLDRAW_ENABLED = config.FEATURE_TLDRAW_ENABLED; diff --git a/apps/server/src/modules/server/api/test/server.api.spec.ts b/apps/server/src/modules/server/api/test/server.api.spec.ts index 03f32116317..2e512f8d5f4 100644 --- a/apps/server/src/modules/server/api/test/server.api.spec.ts +++ b/apps/server/src/modules/server/api/test/server.api.spec.ts @@ -55,6 +55,7 @@ describe('Server Controller (API)', () => { 'FEATURE_COURSE_SHARE', 'FEATURE_CTL_TOOLS_COPY_ENABLED', 'FEATURE_CTL_TOOLS_TAB_ENABLED', + 'FEATURE_PREFERRED_CTL_TOOLS_ENABLED', 'FEATURE_ENABLE_LDAP_SYNC_DURING_MIGRATION', 'FEATURE_ES_COLLECTIONS_ENABLED', 'FEATURE_EXTENSIONS_ENABLED', diff --git a/apps/server/src/modules/server/server.config.ts b/apps/server/src/modules/server/server.config.ts index c3594739d84..8ca31f845de 100644 --- a/apps/server/src/modules/server/server.config.ts +++ b/apps/server/src/modules/server/server.config.ts @@ -300,6 +300,7 @@ const config: ServerConfig = { ) as number, CTL_TOOLS_BACKEND_URL: Configuration.get('PUBLIC_BACKEND_URL') as string, FEATURE_CTL_TOOLS_COPY_ENABLED: Configuration.get('FEATURE_CTL_TOOLS_COPY_ENABLED') as boolean, + FEATURE_PREFERRED_CTL_TOOLS_ENABLED: Configuration.get('FEATURE_PREFERRED_CTL_TOOLS_ENABLED') as boolean, CTL_TOOLS_RELOAD_TIME_MS: Configuration.get('CTL_TOOLS_RELOAD_TIME_MS') as number, HOST: Configuration.get('HOST') as string, FILES_STORAGE__SERVICE_BASE_URL: Configuration.get('FILES_STORAGE__SERVICE_BASE_URL') as string, diff --git a/apps/server/src/modules/tool/external-tool/controller/api-test/tool-configuration.api.spec.ts b/apps/server/src/modules/tool/external-tool/controller/api-test/tool-configuration.api.spec.ts index 20154bf1311..f4f1e043e1c 100644 --- a/apps/server/src/modules/tool/external-tool/controller/api-test/tool-configuration.api.spec.ts +++ b/apps/server/src/modules/tool/external-tool/controller/api-test/tool-configuration.api.spec.ts @@ -34,6 +34,7 @@ import { SchoolExternalToolConfigurationTemplateListResponse, SchoolExternalToolConfigurationTemplateResponse, ToolContextTypesListResponse, + PreferredToolListResponse, } from '../dto'; describe('ToolConfigurationController (API)', () => { @@ -743,4 +744,175 @@ describe('ToolConfigurationController (API)', () => { }); }); }); + + describe('[GET] tools/preferred-tools', () => { + describe('when the user is not authorized', () => { + const setup = async () => { + const school: SchoolEntity = schoolEntityFactory.buildWithId(); + + const { adminUser, adminAccount } = UserAndAccountTestFactory.buildAdmin(); + + const externalTool: ExternalToolEntity = externalToolEntityFactory.buildWithId({ + isPreferred: true, + iconName: 'iconName', + }); + + const schoolExternalTool: SchoolExternalToolEntity = schoolExternalToolEntityFactory.buildWithId({ + school, + tool: externalTool, + }); + + await em.persistAndFlush([school, adminUser, adminAccount, externalTool, schoolExternalTool]); + em.clear(); + + const loggedInClient: TestApiClient = await testApiClient.login(adminAccount); + + return { + loggedInClient, + }; + }; + + it('should return a unauthorized status', async () => { + const { loggedInClient } = await setup(); + + const response: Response = await loggedInClient.get(`/preferred-tools`); + + expect(response.status).toEqual(HttpStatus.UNAUTHORIZED); + }); + }); + + describe('when preferred tools are available for a context', () => { + const setup = async () => { + const school: SchoolEntity = schoolEntityFactory.buildWithId(); + + const { teacherUser, teacherAccount } = UserAndAccountTestFactory.buildTeacher({ school }, [ + Permission.CONTEXT_TOOL_ADMIN, + ]); + + const externalTool: ExternalToolEntity = externalToolEntityFactory.buildWithId({ + restrictToContexts: [], + isPreferred: true, + iconName: 'iconName', + }); + + const externalToolWithContextRestriction: ExternalToolEntity = externalToolEntityFactory.buildWithId({ + restrictToContexts: [ToolContextType.COURSE], + isPreferred: true, + iconName: 'iconName', + }); + + const schoolExternalTool: SchoolExternalToolEntity = schoolExternalToolEntityFactory.buildWithId({ + school, + tool: externalTool, + }); + + const schoolExternalTool2: SchoolExternalToolEntity = schoolExternalToolEntityFactory.buildWithId({ + school, + tool: externalToolWithContextRestriction, + }); + + await em.persistAndFlush([ + school, + teacherUser, + teacherAccount, + externalTool, + externalToolWithContextRestriction, + schoolExternalTool, + schoolExternalTool2, + ]); + em.clear(); + + const loggedInClient: TestApiClient = await testApiClient.login(teacherAccount); + + return { + externalTool, + externalToolWithContextRestriction, + schoolExternalTool, + schoolExternalTool2, + loggedInClient, + }; + }; + + it('should return an array of preferred tools', async () => { + const { + externalTool, + externalToolWithContextRestriction, + schoolExternalTool, + schoolExternalTool2, + loggedInClient, + } = await setup(); + + const response: Response = await loggedInClient.get('/preferred-tools'); + + expect(response.body).toEqual({ + data: [ + { + schoolExternalToolId: schoolExternalTool.id, + name: externalTool.name, + iconName: 'iconName', + }, + { + schoolExternalToolId: schoolExternalTool2.id, + name: externalToolWithContextRestriction.name, + iconName: 'iconName', + }, + ], + }); + }); + + it('should not return the context restricted tool', async () => { + const { loggedInClient, externalTool, schoolExternalTool } = await setup(); + + const response: Response = await loggedInClient.get('/preferred-tools').query({ contextType: 'board-element' }); + + expect(response.body).toEqual({ + data: [ + { + schoolExternalToolId: schoolExternalTool.id, + name: externalTool.name, + iconName: 'iconName', + }, + ], + }); + }); + }); + + describe('when no preferred tools are available', () => { + const setup = async () => { + const school: SchoolEntity = schoolEntityFactory.buildWithId(); + + const { teacherUser, teacherAccount } = UserAndAccountTestFactory.buildTeacher({}, [ + Permission.CONTEXT_TOOL_ADMIN, + ]); + + const externalTool: ExternalToolEntity = externalToolEntityFactory.buildWithId({ + isPreferred: false, + }); + + const schoolExternalTool: SchoolExternalToolEntity = schoolExternalToolEntityFactory.buildWithId({ + school, + tool: externalTool, + }); + + await em.persistAndFlush([teacherUser, school, teacherAccount, externalTool, schoolExternalTool]); + em.clear(); + + const loggedInClient: TestApiClient = await testApiClient.login(teacherAccount); + + return { + loggedInClient, + }; + }; + + it('should return an empty array', async () => { + const { loggedInClient } = await setup(); + + const response: Response = await loggedInClient.get('/preferred-tools'); + + expect(response.body).toEqual({ + data: [], + }); + }); + }); + }); }); diff --git a/apps/server/src/modules/tool/external-tool/controller/dto/request/index.ts b/apps/server/src/modules/tool/external-tool/controller/dto/request/index.ts index fc62b2b4cc4..dddbe0954d0 100644 --- a/apps/server/src/modules/tool/external-tool/controller/dto/request/index.ts +++ b/apps/server/src/modules/tool/external-tool/controller/dto/request/index.ts @@ -11,3 +11,4 @@ export * from './school-external-tool-id.params'; export * from './context-external-tool-id.params'; export { ExternalToolMediumParams } from './external-tool-medium.params'; export { ExternalToolBulkCreateParams } from './external-tool-bulk-create.params'; +export * from './tool-context-type.params'; diff --git a/apps/server/src/modules/tool/external-tool/controller/dto/request/tool-context-type.params.ts b/apps/server/src/modules/tool/external-tool/controller/dto/request/tool-context-type.params.ts new file mode 100644 index 00000000000..0926d961196 --- /dev/null +++ b/apps/server/src/modules/tool/external-tool/controller/dto/request/tool-context-type.params.ts @@ -0,0 +1,14 @@ +import { IsEnum, IsOptional } from 'class-validator'; +import { ApiPropertyOptional } from '@nestjs/swagger'; +import { ToolContextType } from '@modules/tool/common/enum'; + +export class ToolContextTypeParams { + @IsOptional() + @IsEnum(ToolContextType, { each: true }) + @ApiPropertyOptional({ + enum: ToolContextType, + enumName: 'ToolContextType', + description: 'Context types for tools', + }) + contextType?: ToolContextType; +} diff --git a/apps/server/src/modules/tool/external-tool/controller/dto/response/index.ts b/apps/server/src/modules/tool/external-tool/controller/dto/response/index.ts index a1f0b8fff5d..8a78d73d44c 100644 --- a/apps/server/src/modules/tool/external-tool/controller/dto/response/index.ts +++ b/apps/server/src/modules/tool/external-tool/controller/dto/response/index.ts @@ -13,3 +13,5 @@ export { ExternalToolImportResultListResponse, ExternalToolImportResultResponse, } from './external-tool-import-result-response'; +export * from './preferred-tool.response'; +export * from './preferred-tool-list.response'; diff --git a/apps/server/src/modules/tool/external-tool/controller/dto/response/preferred-tool-list.response.ts b/apps/server/src/modules/tool/external-tool/controller/dto/response/preferred-tool-list.response.ts new file mode 100644 index 00000000000..fd116aa231d --- /dev/null +++ b/apps/server/src/modules/tool/external-tool/controller/dto/response/preferred-tool-list.response.ts @@ -0,0 +1,11 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { PreferredToolResponse } from './preferred-tool.response'; + +export class PreferredToolListResponse { + @ApiProperty({ type: [PreferredToolResponse] }) + data: PreferredToolResponse[]; + + constructor(data: PreferredToolResponse[]) { + this.data = data; + } +} diff --git a/apps/server/src/modules/tool/external-tool/controller/dto/response/preferred-tool.response.ts b/apps/server/src/modules/tool/external-tool/controller/dto/response/preferred-tool.response.ts new file mode 100644 index 00000000000..2e7acfef272 --- /dev/null +++ b/apps/server/src/modules/tool/external-tool/controller/dto/response/preferred-tool.response.ts @@ -0,0 +1,21 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class PreferredToolResponse { + @ApiProperty({ type: String, description: 'Id of the school external tool' }) + schoolExternalToolId: string; + + @ApiProperty({ type: String, description: 'Name of the external tool' }) + name: string; + + @ApiProperty({ + type: String, + description: 'Name of the icon to be rendered when displaying it as a preferred tool', + }) + iconName: string; + + constructor(configuration: PreferredToolResponse) { + this.schoolExternalToolId = configuration.schoolExternalToolId; + this.name = configuration.name; + this.iconName = configuration.iconName; + } +} diff --git a/apps/server/src/modules/tool/external-tool/controller/tool-configuration.controller.ts b/apps/server/src/modules/tool/external-tool/controller/tool-configuration.controller.ts index 7b90edab1df..9817690782b 100644 --- a/apps/server/src/modules/tool/external-tool/controller/tool-configuration.controller.ts +++ b/apps/server/src/modules/tool/external-tool/controller/tool-configuration.controller.ts @@ -1,5 +1,5 @@ import { CurrentUser, ICurrentUser, JwtAuthentication } from '@infra/auth-guard'; -import { Controller, Get, Param } from '@nestjs/common'; +import { Controller, Get, Param, Query } from '@nestjs/common'; import { ApiForbiddenResponse, ApiFoundResponse, @@ -22,6 +22,8 @@ import { SchoolExternalToolIdParams, SchoolIdParams, ToolContextTypesListResponse, + PreferredToolListResponse, + ToolContextTypeParams, } from './dto'; @ApiTags('Tool') @@ -95,6 +97,29 @@ export class ToolConfigurationController { return mapped; } + @Get('preferred-tools') + @ApiForbiddenResponse() + @ApiOperation({ summary: 'Lists all preferred tools that can be added for a given context' }) + @ApiOkResponse({ + description: 'List of preferred tools for a context', + type: PreferredToolListResponse, + }) + public async getPreferredToolsForContext( + @CurrentUser() currentUser: ICurrentUser, + @Query() context: ToolContextTypeParams + ): Promise { + const preferedTools: ContextExternalToolTemplateInfo[] = + await this.externalToolConfigurationUc.getPreferedToolsForContext( + currentUser.userId, + currentUser.schoolId, + context.contextType + ); + + const mapped: PreferredToolListResponse = ToolConfigurationMapper.mapToPreferredToolListResponse(preferedTools); + + return mapped; + } + @Get('school-external-tools/:schoolExternalToolId/configuration-template') @ApiUnauthorizedResponse() @ApiForbiddenResponse() diff --git a/apps/server/src/modules/tool/external-tool/mapper/tool-configuration.mapper.ts b/apps/server/src/modules/tool/external-tool/mapper/tool-configuration.mapper.ts index 37d67c810bc..914e97b56c4 100644 --- a/apps/server/src/modules/tool/external-tool/mapper/tool-configuration.mapper.ts +++ b/apps/server/src/modules/tool/external-tool/mapper/tool-configuration.mapper.ts @@ -5,6 +5,8 @@ import { SchoolExternalToolConfigurationTemplateListResponse, SchoolExternalToolConfigurationTemplateResponse, ToolContextTypesListResponse, + PreferredToolListResponse, + PreferredToolResponse, } from '../controller/dto'; import { ExternalTool } from '../domain'; import { ContextExternalToolTemplateInfo } from '../uc'; @@ -77,4 +79,24 @@ export class ToolConfigurationMapper { return mappedTypes; } + + static mapToPreferredToolListResponse(preferedTools: ContextExternalToolTemplateInfo[]): PreferredToolListResponse { + const mappedTools = preferedTools.map((tool): PreferredToolResponse => this.mapToPreferredToolResponse(tool)); + + const mapped = new PreferredToolListResponse(mappedTools); + + return mapped; + } + + static mapToPreferredToolResponse(preferredTool: ContextExternalToolTemplateInfo): PreferredToolResponse { + const { externalTool, schoolExternalTool } = preferredTool; + + const mapped = new PreferredToolResponse({ + schoolExternalToolId: schoolExternalTool.id ?? '', + name: externalTool.name, + iconName: externalTool.iconName ?? '', + }); + + return mapped; + } } diff --git a/apps/server/src/modules/tool/external-tool/testing/external-tool.factory.ts b/apps/server/src/modules/tool/external-tool/testing/external-tool.factory.ts index d1bff9ba0ef..f1b07fb7d78 100644 --- a/apps/server/src/modules/tool/external-tool/testing/external-tool.factory.ts +++ b/apps/server/src/modules/tool/external-tool/testing/external-tool.factory.ts @@ -151,5 +151,6 @@ export const externalToolFactory = ExternalToolFactory.define(ExternalTool, ({ s createdAt: new Date(2020, 1, 1), restrictToContexts: undefined, isPreferred: false, + iconName: undefined, }; }); diff --git a/apps/server/src/modules/tool/external-tool/uc/external-tool-configuration.uc.spec.ts b/apps/server/src/modules/tool/external-tool/uc/external-tool-configuration.uc.spec.ts index 38af6c85ddb..eff5fceeb7e 100644 --- a/apps/server/src/modules/tool/external-tool/uc/external-tool-configuration.uc.spec.ts +++ b/apps/server/src/modules/tool/external-tool/uc/external-tool-configuration.uc.spec.ts @@ -237,7 +237,7 @@ describe('ExternalToolConfigurationUc', () => { }); }); - describe('when getting the list of external tools that can be added to a school', () => { + describe('when getting the list of school external tools that can be added to a context', () => { const setup = () => { const user: User = userFactory.build(); const hiddenTool: ExternalTool = externalToolFactory.buildWithId({ isHidden: true }); @@ -409,7 +409,7 @@ describe('ExternalToolConfigurationUc', () => { }; }; - it('should allow to add one tool multiple times to a school', async () => { + it('should allow to add one tool multiple times to a context', async () => { const { usedTool, usedSchoolExternalTool } = setup(); const availableTools = await uc.getAvailableToolsForContext( @@ -731,4 +731,150 @@ describe('ExternalToolConfigurationUc', () => { }); }); }); + + describe('getPreferedToolsForContext', () => { + describe('when the user has insufficient permission', () => { + const setup = () => { + const user: User = userFactory.build(); + + authorizationService.getUserWithPermissions.mockResolvedValue(user); + authorizationService.checkAllPermissions.mockImplementation(() => { + throw new ForbiddenException(); + }); + + return { user }; + }; + + it('should fail when authorizationService throws ForbiddenException', async () => { + const { user } = setup(); + + const func = async () => uc.getPreferedToolsForContext('userId', 'schoolId', ToolContextType.BOARD_ELEMENT); + + await expect(func).rejects.toThrow(ForbiddenException); + expect(authorizationService.checkAllPermissions).toHaveBeenCalledWith(user, [Permission.CONTEXT_TOOL_ADMIN]); + }); + }); + + describe('when getting the list of preferred external tools that can be added to a context', () => { + const setup = () => { + const user: User = userFactory.build(); + const hiddenExternalTool: ExternalTool = externalToolFactory.build({ isHidden: true, isPreferred: true }); + const usedExternalTool: ExternalTool = externalToolFactory.build({ isPreferred: true }); + const unusedExternalTool: ExternalTool = externalToolFactory.build({ isPreferred: true }); + const externalToolWithoutSchoolTool: ExternalTool = externalToolFactory.build({ isPreferred: true }); + + const usedSchoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.build({ + toolId: usedExternalTool.id, + }); + const unusedSchoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.build({ + toolId: unusedExternalTool.id, + }); + + externalToolService.findExternalTools.mockResolvedValue( + new Page( + [hiddenExternalTool, usedExternalTool, unusedExternalTool, externalToolWithoutSchoolTool], + 4 + ) + ); + schoolExternalToolService.findSchoolExternalTools.mockResolvedValue([ + usedSchoolExternalTool, + unusedSchoolExternalTool, + ]); + authorizationService.getUserWithPermissions.mockResolvedValueOnce(user); + + externalToolConfigurationService.filterForAvailableExternalTools.mockReturnValue([ + { externalTool: usedExternalTool, schoolExternalTool: usedSchoolExternalTool }, + ]); + externalToolConfigurationService.filterForContextRestrictions.mockReturnValue([ + { externalTool: usedExternalTool, schoolExternalTool: usedSchoolExternalTool }, + ]); + + return { + user, + usedExternalTool, + usedSchoolExternalTool, + }; + }; + + it('should call the authorizationService with CONTEXT_TOOL_ADMIN permission', async () => { + const { user } = setup(); + + await uc.getPreferedToolsForContext('userId', 'schoolId', ToolContextType.BOARD_ELEMENT); + + expect(authorizationService.checkAllPermissions).toHaveBeenCalledWith(user, [Permission.CONTEXT_TOOL_ADMIN]); + }); + + it('should call externalToolLogoService', async () => { + const { usedExternalTool } = setup(); + + await uc.getPreferedToolsForContext('userId', 'schoolId', ToolContextType.BOARD_ELEMENT); + + expect(logoService.buildLogoUrl).toHaveBeenCalledWith(usedExternalTool); + }); + + it('should filter for restricted contexts', async () => { + const { usedExternalTool, usedSchoolExternalTool } = setup(); + + await uc.getPreferedToolsForContext('userId', 'schoolId', ToolContextType.BOARD_ELEMENT); + + expect(externalToolConfigurationService.filterForContextRestrictions).toHaveBeenCalledWith( + [{ externalTool: usedExternalTool, schoolExternalTool: usedSchoolExternalTool }], + ToolContextType.BOARD_ELEMENT + ); + }); + + it('should call filterParametersForScope', async () => { + const { usedExternalTool } = setup(); + + await uc.getPreferedToolsForContext('userId', 'schoolId', ToolContextType.BOARD_ELEMENT); + + expect(externalToolConfigurationService.filterParametersForScope).toHaveBeenCalledWith( + usedExternalTool, + CustomParameterScope.CONTEXT + ); + }); + }); + + describe('when configuration of context external tools is enabled', () => { + const setup = () => { + const externalTool: ExternalTool = externalToolFactory.build({ + isPreferred: true, + iconName: 'iconName', + }); + + const schoolExternalTool: SchoolExternalTool = schoolExternalToolFactory.build({ + toolId: externalTool.id, + parameters: [], + }); + + externalToolService.findExternalTools.mockResolvedValue(new Page([externalTool], 1)); + schoolExternalToolService.findSchoolExternalTools.mockResolvedValue([schoolExternalTool]); + + externalToolConfigurationService.filterForAvailableExternalTools.mockReturnValue([ + { externalTool, schoolExternalTool }, + ]); + externalToolConfigurationService.filterForContextRestrictions.mockReturnValue([ + { externalTool, schoolExternalTool }, + ]); + + return { + externalTool, + schoolExternalTool, + }; + }; + + it('should allow to add a preferred tool to a given context', async () => { + const { externalTool, schoolExternalTool } = setup(); + + const preferredTools = await uc.getPreferedToolsForContext('userId', 'schoolId', ToolContextType.BOARD_ELEMENT); + + expect(preferredTools).toEqual([ + { + externalTool, + schoolExternalTool, + }, + ]); + }); + }); + }); }); diff --git a/apps/server/src/modules/tool/external-tool/uc/external-tool-configuration.uc.ts b/apps/server/src/modules/tool/external-tool/uc/external-tool-configuration.uc.ts index 5937b9d9544..85d4db71781 100644 --- a/apps/server/src/modules/tool/external-tool/uc/external-tool-configuration.uc.ts +++ b/apps/server/src/modules/tool/external-tool/uc/external-tool-configuration.uc.ts @@ -98,25 +98,12 @@ export class ExternalToolConfigurationUc { const context: AuthorizationContext = AuthorizationContextBuilder.read([Permission.CONTEXT_TOOL_ADMIN]); await this.ensureContextPermissions(user, contextExternalToolsInUse, context); - let availableToolsForContext: ContextExternalToolTemplateInfo[] = - this.externalToolConfigurationService.filterForAvailableExternalTools(externalTools.data, schoolExternalTools); - - availableToolsForContext = this.externalToolConfigurationService.filterForContextRestrictions( - availableToolsForContext, + const availableToolsForContext: ContextExternalToolTemplateInfo[] = this.prepareAvailableToolsForContext( + externalTools.data, + schoolExternalTools, contextType ); - availableToolsForContext.forEach((toolTemplateInfo) => { - this.externalToolConfigurationService.filterParametersForScope( - toolTemplateInfo.externalTool, - CustomParameterScope.CONTEXT - ); - }); - - availableToolsForContext.forEach((toolTemplateInfo) => { - toolTemplateInfo.externalTool.logoUrl = this.externalToolLogoService.buildLogoUrl(toolTemplateInfo.externalTool); - }); - return availableToolsForContext; } @@ -172,6 +159,62 @@ export class ExternalToolConfigurationUc { }; } + public async getPreferedToolsForContext( + userId: EntityId, + schoolId: EntityId, + contextType?: ToolContextType + ): Promise { + const user: User = await this.authorizationService.getUserWithPermissions(userId); + this.authorizationService.checkAllPermissions(user, [Permission.CONTEXT_TOOL_ADMIN]); + + const externalTools: Page = await this.externalToolService.findExternalTools({ isPreferred: true }); + + const schoolExternalTools: SchoolExternalTool[] = ( + await Promise.all( + externalTools.data.map((externalTool) => + this.schoolExternalToolService.findSchoolExternalTools({ + toolId: externalTool.id, + schoolId, + }) + ) + ) + ).flat(); + + const preferedTools: ContextExternalToolTemplateInfo[] = this.prepareAvailableToolsForContext( + externalTools.data, + schoolExternalTools, + contextType + ); + + return preferedTools; + } + + private prepareAvailableToolsForContext( + externalTools: ExternalTool[], + schoolExternalTools: SchoolExternalTool[], + contextType?: ToolContextType + ): ContextExternalToolTemplateInfo[] { + let availableToolsForContext: ContextExternalToolTemplateInfo[] = + this.externalToolConfigurationService.filterForAvailableExternalTools(externalTools, schoolExternalTools); + + if (contextType) { + availableToolsForContext = this.externalToolConfigurationService.filterForContextRestrictions( + availableToolsForContext, + contextType + ); + } + + availableToolsForContext.forEach((toolTemplateInfo) => { + this.externalToolConfigurationService.filterParametersForScope( + toolTemplateInfo.externalTool, + CustomParameterScope.CONTEXT + ); + toolTemplateInfo.externalTool.logoUrl = this.externalToolLogoService.buildLogoUrl(toolTemplateInfo.externalTool); + }); + + return availableToolsForContext; + } + private async ensureSchoolPermissions( user: User, tools: SchoolExternalTool[], diff --git a/apps/server/src/modules/tool/tool-config.ts b/apps/server/src/modules/tool/tool-config.ts index 8e9755b553d..099a732ab0d 100644 --- a/apps/server/src/modules/tool/tool-config.ts +++ b/apps/server/src/modules/tool/tool-config.ts @@ -7,4 +7,5 @@ export interface ToolConfig { CTL_TOOLS_RELOAD_TIME_MS: number; FILES_STORAGE__SERVICE_BASE_URL: string; CTL_TOOLS__PREFERRED_TOOLS_LIMIT: number; + FEATURE_PREFERRED_CTL_TOOLS_ENABLED: boolean; } diff --git a/backup/setup/external-tools.json b/backup/setup/external-tools.json index 120dfa0f8dd..25587ccdca2 100644 --- a/backup/setup/external-tools.json +++ b/backup/setup/external-tools.json @@ -997,5 +997,108 @@ "board-element", "media-board" ] + }, + { + "_id": { + "$oid": "670670862800fa38ddff1227" + }, + "createdAt": { + "$date": "2023-04-27T09:51:15.592Z" + }, + "updatedAt": { + "$date": "2023-04-27T09:51:15.592Z" + }, + "name": "CY Test Tool Preferred", + "url": "https://google.de/", + "config_type": "basic", + "config_baseUrl": "https://google.de/", + "parameters": [], + "isHidden": false, + "openNewTab": true, + "version": 1, + "isDeactivated": false, + "restrictToContexts": [], + "isPreferred": true, + "iconName": "mdiMagnify" + }, + { + "_id": { + "$oid": "670670bc2800fa38ddff122a" + }, + "createdAt": { + "$date": "2023-04-27T09:51:15.592Z" + }, + "updatedAt": { + "$date": "2023-04-27T09:51:15.592Z" + }, + "name": "CY Test Tool Preferred With Param", + "url": "https://google.de/", + "config_type": "basic", + "config_baseUrl": "https://google.de/", + "parameters": [ + { + "name": "contextParam", + "displayName": "context parameter", + "description": "", + "scope": "context", + "location": "query", + "type": "string", + "isOptional": false, + "isProtected": false + } + ], + "isHidden": false, + "openNewTab": true, + "version": 1, + "isDeactivated": false, + "restrictToContexts": [], + "isPreferred": true, + "iconName": "mdiChatOutline" + }, + { + "_id": { + "$oid": "670d07654c3f9eec4c9b6432" + }, + "createdAt": { + "$date": "2023-04-27T09:51:15.592Z" + }, + "updatedAt": { + "$date": "2023-04-27T09:51:15.592Z" + }, + "name": "CY Test Tool Preferred Course Restriction", + "url": "https://google.de/", + "config_type": "basic", + "config_baseUrl": "https://google.de/", + "parameters": [], + "isHidden": false, + "openNewTab": true, + "version": 1, + "isDeactivated": false, + "restrictToContexts": ["course"], + "isPreferred": true, + "iconName": "mdiFileQuestionOutline" + }, + { + "_id": { + "$oid": "670d07704c3f9eec4c9b6434" + }, + "createdAt": { + "$date": "2023-04-27T09:51:15.592Z" + }, + "updatedAt": { + "$date": "2023-04-27T09:51:15.592Z" + }, + "name": "CY Test Tool Preferred Board Restriction", + "url": "https://google.de/", + "config_type": "basic", + "config_baseUrl": "https://google.de/", + "parameters": [], + "isHidden": false, + "openNewTab": true, + "version": 1, + "isDeactivated": false, + "restrictToContexts": ["board-element"], + "isPreferred": true, + "iconName": "mdiEyeOutline" } ] diff --git a/config/default.schema.json b/config/default.schema.json index 272c2e5bce2..d836f48b4bf 100644 --- a/config/default.schema.json +++ b/config/default.schema.json @@ -1416,6 +1416,11 @@ "default": false, "description": "Enables external tools on the column board" }, + "FEATURE_PREFERRED_CTL_TOOLS_ENABLED": { + "type": "boolean", + "default": false, + "description": "Enables preferred external tools on the column board" + }, "CTL_TOOLS": { "type": "object", "description": "CTL Tools properties", From 5c633de7cddc9f04594e565fa6b59a179c1bd605 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Mon, 28 Oct 2024 06:36:11 +0100 Subject: [PATCH 36/47] ew-1009: Modified files per review comments --- .../card-client/card-client.adapter.ts | 2 +- .../card-client/mapper/card-response.mapper.ts | 13 ++++--------- .../controller/common-cartridge.controller.ts | 12 +++++++----- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts index 4861ec0f241..41e689dee38 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.ts @@ -11,7 +11,7 @@ import { CardResponseMapper } from './mapper/card-response.mapper'; export class CardClientAdapter { constructor(private readonly boardCardApi: BoardCardApi, @Inject(REQUEST) private request: Request) {} - public async getAllBoardCardsByIds(cardsIds: Array): Promise { + public async getAllBoardCardsByIds(cardsIds: string[]): Promise { const options = this.createOptionParams(); const getBoardCardsResponse = await this.boardCardApi .cardControllerGetCards(cardsIds, options) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts index 54cf32a2436..97ec3985d9c 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts @@ -47,7 +47,7 @@ export class CardResponseMapper { private static mapToCardResponseDto(cardResponse: CardResponse): CardResponseDto { return new CardResponseDto( cardResponse.id, - cardResponse.title as string, + cardResponse.title ?? '', cardResponse.height, this.mapToCardResponseElementsInnerDto(cardResponse.elements), this.mapToVisibilitySettingsDto(cardResponse.visibilitySettings), @@ -138,12 +138,7 @@ export class CardResponseMapper { new LinkElementResponseDto( element.id, ContentElementType.LINK, - new LinkElementContentDto( - content.url, - content.title, - content.description as string, - content.imageUrl as string - ), + new LinkElementContentDto(content.url, content.title, content.description ?? '', content.imageUrl ?? ''), this.mapToTimestampDto(element.timestamps) ) ); @@ -171,10 +166,10 @@ export class CardResponseMapper { private static mapToVisibilitySettingsDto( visibilitySettings: VisibilitySettingsResponse ): VisibilitySettingsResponseDto { - return new VisibilitySettingsResponseDto(visibilitySettings.publishedAt as string); + return new VisibilitySettingsResponseDto(visibilitySettings.publishedAt ?? ''); } private static mapToTimestampDto(timestamp: TimestampsResponse): TimestampResponseDto { - return new TimestampResponseDto(timestamp.lastUpdatedAt, timestamp.createdAt, timestamp.deletedAt as string); + return new TimestampResponseDto(timestamp.lastUpdatedAt, timestamp.createdAt, timestamp.deletedAt ?? ''); } } diff --git a/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts b/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts index cccc5656977..5571391eabe 100644 --- a/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts +++ b/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Param } from '@nestjs/common'; +import { Controller, Get, Param, ParseArrayPipe, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { CommonCartridgeUc } from '../uc/common-cartridge.uc'; import { ExportCourseParams } from './dto'; @@ -15,9 +15,11 @@ export class CommonCartridgeController { return this.commonCartridgeUC.exportCourse(exportCourseParams.parentId); } - @Get('export/cards/:parentId') - public async exportCards(@Param() exportCourseParams: ExportCourseParams): Promise { - const ids: Array = new Array(exportCourseParams.parentId); - return this.commonCartridgeUC.exportCardList(ids); + @Get('export/cards') + public async exportCards( + @Query('ids', new ParseArrayPipe({ items: String, separator: ',' })) ids: string[] + ): Promise { + const response: CardListResponseDto = await this.commonCartridgeUC.exportCardList(ids); + return response; } } From db0f2186dcccc41a5eb31aa45310857f8334cd3d Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Mon, 28 Oct 2024 09:15:10 +0100 Subject: [PATCH 37/47] ew-1009: changes to test file structure according to review --- .../mapper/card-response.mapper.spec.ts | 301 ++++++++---------- 1 file changed, 136 insertions(+), 165 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index 6615ab579dc..758351327f2 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -28,189 +28,160 @@ describe('CardResponseMapper', () => { type, content, timestamps: { - lastUpdatedAt: '2024-10-01T10:00:00Z', - createdAt: '2024-10-01T09:00:00Z', + lastUpdatedAt: faker.date.recent().toISOString(), + createdAt: faker.date.soon().toISOString(), deletedAt: null, }, }; }; - - it('should map CardListResponse to CardListResponseDto with all types of elements', () => { - const mockCardListResponse: CardListResponse = { - data: [ - { - id: 'card-1', - title: 'Card 1', - height: 200, - elements: [ - createMockElement( - 'element-1', - ContentElementType.COLLABORATIVE_TEXT_EDITOR, - {} - ) as CollaborativeTextEditorElementResponse, - createMockElement('element-2', ContentElementType.DELETED, { - title: 'Deleted Title', - description: 'Deleted Description', - }) as DeletedElementResponse, - createMockElement('element-3', ContentElementType.SUBMISSION_CONTAINER, { - dueDate: '2024-10-10', - }) as SubmissionContainerElementResponse, - createMockElement('element-4', ContentElementType.DRAWING, { - description: 'Sample Drawing', - }) as DrawingElementResponse, - createMockElement('element-5', ContentElementType.EXTERNAL_TOOL, { - contextExternalToolId: 'external-tool-1', - }) as ExternalToolElementResponse, - createMockElement('element-6', ContentElementType.FILE, { - caption: 'Sample Caption', - alternativeText: 'Sample Alt Text', - }) as FileElementResponse, - createMockElement('element-7', ContentElementType.LINK, { - url: 'https://example.com', - title: 'Example Title', - description: 'Sample Description', - imageUrl: 'https://example.com/image.png', - }) as LinkElementResponse, - createMockElement('element-8', ContentElementType.RICH_TEXT, { - text: 'Rich text content', - inputFormat: 'Markdown', - }) as RichTextElementResponse, - createMockElement( - 'element-unknown', - 'UNKNOWN_TYPE' as ContentElementType, - {} - ) as CardResponseElementsInner, - ], - visibilitySettings: { publishedAt: '2024-10-01T12:00:00Z' }, - timestamps: { - lastUpdatedAt: '2024-10-01T11:00:00Z', - createdAt: '2024-10-01T10:00:00Z', - deletedAt: faker.date.recent().toString(), + describe("when various elements' responses are sent to mapper", () => { + it('should map CardListResponse to CardListResponseDto with all types of elements', () => { + const mockCardListResponse: CardListResponse = { + data: [ + { + id: 'card-1', + title: 'Card 1', + height: 200, + elements: [ + createMockElement( + faker.string.uuid(), + ContentElementType.COLLABORATIVE_TEXT_EDITOR, + {} + ) as CollaborativeTextEditorElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.DELETED, { + title: faker.lorem.sentence(), + description: faker.lorem.words(), + }) as DeletedElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.SUBMISSION_CONTAINER, { + dueDate: faker.date.soon().toISOString(), + }) as SubmissionContainerElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.DRAWING, { + description: faker.lorem.word(), + }) as DrawingElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.EXTERNAL_TOOL, { + contextExternalToolId: faker.string.uuid(), + }) as ExternalToolElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.FILE, { + caption: faker.lorem.sentence(), + alternativeText: faker.lorem.word(), + }) as FileElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.LINK, { + url: faker.internet.url(), + title: faker.lorem.word(), + description: faker.lorem.sentence(), + imageUrl: faker.internet.url(), + }) as LinkElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.RICH_TEXT, { + text: faker.lorem.paragraph(), + inputFormat: faker.internet.domainName(), + }) as RichTextElementResponse, + createMockElement( + faker.string.uuid(), + 'UNKNOWN_TYPE' as ContentElementType, + {} + ) as CardResponseElementsInner, + ], + visibilitySettings: { publishedAt: '2024-10-01T12:00:00Z' }, + timestamps: { + lastUpdatedAt: '2024-10-01T11:00:00Z', + createdAt: faker.date.past().toString(), + deletedAt: faker.date.recent().toString(), + }, }, - }, - ], - }; + ], + }; - const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); - expect(result).toBeDefined(); - expect(result.data).toHaveLength(1); + const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); + expect(result).toBeDefined(); + expect(result.data).toHaveLength(1); - const cardResponseDto = result.data[0]; - expect(cardResponseDto.id).toBe('card-1'); - expect(cardResponseDto.title).toBe('Card 1'); - expect(cardResponseDto.height).toBe(200); - expect(cardResponseDto.visibilitySettings.publishedAt).toBe('2024-10-01T12:00:00Z'); - expect(cardResponseDto.timeStamps.lastUpdatedAt).toBe('2024-10-01T11:00:00Z'); + const cardResponseDto = result.data[0]; + expect(cardResponseDto.id).toBe('card-1'); + expect(cardResponseDto.title).toBe('Card 1'); + expect(cardResponseDto.height).toBe(200); + expect(cardResponseDto.visibilitySettings.publishedAt).toBe('2024-10-01T12:00:00Z'); + expect(cardResponseDto.timeStamps.lastUpdatedAt).toBe('2024-10-01T11:00:00Z'); - expect(cardResponseDto.elements).toHaveLength(8); - expect(cardResponseDto.elements[0].type).toBe(ContentElementType.COLLABORATIVE_TEXT_EDITOR); - expect(cardResponseDto.elements[1].type).toBe(ContentElementType.DELETED); - expect(cardResponseDto.elements[2].type).toBe(ContentElementType.SUBMISSION_CONTAINER); - expect(cardResponseDto.elements[3].type).toBe(ContentElementType.DRAWING); - expect(cardResponseDto.elements[4].type).toBe(ContentElementType.EXTERNAL_TOOL); - expect(cardResponseDto.elements[5].type).toBe(ContentElementType.FILE); - expect(cardResponseDto.elements[6].type).toBe(ContentElementType.LINK); - expect(cardResponseDto.elements[7].type).toBe(ContentElementType.RICH_TEXT); + expect(cardResponseDto.elements).toHaveLength(8); + expect(cardResponseDto.elements[0].type).toBe(ContentElementType.COLLABORATIVE_TEXT_EDITOR); + expect(cardResponseDto.elements[1].type).toBe(ContentElementType.DELETED); + expect(cardResponseDto.elements[2].type).toBe(ContentElementType.SUBMISSION_CONTAINER); + expect(cardResponseDto.elements[3].type).toBe(ContentElementType.DRAWING); + expect(cardResponseDto.elements[4].type).toBe(ContentElementType.EXTERNAL_TOOL); + expect(cardResponseDto.elements[5].type).toBe(ContentElementType.FILE); + expect(cardResponseDto.elements[6].type).toBe(ContentElementType.LINK); + expect(cardResponseDto.elements[7].type).toBe(ContentElementType.RICH_TEXT); + }); }); - it('should handle unknown element types without breaking', () => { - const mockCardListResponse: CardListResponse = { - data: [ - { - id: 'card-2', - title: 'Card 2', - height: 150, - elements: [ - createMockElement( - 'element-unknown', - 'UNKNOWN_TYPE' as ContentElementType, - {} - ) as CardResponseElementsInner, - ], - visibilitySettings: { publishedAt: faker.date.past().toISOString() }, - timestamps: { - lastUpdatedAt: faker.date.past().toISOString(), - createdAt: faker.date.past().toISOString(), - deletedAt: faker.date.recent().toString(), + describe('when there is an unknown element response to handle', () => { + it('should handle unknown element types without breaking', () => { + const mockCardListResponse: CardListResponse = { + data: [ + { + id: 'card-2', + title: 'Card 2', + height: 150, + elements: [ + createMockElement( + 'element-unknown', + 'UNKNOWN_TYPE' as ContentElementType, + {} + ) as CardResponseElementsInner, + ], + visibilitySettings: { publishedAt: faker.date.past().toISOString() }, + timestamps: { + lastUpdatedAt: faker.date.past().toISOString(), + createdAt: faker.date.past().toISOString(), + deletedAt: faker.date.recent().toString(), + }, }, - }, - ], - }; + ], + }; - const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); - expect(result).toBeDefined(); - expect(result.data).toHaveLength(1); + const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); + expect(result).toBeDefined(); + expect(result.data).toHaveLength(1); - const cardResponseDto = result.data[0]; - expect(cardResponseDto.id).toBe('card-2'); - expect(cardResponseDto.title).toBe('Card 2'); - expect(cardResponseDto.height).toBe(150); - expect(cardResponseDto.elements).toHaveLength(0); + const cardResponseDto = result.data[0]; + expect(cardResponseDto.id).toBe('card-2'); + expect(cardResponseDto.title).toBe('Card 2'); + expect(cardResponseDto.height).toBe(150); + expect(cardResponseDto.elements).toHaveLength(0); + }); }); - it('should return an empty list of elements when CardResponse has no elements', () => { - const mockCardListResponse: CardListResponse = { - data: [ - { - id: 'card-3', - title: 'Card 3', - height: 100, - elements: [], - visibilitySettings: { publishedAt: '2024-10-03T12:00:00Z' }, - timestamps: { - lastUpdatedAt: '2024-10-03T11:00:00Z', - createdAt: '2024-10-03T10:00:00Z', - deletedAt: faker.date.recent().toString(), - }, - }, - ], - }; - const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); - expect(result).toBeDefined(); - expect(result.data).toHaveLength(1); - - const cardResponse: CardResponseDto = result.data[0]; - expect(cardResponse.id).toBe('card-3'); - expect(cardResponse.title).toBe('Card 3'); - expect(cardResponse.height).toBe(100); - expect(cardResponse.elements).toHaveLength(0); - expect(cardResponse.visibilitySettings.publishedAt).toBe('2024-10-03T12:00:00Z'); - expect(cardResponse.timeStamps.lastUpdatedAt).toBe('2024-10-03T11:00:00Z'); - }); - - it('should cover default switch case and return an empty object', () => { - const mockCardListResponse: CardListResponse = { - data: [ - { - id: faker.string.uuid(), - title: faker.lorem.sentence(), - height: faker.number.int(), - elements: [ - createMockElement( - faker.string.uuid(), - 'UNKNOWN_TYPE' as ContentElementType, - {} - ) as CardResponseElementsInner, - ], - visibilitySettings: { publishedAt: faker.date.past().toISOString() }, - timestamps: { - lastUpdatedAt: faker.date.recent().toISOString(), - createdAt: faker.date.past().toISOString(), - deletedAt: faker.date.future().toISOString(), + describe('when CardResponse has no elements', () => { + it('should return an empty list of elements', () => { + const mockCardListResponse: CardListResponse = { + data: [ + { + id: 'card-3', + title: 'Card 3', + height: 100, + elements: [], + visibilitySettings: { publishedAt: '2024-10-03T12:00:00Z' }, + timestamps: { + lastUpdatedAt: '2024-10-03T11:00:00Z', + createdAt: '2024-10-03T10:00:00Z', + deletedAt: faker.date.recent().toString(), + }, }, - }, - ], - }; + ], + }; - const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); - expect(result).toBeDefined(); - expect(result.data).toHaveLength(1); + const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); + expect(result).toBeDefined(); + expect(result.data).toHaveLength(1); - const cardResponseDto = result.data[0]; - expect(cardResponseDto.id).toBe(mockCardListResponse.data[0].id); - expect(cardResponseDto.title).toBe(mockCardListResponse.data[0].title); - expect(cardResponseDto.height).toBe(mockCardListResponse.data[0].height); - expect(cardResponseDto.elements).toHaveLength(0); + const cardResponse: CardResponseDto = result.data[0]; + expect(cardResponse.id).toBe('card-3'); + expect(cardResponse.title).toBe('Card 3'); + expect(cardResponse.height).toBe(100); + expect(cardResponse.elements).toHaveLength(0); + expect(cardResponse.visibilitySettings.publishedAt).toBe('2024-10-03T12:00:00Z'); + expect(cardResponse.timeStamps.lastUpdatedAt).toBe('2024-10-03T11:00:00Z'); + }); }); }); }); From 29f0b686dc3305de7cfe7c7357453c08e0b3689c Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Mon, 28 Oct 2024 09:54:54 +0100 Subject: [PATCH 38/47] ew-1009: fixed tests structure and added describe when blocks --- .../card-client/card-client.adapter.spec.ts | 29 +-- .../mapper/card-response.mapper.spec.ts | 201 ++++++++---------- 2 files changed, 100 insertions(+), 130 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts index a15bbccf8b7..22c37f518e7 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts @@ -51,23 +51,26 @@ describe(CardClientAdapter.name, () => { }); describe('getAllBoardCardsByIds', () => { - const setup = () => { - const cardResponseData: CardResponse[] = []; - const data: CardListResponse = { data: cardResponseData }; - const response = createMock>({ - data, - }); + describe('when getAllBoardCardsByIds is called', () => { + const setup = () => { + const cardResponseData: CardResponse[] = []; + const data: CardListResponse = { data: cardResponseData }; + const response = createMock>({ + data, + }); - cardApiMock.cardControllerGetCards.mockResolvedValue(response); + cardApiMock.cardControllerGetCards.mockResolvedValue(response); - return faker.string.uuid(); - }; - it('it should return a list of card response', async () => { - const ids: Array = new Array(setup()); - await adapterUnderTest.getAllBoardCardsByIds(ids); - expect(cardApiMock.cardControllerGetCards).toHaveBeenCalled(); + return faker.string.uuid(); + }; + it('it should return a list of card response', async () => { + const ids: Array = new Array(setup()); + await adapterUnderTest.getAllBoardCardsByIds(ids); + expect(cardApiMock.cardControllerGetCards).toHaveBeenCalled(); + }); }); }); + describe('When no JWT token is found', () => { const setup = () => { const ids: Array = new Array(faker.string.uuid()); diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index 758351327f2..5b127c1c36a 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -17,90 +17,91 @@ import { CardContentElementInner } from '../types/card-content-elements-inner.ty import { CardResponseDto } from '../dto/card-response.dto'; describe('CardResponseMapper', () => { + const createMockElement = ( + id: string, + type: ContentElementType, + content: CardContentElementInner + ): CardContentElementInner => { + return { + id, + type, + content, + timestamps: { + lastUpdatedAt: faker.date.recent().toISOString(), + createdAt: faker.date.soon().toISOString(), + deletedAt: null, + }, + }; + }; describe('mapToCardListResponseDto', () => { - const createMockElement = ( - id: string, - type: ContentElementType, - content: CardContentElementInner - ): CardContentElementInner => { - return { - id, - type, - content, - timestamps: { - lastUpdatedAt: faker.date.recent().toISOString(), - createdAt: faker.date.soon().toISOString(), - deletedAt: null, - }, + const setup = (elementsArray: CardResponseElementsInner[]) => { + const mockCardListResponse: CardListResponse = { + data: [ + { + id: 'card-1', + title: 'Card 1', + height: 100, + elements: elementsArray, + visibilitySettings: { publishedAt: '2024-10-03T12:00:00Z' }, + timestamps: { + lastUpdatedAt: '2024-10-03T11:00:00Z', + createdAt: '2024-10-03T10:00:00Z', + deletedAt: faker.date.recent().toString(), + }, + }, + ], }; + return mockCardListResponse; }; + describe("when various elements' responses are sent to mapper", () => { it('should map CardListResponse to CardListResponseDto with all types of elements', () => { - const mockCardListResponse: CardListResponse = { - data: [ - { - id: 'card-1', - title: 'Card 1', - height: 200, - elements: [ - createMockElement( - faker.string.uuid(), - ContentElementType.COLLABORATIVE_TEXT_EDITOR, - {} - ) as CollaborativeTextEditorElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.DELETED, { - title: faker.lorem.sentence(), - description: faker.lorem.words(), - }) as DeletedElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.SUBMISSION_CONTAINER, { - dueDate: faker.date.soon().toISOString(), - }) as SubmissionContainerElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.DRAWING, { - description: faker.lorem.word(), - }) as DrawingElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.EXTERNAL_TOOL, { - contextExternalToolId: faker.string.uuid(), - }) as ExternalToolElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.FILE, { - caption: faker.lorem.sentence(), - alternativeText: faker.lorem.word(), - }) as FileElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.LINK, { - url: faker.internet.url(), - title: faker.lorem.word(), - description: faker.lorem.sentence(), - imageUrl: faker.internet.url(), - }) as LinkElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.RICH_TEXT, { - text: faker.lorem.paragraph(), - inputFormat: faker.internet.domainName(), - }) as RichTextElementResponse, - createMockElement( - faker.string.uuid(), - 'UNKNOWN_TYPE' as ContentElementType, - {} - ) as CardResponseElementsInner, - ], - visibilitySettings: { publishedAt: '2024-10-01T12:00:00Z' }, - timestamps: { - lastUpdatedAt: '2024-10-01T11:00:00Z', - createdAt: faker.date.past().toString(), - deletedAt: faker.date.recent().toString(), - }, - }, - ], - }; + const mockList: CardListResponse = setup([ + createMockElement( + faker.string.uuid(), + ContentElementType.COLLABORATIVE_TEXT_EDITOR, + {} + ) as CollaborativeTextEditorElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.DELETED, { + title: faker.lorem.sentence(), + description: faker.lorem.words(), + }) as DeletedElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.SUBMISSION_CONTAINER, { + dueDate: faker.date.soon().toISOString(), + }) as SubmissionContainerElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.DRAWING, { + description: faker.lorem.word(), + }) as DrawingElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.EXTERNAL_TOOL, { + contextExternalToolId: faker.string.uuid(), + }) as ExternalToolElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.FILE, { + caption: faker.lorem.sentence(), + alternativeText: faker.lorem.word(), + }) as FileElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.LINK, { + url: faker.internet.url(), + title: faker.lorem.word(), + description: faker.lorem.sentence(), + imageUrl: faker.internet.url(), + }) as LinkElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.RICH_TEXT, { + text: faker.lorem.paragraph(), + inputFormat: faker.internet.domainName(), + }) as RichTextElementResponse, + createMockElement(faker.string.uuid(), 'UNKNOWN_TYPE' as ContentElementType, {}) as CardResponseElementsInner, + ]); - const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); + const result = CardResponseMapper.mapToCardListResponseDto(mockList); expect(result).toBeDefined(); expect(result.data).toHaveLength(1); const cardResponseDto = result.data[0]; expect(cardResponseDto.id).toBe('card-1'); expect(cardResponseDto.title).toBe('Card 1'); - expect(cardResponseDto.height).toBe(200); - expect(cardResponseDto.visibilitySettings.publishedAt).toBe('2024-10-01T12:00:00Z'); - expect(cardResponseDto.timeStamps.lastUpdatedAt).toBe('2024-10-01T11:00:00Z'); + expect(cardResponseDto.height).toBe(100); + expect(cardResponseDto.visibilitySettings.publishedAt).toBe('2024-10-03T12:00:00Z'); + expect(cardResponseDto.timeStamps.lastUpdatedAt).toBe('2024-10-03T11:00:00Z'); expect(cardResponseDto.elements).toHaveLength(8); expect(cardResponseDto.elements[0].type).toBe(ContentElementType.COLLABORATIVE_TEXT_EDITOR); @@ -116,67 +117,33 @@ describe('CardResponseMapper', () => { describe('when there is an unknown element response to handle', () => { it('should handle unknown element types without breaking', () => { - const mockCardListResponse: CardListResponse = { - data: [ - { - id: 'card-2', - title: 'Card 2', - height: 150, - elements: [ - createMockElement( - 'element-unknown', - 'UNKNOWN_TYPE' as ContentElementType, - {} - ) as CardResponseElementsInner, - ], - visibilitySettings: { publishedAt: faker.date.past().toISOString() }, - timestamps: { - lastUpdatedAt: faker.date.past().toISOString(), - createdAt: faker.date.past().toISOString(), - deletedAt: faker.date.recent().toString(), - }, - }, - ], - }; + const mockList: CardListResponse = setup([ + createMockElement('element-unknown', 'UNKNOWN_TYPE' as ContentElementType, {}) as CardResponseElementsInner, + ]); - const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); + const result = CardResponseMapper.mapToCardListResponseDto(mockList); expect(result).toBeDefined(); expect(result.data).toHaveLength(1); const cardResponseDto = result.data[0]; - expect(cardResponseDto.id).toBe('card-2'); - expect(cardResponseDto.title).toBe('Card 2'); - expect(cardResponseDto.height).toBe(150); + expect(cardResponseDto.id).toBe('card-1'); + expect(cardResponseDto.title).toBe('Card 1'); + expect(cardResponseDto.height).toBe(100); expect(cardResponseDto.elements).toHaveLength(0); }); }); describe('when CardResponse has no elements', () => { it('should return an empty list of elements', () => { - const mockCardListResponse: CardListResponse = { - data: [ - { - id: 'card-3', - title: 'Card 3', - height: 100, - elements: [], - visibilitySettings: { publishedAt: '2024-10-03T12:00:00Z' }, - timestamps: { - lastUpdatedAt: '2024-10-03T11:00:00Z', - createdAt: '2024-10-03T10:00:00Z', - deletedAt: faker.date.recent().toString(), - }, - }, - ], - }; + const mockList: CardListResponse = setup([]); - const result = CardResponseMapper.mapToCardListResponseDto(mockCardListResponse); + const result = CardResponseMapper.mapToCardListResponseDto(mockList); expect(result).toBeDefined(); expect(result.data).toHaveLength(1); const cardResponse: CardResponseDto = result.data[0]; - expect(cardResponse.id).toBe('card-3'); - expect(cardResponse.title).toBe('Card 3'); + expect(cardResponse.id).toBe('card-1'); + expect(cardResponse.title).toBe('Card 1'); expect(cardResponse.height).toBe(100); expect(cardResponse.elements).toHaveLength(0); expect(cardResponse.visibilitySettings.publishedAt).toBe('2024-10-03T12:00:00Z'); From efe39d24067f8af8b6e6df8bd755bf8e0489b443 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Mon, 28 Oct 2024 09:58:41 +0100 Subject: [PATCH 39/47] ew-1009: faker used where needed --- .../card-client/mapper/card-response.mapper.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index 5b127c1c36a..6c6d7941f95 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -45,7 +45,7 @@ describe('CardResponseMapper', () => { visibilitySettings: { publishedAt: '2024-10-03T12:00:00Z' }, timestamps: { lastUpdatedAt: '2024-10-03T11:00:00Z', - createdAt: '2024-10-03T10:00:00Z', + createdAt: faker.date.recent().toISOString(), deletedAt: faker.date.recent().toString(), }, }, From 504ecac08142d3ad0cc7e825adf2a5b78ebeafc4 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Mon, 28 Oct 2024 12:28:39 +0100 Subject: [PATCH 40/47] ew-1009: Repositioned test arrange to be in the describe block not the it block --- .../mapper/card-response.mapper.spec.ts | 83 +++++++++---------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index 6c6d7941f95..22ddb1f5cef 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -33,6 +33,7 @@ describe('CardResponseMapper', () => { }, }; }; + describe('mapToCardListResponseDto', () => { const setup = (elementsArray: CardResponseElementsInner[]) => { const mockCardListResponse: CardListResponse = { @@ -55,43 +56,43 @@ describe('CardResponseMapper', () => { }; describe("when various elements' responses are sent to mapper", () => { - it('should map CardListResponse to CardListResponseDto with all types of elements', () => { - const mockList: CardListResponse = setup([ - createMockElement( - faker.string.uuid(), - ContentElementType.COLLABORATIVE_TEXT_EDITOR, - {} - ) as CollaborativeTextEditorElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.DELETED, { - title: faker.lorem.sentence(), - description: faker.lorem.words(), - }) as DeletedElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.SUBMISSION_CONTAINER, { - dueDate: faker.date.soon().toISOString(), - }) as SubmissionContainerElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.DRAWING, { - description: faker.lorem.word(), - }) as DrawingElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.EXTERNAL_TOOL, { - contextExternalToolId: faker.string.uuid(), - }) as ExternalToolElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.FILE, { - caption: faker.lorem.sentence(), - alternativeText: faker.lorem.word(), - }) as FileElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.LINK, { - url: faker.internet.url(), - title: faker.lorem.word(), - description: faker.lorem.sentence(), - imageUrl: faker.internet.url(), - }) as LinkElementResponse, - createMockElement(faker.string.uuid(), ContentElementType.RICH_TEXT, { - text: faker.lorem.paragraph(), - inputFormat: faker.internet.domainName(), - }) as RichTextElementResponse, - createMockElement(faker.string.uuid(), 'UNKNOWN_TYPE' as ContentElementType, {}) as CardResponseElementsInner, - ]); + const mockList: CardListResponse = setup([ + createMockElement( + faker.string.uuid(), + ContentElementType.COLLABORATIVE_TEXT_EDITOR, + {} + ) as CollaborativeTextEditorElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.DELETED, { + title: faker.lorem.sentence(), + description: faker.lorem.words(), + }) as DeletedElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.SUBMISSION_CONTAINER, { + dueDate: faker.date.soon().toISOString(), + }) as SubmissionContainerElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.DRAWING, { + description: faker.lorem.word(), + }) as DrawingElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.EXTERNAL_TOOL, { + contextExternalToolId: faker.string.uuid(), + }) as ExternalToolElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.FILE, { + caption: faker.lorem.sentence(), + alternativeText: faker.lorem.word(), + }) as FileElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.LINK, { + url: faker.internet.url(), + title: faker.lorem.word(), + description: faker.lorem.sentence(), + imageUrl: faker.internet.url(), + }) as LinkElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.RICH_TEXT, { + text: faker.lorem.paragraph(), + inputFormat: faker.internet.domainName(), + }) as RichTextElementResponse, + createMockElement(faker.string.uuid(), 'UNKNOWN_TYPE' as ContentElementType, {}) as CardResponseElementsInner, + ]); + it('should map CardListResponse to CardListResponseDto with all types of elements', () => { const result = CardResponseMapper.mapToCardListResponseDto(mockList); expect(result).toBeDefined(); expect(result.data).toHaveLength(1); @@ -116,11 +117,10 @@ describe('CardResponseMapper', () => { }); describe('when there is an unknown element response to handle', () => { + const mockList: CardListResponse = setup([ + createMockElement('element-unknown', 'UNKNOWN_TYPE' as ContentElementType, {}) as CardResponseElementsInner, + ]); it('should handle unknown element types without breaking', () => { - const mockList: CardListResponse = setup([ - createMockElement('element-unknown', 'UNKNOWN_TYPE' as ContentElementType, {}) as CardResponseElementsInner, - ]); - const result = CardResponseMapper.mapToCardListResponseDto(mockList); expect(result).toBeDefined(); expect(result.data).toHaveLength(1); @@ -134,9 +134,8 @@ describe('CardResponseMapper', () => { }); describe('when CardResponse has no elements', () => { + const mockList: CardListResponse = setup([]); it('should return an empty list of elements', () => { - const mockList: CardListResponse = setup([]); - const result = CardResponseMapper.mapToCardListResponseDto(mockList); expect(result).toBeDefined(); expect(result.data).toHaveLength(1); From 8b229618ae25965c6ed1bbee60ddf75e2c4cf954 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Mon, 28 Oct 2024 14:23:04 +0100 Subject: [PATCH 41/47] ew-1009: fix according to review --- .../card-client/mapper/card-response.mapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts index 97ec3985d9c..ecf86629756 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.ts @@ -67,7 +67,7 @@ export class CardResponseMapper { new CollaborativeTextEditorElementResponseDto( element.id, ContentElementType.COLLABORATIVE_TEXT_EDITOR, - {}, + { ...element.content }, this.mapToTimestampDto(element.timestamps) ) ); From 2d7d8e5fd6eb820b3575b4017412b09015148323 Mon Sep 17 00:00:00 2001 From: Firas Shmit Date: Mon, 28 Oct 2024 15:04:54 +0100 Subject: [PATCH 42/47] EW-1009 modified test structure of card mapper --- .../card-client/mapper/card-response.mapper.spec.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index 22ddb1f5cef..c2b0d464b55 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -94,16 +94,15 @@ describe('CardResponseMapper', () => { it('should map CardListResponse to CardListResponseDto with all types of elements', () => { const result = CardResponseMapper.mapToCardListResponseDto(mockList); + const cardResponseDto = result.data[0]; + expect(result).toBeDefined(); expect(result.data).toHaveLength(1); - - const cardResponseDto = result.data[0]; expect(cardResponseDto.id).toBe('card-1'); expect(cardResponseDto.title).toBe('Card 1'); expect(cardResponseDto.height).toBe(100); expect(cardResponseDto.visibilitySettings.publishedAt).toBe('2024-10-03T12:00:00Z'); expect(cardResponseDto.timeStamps.lastUpdatedAt).toBe('2024-10-03T11:00:00Z'); - expect(cardResponseDto.elements).toHaveLength(8); expect(cardResponseDto.elements[0].type).toBe(ContentElementType.COLLABORATIVE_TEXT_EDITOR); expect(cardResponseDto.elements[1].type).toBe(ContentElementType.DELETED); @@ -122,10 +121,10 @@ describe('CardResponseMapper', () => { ]); it('should handle unknown element types without breaking', () => { const result = CardResponseMapper.mapToCardListResponseDto(mockList); + const cardResponseDto = result.data[0]; + expect(result).toBeDefined(); expect(result.data).toHaveLength(1); - - const cardResponseDto = result.data[0]; expect(cardResponseDto.id).toBe('card-1'); expect(cardResponseDto.title).toBe('Card 1'); expect(cardResponseDto.height).toBe(100); @@ -137,10 +136,10 @@ describe('CardResponseMapper', () => { const mockList: CardListResponse = setup([]); it('should return an empty list of elements', () => { const result = CardResponseMapper.mapToCardListResponseDto(mockList); + const cardResponse: CardResponseDto = result.data[0]; + expect(result).toBeDefined(); expect(result.data).toHaveLength(1); - - const cardResponse: CardResponseDto = result.data[0]; expect(cardResponse.id).toBe('card-1'); expect(cardResponse.title).toBe('Card 1'); expect(cardResponse.height).toBe(100); From 80798aeff4460bd4b51177178b3170b4768035ee Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 29 Oct 2024 09:44:29 +0100 Subject: [PATCH 43/47] ew-1009: changes according to 2nd review --- .../card-client/card-client.adapter.spec.ts | 1 + .../card-client/mapper/card-response.mapper.spec.ts | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts index 22c37f518e7..f4f5ea1ee2f 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts @@ -63,6 +63,7 @@ describe(CardClientAdapter.name, () => { return faker.string.uuid(); }; + it('it should return a list of card response', async () => { const ids: Array = new Array(setup()); await adapterUnderTest.getAllBoardCardsByIds(ids); diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index c2b0d464b55..9987f870850 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -62,33 +62,41 @@ describe('CardResponseMapper', () => { ContentElementType.COLLABORATIVE_TEXT_EDITOR, {} ) as CollaborativeTextEditorElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.DELETED, { title: faker.lorem.sentence(), description: faker.lorem.words(), }) as DeletedElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.SUBMISSION_CONTAINER, { dueDate: faker.date.soon().toISOString(), }) as SubmissionContainerElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.DRAWING, { description: faker.lorem.word(), }) as DrawingElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.EXTERNAL_TOOL, { contextExternalToolId: faker.string.uuid(), }) as ExternalToolElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.FILE, { caption: faker.lorem.sentence(), alternativeText: faker.lorem.word(), }) as FileElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.LINK, { url: faker.internet.url(), title: faker.lorem.word(), description: faker.lorem.sentence(), imageUrl: faker.internet.url(), }) as LinkElementResponse, + createMockElement(faker.string.uuid(), ContentElementType.RICH_TEXT, { text: faker.lorem.paragraph(), inputFormat: faker.internet.domainName(), }) as RichTextElementResponse, + createMockElement(faker.string.uuid(), 'UNKNOWN_TYPE' as ContentElementType, {}) as CardResponseElementsInner, ]); @@ -119,6 +127,7 @@ describe('CardResponseMapper', () => { const mockList: CardListResponse = setup([ createMockElement('element-unknown', 'UNKNOWN_TYPE' as ContentElementType, {}) as CardResponseElementsInner, ]); + it('should handle unknown element types without breaking', () => { const result = CardResponseMapper.mapToCardListResponseDto(mockList); const cardResponseDto = result.data[0]; @@ -134,6 +143,7 @@ describe('CardResponseMapper', () => { describe('when CardResponse has no elements', () => { const mockList: CardListResponse = setup([]); + it('should return an empty list of elements', () => { const result = CardResponseMapper.mapToCardListResponseDto(mockList); const cardResponse: CardResponseDto = result.data[0]; From 3fe4be3a19a0b7ed488c734d59c990cb9ee28af3 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 29 Oct 2024 10:23:27 +0100 Subject: [PATCH 44/47] ew-1009 --- .../card-client/mapper/card-response.mapper.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index 9987f870850..ad2025d7bf0 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -22,7 +22,7 @@ describe('CardResponseMapper', () => { type: ContentElementType, content: CardContentElementInner ): CardContentElementInner => { - return { + const element: CardContentElementInner = { id, type, content, @@ -32,6 +32,8 @@ describe('CardResponseMapper', () => { deletedAt: null, }, }; + + return element; }; describe('mapToCardListResponseDto', () => { From 073725e84d35a023093265b712e47963fec8b2c3 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 29 Oct 2024 10:33:11 +0100 Subject: [PATCH 45/47] ew-1009: removed test endpoint method in controller and usecase --- .../controller/common-cartridge.controller.ts | 11 +---------- .../common-cartridge/uc/common-cartridge.uc.ts | 7 ------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts b/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts index 5571391eabe..bd609c4ff88 100644 --- a/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts +++ b/apps/server/src/modules/common-cartridge/controller/common-cartridge.controller.ts @@ -1,9 +1,8 @@ -import { Controller, Get, Param, ParseArrayPipe, Query } from '@nestjs/common'; +import { Controller, Get, Param } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { CommonCartridgeUc } from '../uc/common-cartridge.uc'; import { ExportCourseParams } from './dto'; import { CourseExportBodyResponse } from './dto/course-export-body.response'; -import { CardListResponseDto } from '../common-cartridge-client/card-client/dto/card-list-response.dto'; @ApiTags('common-cartridge') @Controller('common-cartridge') @@ -14,12 +13,4 @@ export class CommonCartridgeController { public async exportCourse(@Param() exportCourseParams: ExportCourseParams): Promise { return this.commonCartridgeUC.exportCourse(exportCourseParams.parentId); } - - @Get('export/cards') - public async exportCards( - @Query('ids', new ParseArrayPipe({ items: String, separator: ',' })) ids: string[] - ): Promise { - const response: CardListResponseDto = await this.commonCartridgeUC.exportCardList(ids); - return response; - } } diff --git a/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts b/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts index 86b372b2d9c..8caa9381633 100644 --- a/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts +++ b/apps/server/src/modules/common-cartridge/uc/common-cartridge.uc.ts @@ -4,7 +4,6 @@ import { CourseFileIdsResponse } from '../controller/dto'; import { CommonCartridgeExportService } from '../service/common-cartridge-export.service'; import { CourseExportBodyResponse } from '../controller/dto/course-export-body.response'; import { CourseCommonCartridgeMetadataDto } from '../common-cartridge-client/course-client'; -import { CardListResponseDto } from '../common-cartridge-client/card-client/dto/card-list-response.dto'; @Injectable() export class CommonCartridgeUc { @@ -23,10 +22,4 @@ export class CommonCartridgeUc { return response; } - - public async exportCardList(cardIds: Array): Promise { - const cardList = await this.exportService.findAllCardsByIds(cardIds); - - return cardList; - } } From 0504b103327c145321d10f10b1cbb5a79e2407f6 Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 29 Oct 2024 11:07:22 +0100 Subject: [PATCH 46/47] ew-1009: --- .../mapper/card-response.mapper.spec.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts index ad2025d7bf0..29052e30911 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/mapper/card-response.mapper.spec.ts @@ -160,5 +160,29 @@ describe('CardResponseMapper', () => { expect(cardResponse.timeStamps.lastUpdatedAt).toBe('2024-10-03T11:00:00Z'); }); }); + + describe('when the publishedAt in visibilitySettings is null', () => { + const mockList: CardListResponse = setup([]); + mockList.data[0].visibilitySettings.publishedAt = undefined; + + it('should return an empty string', () => { + const mapperResult = CardResponseMapper.mapToCardListResponseDto(mockList); + const cardResponse: CardResponseDto = mapperResult.data[0]; + + expect(cardResponse.visibilitySettings.publishedAt).toBe(''); + }); + }); + + describe('when deletedAt in TimestampsResponse is null', () => { + const mockList: CardListResponse = setup([]); + mockList.data[0].timestamps.deletedAt = undefined; + + it('should return an empty string', () => { + const mapperResult = CardResponseMapper.mapToCardListResponseDto(mockList); + const cardResponse: CardResponseDto = mapperResult.data[0]; + + expect(cardResponse.timeStamps.deletedAt).toBe(''); + }); + }); }); }); From c4f167c55f7e42abdeb72f3a3b1a447c45f08ddf Mon Sep 17 00:00:00 2001 From: Hussam Kayed Date: Tue, 29 Oct 2024 11:26:12 +0100 Subject: [PATCH 47/47] ew-1009: review change --- .../card-client/card-client.adapter.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts index f4f5ea1ee2f..418896d1a22 100644 --- a/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts +++ b/apps/server/src/modules/common-cartridge/common-cartridge-client/card-client/card-client.adapter.spec.ts @@ -9,9 +9,8 @@ import { CardListResponse, CardResponse } from './cards-api-client/models'; import { CardClientAdapter } from './card-client.adapter'; import { BoardCardApi } from './cards-api-client'; -const jwtToken = faker.string.uuid(); - describe(CardClientAdapter.name, () => { + const jwtToken = faker.string.alphanumeric(20); let module: TestingModule; let adapterUnderTest: CardClientAdapter; let cardApiMock: DeepMocked;