From 38ee6bb2f1c40fc77be1c0163e558103dbe93a6f Mon Sep 17 00:00:00 2001 From: Sean Date: Thu, 23 Apr 2020 14:40:46 +0200 Subject: [PATCH] Show first contribution hint in list of speaker Shows a hint in the list of speakers if a speaker contributes for the first time. --- .../list-of-speakers-repository.service.ts | 4 ++++ .../list-of-speakers.component.html | 9 +++++++++ .../list-of-speakers.component.ts | 19 +++++++++++++++++-- .../agenda/models/view-list-of-speakers.ts | 14 +++++++++++++- openslides/agenda/config_variables.py | 10 ++++++++++ 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/client/src/app/core/repositories/agenda/list-of-speakers-repository.service.ts b/client/src/app/core/repositories/agenda/list-of-speakers-repository.service.ts index 942ee9ae7..4aa5b196c 100644 --- a/client/src/app/core/repositories/agenda/list-of-speakers-repository.service.ts +++ b/client/src/app/core/repositories/agenda/list-of-speakers-repository.service.ts @@ -224,6 +224,10 @@ export class ListOfSpeakersRepositoryService extends BaseHasContentObjectReposit await this.httpService.post('/rest/agenda/list-of-speakers/delete_all_speakers/'); } + public isFirstContribution(speaker: ViewSpeaker): boolean { + return !this.getViewModelList().some(list => list.hasSpeakerSpoken(speaker)); + } + /** * Helper function get the url to the speaker rest address * 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 648fc234a..3660de6b6 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 @@ -95,9 +95,18 @@ + + {{ hasSpokenCount(speaker) + 1 }}. {{ 'contribution' | translate }} + + + + {{ 'First contribution' | translate }} + + + ({{ speaker.gender | translate }}) diff --git a/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.ts b/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.ts index a00961eb2..2a932b384 100644 --- a/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.ts +++ b/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, ViewChild } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnInit, ViewChild } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Title } from '@angular/platform-browser'; @@ -31,7 +31,8 @@ import { SpeakerState, ViewSpeaker } from '../../models/view-speaker'; @Component({ selector: 'os-list-of-speakers', templateUrl: './list-of-speakers.component.html', - styleUrls: ['./list-of-speakers.component.scss'] + styleUrls: ['./list-of-speakers.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush }) export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit { @ViewChild(SortingListComponent) @@ -122,6 +123,8 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit private closSubscription: Subscription | null; + public showFistContributionHint: boolean; + /** * Constructor for speaker list component. Generates the forms. * @@ -205,6 +208,9 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit this.subscriptions.push( this.config.get('agenda_present_speakers_only').subscribe(() => { this.filterUsers(); + }), + this.config.get('agenda_show_first_contribution').subscribe(show => { + this.showFistContributionHint = show; }) ); } @@ -416,6 +422,15 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit }).length; } + /** + * Returns true if the speaker did never appear on any list of speakers + * + * @param speaker + */ + public isFirstContribution(speaker: ViewSpeaker): boolean { + return this.listOfSpeakersRepo.isFirstContribution(speaker); + } + /** * Closes the current list of speakers */ diff --git a/client/src/app/site/agenda/models/view-list-of-speakers.ts b/client/src/app/site/agenda/models/view-list-of-speakers.ts index 3281f8743..51e0431de 100644 --- a/client/src/app/site/agenda/models/view-list-of-speakers.ts +++ b/client/src/app/site/agenda/models/view-list-of-speakers.ts @@ -24,11 +24,19 @@ export class ViewListOfSpeakers extends BaseViewModelWithContentObject speaker.state === SpeakerState.FINISHED); + } + /** * Gets the amount of waiting speakers */ public get waitingSpeakerAmount(): number { - return this.speakers.filter(speaker => speaker.state === SpeakerState.WAITING).length; + return this.waitingSpeakers.length; + } + + public get waitingSpeakers(): ViewSpeaker[] { + return this.speakers.filter(speaker => speaker.state === SpeakerState.WAITING); } public get listOfSpeakersUrl(): string { @@ -51,6 +59,10 @@ export class ViewListOfSpeakers extends BaseViewModelWithContentObject this.getTitle() }; } + + public hasSpeakerSpoken(checkSpeaker: ViewSpeaker): boolean { + return this.finishedSpeakers.findIndex(speaker => speaker.user_id === checkSpeaker.user_id) !== -1; + } } interface IListOfSpeakersRelations { speakers: ViewSpeaker[]; diff --git a/openslides/agenda/config_variables.py b/openslides/agenda/config_variables.py index 7e8f739c6..2b21b87cc 100644 --- a/openslides/agenda/config_variables.py +++ b/openslides/agenda/config_variables.py @@ -188,3 +188,13 @@ def get_config_variables(): group="Agenda", subgroup="List of speakers", ) + + yield ConfigVariable( + name="agenda_show_first_contribution", + default_value=False, + input_type="boolean", + label="Show a note when a speaker appears for the first time", + weight=234, + group="Agenda", + subgroup="List of speakers", + )