Speaker repo
Add an own repository service to manage speakers
This commit is contained in:
parent
77e192719d
commit
03c590c66d
@ -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<ViewItem, Item> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<void> {
|
||||
const restUrl = `rest/agenda/item/${item.id}/manage_speaker/`;
|
||||
await this.httpService.post<Identifiable>(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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
const restUrl = `rest/agenda/item/${item.id}/sort_speakers/`;
|
||||
await this.httpService.post(restUrl, { speakers: speakerIds });
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an agenda item
|
||||
*
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
@ -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<void> {
|
||||
const restUrl = this.getRestUrl(item.id, 'manage_speaker');
|
||||
await this.httpService.post<Identifiable>(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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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<void> {
|
||||
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}/`;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -40,8 +40,8 @@
|
||||
<span>{{ number + 1 }}. {{ speaker }}</span>
|
||||
</div>
|
||||
<div class="finished-suffix">
|
||||
{{ durationString(speaker) }}
|
||||
({{ 'Start time' | translate }}: {{ startTimeToString(speaker) }})
|
||||
{{ durationString(speaker) }} ({{ 'Start time' | translate }}:
|
||||
{{ startTimeToString(speaker) }})
|
||||
</div>
|
||||
<button
|
||||
mat-stroked-button
|
||||
@ -131,7 +131,11 @@
|
||||
</mat-card>
|
||||
|
||||
<mat-menu #speakerMenu="matMenu">
|
||||
<os-projector-button *ngIf="viewItem" [object]="viewItem.listOfSpeakersSlide" [menuItem]="true"></os-projector-button>
|
||||
<os-projector-button
|
||||
*ngIf="viewItem"
|
||||
[object]="viewItem.listOfSpeakersSlide"
|
||||
[menuItem]="true"
|
||||
></os-projector-button>
|
||||
|
||||
<button mat-menu-item *ngIf="closedList" (click)="openSpeakerList()">
|
||||
<mat-icon>mic</mat-icon>
|
||||
|
@ -7,12 +7,12 @@ import { Title } from '@angular/platform-browser';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { BehaviorSubject, Subscription } from 'rxjs';
|
||||
|
||||
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
||||
import { BaseViewComponent } from 'app/site/base/base-view';
|
||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||
import { ProjectorRepositoryService } from 'app/core/repositories/projector/projector-repository.service';
|
||||
import { PromptService } from 'app/core/ui-services/prompt.service';
|
||||
import { SpeakerState } from 'app/shared/models/agenda/speaker';
|
||||
import { SpeakerRepositoryService } from 'app/core/repositories/agenda/speaker-repository.service';
|
||||
import { ViewItem } from '../../models/view-item';
|
||||
import { ViewSpeaker } from '../../models/view-speaker';
|
||||
import { ViewProjector } from 'app/site/projector/models/view-projector';
|
||||
@ -20,6 +20,7 @@ import { ViewUser } from 'app/site/users/models/view-user';
|
||||
import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service';
|
||||
import { DurationService } from 'app/core/ui-services/duration.service';
|
||||
import { CurrentAgendaItemService } from 'app/site/projector/services/current-agenda-item.service';
|
||||
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
||||
|
||||
/**
|
||||
* The list of speakers for agenda items.
|
||||
@ -101,7 +102,8 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
* @param projectorRepo
|
||||
* @param route Angulars ActivatedRoute
|
||||
* @param DS the DataStore
|
||||
* @param itemRepo Repository fpr agenda items
|
||||
* @param repo Repository for speakers
|
||||
* @param itemRepo Repository for agendaItems
|
||||
* @param op the current operator
|
||||
* @param promptService
|
||||
* @param currentAgendaItemService
|
||||
@ -113,6 +115,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
snackBar: MatSnackBar,
|
||||
projectorRepo: ProjectorRepositoryService,
|
||||
private route: ActivatedRoute,
|
||||
private repo: SpeakerRepositoryService,
|
||||
private itemRepo: ItemRepositoryService,
|
||||
private op: OperatorService,
|
||||
private promptService: PromptService,
|
||||
@ -144,7 +147,12 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
public ngOnInit(): void {
|
||||
// load and observe users
|
||||
this.users = new BehaviorSubject(this.userRepository.getViewModelList());
|
||||
this.userRepository.getSortedViewModelListObservable().subscribe(users => this.users.next(users));
|
||||
this.userRepository.getSortedViewModelListObservable().subscribe(users => {
|
||||
this.users.next(users);
|
||||
if (this.viewItem) {
|
||||
this.setSpeakerList(this.viewItem.id);
|
||||
}
|
||||
});
|
||||
|
||||
// detect changes in the form
|
||||
this.addSpeakerForm.valueChanges.subscribe(formResult => {
|
||||
@ -174,7 +182,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the current lost of speakers of a given projector.
|
||||
* Shows the current list of speakers (CLOS) of a given projector.
|
||||
* Triggers after mat-select-change
|
||||
*
|
||||
* @param event Mat select change event, holds the projector in value
|
||||
@ -212,7 +220,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
this.itemRepo.getViewModelObservable(id).subscribe(newAgendaItem => {
|
||||
if (newAgendaItem) {
|
||||
this.viewItem = newAgendaItem;
|
||||
const allSpeakers = this.itemRepo.createViewSpeakers(newAgendaItem.item);
|
||||
const allSpeakers = this.repo.createSpeakerList(newAgendaItem.item);
|
||||
this.speakers = allSpeakers.filter(speaker => speaker.state === SpeakerState.WAITING);
|
||||
this.finishedSpeakers = allSpeakers.filter(speaker => speaker.state === SpeakerState.FINISHED);
|
||||
this.activeSpeaker = allSpeakers.find(speaker => speaker.state === SpeakerState.CURRENT);
|
||||
@ -226,7 +234,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
* @param userId the user id to add to the list. No parameter adds the operators user as speaker.
|
||||
*/
|
||||
public addNewSpeaker(userId?: number): void {
|
||||
this.itemRepo.addSpeaker(userId, this.viewItem).then(() => this.addSpeakerForm.reset(), this.raiseError);
|
||||
this.repo.create(userId, this.viewItem).then(() => this.addSpeakerForm.reset(), this.raiseError);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,7 +245,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
public onSortingChange(listInNewOrder: ViewSpeaker[]): void {
|
||||
// extract the ids from the ViewSpeaker array
|
||||
const userIds = listInNewOrder.map(speaker => speaker.id);
|
||||
this.itemRepo.sortSpeakers(userIds, this.viewItem.item).then(null, this.raiseError);
|
||||
this.repo.sortSpeakers(userIds, this.viewItem.item).then(null, this.raiseError);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,14 +254,14 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
* @param item the speaker marked in the list
|
||||
*/
|
||||
public onStartButton(item: ViewSpeaker): void {
|
||||
this.itemRepo.startSpeaker(item.id, this.viewItem).then(null, this.raiseError);
|
||||
this.repo.startSpeaker(item.id, this.viewItem).then(null, this.raiseError);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click on the mic-cross button
|
||||
*/
|
||||
public onStopButton(): void {
|
||||
this.itemRepo.stopCurrentSpeaker(this.viewItem).then(null, this.raiseError);
|
||||
this.repo.stopCurrentSpeaker(this.viewItem).then(null, this.raiseError);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -262,7 +270,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
* @param item
|
||||
*/
|
||||
public onMarkButton(item: ViewSpeaker): void {
|
||||
this.itemRepo.markSpeaker(item.user.id, !item.marked, this.viewItem).then(null, this.raiseError);
|
||||
this.repo.markSpeaker(item.user.id, !item.marked, this.viewItem).then(null, this.raiseError);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -271,7 +279,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
* @param speaker
|
||||
*/
|
||||
public onDeleteButton(speaker?: ViewSpeaker): void {
|
||||
this.itemRepo.deleteSpeaker(this.viewItem, speaker ? speaker.id : null).then(null, this.raiseError);
|
||||
this.repo.delete(this.viewItem, speaker ? speaker.id : null).then(null, this.raiseError);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -318,7 +326,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
||||
public async clearSpeakerList(): Promise<void> {
|
||||
const content = this.translate.instant('This will clear all speakers from the list.');
|
||||
if (await this.promptService.open('Are you sure?', content)) {
|
||||
this.itemRepo.deleteAllSpeakers(this.viewItem);
|
||||
this.repo.deleteAllSpeakers(this.viewItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user