From 448349909175930a56dbdedb09cec1051d114636 Mon Sep 17 00:00:00 2001 From: virgilchiriac <17074330+virgilchiriac@users.noreply.github.com> Date: Thu, 21 Sep 2023 13:43:05 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20hpi-schu?= =?UTF-8?q?l-cloud/schulcloud-server@84c8f45a8c3b67f7f881a799e4f013f36e8b0?= =?UTF-8?q?050=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- classes/BoardDoAuthorizable.html | 8 +- classes/CourseScope.html | 2 +- classes/SubmissionItemResponse.html | 31 +- classes/SubmissionItemResponseMapper.html | 203 ++++++- classes/SubmissionsResponse.html | 351 ++++++++++++ classes/UsersList.html | 524 ++++++++++++++++++ controllers/BoardSubmissionController.html | 33 +- controllers/ElementController.html | 2 +- coverage.html | 28 +- entities/Course.html | 80 ++- injectables/BoardDoAuthorizableService.html | 30 +- injectables/CourseRepo.html | 2 +- injectables/SubmissionItemUc.html | 44 +- interfaces/BoardDoAuthorizableProps.html | 2 + interfaces/ICourseProperties.html | 54 +- interfaces/UserBoardRoles.html | 92 +++ js/menu-wc.js | 6 + js/search/search_index.js | 4 +- miscellaneous/variables.html | 192 +++---- modules/AuthenticationModule.html | 160 +++--- modules/AuthenticationModule/dependencies.svg | 160 +++--- modules/BoardModule.html | 186 +++---- modules/BoardModule/dependencies.svg | 186 +++---- modules/CacheWrapperModule.html | 8 +- modules/CacheWrapperModule/dependencies.svg | 8 +- modules/CollaborativeStorageModule.html | 8 +- .../dependencies.svg | 8 +- modules/CommonToolModule.html | 8 +- modules/CommonToolModule/dependencies.svg | 8 +- modules/ContextExternalToolModule.html | 8 +- .../dependencies.svg | 8 +- modules/CopyHelperModule.html | 8 +- modules/CopyHelperModule/dependencies.svg | 8 +- modules/CoreModule.html | 8 +- modules/CoreModule/dependencies.svg | 8 +- modules/DatabaseManagementModule.html | 8 +- .../DatabaseManagementModule/dependencies.svg | 8 +- modules/ExternalToolModule.html | 8 +- modules/ExternalToolModule/dependencies.svg | 8 +- modules/FeathersModule.html | 8 +- modules/FeathersModule/dependencies.svg | 8 +- modules/FileSystemModule.html | 8 +- modules/FileSystemModule/dependencies.svg | 8 +- modules/FilesStorageAMQPModule.html | 46 +- .../FilesStorageAMQPModule/dependencies.svg | 46 +- modules/FilesStorageApiModule.html | 54 +- .../FilesStorageApiModule/dependencies.svg | 54 +- modules/FilesStorageClientModule.html | 74 +-- .../FilesStorageClientModule/dependencies.svg | 74 +-- modules/FilesStorageModule.html | 112 ++-- modules/FilesStorageModule/dependencies.svg | 112 ++-- modules/FwuLearningContentsModule.html | 70 +-- .../dependencies.svg | 70 +-- modules/GroupModule.html | 8 +- modules/GroupModule/dependencies.svg | 8 +- modules/IdentityManagementModule.html | 8 +- .../IdentityManagementModule/dependencies.svg | 8 +- modules/KeycloakConfigurationModule.html | 112 ++-- .../dependencies.svg | 112 ++-- modules/KeycloakModule.html | 8 +- modules/KeycloakModule/dependencies.svg | 8 +- modules/LearnroomApiModule.html | 158 +++--- modules/LearnroomApiModule/dependencies.svg | 158 +++--- modules/LearnroomModule.html | 8 +- modules/LearnroomModule/dependencies.svg | 8 +- modules/LegacySchoolModule.html | 8 +- modules/LegacySchoolModule/dependencies.svg | 8 +- modules/LessonApiModule.html | 38 +- modules/LessonApiModule/dependencies.svg | 38 +- modules/LessonModule.html | 8 +- modules/LessonModule/dependencies.svg | 8 +- modules/ManagementModule.html | 102 ++-- modules/ManagementModule/dependencies.svg | 102 ++-- modules/NewsModule.html | 56 +- modules/NewsModule/dependencies.svg | 56 +- modules/OauthProviderApiModule.html | 110 ++-- .../OauthProviderApiModule/dependencies.svg | 110 ++-- modules/OauthProviderModule.html | 114 ++-- modules/OauthProviderModule/dependencies.svg | 114 ++-- modules/ProvisioningModule.html | 8 +- modules/ProvisioningModule/dependencies.svg | 8 +- modules/PseudonymModule.html | 8 +- modules/PseudonymModule/dependencies.svg | 8 +- modules/SchoolExternalToolModule.html | 8 +- .../SchoolExternalToolModule/dependencies.svg | 8 +- modules/SharingModule.html | 90 +-- modules/SharingModule/dependencies.svg | 90 +-- modules/SystemApiModule.html | 26 +- modules/SystemApiModule/dependencies.svg | 26 +- modules/SystemModule.html | 64 +-- modules/SystemModule/dependencies.svg | 64 +-- modules/TaskModule.html | 114 ++-- modules/TaskModule/dependencies.svg | 114 ++-- modules/ToolLaunchModule.html | 128 ++--- modules/ToolLaunchModule/dependencies.svg | 128 ++--- modules/UserApiModule.html | 26 +- modules/UserApiModule/dependencies.svg | 26 +- modules/UserLoginMigrationModule.html | 144 ++--- .../UserLoginMigrationModule/dependencies.svg | 144 ++--- modules/VideoConferenceModule.html | 8 +- .../VideoConferenceModule/dependencies.svg | 8 +- overview.html | 2 +- 102 files changed, 3640 insertions(+), 2338 deletions(-) create mode 100644 classes/SubmissionsResponse.html create mode 100644 classes/UsersList.html diff --git a/classes/BoardDoAuthorizable.html b/classes/BoardDoAuthorizable.html index 7551b21a457..308e18c4777 100644 --- a/classes/BoardDoAuthorizable.html +++ b/classes/BoardDoAuthorizable.html @@ -261,7 +261,7 @@

-
Defined in apps/server/src/shared/domain/domainobject/board/types/board-do-authorizable.ts:30
+
Defined in apps/server/src/shared/domain/domainobject/board/types/board-do-authorizable.ts:32
@@ -283,7 +283,7 @@

-
Defined in apps/server/src/shared/domain/domainobject/board/types/board-do-authorizable.ts:34
+
Defined in apps/server/src/shared/domain/domainobject/board/types/board-do-authorizable.ts:36
@@ -294,7 +294,7 @@

-
Defined in apps/server/src/shared/domain/domainobject/board/types/board-do-authorizable.ts:38
+
Defined in apps/server/src/shared/domain/domainobject/board/types/board-do-authorizable.ts:40
@@ -358,6 +358,8 @@

} export interface UserBoardRoles { + firstName?: string; + lastName?: string; roles: BoardRoles[]; userId: EntityId; userRoleEnum: UserRoleEnum; diff --git a/classes/CourseScope.html b/classes/CourseScope.html index 5b16987138c..f02b7e85578 100644 --- a/classes/CourseScope.html +++ b/classes/CourseScope.html @@ -809,7 +809,7 @@

async findById(id: EntityId, populate = true): Promise<Course> { const course = await super.findById(id); if (populate) { - await this._em.populate(course, ['courseGroups', 'teachers']); + await this._em.populate(course, ['courseGroups', 'teachers', 'substitutionTeachers', 'students']); } return course; } diff --git a/classes/SubmissionItemResponse.html b/classes/SubmissionItemResponse.html index cdfe09f7063..f30c90c8742 100644 --- a/classes/SubmissionItemResponse.html +++ b/classes/SubmissionItemResponse.html @@ -102,7 +102,7 @@

Properties
  • - userData + userId
  • @@ -128,7 +128,7 @@

    Constructor

    -
    Defined in apps/server/src/modules/board/controller/dto/submission-item/submission-item.response.ts:5
    +
    Defined in apps/server/src/modules/board/controller/dto/submission-item/submission-item.response.ts:4
    @@ -199,7 +199,7 @@

    -
    Defined in apps/server/src/modules/board/controller/dto/submission-item/submission-item.response.ts:20
    +
    Defined in apps/server/src/modules/board/controller/dto/submission-item/submission-item.response.ts:19
    @@ -235,7 +235,7 @@

    -
    Defined in apps/server/src/modules/board/controller/dto/submission-item/submission-item.response.ts:14
    +
    Defined in apps/server/src/modules/board/controller/dto/submission-item/submission-item.response.ts:13
    @@ -271,7 +271,7 @@

    -
    Defined in apps/server/src/modules/board/controller/dto/submission-item/submission-item.response.ts:17
    +
    Defined in apps/server/src/modules/board/controller/dto/submission-item/submission-item.response.ts:16
    @@ -282,17 +282,17 @@

    - + - userData - + userId + - Type : UserDataResponse + Type : string @@ -301,13 +301,13 @@

    Decorators :
    - @ApiProperty()
    + @ApiProperty({pattern: '[a-f0-9]{24}'})
    -
    Defined in apps/server/src/modules/board/controller/dto/submission-item/submission-item.response.ts:23
    +
    Defined in apps/server/src/modules/board/controller/dto/submission-item/submission-item.response.ts:22
    @@ -328,14 +328,13 @@

    import { ApiProperty } from '@nestjs/swagger';
     import { TimestampsResponse } from '../timestamps.response';
    -import { UserDataResponse } from '../user-data.response';
     
     export class SubmissionItemResponse {
    -	constructor({ id, timestamps, completed, userData }: SubmissionItemResponse) {
    +	constructor({ id, timestamps, completed, userId }: SubmissionItemResponse) {
     		this.id = id;
     		this.timestamps = timestamps;
     		this.completed = completed;
    -		this.userData = userData;
    +		this.userId = userId;
     	}
     
     	@ApiProperty({ pattern: '[a-f0-9]{24}' })
    @@ -347,8 +346,8 @@ 

    @ApiProperty() completed: boolean; - @ApiProperty() - userData: UserDataResponse; + @ApiProperty({ pattern: '[a-f0-9]{24}' }) + userId: string; }

    diff --git a/classes/SubmissionItemResponseMapper.html b/classes/SubmissionItemResponseMapper.html index 6b74e4a9859..b9a1ec285b5 100644 --- a/classes/SubmissionItemResponseMapper.html +++ b/classes/SubmissionItemResponseMapper.html @@ -109,10 +109,18 @@

    Methods
    Static getInstance +
  • + Public + mapSubmissionsToResponse +
  • Public mapToResponse
  • +
  • + Private + mapUsersToResponse +
  • @@ -205,6 +213,77 @@

    + + + + + + + + + + + + + + + + + + + +
    + + + Public + mapSubmissionsToResponse + + +
    + + mapSubmissionsToResponse(submissionItem: SubmissionItem) +
    + +
    + +
    + Parameters : + + + + + + + + + + + + + + + + + + + +
    NameTypeOptional
    submissionItem + SubmissionItem + + No +
    +
    +
    +
    +
    + Returns : SubmissionItemResponse + +
    +
    + +
    +
    @@ -220,7 +299,7 @@

    @@ -249,9 +328,21 @@

    - + + + + + + + + + + + +
    - mapToResponse(submissionItem: SubmissionItem) + mapToResponse(submissionItems: SubmissionItem[], users: UserBoardRoles[])
    submissionItemsubmissionItems - SubmissionItem + SubmissionItem[] + + No +
    users + UserBoardRoles[] @@ -266,7 +357,78 @@

    - Returns : SubmissionItemResponse + Returns : SubmissionsResponse + +
    +
    + +
    +

    + + + + + + + + + + + + + + + + + @@ -211,7 +211,7 @@

    @@ -257,8 +257,8 @@

    @@ -339,15 +339,11 @@

    import { ApiValidationError } from '@shared/common'; import { ICurrentUser } from '@src/modules/authentication'; import { Authenticate, CurrentUser } from '@src/modules/authentication/decorator/auth.decorator'; +import { SubmissionsResponse } from '@src/modules/board/controller/dto/submission-item/submissions.response'; import { CardUc } from '../uc'; import { ElementUc } from '../uc/element.uc'; import { SubmissionItemUc } from '../uc/submission-item.uc'; -import { - SubmissionContainerUrlParams, - SubmissionItemResponse, - SubmissionItemUrlParams, - UpdateSubmissionItemBodyParams, -} from './dto'; +import { SubmissionContainerUrlParams, SubmissionItemUrlParams, UpdateSubmissionItemBodyParams } from './dto'; import { SubmissionItemResponseMapper } from './mapper'; @ApiTags('Board Submission') @@ -361,17 +357,22 @@

    ) {} @ApiOperation({ summary: 'Get a list of submission items by their parent container.' }) - @ApiResponse({ status: 200, type: [SubmissionItemResponse] }) + @ApiResponse({ status: 200, type: SubmissionsResponse }) @ApiResponse({ status: 400, type: ApiValidationError }) @ApiResponse({ status: 403, type: ForbiddenException }) @Get(':submissionContainerId') async getSubmissionItems( @CurrentUser() currentUser: ICurrentUser, @Param() urlParams: SubmissionContainerUrlParams - ): Promise<SubmissionItemResponse[]> { - const items = await this.submissionItemUc.findSubmissionItems(currentUser.userId, urlParams.submissionContainerId); + ): Promise<SubmissionsResponse> { + const { submissionItems, users } = await this.submissionItemUc.findSubmissionItems( + currentUser.userId, + urlParams.submissionContainerId + ); const mapper = SubmissionItemResponseMapper.getInstance(); - return items.map((item) => mapper.mapToResponse(item)); + const response = mapper.mapToResponse(submissionItems, users); + + return response; } @ApiOperation({ summary: 'Update a single submission item.' }) diff --git a/controllers/ElementController.html b/controllers/ElementController.html index 9b601e5c2ef..43cf27b24fe 100644 --- a/controllers/ElementController.html +++ b/controllers/ElementController.html @@ -689,7 +689,7 @@

    bodyParams.completed ); const mapper = SubmissionItemResponseMapper.getInstance(); - const response = mapper.mapToResponse(submissionItem); + const response = mapper.mapSubmissionsToResponse(submissionItem); return response; } diff --git a/coverage.html b/coverage.html index b5a389e76f9..bd26d985f4b 100644 --- a/coverage.html +++ b/coverage.html @@ -1975,6 +1975,18 @@ (0/2) +

    + + + + + @@ -11704,7 +11716,7 @@ @@ -12151,6 +12163,18 @@ (0/1) + + + + + + @@ -232,7 +232,7 @@

    @@ -267,7 +267,7 @@

    @@ -308,7 +308,7 @@

    @@ -345,7 +345,7 @@

    @@ -386,7 +386,7 @@

    @@ -423,7 +423,7 @@

    @@ -461,7 +461,7 @@

    @@ -498,7 +498,7 @@

    @@ -534,7 +534,7 @@

    @@ -570,7 +570,7 @@

    @@ -606,7 +606,7 @@

    @@ -644,7 +644,7 @@

    @@ -694,6 +694,14 @@

    VIDEOCONFERENCE = 'videoconference', } +export class UsersList { + id!: string; + + firstName!: string; + + lastName!: string; +} + @Entity({ tableName: 'courses' }) export class Course extends BaseEntityWithTimestamps @@ -761,21 +769,21 @@

    } public getStudentIds(): EntityId[] { - const studentIds = this.extractIds(this.students); + const studentIds = Course.extractIds(this.students); return studentIds; } public getTeacherIds(): EntityId[] { - const teacherIds = this.extractIds(this.teachers); + const teacherIds = Course.extractIds(this.teachers); return teacherIds; } public getSubstitutionTeacherIds(): EntityId[] { - const substitutionTeacherIds = this.extractIds(this.substitutionTeachers); + const substitutionTeacherIds = Course.extractIds(this.substitutionTeachers); return substitutionTeacherIds; } - private extractIds(users: Collection<User>): EntityId[] { + private static extractIds(users: Collection<User>): EntityId[] { if (!users) { throw new InternalServerErrorException( `Students, teachers or stubstitution is undefined. The course needs to be populated` @@ -788,6 +796,44 @@

    return ids; } + public getStudentsList(): UsersList[] { + const users = this.students.getItems(); + if (users.length) { + const usersList = Course.extractUserList(users); + return usersList; + } + return []; + } + + public getTeachersList(): UsersList[] { + const users = this.teachers.getItems(); + if (users.length) { + const usersList = Course.extractUserList(users); + return usersList; + } + return []; + } + + public getSubstitutionTeachersList(): UsersList[] { + const users = this.substitutionTeachers.getItems(); + if (users.length) { + const usersList = Course.extractUserList(users); + return usersList; + } + return []; + } + + private static extractUserList(users: User[]): UsersList[] { + const usersList: UsersList[] = users.map((user) => { + return { + id: user.id, + firstName: user.firstName, + lastName: user.lastName, + }; + }); + return usersList; + } + public isUserSubstitutionTeacher(user: User): boolean { const isSubstitutionTeacher = this.substitutionTeachers.contains(user); diff --git a/injectables/BoardDoAuthorizableService.html b/injectables/BoardDoAuthorizableService.html index dfb6183116a..f1d0ba52ee6 100644 --- a/injectables/BoardDoAuthorizableService.html +++ b/injectables/BoardDoAuthorizableService.html @@ -444,14 +444,32 @@

    private mapCourseUsersToUsergroup(course: Course): UserBoardRoles[] { const users = [ - ...course.getTeacherIds().map((userId) => { - return { userId, roles: [BoardRoles.EDITOR], userRoleEnum: UserRoleEnum.TEACHER }; + ...course.getTeachersList().map((user) => { + return { + userId: user.id, + firstName: user.firstName, + lastName: user.lastName, + roles: [BoardRoles.EDITOR], + userRoleEnum: UserRoleEnum.TEACHER, + }; }), - ...course.getSubstitutionTeacherIds().map((userId) => { - return { userId, roles: [BoardRoles.EDITOR], userRoleEnum: UserRoleEnum.SUBSTITUTION_TEACHER }; + ...course.getSubstitutionTeachersList().map((user) => { + return { + userId: user.id, + firstName: user.firstName, + lastName: user.lastName, + roles: [BoardRoles.EDITOR], + userRoleEnum: UserRoleEnum.SUBSTITUTION_TEACHER, + }; }), - ...course.getStudentIds().map((userId) => { - return { userId, roles: [BoardRoles.READER], userRoleEnum: UserRoleEnum.STUDENT }; + ...course.getStudentsList().map((user) => { + return { + userId: user.id, + firstName: user.firstName, + lastName: user.lastName, + roles: [BoardRoles.READER], + userRoleEnum: UserRoleEnum.STUDENT, + }; }), ]; return users; diff --git a/injectables/CourseRepo.html b/injectables/CourseRepo.html index 2989219daf8..d4a321c552c 100644 --- a/injectables/CourseRepo.html +++ b/injectables/CourseRepo.html @@ -993,7 +993,7 @@

    async findById(id: EntityId, populate = true): Promise<Course> { const course = await super.findById(id); if (populate) { - await this._em.populate(course, ['courseGroups', 'teachers']); + await this._em.populate(course, ['courseGroups', 'teachers', 'substitutionTeachers', 'students']); } return course; } diff --git a/injectables/SubmissionItemUc.html b/injectables/SubmissionItemUc.html index 90933408db2..c826ff61b7c 100644 --- a/injectables/SubmissionItemUc.html +++ b/injectables/SubmissionItemUc.html @@ -130,7 +130,7 @@

    Constructor

    @@ -244,8 +244,8 @@

    @@ -351,8 +351,8 @@

    @@ -402,7 +402,7 @@

    - Returns : Promise<SubmissionItem[]> + Returns : Promise<literal type>
    @@ -435,8 +435,8 @@

    @@ -507,8 +507,8 @@

    @@ -590,8 +590,8 @@

    @@ -670,7 +670,14 @@

    import { ForbiddenException, forwardRef, HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common';
    -import { AnyBoardDo, EntityId, SubmissionContainerElement, SubmissionItem, UserRoleEnum } from '@shared/domain';
    +import {
    +	AnyBoardDo,
    +	EntityId,
    +	SubmissionContainerElement,
    +	SubmissionItem,
    +	UserBoardRoles,
    +	UserRoleEnum,
    +} from '@shared/domain';
     import { Logger } from '@src/core/logger';
     import { AuthorizationService } from '@src/modules/authorization';
     import { Action } from '@src/modules/authorization/types/action.enum';
    @@ -689,7 +696,10 @@ 

    this.logger.setContext(SubmissionItemUc.name); } - async findSubmissionItems(userId: EntityId, submissionContainerId: EntityId): Promise<SubmissionItem[]> { + async findSubmissionItems( + userId: EntityId, + submissionContainerId: EntityId + ): Promise<{ submissionItems: SubmissionItem[]; users: UserBoardRoles[] }> { const submissionContainer = await this.getSubmissionContainer(submissionContainerId); await this.checkPermission(userId, submissionContainer, Action.read); @@ -702,12 +712,16 @@

    ); } + const boardAuthorizable = await this.boardDoAuthorizableService.getBoardAuthorizable(submissionContainer); + let users = boardAuthorizable.users.filter((user) => user.userRoleEnum === UserRoleEnum.STUDENT); + const isAuthorizedStudent = await this.isAuthorizedStudent(userId, submissionContainer); if (isAuthorizedStudent) { submissionItems = submissionItems.filter((item) => item.userId === userId); + users = []; } - return submissionItems; + return { submissionItems, users }; } async updateSubmissionItem( diff --git a/interfaces/BoardDoAuthorizableProps.html b/interfaces/BoardDoAuthorizableProps.html index 353f58285d0..031be4c90f7 100644 --- a/interfaces/BoardDoAuthorizableProps.html +++ b/interfaces/BoardDoAuthorizableProps.html @@ -251,6 +251,8 @@

    Properties

    } export interface UserBoardRoles { + firstName?: string; + lastName?: string; roles: BoardRoles[]; userId: EntityId; userRoleEnum: UserRoleEnum; diff --git a/interfaces/ICourseProperties.html b/interfaces/ICourseProperties.html index 64efaf7ddbf..ded6b7fa665 100644 --- a/interfaces/ICourseProperties.html +++ b/interfaces/ICourseProperties.html @@ -632,6 +632,14 @@

    Properties

    VIDEOCONFERENCE = 'videoconference', } +export class UsersList { + id!: string; + + firstName!: string; + + lastName!: string; +} + @Entity({ tableName: 'courses' }) export class Course extends BaseEntityWithTimestamps @@ -699,21 +707,21 @@

    Properties

    } public getStudentIds(): EntityId[] { - const studentIds = this.extractIds(this.students); + const studentIds = Course.extractIds(this.students); return studentIds; } public getTeacherIds(): EntityId[] { - const teacherIds = this.extractIds(this.teachers); + const teacherIds = Course.extractIds(this.teachers); return teacherIds; } public getSubstitutionTeacherIds(): EntityId[] { - const substitutionTeacherIds = this.extractIds(this.substitutionTeachers); + const substitutionTeacherIds = Course.extractIds(this.substitutionTeachers); return substitutionTeacherIds; } - private extractIds(users: Collection<User>): EntityId[] { + private static extractIds(users: Collection<User>): EntityId[] { if (!users) { throw new InternalServerErrorException( `Students, teachers or stubstitution is undefined. The course needs to be populated` @@ -726,6 +734,44 @@

    Properties

    return ids; } + public getStudentsList(): UsersList[] { + const users = this.students.getItems(); + if (users.length) { + const usersList = Course.extractUserList(users); + return usersList; + } + return []; + } + + public getTeachersList(): UsersList[] { + const users = this.teachers.getItems(); + if (users.length) { + const usersList = Course.extractUserList(users); + return usersList; + } + return []; + } + + public getSubstitutionTeachersList(): UsersList[] { + const users = this.substitutionTeachers.getItems(); + if (users.length) { + const usersList = Course.extractUserList(users); + return usersList; + } + return []; + } + + private static extractUserList(users: User[]): UsersList[] { + const usersList: UsersList[] = users.map((user) => { + return { + id: user.id, + firstName: user.firstName, + lastName: user.lastName, + }; + }); + return usersList; + } + public isUserSubstitutionTeacher(user: User): boolean { const isSubstitutionTeacher = this.substitutionTeachers.contains(user); diff --git a/interfaces/UserBoardRoles.html b/interfaces/UserBoardRoles.html index 5da6afc3d59..bf7e96d634f 100644 --- a/interfaces/UserBoardRoles.html +++ b/interfaces/UserBoardRoles.html @@ -89,6 +89,20 @@
    Properties

    + + + Private + mapUsersToResponse + + +
    + + mapUsersToResponse(user: UserBoardRoles) +
    + +
    + +
    + Parameters : + + + + + + + + + + + + + + + + + + + +
    NameTypeOptional
    user + UserBoardRoles + + No +
    +
    +
    +
    +
    + Returns : any
    @@ -286,8 +448,8 @@

    -
    import { SubmissionItem } from '@shared/domain';
    -import { SubmissionItemResponse, TimestampsResponse, UserDataResponse } from '../dto';
    +        
    import { SubmissionItem, UserBoardRoles } from '@shared/domain';
    +import { SubmissionItemResponse, SubmissionsResponse, TimestampsResponse, UserDataResponse } from '../dto';
     
     export class SubmissionItemResponseMapper {
     	private static instance: SubmissionItemResponseMapper;
    @@ -300,7 +462,18 @@ 

    return SubmissionItemResponseMapper.instance; } - public mapToResponse(submissionItem: SubmissionItem): SubmissionItemResponse { + public mapToResponse(submissionItems: SubmissionItem[], users: UserBoardRoles[]): SubmissionsResponse { + const submissionItemsResponse: SubmissionItemResponse[] = submissionItems.map((item) => + this.mapSubmissionsToResponse(item) + ); + const usersResponse: UserDataResponse[] = users.map((user) => this.mapUsersToResponse(user)); + + const response = new SubmissionsResponse(submissionItemsResponse, usersResponse); + + return response; + } + + public mapSubmissionsToResponse(submissionItem: SubmissionItem): SubmissionItemResponse { const result = new SubmissionItemResponse({ completed: submissionItem.completed, id: submissionItem.id, @@ -308,16 +481,20 @@

    lastUpdatedAt: submissionItem.updatedAt, createdAt: submissionItem.createdAt, }), - userData: new UserDataResponse({ - // TODO: put valid user info here which comes from the submission owner - firstName: 'John', - lastName: 'Mr Doe', - userId: submissionItem.userId, - }), + userId: submissionItem.userId, }); return result; } + + private mapUsersToResponse(user: UserBoardRoles) { + const result = new UserDataResponse({ + userId: user.userId, + firstName: user.firstName || '', + lastName: user.lastName || '', + }); + return result; + } }

    diff --git a/classes/SubmissionsResponse.html b/classes/SubmissionsResponse.html new file mode 100644 index 00000000000..0882fd942a3 --- /dev/null +++ b/classes/SubmissionsResponse.html @@ -0,0 +1,351 @@ + + + + + + schulcloud-server documentation + + + + + + + + + + + + + +
    +
    + + +
    +
    + + + + + + + + + + + + + + + + +
    +
    +

    +

    File

    +

    +

    + apps/server/src/modules/board/controller/dto/submission-item/submissions.response.ts +

    + + + + + + +
    +

    Index

    + + + + + + + + + + + + + + + +
    +
    Properties
    +
    + +
    +
    + +
    +

    Constructor

    + + + + + + + + + + + + + +
    +constructor(submissionItemsResponse: SubmissionItemResponse[], users: UserDataResponse[]) +
    + +
    +
    + Parameters : + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeOptional
    submissionItemsResponse + SubmissionItemResponse[] + + No +
    users + UserDataResponse[] + + No +
    +
    +
    +
    + +
    + +

    + Properties +

    + + + + + + + + + + + + + + + + + +
    + + + + submissionItemsResponse + + +
    + Type : SubmissionItemResponse[] + +
    + Decorators : +
    + + @ApiProperty({type: undefined})
    +
    +
    + +
    + + + + + + + + + + + + + + + + + +
    + + + + users + + +
    + Type : UserDataResponse[] + +
    + Decorators : +
    + + @ApiProperty({type: undefined})
    +
    +
    + +
    +
    + + + + + + + +
    + + +
    +
    import { SubmissionItemResponse, UserDataResponse } from '@src/modules/board/controller/dto';
    +import { ApiProperty } from '@nestjs/swagger';
    +
    +export class SubmissionsResponse {
    +	constructor(submissionItemsResponse: SubmissionItemResponse[], users: UserDataResponse[]) {
    +		this.submissionItemsResponse = submissionItemsResponse;
    +		this.users = users;
    +	}
    +
    +	@ApiProperty({
    +		type: [SubmissionItemResponse],
    +	})
    +	submissionItemsResponse: SubmissionItemResponse[];
    +
    +	@ApiProperty({
    +		type: [UserDataResponse],
    +	})
    +	users: UserDataResponse[];
    +}
    +
    +
    +
    + + + + + + + + + +
    +
    +

    results matching ""

    +
      +
      +
      +

      No results matching ""

      +
      +
      +
      + +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/classes/UsersList.html b/classes/UsersList.html new file mode 100644 index 00000000000..aa3f8b9a479 --- /dev/null +++ b/classes/UsersList.html @@ -0,0 +1,524 @@ + + + + + + schulcloud-server documentation + + + + + + + + + + + + + +
      +
      + + +
      +
      + + + + + + + + + + + + + + + + +
      +
      +

      +

      File

      +

      +

      + apps/server/src/shared/domain/entity/course.entity.ts +

      + + + + + + +
      +

      Index

      + + + + + + + + + + + + + + + +
      +
      Properties
      +
      + +
      +
      + + +
      + +

      + Properties +

      + + + + + + + + + + + + + + +
      + + + firstName + + +
      + Type : string + +
      + +
      + + + + + + + + + + + + + + +
      + + + id + + +
      + Type : string + +
      + +
      + + + + + + + + + + + + + + +
      + + + lastName + + +
      + Type : string + +
      + +
      +
      + + + + + + + +
      + + +
      +
      import { Collection, Entity, Enum, Index, ManyToMany, ManyToOne, OneToMany, Property, Unique } from '@mikro-orm/core';
      +import { InternalServerErrorException } from '@nestjs/common/exceptions/internal-server-error.exception';
      +import { IEntityWithSchool, ILearnroom } from '@shared/domain/interface';
      +import { EntityId, LearnroomMetadata, LearnroomTypes } from '../types';
      +import { BaseEntityWithTimestamps } from './base.entity';
      +import { CourseGroup } from './coursegroup.entity';
      +import type { ILessonParent } from './lesson.entity';
      +import { SchoolEntity } from './school.entity';
      +import type { ITaskParent } from './task.entity';
      +import type { User } from './user.entity';
      +
      +export interface ICourseProperties {
      +	name?: string;
      +	description?: string;
      +	school: SchoolEntity;
      +	students?: User[];
      +	teachers?: User[];
      +	substitutionTeachers?: User[];
      +	// TODO: color format
      +	color?: string;
      +	startDate?: Date;
      +	untilDate?: Date;
      +	copyingSince?: Date;
      +	features?: CourseFeatures[];
      +}
      +
      +// that is really really shit default handling :D constructor, getter, js default, em default...what the hell
      +// i hope it can cleanup with adding schema instant of I...Properties.
      +const DEFAULT = {
      +	color: '#ACACAC',
      +	name: 'Kurse',
      +	description: '',
      +};
      +
      +const enum CourseFeatures {
      +	VIDEOCONFERENCE = 'videoconference',
      +}
      +
      +export class UsersList {
      +	id!: string;
      +
      +	firstName!: string;
      +
      +	lastName!: string;
      +}
      +
      +@Entity({ tableName: 'courses' })
      +export class Course
      +	extends BaseEntityWithTimestamps
      +	implements ILearnroom, IEntityWithSchool, ITaskParent, ILessonParent
      +{
      +	@Property()
      +	name: string = DEFAULT.name;
      +
      +	@Property()
      +	description: string = DEFAULT.description;
      +
      +	@Index()
      +	@ManyToOne(() => SchoolEntity, { fieldName: 'schoolId' })
      +	school: SchoolEntity;
      +
      +	@Index()
      +	@ManyToMany('User', undefined, { fieldName: 'userIds' })
      +	students = new Collection<User>(this);
      +
      +	@Index()
      +	@ManyToMany('User', undefined, { fieldName: 'teacherIds' })
      +	teachers = new Collection<User>(this);
      +
      +	@Index()
      +	@ManyToMany('User', undefined, { fieldName: 'substitutionIds' })
      +	substitutionTeachers = new Collection<User>(this);
      +
      +	@OneToMany('CourseGroup', 'course', { orphanRemoval: true })
      +	courseGroups = new Collection<CourseGroup>(this);
      +
      +	// TODO: string color format
      +	@Property()
      +	color: string = DEFAULT.color;
      +
      +	@Property({ nullable: true })
      +	startDate?: Date;
      +
      +	@Index()
      +	@Property({ nullable: true })
      +	untilDate?: Date;
      +
      +	@Property({ nullable: true })
      +	copyingSince?: Date;
      +
      +	@Property({ nullable: true })
      +	@Unique({ options: { sparse: true } })
      +	shareToken?: string;
      +
      +	@Enum({ nullable: true, array: true })
      +	features?: CourseFeatures[];
      +
      +	constructor(props: ICourseProperties) {
      +		super();
      +		if (props.name) this.name = props.name;
      +		if (props.description) this.description = props.description;
      +		this.school = props.school;
      +		this.students.set(props.students || []);
      +		this.teachers.set(props.teachers || []);
      +		this.substitutionTeachers.set(props.substitutionTeachers || []);
      +		if (props.color) this.color = props.color;
      +		if (props.untilDate) this.untilDate = props.untilDate;
      +		if (props.startDate) this.startDate = props.startDate;
      +		if (props.copyingSince) this.copyingSince = props.copyingSince;
      +		if (props.features) this.features = props.features;
      +	}
      +
      +	public getStudentIds(): EntityId[] {
      +		const studentIds = Course.extractIds(this.students);
      +		return studentIds;
      +	}
      +
      +	public getTeacherIds(): EntityId[] {
      +		const teacherIds = Course.extractIds(this.teachers);
      +		return teacherIds;
      +	}
      +
      +	public getSubstitutionTeacherIds(): EntityId[] {
      +		const substitutionTeacherIds = Course.extractIds(this.substitutionTeachers);
      +		return substitutionTeacherIds;
      +	}
      +
      +	private static extractIds(users: Collection<User>): EntityId[] {
      +		if (!users) {
      +			throw new InternalServerErrorException(
      +				`Students, teachers or stubstitution is undefined. The course needs to be populated`
      +			);
      +		}
      +
      +		const objectIds = users.getIdentifiers('_id');
      +		const ids = objectIds.map((id): string => id.toString());
      +
      +		return ids;
      +	}
      +
      +	public getStudentsList(): UsersList[] {
      +		const users = this.students.getItems();
      +		if (users.length) {
      +			const usersList = Course.extractUserList(users);
      +			return usersList;
      +		}
      +		return [];
      +	}
      +
      +	public getTeachersList(): UsersList[] {
      +		const users = this.teachers.getItems();
      +		if (users.length) {
      +			const usersList = Course.extractUserList(users);
      +			return usersList;
      +		}
      +		return [];
      +	}
      +
      +	public getSubstitutionTeachersList(): UsersList[] {
      +		const users = this.substitutionTeachers.getItems();
      +		if (users.length) {
      +			const usersList = Course.extractUserList(users);
      +			return usersList;
      +		}
      +		return [];
      +	}
      +
      +	private static extractUserList(users: User[]): UsersList[] {
      +		const usersList: UsersList[] = users.map((user) => {
      +			return {
      +				id: user.id,
      +				firstName: user.firstName,
      +				lastName: user.lastName,
      +			};
      +		});
      +		return usersList;
      +	}
      +
      +	public isUserSubstitutionTeacher(user: User): boolean {
      +		const isSubstitutionTeacher = this.substitutionTeachers.contains(user);
      +
      +		return isSubstitutionTeacher;
      +	}
      +
      +	public getCourseGroupItems(): CourseGroup[] {
      +		if (!this.courseGroups.isInitialized(true)) {
      +			throw new InternalServerErrorException('Courses trying to access their course groups that are not loaded.');
      +		}
      +		const courseGroups = this.courseGroups.getItems();
      +
      +		return courseGroups;
      +	}
      +
      +	getShortTitle(): string {
      +		if (this.name.length === 1) {
      +			return this.name;
      +		}
      +		const [firstChar, secondChar] = [...this.name];
      +		const pattern = /\p{Extended_Pictographic}/u;
      +		if (pattern.test(firstChar)) {
      +			return firstChar;
      +		}
      +		return firstChar + secondChar;
      +	}
      +
      +	public getMetadata(): LearnroomMetadata {
      +		return {
      +			id: this.id,
      +			type: LearnroomTypes.Course,
      +			title: this.name,
      +			shortTitle: this.getShortTitle(),
      +			displayColor: this.color,
      +			untilDate: this.untilDate,
      +			startDate: this.startDate,
      +			copyingSince: this.copyingSince,
      +		};
      +	}
      +
      +	public isFinished(): boolean {
      +		if (!this.untilDate) {
      +			return false;
      +		}
      +		const isFinished = this.untilDate < new Date();
      +
      +		return isFinished;
      +	}
      +
      +	public removeUser(userId: EntityId): void {
      +		this.removeStudent(userId);
      +		this.removeTeacher(userId);
      +		this.removeSubstitutionTeacher(userId);
      +	}
      +
      +	private removeStudent(userId: EntityId): void {
      +		this.students.remove((u) => u.id === userId);
      +	}
      +
      +	private removeTeacher(userId: EntityId): void {
      +		this.teachers.remove((u) => u.id === userId);
      +	}
      +
      +	private removeSubstitutionTeacher(userId: EntityId): void {
      +		this.substitutionTeachers.remove((u) => u.id === userId);
      +	}
      +}
      +
      +
      +
      + + + + + + + + + +
      +
      +

      results matching ""

      +
        +
        +
        +

        No results matching ""

        +
        +
        +
        + +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/controllers/BoardSubmissionController.html b/controllers/BoardSubmissionController.html index 23036903fb6..4630966e9ee 100644 --- a/controllers/BoardSubmissionController.html +++ b/controllers/BoardSubmissionController.html @@ -154,14 +154,14 @@

        Decorators :
        - @ApiOperation({summary: 'Get a list of submission items by their parent container.'})
        @ApiResponse({status: 200, type: undefined})
        @ApiResponse({status: 400, type: ApiValidationError})
        @ApiResponse({status: 403, type: ForbiddenException})
        @Get(':submissionContainerId')
        + @ApiOperation({summary: 'Get a list of submission items by their parent container.'})
        @ApiResponse({status: 200, type: SubmissionsResponse})
        @ApiResponse({status: 400, type: ApiValidationError})
        @ApiResponse({status: 403, type: ForbiddenException})
        @Get(':submissionContainerId')
        - +
        - +
        + + apps/server/src/modules/board/controller/dto/submission-item/submissions.response.ts + classSubmissionsResponse + 0 % + (0/4) +
        @@ -2128,7 +2140,7 @@ SubmissionItemResponseMapper 0 % - (0/4) + (0/6)
        UserBoardRoles 0 % - (0/4) + (0/6)
        + + apps/server/src/shared/domain/entity/course.entity.ts + classUsersList + 0 % + (0/4) +
        diff --git a/entities/Course.html b/entities/Course.html index 2d8b89dd1da..53f0d336e96 100644 --- a/entities/Course.html +++ b/entities/Course.html @@ -195,7 +195,7 @@

        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +