From c8faa982ac4b5c7bc4eee3e3e2609ca4c326caed Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Wed, 22 Apr 2020 18:46:48 +0200 Subject: [PATCH] Subtitles for projected elements in the projector detail view --- .../core/core-services/projector.service.ts | 9 +++- .../agenda/item-repository.service.ts | 37 ++++------------- ...t-of-speakers-content-object-repository.ts | 25 +++-------- ...s-agenda-item-content-object-repository.ts | 32 +++------------ .../motions/motion-repository.service.ts | 41 ++++++++----------- .../topics/topic-repository.service.ts | 11 +---- .../agenda/models/view-list-of-speakers.ts | 5 ++- .../agenda/services/agenda-pdf.service.ts | 2 +- .../site/base/base-projectable-view-model.ts | 7 ++-- .../base/base-view-model-with-agenda-item.ts | 32 +++++++-------- client/src/app/site/base/projectable.ts | 3 +- .../projector-detail.component.html | 23 ++++++++++- .../projector-detail.component.ts | 6 ++- client/src/app/slides/slide-manifest.ts | 3 +- .../styles/global-components-style.scss | 8 +++- 15 files changed, 105 insertions(+), 139 deletions(-) diff --git a/client/src/app/core/core-services/projector.service.ts b/client/src/app/core/core-services/projector.service.ts index 5e5fc592f..de2cb5771 100644 --- a/client/src/app/core/core-services/projector.service.ts +++ b/client/src/app/core/core-services/projector.service.ts @@ -25,6 +25,11 @@ import { HttpService } from './http.service'; import { ProjectorDataService } from './projector-data.service'; import { ViewModelStoreService } from './view-model-store.service'; +export interface ProjectorTitle { + title: string; + subtitle?: string; +} + /** * This service cares about Projectables being projected and manage all projection-related * actions. @@ -325,7 +330,7 @@ export class ProjectorService { /** */ - public getSlideTitle(element: ProjectorElement): string { + public getSlideTitle(element: ProjectorElement): ProjectorTitle { if (this.slideManager.canSlideBeMappedToModel(element.name)) { const idElement = this.slideManager.getIdentifialbeProjectorElement(element); const viewModel = this.getViewModelFromProjectorElement(idElement); @@ -338,7 +343,7 @@ export class ProjectorService { return configuration.getSlideTitle(element, this.translate, this.viewModelStore); } - return this.translate.instant(this.slideManager.getSlideVerboseName(element.name)); + return { title: this.translate.instant(this.slideManager.getSlideVerboseName(element.name)) }; } /** 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 b6ad5e431..b02ffaeae 100644 --- a/client/src/app/core/repositories/agenda/item-repository.service.ts +++ b/client/src/app/core/repositories/agenda/item-repository.service.ts @@ -14,6 +14,7 @@ import { Identifiable } from 'app/shared/models/base/identifiable'; import { ItemTitleInformation, ViewItem } from 'app/site/agenda/models/view-item'; import { ViewAssignment } from 'app/site/assignments/models/view-assignment'; import { + AgendaListTitle, BaseViewModelWithAgendaItem, isBaseViewModelWithAgendaItem } from 'app/site/base/base-view-model-with-agenda-item'; @@ -79,7 +80,7 @@ export class ItemRepositoryService extends BaseHasContentObjectRepository< return this.translate.instant(plural ? 'Items' : 'Item'); }; - public getTitle = (titleInformation: ItemTitleInformation) => { + private getAgendaTitle(titleInformation: ItemTitleInformation): AgendaListTitle { if (titleInformation.contentObject) { return titleInformation.contentObject.getAgendaListTitle(); } else { @@ -88,36 +89,14 @@ export class ItemRepositoryService extends BaseHasContentObjectRepository< ) as BaseIsAgendaItemContentObjectRepository; return repo.getAgendaListTitle(titleInformation.title_information); } + } + + public getTitle = (titleInformation: ItemTitleInformation) => { + return this.getAgendaTitle(titleInformation).title; }; - /** - * Overrides the base function, if implemented. - * - * @returns An optional subtitle as `string`. Defaults to `null`. - */ - public getSubtitle = (viewItem: ViewItem) => { - if (viewItem.contentObject) { - return viewItem.contentObject.getAgendaSubtitle(); - } else { - // The subtitle is not present in the title_information yet. - return null; - } - }; - - /** - * Overrides the base function. - * - * @returns The title without any prefix like item number. - */ - public getTitleWithoutItemNumber = (titleInformation: ItemTitleInformation) => { - if (titleInformation.contentObject) { - return titleInformation.contentObject.getAgendaListTitleWithoutItemNumber(); - } else { - const repo = this.collectionStringMapperService.getRepository( - titleInformation.contentObjectData.collection - ) as BaseIsAgendaItemContentObjectRepository; - return repo.getAgendaListTitleWithoutItemNumber(titleInformation.title_information); - } + public getSubtitle = (titleInformation: ItemTitleInformation) => { + return this.getAgendaTitle(titleInformation).subtitle; }; /** 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 c0181ae12..9a359f160 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 @@ -3,6 +3,7 @@ import { ViewItem } from 'app/site/agenda/models/view-item'; import { ViewListOfSpeakers } from 'app/site/agenda/models/view-list-of-speakers'; import { BaseProjectableViewModel } from 'app/site/base/base-projectable-view-model'; import { + AgendaListTitle, BaseViewModelWithAgendaItem, TitleInformationWithAgendaItem } from 'app/site/base/base-view-model-with-agenda-item'; @@ -52,14 +53,11 @@ export abstract class BaseIsAgendaItemAndListOfSpeakersContentObjectRepository< }); } - public getAgendaListTitle(titleInformation: T): string { + public getAgendaListTitle(titleInformation: T): AgendaListTitle { // Return the agenda title with the model's verbose name appended const numberPrefix = titleInformation.agenda_item_number() ? `${titleInformation.agenda_item_number()} · ` : ''; - return numberPrefix + this.getTitle(titleInformation) + ' (' + this.getVerboseName() + ')'; - } - - public getAgendaSubtitle(viewModel: V): string | null { - return null; + const title = numberPrefix + this.getTitle(titleInformation) + ' (' + this.getVerboseName() + ')'; + return { title }; } public getAgendaSlideTitle(titleInformation: T): string { @@ -68,19 +66,8 @@ export abstract class BaseIsAgendaItemAndListOfSpeakersContentObjectRepository< return numberPrefix + this.getTitle(titleInformation); } - /** - * Function to get the list-title without the item-number. - * - * @param titleInformation The title-information for an object. - * - * @returns {string} The title without any prefix like item-number. - */ - public getAgendaListTitleWithoutItemNumber(titleInformation: T): string { - return this.getTitle(titleInformation) + ' (' + this.getVerboseName() + ')'; - } - public getListOfSpeakersTitle = (titleInformation: T) => { - return this.getAgendaListTitle(titleInformation); + return this.getAgendaListTitle(titleInformation).title; }; public getListOfSpeakersSlideTitle = (titleInformation: T) => { @@ -90,9 +77,7 @@ export abstract class BaseIsAgendaItemAndListOfSpeakersContentObjectRepository< protected createViewModelWithTitles(model: M): V { const viewModel = super.createViewModelWithTitles(model); viewModel.getAgendaListTitle = () => this.getAgendaListTitle(viewModel); - viewModel.getAgendaListTitleWithoutItemNumber = () => this.getAgendaListTitleWithoutItemNumber(viewModel); viewModel.getAgendaSlideTitle = () => this.getAgendaSlideTitle(viewModel); - viewModel.getAgendaSubtitle = () => this.getAgendaSubtitle(viewModel); viewModel.getListOfSpeakersTitle = () => this.getListOfSpeakersTitle(viewModel); viewModel.getListOfSpeakersSlideTitle = () => this.getListOfSpeakersSlideTitle(viewModel); return viewModel; diff --git a/client/src/app/core/repositories/base-is-agenda-item-content-object-repository.ts b/client/src/app/core/repositories/base-is-agenda-item-content-object-repository.ts index 965ce9985..96cbc4ea0 100644 --- a/client/src/app/core/repositories/base-is-agenda-item-content-object-repository.ts +++ b/client/src/app/core/repositories/base-is-agenda-item-content-object-repository.ts @@ -2,6 +2,7 @@ import { TranslateService } from '@ngx-translate/core'; import { ViewItem } from 'app/site/agenda/models/view-item'; import { + AgendaListTitle, BaseViewModelWithAgendaItem, TitleInformationWithAgendaItem } from 'app/site/base/base-view-model-with-agenda-item'; @@ -29,8 +30,7 @@ export interface IBaseIsAgendaItemContentObjectRepository< M extends BaseModel, T extends TitleInformationWithAgendaItem > extends BaseRepository { - getAgendaListTitle: (titleInformation: T) => string; - getAgendaListTitleWithoutItemNumber: (titleInformation: T) => string; + getAgendaListTitle: (titleInformation: T) => AgendaListTitle; getAgendaSlideTitle: (titleInformation: T) => string; } @@ -77,31 +77,11 @@ export abstract class BaseIsAgendaItemContentObjectRepository< * @returns the agenda title for the agenda item list. Should * be ` · (<type>)`. E.g. `7 · the is an election (Election)`. */ - public getAgendaListTitle(titleInformation: T): string { + public getAgendaListTitle(titleInformation: T): AgendaListTitle { // Return the agenda title with the model's verbose name appended const numberPrefix = titleInformation.agenda_item_number() ? `${titleInformation.agenda_item_number()} · ` : ''; - return numberPrefix + this.getTitle(titleInformation) + ' (' + this.getVerboseName() + ')'; - } - - /** - * Overrides the base function. Returns an optional subtitle. - * - * @param viewModel The model to get the subtitle from. - * @returns A string as subtitle. Defaults to `null`. - */ - public getAgendaSubtitle(viewModel: V): string | null { - return null; - } - - /** - * Function to return the title without item-number, in example used for pdf-creation. - * - * @param titleInformation The title information. - * - * @returns {string} The title without any prefix like the item-number. - */ - public getAgendaListTitleWithoutItemNumber(titleInformation: T): string { - return this.getTitle(titleInformation) + ' (' + this.getVerboseName() + ')'; + const title = numberPrefix + this.getTitle(titleInformation) + ' (' + this.getVerboseName() + ')'; + return { title }; } /** @@ -117,9 +97,7 @@ export abstract class BaseIsAgendaItemContentObjectRepository< protected createViewModelWithTitles(model: M): V { const viewModel = super.createViewModelWithTitles(model); viewModel.getAgendaListTitle = () => this.getAgendaListTitle(viewModel); - viewModel.getAgendaListTitleWithoutItemNumber = () => this.getAgendaListTitleWithoutItemNumber(viewModel); viewModel.getAgendaSlideTitle = () => this.getAgendaSlideTitle(viewModel); - viewModel.getAgendaSubtitle = () => this.getAgendaSubtitle(viewModel); return viewModel; } } 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 b9f4af858..5b79f114a 100644 --- a/client/src/app/core/repositories/motions/motion-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-repository.service.ts @@ -17,6 +17,7 @@ import { Motion } from 'app/shared/models/motions/motion'; import { Submitter } from 'app/shared/models/motions/submitter'; import { ViewUnifiedChange, ViewUnifiedChangeType } from 'app/shared/models/motions/view-unified-change'; import { PersonalNoteContent } from 'app/shared/models/users/personal-note'; +import { AgendaListTitle } from 'app/site/base/base-view-model-with-agenda-item'; import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile'; import { ViewCategory } from 'app/site/motions/models/view-category'; import { MotionTitleInformation, ViewMotion } from 'app/site/motions/models/view-motion'; @@ -269,46 +270,40 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo public getAgendaListTitle = (titleInformation: MotionTitleInformation) => { const numberPrefix = titleInformation.agenda_item_number() ? `${titleInformation.agenda_item_number()} · ` : ''; // Append the verbose name only, if not the special format 'Motion <identifier>' is used. + let title; if (titleInformation.identifier) { - return `${numberPrefix}${this.translate.instant('Motion')} ${titleInformation.identifier} · ${ + title = `${numberPrefix}${this.translate.instant('Motion')} ${titleInformation.identifier} · ${ titleInformation.title }`; } else { - return `${numberPrefix}${titleInformation.title} (${this.getVerboseName()})`; + title = `${numberPrefix}${titleInformation.title} (${this.getVerboseName()})`; } - }; + const agendaTitle: AgendaListTitle = { title }; - /** - * @override The base function and returns the submitters as optional subtitle. - */ - public getAgendaSubtitle = (motion: ViewMotion) => { - if (motion.submittersAsUsers && motion.submittersAsUsers.length) { - return `${this.translate.instant('by')} ${motion.submittersAsUsers.join(', ')}`; - } else { - return null; - } - }; - - /** - * @override The base function - */ - public getAgendaListTitleWithoutItemNumber = (titleInformation: MotionTitleInformation) => { - if (titleInformation.identifier) { - return this.translate.instant('Motion') + ' ' + titleInformation.identifier; - } else { - return titleInformation.title + `(${this.getVerboseName()})`; + // Subtitle. + // This is a bit hacky: If one has not motions.can_see, the titleinformation is nut sufficient for + // submitters. So try-cast titleInformation to a ViewMotion and check, if submittersAsUsers is available + const viewMotion: ViewMotion = titleInformation as ViewMotion; + if (viewMotion.submittersAsUsers && viewMotion.submittersAsUsers.length) { + agendaTitle.subtitle = `${this.translate.instant('by')} ${viewMotion.submittersAsUsers.join(', ')}`; } + return agendaTitle; }; public getVerboseName = (plural: boolean = false) => { return this.translate.instant(plural ? 'Motions' : 'Motion'); }; + public getProjectorTitle = (viewMotion: ViewMotion) => { + const subtitle = viewMotion.item && viewMotion.item.comment ? viewMotion.item.comment : null; + return { title: this.getAgendaSlideTitle(viewMotion), subtitle }; + }; + protected createViewModelWithTitles(model: Motion): ViewMotion { const viewModel = super.createViewModelWithTitles(model); viewModel.getIdentifierOrTitle = () => this.getIdentifierOrTitle(viewModel); - viewModel.getProjectorTitle = () => this.getAgendaSlideTitle(viewModel); + viewModel.getProjectorTitle = () => this.getProjectorTitle(viewModel); return viewModel; } 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 3915a2f6e..8377d1896 100644 --- a/client/src/app/core/repositories/topics/topic-repository.service.ts +++ b/client/src/app/core/repositories/topics/topic-repository.service.ts @@ -61,7 +61,7 @@ export class TopicRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCon public getAgendaListTitle = (titleInformation: TopicTitleInformation) => { // Do not append ' (Topic)' to the title. - return this.getTitle(titleInformation); + return { title: this.getTitle(titleInformation) }; }; public getAgendaSlideTitle = (titleInformation: TopicTitleInformation) => { @@ -69,15 +69,6 @@ export class TopicRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCon return this.getTitle(titleInformation); }; - /** - * @override The base function. - * - * @returns The plain title. - */ - public getAgendaListTitleWithoutItemNumber = (titleInformation: TopicTitleInformation) => { - return titleInformation.title; - }; - public getVerboseName = (plural: boolean = false) => { return this.translate.instant(plural ? 'Topics' : 'Topic'); }; 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 330a6647a..3281f8743 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 @@ -1,3 +1,4 @@ +import { ProjectorTitle } from 'app/core/core-services/projector.service'; import { ListOfSpeakers, ListOfSpeakersWithoutNestedModels } from 'app/shared/models/agenda/list-of-speakers'; import { ContentObject } from 'app/shared/models/base/content-object'; import { BaseViewModelWithContentObject } from 'app/site/base/base-view-model-with-content-object'; @@ -34,8 +35,8 @@ export class ViewListOfSpeakers extends BaseViewModelWithContentObject<ListOfSpe return `/agenda/speakers/${this.id}`; } - public getProjectorTitle(): string { - return this.getTitle(); + public getProjectorTitle(): ProjectorTitle { + return { title: this.getTitle() }; } public getSlide(): ProjectorElementBuildDeskriptor { diff --git a/client/src/app/site/agenda/services/agenda-pdf.service.ts b/client/src/app/site/agenda/services/agenda-pdf.service.ts index 1832d0886..5473d74e4 100644 --- a/client/src/app/site/agenda/services/agenda-pdf.service.ts +++ b/client/src/app/site/agenda/services/agenda-pdf.service.ts @@ -87,7 +87,7 @@ export class AgendaPdfService { text: nodeItem.item.item_number }, { - text: nodeItem.item.contentObject.getAgendaListTitleWithoutItemNumber() + text: nodeItem.item.contentObject.getListTitle() } ] }; diff --git a/client/src/app/site/base/base-projectable-view-model.ts b/client/src/app/site/base/base-projectable-view-model.ts index e647bf9af..ebd8200e4 100644 --- a/client/src/app/site/base/base-projectable-view-model.ts +++ b/client/src/app/site/base/base-projectable-view-model.ts @@ -1,3 +1,4 @@ +import { ProjectorTitle } from 'app/core/core-services/projector.service'; import { ConfigService } from 'app/core/ui-services/config.service'; import { BaseModel } from 'app/shared/models/base/base-model'; import { BaseViewModel } from './base-view-model'; @@ -13,7 +14,7 @@ export abstract class BaseProjectableViewModel<M extends BaseModel = any> extend /** * @returns the projector title used for managing projector elements. */ - public getProjectorTitle = () => { - return this.getTitle(); - }; + public getProjectorTitle(): ProjectorTitle { + return { title: this.getTitle() }; + } } diff --git a/client/src/app/site/base/base-view-model-with-agenda-item.ts b/client/src/app/site/base/base-view-model-with-agenda-item.ts index 0e239eb78..3b52dfdae 100644 --- a/client/src/app/site/base/base-view-model-with-agenda-item.ts +++ b/client/src/app/site/base/base-view-model-with-agenda-item.ts @@ -1,3 +1,4 @@ +import { ProjectorTitle } from 'app/core/core-services/projector.service'; import { SearchRepresentation } from 'app/core/ui-services/search.service'; import { BaseModelWithAgendaItem } from 'app/shared/models/base/base-model-with-agenda-item'; import { DetailNavigable, isDetailNavigable } from 'app/shared/models/base/detail-navigable'; @@ -5,6 +6,11 @@ import { BaseProjectableViewModel } from './base-projectable-view-model'; import { TitleInformation } from './base-view-model'; import { isSearchable, Searchable } from './searchable'; +export interface AgendaListTitle { + title: string; + subtitle?: string; +} + export function isBaseViewModelWithAgendaItem(obj: any): obj is BaseViewModelWithAgendaItem { const model = <BaseViewModelWithAgendaItem>obj; return ( @@ -13,7 +19,6 @@ export function isBaseViewModelWithAgendaItem(obj: any): obj is BaseViewModelWit isSearchable(model) && model.getAgendaSlideTitle !== undefined && model.getAgendaListTitle !== undefined && - model.getAgendaSubtitle !== undefined && model.getCSVExportText !== undefined && model.item !== undefined && model.getModel !== undefined && @@ -42,12 +47,7 @@ export interface BaseViewModelWithAgendaItem<M extends BaseModelWithAgendaItem = /** * @return the agenda title with the verbose name of the content object */ - getAgendaListTitle: () => string; - - /** - * @return the agenda title with the verbose name of the content object - */ - getAgendaListTitleWithoutItemNumber: () => string; + getAgendaListTitle: () => AgendaListTitle; } /** @@ -62,6 +62,15 @@ export abstract class BaseViewModelWithAgendaItem< return this.item && this.item.item_number ? this.item.item_number : null; } + /** + * @returns the projector title used for managing projector elements. + * Appends the agneda item comment as the subtitle, if this model has an agenda item + */ + public getProjectorTitle(): ProjectorTitle { + const subtitle = this.item.comment || null; + return { title: this.getTitle(), subtitle }; + } + /** * @returns the (optional) descriptive text to be exported in the CSV. * May be overridden by inheriting classes @@ -70,15 +79,6 @@ export abstract class BaseViewModelWithAgendaItem< return ''; } - /** - * @override The base-method from `IBaseViewModelWithAgendaItem`. - * - * @returns Defaults to `null`. - */ - public getAgendaSubtitle(): string | null { - return null; - } - public abstract getDetailStateURL(): string; /** diff --git a/client/src/app/site/base/projectable.ts b/client/src/app/site/base/projectable.ts index 626840a07..c85b1fb74 100644 --- a/client/src/app/site/base/projectable.ts +++ b/client/src/app/site/base/projectable.ts @@ -1,3 +1,4 @@ +import { ProjectorTitle } from 'app/core/core-services/projector.service'; import { ConfigService } from 'app/core/ui-services/config.service'; import { IdentifiableProjectorElement, ProjectorElementOptions } from 'app/shared/models/core/projector'; import { Displayable } from 'app/site/base/displayable'; @@ -32,7 +33,7 @@ export function isProjectable(obj: any): obj is Projectable { * Interface for every model, that should be projectable. */ export interface Projectable extends Displayable { - getProjectorTitle: () => string; + getProjectorTitle: () => ProjectorTitle; getSlide(configSerice?: ConfigService): ProjectorElementBuildDeskriptor; } diff --git a/client/src/app/site/projector/components/projector-detail/projector-detail.component.html b/client/src/app/site/projector/components/projector-detail/projector-detail.component.html index 0fcd8a63d..6e3a7c3bd 100644 --- a/client/src/app/site/projector/components/projector-detail/projector-detail.component.html +++ b/client/src/app/site/projector/components/projector-detail/projector-detail.component.html @@ -169,8 +169,18 @@ <mat-icon>videocam</mat-icon> </button> + <!-- Slide title and subtitle --> <span class="ellipsis-overflow current-element-text"> {{ getSlideTitle(element) }} + <os-icon-container + class="subtitle-nocolor" + size="small" + icon="comment" + [noWrap]="true" + *ngIf="getSlideSubtitle(element)" + > + {{ getSlideSubtitle(element) }} + </os-icon-container> </span> <button type="button" mat-icon-button (click)="unprojectCurrent(element)"> @@ -207,8 +217,18 @@ <mat-icon>videocam</mat-icon> </button> </div> + <!-- Slide title ans subtitle --> <div class="name"> - <span>{{ getSlideTitle(element) }}</span> + <span class="ellipsis-overflow">{{ getSlideTitle(element) }}</span> + <os-icon-container + class="subtitle" + size="small" + icon="comment" + [noWrap]="true" + *ngIf="getSlideSubtitle(element)" + > + {{ getSlideSubtitle(element) }} + </os-icon-container> </div> <div class="button-right" *ngIf="editQueue"> <div> @@ -335,6 +355,7 @@ <ol> <li *ngFor="let elements of projector.elements_history"> {{ getSlideTitle(elements[0]) }} + {{ getSlideSubtitle(elements[0]) }} </li> </ol> </mat-expansion-panel> 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 dd457a4ee..cb5a4a2db 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 @@ -208,7 +208,11 @@ export class ProjectorDetailComponent extends BaseViewComponent implements OnIni } public getSlideTitle(element: ProjectorElement): string { - return this.projectorService.getSlideTitle(element); + return this.projectorService.getSlideTitle(element).title; + } + + public getSlideSubtitle(element: ProjectorElement): string | null { + return this.projectorService.getSlideTitle(element).subtitle; } public isProjected(obj: Projectable): boolean { diff --git a/client/src/app/slides/slide-manifest.ts b/client/src/app/slides/slide-manifest.ts index a8f6fc67e..f57650799 100644 --- a/client/src/app/slides/slide-manifest.ts +++ b/client/src/app/slides/slide-manifest.ts @@ -3,6 +3,7 @@ import { LoadChildrenCallback } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; +import { ProjectorTitle } from 'app/core/core-services/projector.service'; import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service'; import { IdentifiableProjectorElement, ProjectorElement } from 'app/shared/models/core/projector'; @@ -30,7 +31,7 @@ export interface SlideDynamicConfiguration { element: ProjectorElement, translate: TranslateService, viewModelStore: ViewModelStoreService - ) => string; + ) => ProjectorTitle; } /** diff --git a/client/src/assets/styles/global-components-style.scss b/client/src/assets/styles/global-components-style.scss index e657fdd85..cac868dfb 100644 --- a/client/src/assets/styles/global-components-style.scss +++ b/client/src/assets/styles/global-components-style.scss @@ -93,12 +93,16 @@ color: mat-color($foreground, secondary-text); } - .subtitle { - color: mat-color($foreground, secondary-text); + .subtitle-nocolor { font-size: 12px; font-weight: 400; } + .subtitle { + @extend .subtitle-nocolor; + color: mat-color($foreground, secondary-text); + } + .user-subtitle { color: mat-color($foreground, secondary-text); }