From c9cf99d0e4245b14ea215fdf48eddd565a7ff54c Mon Sep 17 00:00:00 2001 From: Sean Engelhardt Date: Mon, 9 Dec 2019 15:00:32 +0100 Subject: [PATCH] Add leftover changes for 3.1 Adds various changes for a more complete 3.1 release - cleaner "current slide" description in projector detail (grid with ellipsis) - show the previously projected slides as ordered lists under the accordion - fix a bug where everyone could access the projection manage view (although it was unfunctional without the correct permissions) - assignment list now uses the correct ellipsis - fixes a bug where the lable "list of speakers" was not translated on the projector slide - Show a lock on the "list of speaker"-slide if it has been closed - enable dialog tests that have previously been disabled --- ...t-of-speakers-content-object-repository.ts | 3 +- .../motions/motion-repository.service.ts | 6 +- .../topics/topic-repository.service.ts | 4 +- .../choice-dialog.component.html | 4 +- .../choice-dialog.component.spec.ts | 32 +++-- .../choice-dialog/choice-dialog.component.ts | 2 +- .../projection-dialog.component.html | 16 ++- .../projection-dialog.component.spec.ts | 28 +++-- .../projection-dialog.component.ts | 36 +++--- .../prompt-dialog.component.html | 14 ++- .../prompt-dialog.component.spec.ts | 28 +++-- .../item-info-dialog.component.html | 2 +- .../item-info-dialog.component.spec.ts | 29 +++-- .../item-info-dialog.component.ts | 13 +- .../assignment-detail.component.html | 3 +- .../assignment-detail.component.ts | 2 +- .../assignment-list.component.html | 4 +- .../countdown-controls.component.scss | 3 +- .../message-dialog.component.spec.ts | 4 - .../projector-detail.component.html | 117 ++++++++++++------ .../projector-detail.component.scss | 28 +++-- .../projector-detail.component.ts | 32 ++++- .../projector-list-entry.component.html | 13 +- .../projector-list-entry.component.ts | 17 ++- .../projector/projector-routing.module.ts | 2 +- .../common-list-of-speakers-slide-data.ts | 7 +- ...mmon-list-of-speakers-slide.component.html | 5 +- ...common-list-of-speakers-slide.component.ts | 19 ++- openslides/agenda/projector.py | 3 +- 29 files changed, 323 insertions(+), 153 deletions(-) diff --git a/client/src/app/core/repositories/base-is-agenda-item-and-list-of-speakers-content-object-repository.ts b/client/src/app/core/repositories/base-is-agenda-item-and-list-of-speakers-content-object-repository.ts index 40e4b960e..c0181ae12 100644 --- a/client/src/app/core/repositories/base-is-agenda-item-and-list-of-speakers-content-object-repository.ts +++ b/client/src/app/core/repositories/base-is-agenda-item-and-list-of-speakers-content-object-repository.ts @@ -63,7 +63,8 @@ export abstract class BaseIsAgendaItemAndListOfSpeakersContentObjectRepository< } public getAgendaSlideTitle(titleInformation: T): string { - const numberPrefix = titleInformation.agenda_item_number() ? `${titleInformation.agenda_item_number()} · ` : ''; + const itemNumber = titleInformation.agenda_item_number(); + const numberPrefix = itemNumber ? `${itemNumber} · ` : ''; return numberPrefix + this.getTitle(titleInformation); } diff --git a/client/src/app/core/repositories/motions/motion-repository.service.ts b/client/src/app/core/repositories/motions/motion-repository.service.ts index a9e10c5ec..32842a1b8 100644 --- a/client/src/app/core/repositories/motions/motion-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-repository.service.ts @@ -237,7 +237,7 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo public getTitle = (titleInformation: MotionTitleInformation) => { if (titleInformation.identifier) { - return titleInformation.identifier + ': ' + titleInformation.title; + return `${titleInformation.identifier}: ${titleInformation.title}`; } else { return titleInformation.title; } @@ -255,9 +255,9 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo const numberPrefix = titleInformation.agenda_item_number() ? `${titleInformation.agenda_item_number()} · ` : ''; // if the identifier is set, the title will be 'Motion '. if (titleInformation.identifier) { - return numberPrefix + this.translate.instant('Motion') + ' ' + titleInformation.identifier; + return `${numberPrefix} ${this.translate.instant('Motion')} ${titleInformation.identifier}`; } else { - return numberPrefix + titleInformation.title; + return `${numberPrefix} ${titleInformation.title}`; } }; diff --git a/client/src/app/core/repositories/topics/topic-repository.service.ts b/client/src/app/core/repositories/topics/topic-repository.service.ts index 188d4df41..3915a2f6e 100644 --- a/client/src/app/core/repositories/topics/topic-repository.service.ts +++ b/client/src/app/core/repositories/topics/topic-repository.service.ts @@ -52,8 +52,8 @@ export class TopicRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCon } public getTitle = (titleInformation: TopicTitleInformation) => { - if (titleInformation.agenda_item_number()) { - return titleInformation.agenda_item_number() + ' · ' + titleInformation.title; + if (titleInformation.agenda_item_number && titleInformation.agenda_item_number()) { + return `${titleInformation.agenda_item_number()} · ${titleInformation.title}`; } else { return titleInformation.title; } diff --git a/client/src/app/shared/components/choice-dialog/choice-dialog.component.html b/client/src/app/shared/components/choice-dialog/choice-dialog.component.html index 3491657bb..45455a089 100644 --- a/client/src/app/shared/components/choice-dialog/choice-dialog.component.html +++ b/client/src/app/shared/components/choice-dialog/choice-dialog.component.html @@ -1,7 +1,7 @@ -

{{ data.title | translate }}

+

{{ data.title | translate }}

-
+
{ - // let component: ChoiceDialogComponent; - // let fixture: ComponentFixture; + let component: ChoiceDialogComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [E2EImportsModule] + imports: [E2EImportsModule], + providers: [ + { provide: MatDialogRef, useValue: {} }, + { + provide: MAT_DIALOG_DATA, + useValue: null + } + ] }).compileComponents(); })); - // TODO: You cannot create this component in the standard way. Needs different testing. beforeEach(() => { - /*fixture = TestBed.createComponent(PromptDialogComponent); - component = fixture.componentInstance; - fixture.detectChanges();*/ + fixture = TestBed.createComponent(ChoiceDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); }); - /*it('should create', () => { - expect(component).toBeTruthy(); -});*/ + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/client/src/app/shared/components/choice-dialog/choice-dialog.component.ts b/client/src/app/shared/components/choice-dialog/choice-dialog.component.ts index 0f55e8290..6130a0fa2 100644 --- a/client/src/app/shared/components/choice-dialog/choice-dialog.component.ts +++ b/client/src/app/shared/components/choice-dialog/choice-dialog.component.ts @@ -73,7 +73,7 @@ export class ChoiceDialogComponent { * @returns true if there is a selection chosen */ public get hasSelection(): boolean { - if (this.data.choices) { + if (this.data && this.data.choices) { if (this.selectForm.get('select').value) { return !!this.selectForm.get('select').value || !!this.selectForm.get('select').value.length; } else { diff --git a/client/src/app/shared/components/projection-dialog/projection-dialog.component.html b/client/src/app/shared/components/projection-dialog/projection-dialog.component.html index a076be715..eb9bc185c 100644 --- a/client/src/app/shared/components/projection-dialog/projection-dialog.component.html +++ b/client/src/app/shared/components/projection-dialog/projection-dialog.component.html @@ -1,23 +1,29 @@

Project selection?

-
{{ projectorElementBuildDescriptor.getDialogTitle() }}
+
+ {{ projectorElementBuildDescriptor.getDialogTitle() }} +
-
+ [ngClass]="isProjectedOn(projector) ? 'projected' : ''" + > {{ projector.name | translate }} - videocam + videocam
-
+
{ - // let component: ProjectionDialogComponent; - // let fixture: ComponentFixture; + let component: ProjectionDialogComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [E2EImportsModule] + imports: [E2EImportsModule], + providers: [ + { provide: MatDialogRef, useValue: {} }, + { + provide: MAT_DIALOG_DATA, + useValue: null + } + ] }).compileComponents(); })); - // TODO: You cannot create this component in the standard way. Needs different testing. beforeEach(() => { - /*fixture = TestBed.createComponent(ProjectionDialogComponent); + fixture = TestBed.createComponent(ProjectionDialogComponent); component = fixture.componentInstance; - fixture.detectChanges();*/ + fixture.detectChanges(); }); - /*it('should create', () => { + it('should create', () => { expect(component).toBeTruthy(); - });*/ + }); }); diff --git a/client/src/app/shared/components/projection-dialog/projection-dialog.component.ts b/client/src/app/shared/components/projection-dialog/projection-dialog.component.ts index ec35f7c58..e896f3286 100644 --- a/client/src/app/shared/components/projection-dialog/projection-dialog.component.ts +++ b/client/src/app/shared/components/projection-dialog/projection-dialog.component.ts @@ -38,26 +38,28 @@ export class ProjectionDialogComponent { this.projectors = this.DS.getAll('core/projector'); // TODO: Maybe watch. But this may not be necessary for the short living time of this dialog. - this.selectedProjectors = this.projectorService.getProjectorsWhichAreProjecting( - this.projectorElementBuildDescriptor - ); - - // Add default projector, if the projectable is not projected on it. - if (this.projectorElementBuildDescriptor.projectionDefaultName) { - const defaultProjector: Projector = this.projectorService.getProjectorForDefault( - this.projectorElementBuildDescriptor.projectionDefaultName + if (projectorElementBuildDescriptor) { + this.selectedProjectors = this.projectorService.getProjectorsWhichAreProjecting( + this.projectorElementBuildDescriptor ); - if (defaultProjector && !this.selectedProjectors.includes(defaultProjector)) { - this.selectedProjectors.push(defaultProjector); + + // Add default projector, if the projectable is not projected on it. + if (this.projectorElementBuildDescriptor.projectionDefaultName) { + const defaultProjector: Projector = this.projectorService.getProjectorForDefault( + this.projectorElementBuildDescriptor.projectionDefaultName + ); + if (defaultProjector && !this.selectedProjectors.includes(defaultProjector)) { + this.selectedProjectors.push(defaultProjector); + } } + + // Set option defaults + this.projectorElementBuildDescriptor.slideOptions.forEach(option => { + this.optionValues[option.key] = option.default; + }); + + this.options = this.projectorElementBuildDescriptor.slideOptions; } - - // Set option defaults - this.projectorElementBuildDescriptor.slideOptions.forEach(option => { - this.optionValues[option.key] = option.default; - }); - - this.options = this.projectorElementBuildDescriptor.slideOptions; } public toggleProjector(projector: Projector): void { diff --git a/client/src/app/shared/components/prompt-dialog/prompt-dialog.component.html b/client/src/app/shared/components/prompt-dialog/prompt-dialog.component.html index de36d185e..d15a10a8a 100644 --- a/client/src/app/shared/components/prompt-dialog/prompt-dialog.component.html +++ b/client/src/app/shared/components/prompt-dialog/prompt-dialog.component.html @@ -1,6 +1,8 @@ -

{{ data.title }}

- - - - - +
+

{{ data.title }}

+ + + + + +
diff --git a/client/src/app/shared/components/prompt-dialog/prompt-dialog.component.spec.ts b/client/src/app/shared/components/prompt-dialog/prompt-dialog.component.spec.ts index 5555c0e08..060f5f0be 100644 --- a/client/src/app/shared/components/prompt-dialog/prompt-dialog.component.spec.ts +++ b/client/src/app/shared/components/prompt-dialog/prompt-dialog.component.spec.ts @@ -1,26 +1,34 @@ -import { async, TestBed } from '@angular/core/testing'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; -// import { PromptDialogComponent } from './prompt-dialog.component'; import { E2EImportsModule } from 'e2e-imports.module'; +import { PromptDialogComponent } from './prompt-dialog.component'; + describe('PromptDialogComponent', () => { - // let component: PromptDialogComponent; - // let fixture: ComponentFixture; + let component: PromptDialogComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [E2EImportsModule] + imports: [E2EImportsModule], + providers: [ + { provide: MatDialogRef, useValue: {} }, + { + provide: MAT_DIALOG_DATA, + useValue: null + } + ] }).compileComponents(); })); - // TODO: You cannot create this component in the standard way. Needs different testing. beforeEach(() => { - /*fixture = TestBed.createComponent(PromptDialogComponent); + fixture = TestBed.createComponent(PromptDialogComponent); component = fixture.componentInstance; - fixture.detectChanges();*/ + fixture.detectChanges(); }); - /*it('should create', () => { + it('should create', () => { expect(component).toBeTruthy(); - });*/ + }); }); diff --git a/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.html b/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.html index 0f0532415..89d14c3ea 100644 --- a/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.html +++ b/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.html @@ -1,4 +1,4 @@ -

{{ 'Edit details for' | translate }} {{ item.getTitle() }}

+

{{ 'Edit details for' | translate }} {{ item.getTitle() }}

diff --git a/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.spec.ts b/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.spec.ts index 347ecf7fc..725ce12e4 100644 --- a/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.spec.ts +++ b/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.spec.ts @@ -1,26 +1,35 @@ -import { async, TestBed } from '@angular/core/testing'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; -// import { ItemInfoDialogComponent } from './item-info-dialog.component'; import { E2EImportsModule } from 'e2e-imports.module'; +import { ItemInfoDialogComponent } from './item-info-dialog.component'; + describe('ItemInfoDialogComponent', () => { - // let component: ItemInfoDialogComponent; - // let fixture: ComponentFixture; + let component: ItemInfoDialogComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [E2EImportsModule] + imports: [E2EImportsModule], + declarations: [ItemInfoDialogComponent], + providers: [ + { provide: MatDialogRef, useValue: {} }, + { + provide: MAT_DIALOG_DATA, + useValue: null + } + ] }).compileComponents(); })); - // TODO: You cannot create this component in the standard way. Needs different testing. beforeEach(() => { - /*fixture = TestBed.createComponent(ItemInfoDialogComponent); + fixture = TestBed.createComponent(ItemInfoDialogComponent); component = fixture.componentInstance; - fixture.detectChanges();*/ + fixture.detectChanges(); }); - /*it('should create', () => { + it('should create', () => { expect(component).toBeTruthy(); - });*/ + }); }); diff --git a/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.ts b/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.ts index 05138abcd..06490957a 100644 --- a/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.ts +++ b/client/src/app/site/agenda/components/item-info-dialog/item-info-dialog.component.ts @@ -38,8 +38,7 @@ export class ItemInfoDialogComponent { public formBuilder: FormBuilder, public durationService: DurationService, public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) - public item: ViewItem + @Inject(MAT_DIALOG_DATA) public item: ViewItem ) { this.agendaInfoForm = this.formBuilder.group({ type: [''], @@ -49,10 +48,12 @@ export class ItemInfoDialogComponent { }); // load current values - this.agendaInfoForm.get('type').setValue(item.type); - this.agendaInfoForm.get('durationText').setValue(this.durationService.durationToString(item.duration, 'h')); - this.agendaInfoForm.get('item_number').setValue(item.item_number); - this.agendaInfoForm.get('comment').setValue(item.comment); + if (item) { + this.agendaInfoForm.get('type').setValue(item.type); + this.agendaInfoForm.get('durationText').setValue(this.durationService.durationToString(item.duration, 'h')); + this.agendaInfoForm.get('item_number').setValue(item.item_number); + this.agendaInfoForm.get('comment').setValue(item.comment); + } } /** diff --git a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html index 39b69e895..dba66ddda 100644 --- a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html +++ b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html @@ -168,7 +168,7 @@ [input]="assignment.assignment_related_users" [live]="true" [count]="true" - [enable]="hasPerms('addOthers')" + [enable]="hasPerms('manage')" (sortEvent)="onSortingChange($event)" > @@ -177,6 +177,7 @@ +
+ + + + + + + + -
+
@@ -16,18 +49,30 @@
- - - @@ -73,8 +118,12 @@ arrow_downward - @@ -113,18 +162,20 @@ - - {{ getSlideTitle(element) }} -
-
- -
+
+ + + + {{ getSlideTitle(element) }} + + +
@@ -178,16 +229,6 @@ - - - - Previous slides - -

- {{ i + 1 }}.   {{ getSlideTitle(elements[0]) }} -

-
- @@ -287,14 +328,16 @@ - - +
    +
  1. + {{ getSlideTitle(elements[0]) }} +
  2. +
+ diff --git a/client/src/app/site/projector/components/projector-detail/projector-detail.component.scss b/client/src/app/site/projector/components/projector-detail/projector-detail.component.scss index dbe802f48..69051f2d6 100644 --- a/client/src/app/site/projector/components/projector-detail/projector-detail.component.scss +++ b/client/src/app/site/projector/components/projector-detail/projector-detail.component.scss @@ -1,8 +1,9 @@ @import '~assets/styles/drag.scss'; -#projector { - width: 100%; /*1000px;*/ - border: 1px solid lightgrey; +.projector-detail-wrapper { + #projector { + border: 1px solid lightgrey; + } } .column-left { @@ -32,22 +33,29 @@ text-align: right; } -.currentElement { +.current-element { margin-bottom: 20px; box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.25); - .button-right { - position: absolute; - right: 10px; + .emelent-grid { + display: grid; + width: 100%; + grid-gap: 5px; + grid-template-columns: min-content 1fr min-content; + .mat-icon-button { + display: inherit; + } + .current-element-text { + margin-top: auto; + margin-bottom: auto; + } } } -.queue, -.previous-slides { +.queue { box-shadow: none !important; background: none !important; margin-bottom: 20px; - .queue-element { margin-bottom: 5px; } diff --git a/client/src/app/site/projector/components/projector-detail/projector-detail.component.ts b/client/src/app/site/projector/components/projector-detail/projector-detail.component.ts index abd4af1dc..dd457a4ee 100644 --- a/client/src/app/site/projector/components/projector-detail/projector-detail.component.ts +++ b/client/src/app/site/projector/components/projector-detail/projector-detail.component.ts @@ -8,6 +8,7 @@ import { ActivatedRoute } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { timer } from 'rxjs'; +import { OperatorService } from 'app/core/core-services/operator.service'; import { ProjectorService } from 'app/core/core-services/projector.service'; import { CountdownRepositoryService } from 'app/core/repositories/projector/countdown-repository.service'; import { ProjectorMessageRepositoryService } from 'app/core/repositories/projector/projector-message-repository.service'; @@ -16,6 +17,7 @@ import { ScrollScaleDirection } from 'app/core/repositories/projector/projector-repository.service'; import { DurationService } from 'app/core/ui-services/duration.service'; +import { PromptService } from 'app/core/ui-services/prompt.service'; import { SizeObject } from 'app/shared/components/tile/tile.component'; import { Countdown } from 'app/shared/models/core/countdown'; import { ProjectorElement } from 'app/shared/models/core/projector'; @@ -92,7 +94,9 @@ export class ProjectorDetailComponent extends BaseViewComponent implements OnIni private currentListOfSpeakersSlideService: CurrentListOfSpeakersSlideService, private currentSpeakerChyronService: CurrentSpeakerChyronSlideService, private durationService: DurationService, - private cd: ChangeDetectorRef + private cd: ChangeDetectorRef, + private promptService: PromptService, + private opertator: OperatorService ) { super(titleService, translate, matSnackBar); @@ -135,6 +139,32 @@ export class ProjectorDetailComponent extends BaseViewComponent implements OnIni }); } + /** + * Handler to set the current reference projector + * TODO: same with projector list entry + */ + public onSetAsClosRef(): void { + this.repo.setReferenceProjector(this.projector.id); + } + + /** + * Handler for the delete Projector button + * TODO: same with projector list entry + */ + public async onDeleteProjectorButton(): Promise { + const title = this.translate.instant('Are you sure you want to delete this projector?'); + if (await this.promptService.open(title, this.projector.name)) { + this.repo.delete(this.projector).catch(this.raiseError); + } + } + + /** + * @returns true if the operator can manage + */ + public canManage(): boolean { + return this.opertator.hasPerms('core.can_manage_projector'); + } + /** * Change the scroll * diff --git a/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.html b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.html index 6500347cb..a39582243 100644 --- a/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.html +++ b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.html @@ -8,18 +8,23 @@ (click)="onSetAsClosRef()" matTooltip="{{ 'Sets this projector as the reference for the current list of speakers' | translate }}" > - star - star_border + star + star_border - -
+
diff --git a/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.ts b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.ts index 70799af51..59034528d 100644 --- a/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.ts +++ b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.ts @@ -5,6 +5,7 @@ import { Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; +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 { largeDialogSettings } from 'app/shared/utils/dialog-settings'; @@ -54,7 +55,8 @@ export class ProjectorListEntryComponent extends BaseViewComponent implements On matSnackBar: MatSnackBar, private repo: ProjectorRepositoryService, private promptService: PromptService, - private dialogService: MatDialog + private dialogService: MatDialog, + private operator: OperatorService ) { super(titleService, translate, matSnackBar); } @@ -78,6 +80,19 @@ export class ProjectorListEntryComponent extends BaseViewComponent implements On this.repo.setReferenceProjector(this.projector.id); } + /** + * Determines the detail link by permission. + * Without manage permission, the user should see the full screen projector + * and not the detail view + */ + public getDetailLink(): string { + if (this.operator.hasPerms('core.can_can_manage_projector')) { + return `/projectors/detail/${this.projector.id}`; + } else { + return `/projector/${this.projector.id}`; + } + } + /** * Delete the projector. */ diff --git a/client/src/app/site/projector/projector-routing.module.ts b/client/src/app/site/projector/projector-routing.module.ts index 83d1f02b9..ff6f28d1e 100644 --- a/client/src/app/site/projector/projector-routing.module.ts +++ b/client/src/app/site/projector/projector-routing.module.ts @@ -13,7 +13,7 @@ const routes: Routes = [ { path: 'detail/:id', component: ProjectorDetailComponent, - data: { basePerm: 'core.can_see_projector' } + data: { basePerm: 'core.can_can_manage_projector' } } ]; diff --git a/client/src/app/slides/agenda/common/common-list-of-speakers-slide-data.ts b/client/src/app/slides/agenda/common/common-list-of-speakers-slide-data.ts index 45707de0c..bb9626989 100644 --- a/client/src/app/slides/agenda/common/common-list-of-speakers-slide-data.ts +++ b/client/src/app/slides/agenda/common/common-list-of-speakers-slide-data.ts @@ -7,6 +7,11 @@ export interface CommonListOfSpeakersSlideData { waiting?: SlideSpeaker[]; current?: SlideSpeaker; finished?: SlideSpeaker[]; - title_information?: object; + title_information?: { + _agenda_item_number: string; + agend_item_number: () => string; + [key: string]: any; + }; content_object_collection?: string; + closed?: boolean; } diff --git a/client/src/app/slides/agenda/common/common-list-of-speakers-slide.component.html b/client/src/app/slides/agenda/common/common-list-of-speakers-slide.component.html index edacee4f0..aa37be242 100644 --- a/client/src/app/slides/agenda/common/common-list-of-speakers-slide.component.html +++ b/client/src/app/slides/agenda/common/common-list-of-speakers-slide.component.html @@ -1,6 +1,9 @@
-

List of speakers

+

+ List of speakers + lock +

{{ getTitle() }} diff --git a/client/src/app/slides/agenda/common/common-list-of-speakers-slide.component.ts b/client/src/app/slides/agenda/common/common-list-of-speakers-slide.component.ts index c5c340e23..4012863f2 100644 --- a/client/src/app/slides/agenda/common/common-list-of-speakers-slide.component.ts +++ b/client/src/app/slides/agenda/common/common-list-of-speakers-slide.component.ts @@ -1,8 +1,10 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { CollectionStringMapperService } from 'app/core/core-services/collection-string-mapper.service'; +import { SlideData } from 'app/core/core-services/projector-data.service'; import { isBaseIsAgendaItemContentObjectRepository } from 'app/core/repositories/base-is-agenda-item-content-object-repository'; import { ConfigService } from 'app/core/ui-services/config.service'; +import { ProjectorElement } from 'app/shared/models/core/projector'; import { BaseSlideComponent } from 'app/slides/base-slide-component'; import { CommonListOfSpeakersSlideData } from './common-list-of-speakers-slide-data'; @@ -13,6 +15,21 @@ import { CommonListOfSpeakersSlideData } from './common-list-of-speakers-slide-d }) export class CommonListOfSpeakersSlideComponent extends BaseSlideComponent implements OnInit { + @Input() + public set data(value: SlideData) { + // In the case of projected references without ListOfSpeakers Slide + if (Object.entries(value.data).length) { + value.data.title_information.agenda_item_number = () => value.data.title_information._agenda_item_number; + this._data = value; + } + } + + public get data(): SlideData { + return this._data; + } + + private _data: SlideData; + /** * Boolean, whether the amount of speakers should be shown. */ diff --git a/openslides/agenda/projector.py b/openslides/agenda/projector.py index 0ee13e5a0..36d0a47d4 100644 --- a/openslides/agenda/projector.py +++ b/openslides/agenda/projector.py @@ -123,7 +123,7 @@ async def get_list_of_speakers_slide_data( list_of_speakers["content_object"]["id"] ].get("agenda_item_id") if agenda_item_id: - title_information["agenda_item_number"] = all_data["agenda/item"][ + title_information["_agenda_item_number"] = all_data["agenda/item"][ agenda_item_id ]["item_number"] @@ -169,6 +169,7 @@ async def get_list_of_speakers_slide_data( "finished": speakers_finished, "content_object_collection": list_of_speakers["content_object"]["collection"], "title_information": title_information, + "closed": list_of_speakers["closed"], }