diff --git a/client/src/app/core/repositories/agenda/item-repository.service.ts b/client/src/app/core/repositories/agenda/item-repository.service.ts index a6a358247..48ba51a2f 100644 --- a/client/src/app/core/repositories/agenda/item-repository.service.ts +++ b/client/src/app/core/repositories/agenda/item-repository.service.ts @@ -11,14 +11,11 @@ import { HttpService } from 'app/core/core-services/http.service'; import { Identifiable } from 'app/shared/models/base/identifiable'; import { Item } from 'app/shared/models/agenda/item'; import { OSTreeSortEvent } from 'app/shared/components/sorting-tree/sorting-tree.component'; -import { Speaker } from 'app/shared/models/agenda/speaker'; import { ViewItem } from 'app/site/agenda/models/view-item'; -import { ViewSpeaker } from 'app/site/agenda/models/view-speaker'; import { TreeService } from 'app/core/ui-services/tree.service'; import { BaseAgendaViewModel } from 'app/site/base/base-agenda-view-model'; import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service'; import { BaseViewModel } from 'app/site/base/base-view-model'; -import { ViewUser } from 'app/site/users/models/view-user'; import { TranslateService } from '@ngx-translate/core'; import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository'; @@ -130,105 +127,6 @@ export class ItemRepositoryService extends BaseRepository { } } - /** - * Generate viewSpeaker objects from a given agenda Item - * - * @param item agenda Item holding speakers - * @returns the list of view speakers corresponding to the given item - */ - public createViewSpeakers(item: Item): ViewSpeaker[] { - let viewSpeakers = []; - const speakers = item.speakers; - if (speakers && speakers.length > 0) { - speakers.forEach((speaker: Speaker) => { - const user = this.viewModelStoreService.get(ViewUser, speaker.user_id); - viewSpeakers.push(new ViewSpeaker(speaker, user)); - }); - } - // sort speakers by their weight - viewSpeakers = viewSpeakers.sort((a, b) => a.weight - b.weight); - return viewSpeakers; - } - - /** - * Add a new speaker to an agenda item. - * Sends the users ID to the server - * Might need another repo - * - * @param speakerId {@link User} id of the new speaker - * @param item the target agenda item - */ - public async addSpeaker(speakerId: number, item: ViewItem): Promise { - const restUrl = `rest/agenda/item/${item.id}/manage_speaker/`; - await this.httpService.post(restUrl, { user: speakerId }); - } - - /** - * Sets the given speaker ID to Speak - * - * @param speakerId the speakers id - * @param item the target agenda item - */ - public async startSpeaker(speakerId: number, item: ViewItem): Promise { - const restUrl = `rest/agenda/item/${item.id}/speak/`; - await this.httpService.put(restUrl, { speaker: speakerId }); - } - - /** - * Stops the current speaker - * - * @param item the target agenda item - */ - public async stopCurrentSpeaker(item: ViewItem): Promise { - const restUrl = `rest/agenda/item/${item.id}/speak/`; - await this.httpService.delete(restUrl); - } - - /** - * Marks the current speaker - * - * @param speakerId {@link User} id of the new speaker - * @param mark determine if the user was marked or not - * @param item the target agenda item - */ - public async markSpeaker(speakerId: number, mark: boolean, item: ViewItem): Promise { - const restUrl = `rest/agenda/item/${item.id}/manage_speaker/`; - await this.httpService.patch(restUrl, { user: speakerId, marked: mark }); - } - - /** - * Deletes the given speaker for the agenda item - * - * @param item the target agenda item - * @param speakerId (otional) the speakers id. If no id is given, the current operator - * is removed. - */ - public async deleteSpeaker(item: ViewItem, speakerId?: number): Promise { - const restUrl = `rest/agenda/item/${item.id}/manage_speaker/`; - await this.httpService.delete(restUrl, speakerId ? { speaker: speakerId } : null); - } - - /** - * Deletes all speakers of the given agenda item. - * - * @param item the target agenda item - */ - public async deleteAllSpeakers(item: ViewItem): Promise { - const restUrl = `rest/agenda/item/${item.id}/manage_speaker/`; - await this.httpService.delete(restUrl, { speaker: item.speakers.map(speaker => speaker.id) }); - } - - /** - * Posts an (manually) sorted speaker list to the server - * - * @param speakerIds array of speaker id numbers - * @param Item the target agenda item - */ - public async sortSpeakers(speakerIds: number[], item: Item): Promise { - const restUrl = `rest/agenda/item/${item.id}/sort_speakers/`; - await this.httpService.post(restUrl, { speakers: speakerIds }); - } - /** * Updates an agenda item * diff --git a/client/src/app/core/repositories/agenda/speaker-repository.service.spec.ts b/client/src/app/core/repositories/agenda/speaker-repository.service.spec.ts new file mode 100644 index 000000000..d458f1a01 --- /dev/null +++ b/client/src/app/core/repositories/agenda/speaker-repository.service.spec.ts @@ -0,0 +1,17 @@ +import { TestBed } from '@angular/core/testing'; + +import { SpeakerRepositoryService } from './speaker-repository.service'; +import { E2EImportsModule } from 'e2e-imports.module'; + +describe('SpeakerRepositoryService', () => { + beforeEach(() => + TestBed.configureTestingModule({ + imports: [E2EImportsModule] + }) + ); + + it('should be created', () => { + const service: SpeakerRepositoryService = TestBed.get(SpeakerRepositoryService); + expect(service).toBeTruthy(); + }); +}); diff --git a/client/src/app/core/repositories/agenda/speaker-repository.service.ts b/client/src/app/core/repositories/agenda/speaker-repository.service.ts new file mode 100644 index 000000000..f7dddad45 --- /dev/null +++ b/client/src/app/core/repositories/agenda/speaker-repository.service.ts @@ -0,0 +1,163 @@ +import { Injectable } from '@angular/core'; + +import { TranslateService } from '@ngx-translate/core'; + +import { HttpService } from 'app/core/core-services/http.service'; +import { Identifiable } from 'app/shared/models/base/identifiable'; +import { Item } from 'app/shared/models/agenda/item'; +import { Speaker } from 'app/shared/models/agenda/speaker'; +import { ViewSpeaker } from 'app/site/agenda/models/view-speaker'; +import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service'; +import { ViewItem } from 'app/site/agenda/models/view-item'; +import { ViewUser } from 'app/site/users/models/view-user'; + +/** + * Define what actions might occur on speaker lists + */ +type SpeakerAction = 'manage_speaker' | 'sort_speakers' | 'speak'; + +/** + * Repository for speakers. + * + * Since speakers are no base models, normal repository methods do not apply here. + */ +@Injectable({ + providedIn: 'root' +}) +export class SpeakerRepositoryService { + /** + * Constructor + * + * @param viewModelStoreService To get the view users + * @param httpService make custom requests + * @param translate translate + */ + public constructor( + private viewModelStoreService: ViewModelStoreService, + private httpService: HttpService, + private translate: TranslateService + ) {} + + /** + * Add a new speaker to an agenda item. + * Sends the users ID to the server + * Might need another repo + * + * @param speakerId {@link User} id of the new speaker + * @param item the target agenda item + */ + public async create(speakerId: number, item: ViewItem): Promise { + const restUrl = this.getRestUrl(item.id, 'manage_speaker'); + await this.httpService.post(restUrl, { user: speakerId }); + } + + /** + * Removes the given speaker for the agenda item + * + * @param item the target agenda item + * @param speakerId (otional) the speakers id. If no id is given, the current operator + * is removed. + */ + public async delete(item: ViewItem, speakerId?: number): Promise { + const restUrl = this.getRestUrl(item.id, 'manage_speaker'); + await this.httpService.delete(restUrl, speakerId ? { speaker: speakerId } : null); + } + + /** + * Creates and returns a new ViewSpeaker out of a speaker model + * + * @param speaker speaker to transform + * @return a new ViewSpeaker + */ + private createViewModel(speaker: Speaker): ViewSpeaker { + const user = this.viewModelStoreService.get(ViewUser, speaker.user_id); + const viewSpeaker = new ViewSpeaker(speaker, user); + viewSpeaker.getVerboseName = (plural: boolean = false) => { + return this.translate.instant(plural ? 'Speakers' : 'Speaker'); + }; + return viewSpeaker; + } + + /** + * Generate viewSpeaker objects from a given agenda Item + * + * @param item agenda Item holding speakers + * @returns the list of view speakers corresponding to the given item + */ + public createSpeakerList(item: Item): ViewSpeaker[] { + let viewSpeakers = []; + const speakers = item.speakers; + if (speakers && speakers.length > 0) { + viewSpeakers = speakers.map(speaker => { + return this.createViewModel(speaker); + }); + } + // sort speakers by their weight + viewSpeakers = viewSpeakers.sort((a, b) => a.weight - b.weight); + return viewSpeakers; + } + + /** + * Deletes all speakers of the given agenda item. + * + * @param item the target agenda item + */ + public async deleteAllSpeakers(item: ViewItem): Promise { + const restUrl = this.getRestUrl(item.id, 'manage_speaker'); + await this.httpService.delete(restUrl, { speaker: item.speakers.map(speaker => speaker.id) }); + } + + /** + * Posts an (manually) sorted speaker list to the server + * + * @param speakerIds array of speaker id numbers + * @param Item the target agenda item + */ + public async sortSpeakers(speakerIds: number[], item: Item): Promise { + const restUrl = this.getRestUrl(item.id, 'sort_speakers'); + await this.httpService.post(restUrl, { speakers: speakerIds }); + } + + /** + * Marks the current speaker + * + * @param speakerId {@link User} id of the new speaker + * @param mark determine if the user was marked or not + * @param item the target agenda item + */ + public async markSpeaker(speakerId: number, mark: boolean, item: ViewItem): Promise { + const restUrl = this.getRestUrl(item.id, 'manage_speaker'); + await this.httpService.patch(restUrl, { user: speakerId, marked: mark }); + } + + /** + * Stops the current speaker + * + * @param item the target agenda item + */ + public async stopCurrentSpeaker(item: ViewItem): Promise { + const restUrl = this.getRestUrl(item.id, 'speak'); + await this.httpService.delete(restUrl); + } + + /** + * Sets the given speaker ID to Speak + * + * @param speakerId the speakers id + * @param item the target agenda item + */ + public async startSpeaker(speakerId: number, item: ViewItem): Promise { + const restUrl = this.getRestUrl(item.id, 'speak'); + await this.httpService.put(restUrl, { speaker: speakerId }); + } + + /** + * Helper function get the url to the speaker rest address + * + * @param itemId id of the agenda item + * @param suffix the desired speaker action + */ + private getRestUrl(itemId: number, suffix: SpeakerAction): string { + return `rest/agenda/item/${itemId}/${suffix}/`; + } +} diff --git a/client/src/app/shared/models/agenda/speaker.ts b/client/src/app/shared/models/agenda/speaker.ts index 2480eb1eb..432816805 100644 --- a/client/src/app/shared/models/agenda/speaker.ts +++ b/client/src/app/shared/models/agenda/speaker.ts @@ -17,6 +17,8 @@ export enum SpeakerState { * @ignore */ export class Speaker extends Deserializer { + public static COLLECTIONSTRING = 'agenda/item/speakers'; + public id: number; public user_id: number; diff --git a/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.html b/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.html index c89d4b00d..925d2eaa2 100644 --- a/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.html +++ b/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.html @@ -40,8 +40,8 @@ {{ number + 1 }}. {{ speaker }}
-    {{ durationString(speaker) }} - ({{ 'Start time' | translate }}: {{ startTimeToString(speaker) }}) +    {{ durationString(speaker) }} ({{ 'Start time' | translate }}: + {{ startTimeToString(speaker) }})