From 9c67b1c77311042239533ba53a46ade615843bc7 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Mon, 25 Feb 2019 14:36:04 +0100 Subject: [PATCH] sorting from inside base repositories Authors: FinnStutzenstein, MaximilianKrambach, tsiegleauq --- .../agenda/item-repository.service.ts | 13 ++-- .../agenda/topic-repository.service.ts | 6 +- .../assignment-repository.service.ts | 4 +- .../base-agenda-content-object-repository.ts | 13 +++- .../app/core/repositories/base-repository.ts | 78 +++++++++++++++---- .../common/chatmessage-repository.service.ts | 4 +- .../config/config-repository.service.ts | 6 +- .../history/history-repository.service.ts | 6 +- .../mediafile-repository.service.ts | 16 +++- .../motions/category-repository.service.ts | 55 ++++++------- ...hange-recommendation-repository.service.ts | 8 +- .../motion-block-repository.service.ts | 8 +- ...tion-comment-section-repository.service.ts | 8 +- .../motions/motion-repository.service.ts | 48 +++++++++++- .../statute-paragraph-repository.service.ts | 6 +- .../motions/workflow-repository.service.ts | 12 +-- .../projector/countdown-repository.service.ts | 6 +- .../projector-message-repository.service.ts | 6 +- .../projector/projector-repository.service.ts | 8 +- .../tags/tag-repository.service.ts | 6 +- .../users/group-repository.service.ts | 8 +- .../users/personal-note-repository.service.ts | 9 ++- .../users/user-repository.service.ts | 66 +++++++--------- .../ui-services/base-filter-list.service.ts | 2 +- .../ui-services/base-sort-list.service.ts | 44 ++++++----- .../list-of-speakers.component.ts | 7 +- .../src/app/site/agenda/models/view-item.ts | 8 +- client/src/app/site/base/list-view-base.ts | 10 ++- .../category-list/category-list.component.ts | 18 +---- .../motion-block-list.component.ts | 1 - .../motion-detail/motion-detail.component.ts | 17 +--- .../motion-export-dialog.component.ts | 2 +- .../motion-list/motion-list.component.ts | 2 +- .../services/motion-filter-list.service.ts | 2 +- .../services/motion-multiselect.service.ts | 22 ++++-- .../motions/services/motion-pdf.service.ts | 8 +- .../services/motion-sort-list.service.ts | 2 +- .../projector-list.component.html | 2 +- .../projector-list.component.ts | 1 + .../projector-message-list.component.ts | 2 +- .../user-detail/user-detail.component.ts | 2 +- .../user-list/user-list.component.ts | 3 +- .../users/services/user-sort-list.service.ts | 2 +- 43 files changed, 326 insertions(+), 231 deletions(-) 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 892f5503c..a9b5ec004 100644 --- a/client/src/app/core/repositories/agenda/item-repository.service.ts +++ b/client/src/app/core/repositories/agenda/item-repository.service.ts @@ -2,6 +2,8 @@ import { Injectable } from '@angular/core'; import { tap, map } from 'rxjs/operators'; import { Observable } from 'rxjs'; +import { TranslateService } from '@ngx-translate/core'; + import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository'; import { BaseRepository } from '../base-repository'; import { BaseAgendaViewModel } from 'app/site/base/base-agenda-view-model'; @@ -13,7 +15,6 @@ import { DataStoreService } from '../../core-services/data-store.service'; import { HttpService } from 'app/core/core-services/http.service'; import { Item } from 'app/shared/models/agenda/item'; import { OSTreeSortEvent } from 'app/shared/components/sorting-tree/sorting-tree.component'; -import { TranslateService } from '@ngx-translate/core'; import { TreeService } from 'app/core/ui-services/tree.service'; import { ViewItem } from 'app/site/agenda/models/view-item'; import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service'; @@ -39,15 +40,15 @@ export class ItemRepositoryService extends BaseRepository { */ public constructor( DS: DataStoreService, + dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, - protected dataSend: DataSendService, + translate: TranslateService, private httpService: HttpService, private config: ConfigService, - private treeService: TreeService, - private translate: TranslateService + private treeService: TreeService ) { - super(DS, dataSend, mapperService, viewModelStoreService, Item); + super(DS, dataSend, mapperService, viewModelStoreService, translate, Item); } public getVerboseName = (plural: boolean = false) => { @@ -85,7 +86,7 @@ export class ItemRepositoryService extends BaseRepository { const repo = this.collectionStringMapperService.getRepository( viewItem.item.content_object.collection ) as BaseAgendaContentObjectRepository; - return numberPrefix + repo.getAgendaTitleWithType(viewItem); + return numberPrefix + repo.getAgendaTitleWithType(viewItem.title_information); } }; viewItem.getListTitle = viewItem.getTitle; diff --git a/client/src/app/core/repositories/agenda/topic-repository.service.ts b/client/src/app/core/repositories/agenda/topic-repository.service.ts index 1f583fade..ece32b83d 100644 --- a/client/src/app/core/repositories/agenda/topic-repository.service.ts +++ b/client/src/app/core/repositories/agenda/topic-repository.service.ts @@ -30,12 +30,12 @@ export class TopicRepositoryService extends BaseAgendaContentObjectRepository | Partial) => { diff --git a/client/src/app/core/repositories/assignments/assignment-repository.service.ts b/client/src/app/core/repositories/assignments/assignment-repository.service.ts index 05d50f94b..a33cf4df6 100644 --- a/client/src/app/core/repositories/assignments/assignment-repository.service.ts +++ b/client/src/app/core/repositories/assignments/assignment-repository.service.ts @@ -36,9 +36,9 @@ export class AssignmentRepositoryService extends BaseAgendaContentObjectReposito dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, - private translate: TranslateService + translate: TranslateService ) { - super(DS, dataSend, mapperService, viewModelStoreService, Assignment, [User, Item, Tag]); + super(DS, dataSend, mapperService, viewModelStoreService, translate, Assignment, [User, Item, Tag]); } public getAgendaTitle = (assignment: Partial | Partial) => { diff --git a/client/src/app/core/repositories/base-agenda-content-object-repository.ts b/client/src/app/core/repositories/base-agenda-content-object-repository.ts index a2bf4de3b..affed5368 100644 --- a/client/src/app/core/repositories/base-agenda-content-object-repository.ts +++ b/client/src/app/core/repositories/base-agenda-content-object-repository.ts @@ -1,3 +1,5 @@ +import { TranslateService } from '@ngx-translate/core'; + import { BaseViewModel } from '../../site/base/base-view-model'; import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model'; import { CollectionStringMapperService } from '../core-services/collectionStringMapper.service'; @@ -25,9 +27,18 @@ export abstract class BaseAgendaContentObjectRepository< dataSend: DataSendService, collectionStringMapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, + translate: TranslateService, baseModelCtor: ModelConstructor, depsModelCtors?: ModelConstructor[] ) { - super(DS, dataSend, collectionStringMapperService, viewModelStoreService, baseModelCtor, depsModelCtors); + super( + DS, + dataSend, + collectionStringMapperService, + viewModelStoreService, + translate, + baseModelCtor, + depsModelCtors + ); } } diff --git a/client/src/app/core/repositories/base-repository.ts b/client/src/app/core/repositories/base-repository.ts index d10a52d43..9983af550 100644 --- a/client/src/app/core/repositories/base-repository.ts +++ b/client/src/app/core/repositories/base-repository.ts @@ -1,4 +1,5 @@ import { BehaviorSubject, Observable, Subject } from 'rxjs'; +import { TranslateService } from '@ngx-translate/core'; import { BaseViewModel } from '../../site/base/base-view-model'; import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model'; @@ -24,17 +25,35 @@ export abstract class BaseRepository } = {}; /** - * Observable subject for the whole list + * Observable subject for the whole list. These entries are unsorted an not piped through + * autodTime. Just use this internally. + * + * It's used to debounce messages on the sortedViewModelListSubject */ - protected readonly viewModelListSubject: BehaviorSubject = new BehaviorSubject([]); + private readonly viewModelListSubject: BehaviorSubject = new BehaviorSubject([]); - protected readonly viewModelListAuditSubject: BehaviorSubject = new BehaviorSubject([]); + /** + * Observable subject for the sorted view model list. + * + * All data is piped through an auditTime of 1ms. This is to prevent massive + * updates, if e.g. an autoupdate with a lot motions come in. The result is just one + * update of the new list instead of many unnecessary updates. + */ + protected readonly sortedViewModelListSubject: BehaviorSubject = new BehaviorSubject([]); /** * Observable subject for any changes of view models. */ protected readonly generalViewModelSubject: Subject = new Subject(); + /** + * Can be used by the sort functions. + */ + protected languageCollator: Intl.Collator; + + /** + * The collection string of the managed model. + */ private _collectionString: string; public get collectionString(): string { @@ -65,16 +84,28 @@ export abstract class BaseRepository, protected depsModelCtors?: ModelConstructor[] ) { this._collectionString = baseModelCtor.COLLECTIONSTRING; - this.getViewModelListObservable().subscribe(x => this.viewModelListAuditSubject.next(x)); + // All data is piped through an auditTime of 1ms. This is to prevent massive + // updates, if e.g. an autoupdate with a lot motions come in. The result is just one + // update of the new list instead of many unnecessary updates. + this.viewModelListSubject.pipe(auditTime(1)).subscribe(models => { + this.sortedViewModelListSubject.next(models.sort(this.viewModelSortFn)); + }); + + this.languageCollator = new Intl.Collator(this.translate.currentLang); } public onAfterAppsLoaded(): void { this.DS.clearObservable.subscribe(() => this.clear()); + this.translate.onLangChange.subscribe(change => { + this.languageCollator = new Intl.Collator(change.lang); + this.updateViewModelListObservable(); + }); // Populate the local viewModelStore with ViewModel Objects. this.DS.getAll(this.baseModelCtor).forEach((model: M) => { @@ -202,6 +233,19 @@ export abstract class BaseRepository number = (a: V, b: V) => a.id - b.id; + + /** + * Setter for a sort function. Updates the sorting. + * + * @param fn a sort function + */ + public setSortFunction(fn: (a: V, b: V) => number): void { + this.viewModelSortFn = fn; this.updateViewModelListObservable(); } @@ -213,14 +257,24 @@ export abstract class BaseRepository { if (!this.viewModelSubjects[id]) { @@ -230,14 +284,10 @@ export abstract class BaseRepository { - return this.viewModelListSubject.asObservable().pipe(auditTime(1)); + return this.sortedViewModelListSubject.asObservable(); } /** @@ -247,7 +297,7 @@ export abstract class BaseRepository { - return this.viewModelListAuditSubject; + return this.sortedViewModelListSubject; } /** @@ -268,7 +318,7 @@ export abstract class BaseRepository { diff --git a/client/src/app/core/repositories/config/config-repository.service.ts b/client/src/app/core/repositories/config/config-repository.service.ts index 4d420800a..1c13b6d8d 100644 --- a/client/src/app/core/repositories/config/config-repository.service.ts +++ b/client/src/app/core/repositories/config/config-repository.service.ts @@ -100,11 +100,11 @@ export class ConfigRepositoryService extends BaseRepository dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, + translate: TranslateService, private constantsService: ConstantsService, - private http: HttpService, - private translate: TranslateService + private http: HttpService ) { - super(DS, dataSend, mapperService, viewModelStoreService, Config); + super(DS, dataSend, mapperService, viewModelStoreService, translate, Config); this.constantsService.get('OpenSlidesConfigVariables').subscribe(constant => { this.createConfigStructure(constant); diff --git a/client/src/app/core/repositories/history/history-repository.service.ts b/client/src/app/core/repositories/history/history-repository.service.ts index d1348b8b6..e0c48a9d5 100644 --- a/client/src/app/core/repositories/history/history-repository.service.ts +++ b/client/src/app/core/repositories/history/history-repository.service.ts @@ -35,11 +35,11 @@ export class HistoryRepositoryService extends BaseRepository { diff --git a/client/src/app/core/repositories/mediafiles/mediafile-repository.service.ts b/client/src/app/core/repositories/mediafiles/mediafile-repository.service.ts index 90023e3da..4ef62e80c 100644 --- a/client/src/app/core/repositories/mediafiles/mediafile-repository.service.ts +++ b/client/src/app/core/repositories/mediafiles/mediafile-repository.service.ts @@ -32,11 +32,12 @@ export class MediafileRepositoryService extends BaseRepository { @@ -69,4 +70,13 @@ export class MediafileRepositoryService extends BaseRepository(restPath, file, {}, emptyHeader); } + + /** + * Sets the default sorting (e.g. in dropdowns and for new users) to 'title' + */ + private initSorting(): void { + this.setSortFunction((a: ViewMediafile, b: ViewMediafile) => { + return this.languageCollator.compare(a.title, b.title); + }); + } } diff --git a/client/src/app/core/repositories/motions/category-repository.service.ts b/client/src/app/core/repositories/motions/category-repository.service.ts index ec35abb6f..e3ff051fd 100644 --- a/client/src/app/core/repositories/motions/category-repository.service.ts +++ b/client/src/app/core/repositories/motions/category-repository.service.ts @@ -1,6 +1,5 @@ import { Injectable } from '@angular/core'; -import { BehaviorSubject, Observable } from 'rxjs'; import { TranslateService } from '@ngx-translate/core'; import { BaseRepository } from '../base-repository'; @@ -13,6 +12,8 @@ import { HttpService } from '../../core-services/http.service'; import { ViewCategory } from 'app/site/motions/models/view-category'; import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service'; +type SortProperty = 'prefix' | 'name'; + /** * Repository Services for Categories * @@ -27,6 +28,8 @@ import { ViewModelStoreService } from 'app/core/core-services/view-model-store.s providedIn: 'root' }) export class CategoryRepositoryService extends BaseRepository { + private sortProperty: SortProperty; + /** * Creates a CategoryRepository * Converts existing and incoming category to ViewCategories @@ -40,15 +43,21 @@ export class CategoryRepositoryService extends BaseRepository('motions_category_sorting').subscribe(conf => { + this.sortProperty = conf; + this.setConfigSortFn(); + }); } public getVerboseName = (plural: boolean = false) => { @@ -66,8 +75,7 @@ export class CategoryRepositoryService extends BaseRepository category.id === category_id); + return this.DS.find(Category, cat => cat.id === category_id); } /** @@ -81,36 +89,19 @@ export class CategoryRepositoryService extends BaseRepository { - const subject = new BehaviorSubject([]); - this.getViewModelListObservable().subscribe(categories => { - subject.next(this.sortViewCategoriesByConfig(categories)); - }); - return subject.asObservable(); - } - - /** - * Sort viewCategories by the configured settings - * - * @param categories - * @returns the categories sorted by prefix or name, according to the config setting - * - * TODO: That operation is HEAVY - */ - public sortViewCategoriesByConfig(categories: ViewCategory[]): ViewCategory[] { - const sort = this.configService.instant<'prefix' | 'name'>('motions_category_sorting') || 'prefix'; - return categories.sort((a, b) => { - if (a[sort] && b[sort]) { - return a[sort].localeCompare(b[sort], this.translate.currentLang); - } else if (sort === 'prefix') { + public setConfigSortFn(): void { + this.setSortFunction((a: ViewCategory, b: ViewCategory) => { + if (a[this.sortProperty] && b[this.sortProperty]) { + return this.languageCollator.compare(a[this.sortProperty], b[this.sortProperty]); + } else if (this.sortProperty === 'prefix') { if (a.prefix) { return 1; } else if (b.prefix) { return -1; } else { - return a.name.localeCompare(b.name); + return this.languageCollator.compare(a.name, b.name); } } }); diff --git a/client/src/app/core/repositories/motions/change-recommendation-repository.service.ts b/client/src/app/core/repositories/motions/change-recommendation-repository.service.ts index 4ba00800c..6ce31d080 100644 --- a/client/src/app/core/repositories/motions/change-recommendation-repository.service.ts +++ b/client/src/app/core/repositories/motions/change-recommendation-repository.service.ts @@ -45,12 +45,12 @@ export class ChangeRecommendationRepositoryService extends BaseRepository< */ public constructor( DS: DataStoreService, + dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, - protected dataSend: DataSendService, - private translate: TranslateService + translate: TranslateService ) { - super(DS, dataSend, mapperService, viewModelStoreService, MotionChangeRecommendation, [ + super(DS, dataSend, mapperService, viewModelStoreService, translate, MotionChangeRecommendation, [ Category, User, Workflow @@ -85,7 +85,7 @@ export class ChangeRecommendationRepositoryService extends BaseRepository< * return the Observable of all change recommendations belonging to the given motion */ public getChangeRecosOfMotionObservable(motion_id: number): Observable { - return this.viewModelListSubject.asObservable().pipe( + return this.getViewModelListObservable().pipe( map((recos: ViewMotionChangeRecommendation[]) => { return recos.filter(reco => reco.motion_id === motion_id); }) diff --git a/client/src/app/core/repositories/motions/motion-block-repository.service.ts b/client/src/app/core/repositories/motions/motion-block-repository.service.ts index 6df071b37..cd59c6acd 100644 --- a/client/src/app/core/repositories/motions/motion-block-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-block-repository.service.ts @@ -36,14 +36,14 @@ export class MotionBlockRepositoryService extends BaseAgendaContentObjectReposit */ public constructor( DS: DataStoreService, + dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, - protected dataSend: DataSendService, + translate: TranslateService, private motionRepo: MotionRepositoryService, - private httpService: HttpService, - private translate: TranslateService + private httpService: HttpService ) { - super(DS, dataSend, mapperService, viewModelStoreService, MotionBlock, [Item]); + super(DS, dataSend, mapperService, viewModelStoreService, translate, MotionBlock, [Item]); } public getAgendaTitle = (motionBlock: Partial | Partial) => { diff --git a/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts b/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts index 972a56389..c3b3b1bd9 100644 --- a/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts @@ -42,13 +42,13 @@ export class MotionCommentSectionRepositoryService extends BaseRepository< */ public constructor( DS: DataStoreService, + dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, - protected dataSend: DataSendService, - private http: HttpService, - private translate: TranslateService + translate: TranslateService, + private http: HttpService ) { - super(DS, dataSend, mapperService, viewModelStoreService, MotionCommentSection, [Group]); + super(DS, dataSend, mapperService, viewModelStoreService, translate, MotionCommentSection, [Group]); } public getVerboseName = (plural: boolean = false) => { 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 a4f7f1ecd..70d0ee029 100644 --- a/client/src/app/core/repositories/motions/motion-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-repository.service.ts @@ -7,6 +7,8 @@ import { tap, map } from 'rxjs/operators'; import { Category } from 'app/shared/models/motions/category'; import { ChangeRecoMode, ViewMotion } from 'app/site/motions/models/view-motion'; import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service'; +import { ConfigService } from 'app/core/ui-services/config.service'; + import { DataSendService } from '../../core-services/data-send.service'; import { DataStoreService } from '../../core-services/data-store.service'; import { DiffLinesInParagraph, DiffService, LineRange, ModificationType } from '../../ui-services/diff.service'; @@ -42,6 +44,8 @@ import { PersonalNote, PersonalNoteContent } from 'app/shared/models/users/perso import { ViewPersonalNote } from 'app/site/users/models/view-personal-note'; import { OperatorService } from 'app/core/core-services/operator.service'; +type SortProperty = 'callListWeight' | 'identifier'; + /** * Repository Services for motions (and potentially categories) * @@ -56,6 +60,11 @@ import { OperatorService } from 'app/core/core-services/operator.service'; providedIn: 'root' }) export class MotionRepositoryService extends BaseAgendaContentObjectRepository { + /** + * The property the incoming data is sorted by + */ + protected sortProperty: SortProperty; + /** * Creates a MotionRepository * @@ -68,20 +77,23 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository('motions_motions_sorting').subscribe(conf => { + this.sortProperty = conf; + this.setConfigSortFn(); + }); } public getTitle = (motion: Partial | Partial) => { @@ -839,4 +855,30 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository { + if (a[this.sortProperty] && b[this.sortProperty]) { + if (a[this.sortProperty] === b[this.sortProperty]) { + return this.languageCollator.compare(a.title, b.title); + } else { + if (this.sortProperty === 'callListWeight') { + // handling numerical values + return a.callListWeight - b.callListWeight; + } else { + return this.languageCollator.compare(a[this.sortProperty], b[this.sortProperty]); + } + } + } else if (a[this.sortProperty]) { + return -1; + } else if (b[this.sortProperty]) { + return 1; + } else { + return this.languageCollator.compare(a.title, b.title); + } + }); + } } diff --git a/client/src/app/core/repositories/motions/statute-paragraph-repository.service.ts b/client/src/app/core/repositories/motions/statute-paragraph-repository.service.ts index 17decebfd..af60d76e9 100644 --- a/client/src/app/core/repositories/motions/statute-paragraph-repository.service.ts +++ b/client/src/app/core/repositories/motions/statute-paragraph-repository.service.ts @@ -31,12 +31,12 @@ export class StatuteParagraphRepositoryService extends BaseRepository { diff --git a/client/src/app/core/repositories/motions/workflow-repository.service.ts b/client/src/app/core/repositories/motions/workflow-repository.service.ts index 27b1957e1..5c2a06daa 100644 --- a/client/src/app/core/repositories/motions/workflow-repository.service.ts +++ b/client/src/app/core/repositories/motions/workflow-repository.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@angular/core'; -import { auditTime } from 'rxjs/operators'; import { Workflow } from 'app/shared/models/motions/workflow'; import { ViewWorkflow } from 'app/site/motions/models/view-workflow'; @@ -43,14 +42,15 @@ export class WorkflowRepositoryService extends BaseRepository { + super(DS, dataSend, mapperService, viewModelStoreService, translate, Workflow); + + this.sortedViewModelListSubject.subscribe(models => { if (models && models.length > 0) { this.initSorting(models); } diff --git a/client/src/app/core/repositories/projector/countdown-repository.service.ts b/client/src/app/core/repositories/projector/countdown-repository.service.ts index 7885b521d..e8c96b80e 100644 --- a/client/src/app/core/repositories/projector/countdown-repository.service.ts +++ b/client/src/app/core/repositories/projector/countdown-repository.service.ts @@ -15,13 +15,13 @@ import { ServertimeService } from 'app/core/core-services/servertime.service'; export class CountdownRepositoryService extends BaseRepository { public constructor( DS: DataStoreService, + dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, - protected dataSend: DataSendService, - private translate: TranslateService, + translate: TranslateService, private servertimeService: ServertimeService ) { - super(DS, dataSend, mapperService, viewModelStoreService, Countdown); + super(DS, dataSend, mapperService, viewModelStoreService, translate, Countdown); } public getVerboseName = (plural: boolean = false) => { diff --git a/client/src/app/core/repositories/projector/projector-message-repository.service.ts b/client/src/app/core/repositories/projector/projector-message-repository.service.ts index f4f0edd5d..b957c7c8c 100644 --- a/client/src/app/core/repositories/projector/projector-message-repository.service.ts +++ b/client/src/app/core/repositories/projector/projector-message-repository.service.ts @@ -14,12 +14,12 @@ import { DataSendService } from 'app/core/core-services/data-send.service'; export class ProjectorMessageRepositoryService extends BaseRepository { public constructor( DS: DataStoreService, + dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, - protected dataSend: DataSendService, - private translate: TranslateService + translate: TranslateService ) { - super(DS, dataSend, mapperService, viewModelStoreService, ProjectorMessage); + super(DS, dataSend, mapperService, viewModelStoreService, translate, ProjectorMessage); } public getVerboseName = (plural: boolean = false) => { diff --git a/client/src/app/core/repositories/projector/projector-repository.service.ts b/client/src/app/core/repositories/projector/projector-repository.service.ts index 66f72ca74..4cfb999fa 100644 --- a/client/src/app/core/repositories/projector/projector-repository.service.ts +++ b/client/src/app/core/repositories/projector/projector-repository.service.ts @@ -37,13 +37,13 @@ export class ProjectorRepositoryService extends BaseRepository { diff --git a/client/src/app/core/repositories/tags/tag-repository.service.ts b/client/src/app/core/repositories/tags/tag-repository.service.ts index e82b57f82..3aea0acda 100644 --- a/client/src/app/core/repositories/tags/tag-repository.service.ts +++ b/client/src/app/core/repositories/tags/tag-repository.service.ts @@ -34,12 +34,12 @@ export class TagRepositoryService extends BaseRepository { */ public constructor( DS: DataStoreService, + dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, - protected dataSend: DataSendService, - private translate: TranslateService + translate: TranslateService ) { - super(DS, dataSend, mapperService, viewModelStoreService, Tag); + super(DS, dataSend, mapperService, viewModelStoreService, translate, Tag); } public getVerboseName = (plural: boolean = false) => { diff --git a/client/src/app/core/repositories/users/group-repository.service.ts b/client/src/app/core/repositories/users/group-repository.service.ts index 91a8dbc0b..ee02196ad 100644 --- a/client/src/app/core/repositories/users/group-repository.service.ts +++ b/client/src/app/core/repositories/users/group-repository.service.ts @@ -49,13 +49,13 @@ export class GroupRepositoryService extends BaseRepository { */ public constructor( DS: DataStoreService, + dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, - protected dataSend: DataSendService, - private constants: ConstantsService, - private translate: TranslateService + translate: TranslateService, + private constants: ConstantsService ) { - super(DS, dataSend, mapperService, viewModelStoreService, Group); + super(DS, dataSend, mapperService, viewModelStoreService, translate, Group); this.sortPermsPerApp(); } diff --git a/client/src/app/core/repositories/users/personal-note-repository.service.ts b/client/src/app/core/repositories/users/personal-note-repository.service.ts index e7d3be8c9..12714c593 100644 --- a/client/src/app/core/repositories/users/personal-note-repository.service.ts +++ b/client/src/app/core/repositories/users/personal-note-repository.service.ts @@ -1,13 +1,14 @@ import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +import { DataSendService } from 'app/core/core-services/data-send.service'; import { DataStoreService } from '../../core-services/data-store.service'; import { BaseRepository } from '../base-repository'; import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service'; import { PersonalNote } from 'app/shared/models/users/personal-note'; import { ViewPersonalNote } from 'app/site/users/models/view-personal-note'; import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service'; -import { TranslateService } from '@ngx-translate/core'; -import { DataSendService } from 'app/core/core-services/data-send.service'; /** */ @@ -24,9 +25,9 @@ export class PersonalNoteRepositoryService extends BaseRepository { diff --git a/client/src/app/core/repositories/users/user-repository.service.ts b/client/src/app/core/repositories/users/user-repository.service.ts index 815c8d157..5fe00916f 100644 --- a/client/src/app/core/repositories/users/user-repository.service.ts +++ b/client/src/app/core/repositories/users/user-repository.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Observable, BehaviorSubject } from 'rxjs'; + import { TranslateService } from '@ngx-translate/core'; import { BaseRepository } from '../base-repository'; @@ -22,6 +22,8 @@ import { ViewModelStoreService } from 'app/core/core-services/view-model-store.s */ type StringNamingSchema = 'lastCommaFirst' | 'firstSpaceLast'; +type SortProperty = 'first_name' | 'last_name' | 'number'; + /** * Repository service for users * @@ -31,23 +33,36 @@ type StringNamingSchema = 'lastCommaFirst' | 'firstSpaceLast'; providedIn: 'root' }) export class UserRepositoryService extends BaseRepository { + /** + * The property the incoming data is sorted by + */ + protected sortProperty: SortProperty; + /** * Constructor for the user repo * * @param DS The DataStore * @param mapperService Maps collection strings to classes * @param dataSend sending changed objects + * @param translate + * @param httpService + * @param configService */ public constructor( DS: DataStoreService, + dataSend: DataSendService, mapperService: CollectionStringMapperService, viewModelStoreService: ViewModelStoreService, - protected dataSend: DataSendService, - private translate: TranslateService, + translate: TranslateService, private httpService: HttpService, private configService: ConfigService ) { - super(DS, dataSend, mapperService, viewModelStoreService, User, [Group]); + super(DS, dataSend, mapperService, viewModelStoreService, translate, User, [Group]); + this.sortProperty = this.configService.instant('users_sort_by'); + this.configService.get('users_sort_by').subscribe(conf => { + this.sortProperty = conf; + this.setConfigSortFn(); + }); } public getVerboseName = (plural: boolean = false) => { @@ -219,7 +234,7 @@ export class UserRepositoryService extends BaseRepository { * Searches and returns Users by full name * * @param name - * @returns all users matching that name + * @returns all users matching that name (unsorted) */ public getUsersByName(name: string): ViewUser[] { return this.getViewModelList().filter(user => { @@ -301,43 +316,22 @@ export class UserRepositoryService extends BaseRepository { } /** - * @returns the observable for users sorted according to configuration - * - * TODO: This is leading to heavy operations + * Triggers an update for the sort function responsible for the default sorting of data items */ - public getSortedViewModelListObservable(): Observable { - const subject = new BehaviorSubject([]); - this.getViewModelListObservable().subscribe(users => { - subject.next(this.sortViewUsersByConfig(users)); - }); - return subject.asObservable(); - } - - /** - * Sort viewUsers by the configured settings - * - * @param users - * @returns the users sorted by first name, last name or number, according - * to the config setting. Fallthrough and identical cases will be sorted by - * 'short_name' - * - * TODO: That operation is HEAVY - */ - public sortViewUsersByConfig(users: ViewUser[]): ViewUser[] { - const sort = this.configService.instant<'first_name' | 'last_name' | 'number'>('users_sort_by') || 'last_name'; - return users.sort((a, b) => { - if (a[sort] && b[sort]) { - if (a[sort] === b[sort]) { - return a.short_name.localeCompare(b.short_name, this.translate.currentLang); + public setConfigSortFn(): void { + this.setSortFunction((a: ViewUser, b: ViewUser) => { + if (a[this.sortProperty] && b[this.sortProperty]) { + if (a[this.sortProperty] === b[this.sortProperty]) { + return this.languageCollator.compare(a.short_name, b.short_name); } else { - return a[sort].localeCompare(b[sort], this.translate.currentLang); + return this.languageCollator.compare(a[this.sortProperty], b[this.sortProperty]); } - } else if (a[sort] && !b[sort]) { + } else if (a[this.sortProperty] && !b[this.sortProperty]) { return -1; - } else if (b[sort]) { + } else if (b[this.sortProperty]) { return 1; } else { - return a.short_name.localeCompare(b.short_name); + return this.languageCollator.compare(a.short_name, b.short_name); } }); } diff --git a/client/src/app/core/ui-services/base-filter-list.service.ts b/client/src/app/core/ui-services/base-filter-list.service.ts index c5019180c..0f3d67d73 100644 --- a/client/src/app/core/ui-services/base-filter-list.service.ts +++ b/client/src/app/core/ui-services/base-filter-list.service.ts @@ -118,7 +118,7 @@ export abstract class BaseFilterListService { this.repo .getViewModelListObservable() - .pipe(auditTime(100)) + .pipe(auditTime(10)) .subscribe(data => { this.currentRawData = data; this.filteredData = this.filterData(data); diff --git a/client/src/app/core/ui-services/base-sort-list.service.ts b/client/src/app/core/ui-services/base-sort-list.service.ts index e57f1bc3d..e20fcf9d1 100644 --- a/client/src/app/core/ui-services/base-sort-list.service.ts +++ b/client/src/app/core/ui-services/base-sort-list.service.ts @@ -50,6 +50,11 @@ export abstract class BaseSortListService { */ private sortFn: (a: V, b: V) => number; + /** + * default sorting to use if the client was not initialized before + */ + protected defaultSorting: keyof V = 'id'; + /** * Constructor. Does nothing. TranslateService is used for localeCompeare. */ @@ -113,7 +118,7 @@ export abstract class BaseSortListService { * get the property of the viewModel the sorting is based on. */ public get sortProperty(): string { - return this.sortOptions.sortProperty as string; + return this.sortOptions ? (this.sortOptions.sortProperty as string) : ''; } public get isActive(): boolean { @@ -138,7 +143,7 @@ export abstract class BaseSortListService { * @param option */ public getSortIcon(option: OsSortingItem): string { - if (this.sortProperty !== (option.property as string)) { + if (!this.sortProperty || this.sortProperty !== (option.property as string)) { return ''; } return this.ascending ? 'arrow_downward' : 'arrow_upward'; @@ -156,20 +161,21 @@ export abstract class BaseSortListService { * Retrieve the currently saved sorting definition from the borwser's * store */ - private loadStorageDefinition(): void { - const me = this; - this.store.get('sorting_' + this.name).then(function(sorting: OsSortingDefinition | null): void { - if (sorting) { - if (sorting.sortProperty) { - me.sortOptions.sortProperty = sorting.sortProperty; - if (sorting.sortAscending !== undefined) { - me.sortOptions.sortAscending = sorting.sortAscending; - } + private async loadStorageDefinition(): Promise { + const sorting: OsSortingDefinition | null = await this.store.get('sorting_' + this.name); + if (sorting) { + if (sorting.sortProperty) { + this.sortOptions.sortProperty = sorting.sortProperty; + if (sorting.sortAscending !== undefined) { + this.sortOptions.sortAscending = sorting.sortAscending; } } - me.updateSortFn(); - me.doAsyncSorting(); - }); + } else { + this.sortOptions.sortProperty = this.defaultSorting; + this.sortOptions.sortAscending = true; + } + this.updateSortFn(); + this.doAsyncSorting(); } /** @@ -197,10 +203,10 @@ export abstract class BaseSortListService { * Recreates the sorting function. Is supposed to be called on init and * every time the sorting (property, ascending/descending) or the language changes */ - private updateSortFn(): void { + protected updateSortFn(): void { const property = this.sortProperty as string; const ascending = this.ascending; - const lang = this.translate.currentLang; // TODO: observe and update sorting on change + const intl = new Intl.Collator(this.translate.currentLang); // TODO: observe and update sorting on language change this.sortFn = function(itemA: V, itemB: V): number { const firstProperty = ascending ? itemA[property] : itemB[property]; @@ -234,16 +240,16 @@ export abstract class BaseSortListService { if (!firstProperty) { return 1; } - return firstProperty.localeCompare(secondProperty, lang); + return intl.compare(firstProperty, secondProperty); case 'function': const a = firstProperty(); const b = secondProperty(); - return a.localeCompare(b, lang); + return intl.compare(a, b); case 'object': if (firstProperty instanceof Date) { return firstProperty > secondProperty ? 1 : -1; } else { - return firstProperty.toString().localeCompare(secondProperty.toString(), lang); + return intl.compare(firstProperty.toString(), secondProperty.toString()); } case 'undefined': return 1; 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 1e21c66ff..ccf7e6313 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 @@ -140,7 +140,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit this.addSpeakerForm = new FormGroup({ user_id: new FormControl([]) }); if (this.currentListOfSpeakers) { - this.projectors = projectorRepo.getViewModelList(); + this.projectors = projectorRepo.getSortedViewModelList(); this.updateClosProjector(); projectorRepo.getViewModelListObservable().subscribe(newProjectors => { this.projectors = newProjectors; @@ -160,11 +160,6 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit public ngOnInit(): void { // load and observe users this.users = this.userRepository.getViewModelListBehaviorSubject(); - this.userRepository.getViewModelListBehaviorSubject().subscribe(newUsers => { - if (this.viewItem) { - this.setSpeakerList(this.viewItem.id); - } - }); // detect changes in the form this.addSpeakerForm.valueChanges.subscribe(formResult => { diff --git a/client/src/app/site/agenda/models/view-item.ts b/client/src/app/site/agenda/models/view-item.ts index 552878bbe..dc35acf14 100644 --- a/client/src/app/site/agenda/models/view-item.ts +++ b/client/src/app/site/agenda/models/view-item.ts @@ -13,13 +13,13 @@ export class ViewItem extends BaseViewModel { /** * virtual weight defined by the order in the agenda tree, representing a shortcut to sorting by * weight, parent_id and the parents' weight(s) - * TODO will be accurate if the viewMotion is observed via {@link getViewModelListObservable}, else, it will be undefined + * TODO will be accurate if the viewMotion is observed via {@link getSortedViewModelListObservable}, else, it will be undefined */ public agendaListWeight: number; /** * The amount of parents in the agenda list tree. - * TODO will be accurate if the viewMotion is observed via {@link getViewModelListObservable}, else, it will be undefined + * TODO will be accurate if the viewMotion is observed via {@link getSortedViewModelListObservable}, else, it will be undefined */ public agendaListLevel: number; @@ -39,6 +39,10 @@ export class ViewItem extends BaseViewModel { return this.item.item_number; } + public get title_information(): object { + return this.item.title_information; + } + public get duration(): number { return this.item.duration; } diff --git a/client/src/app/site/base/list-view-base.ts b/client/src/app/site/base/list-view-base.ts index 61e23c7e8..b3a78e67b 100644 --- a/client/src/app/site/base/list-view-base.ts +++ b/client/src/app/site/base/list-view-base.ts @@ -98,9 +98,13 @@ export abstract class ListViewBaseComponent (this.sortService.data = filteredData)) - ); + if (this.sortService) { + this.subscriptions.push( + this.filterService.filter().subscribe(filteredData => (this.sortService.data = filteredData)) + ); + } else { + this.filterService.filter().subscribe(filteredData => (this.dataSource.data = filteredData)); + } } /** diff --git a/client/src/app/site/motions/modules/category/components/category-list/category-list.component.ts b/client/src/app/site/motions/modules/category/components/category-list/category-list.component.ts index 396475709..6a9bbfe3a 100644 --- a/client/src/app/site/motions/modules/category/components/category-list/category-list.component.ts +++ b/client/src/app/site/motions/modules/category/components/category-list/category-list.component.ts @@ -101,7 +101,7 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit { */ public ngOnInit(): void { super.setTitle('Category'); - this.repo.getSortedViewModelListObservable().subscribe(newViewCategories => { + this.repo.getViewModelListObservable().subscribe(newViewCategories => { this.categories = newViewCategories; }); } @@ -187,21 +187,7 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit { * @returns all motions in the category */ public motionsInCategory(category: Category): ViewMotion[] { - const coll = new Intl.Collator(this.translate.currentLang); - return this.motionRepo - .getViewModelList() - .filter(m => m.category_id === category.id) - .sort((motion1, motion2) => { - if (motion1.identifier && motion2.identifier) { - return coll.compare(motion1.identifier, motion2.identifier); - } else if (motion1.identifier) { - return 1; - } else if (motion2.identifier) { - return -1; - } else { - return coll.compare(motion1.getTitle(), motion2.getTitle()); - } - }); + return this.motionRepo.getSortedViewModelList().filter(m => m.category_id === category.id); } /** diff --git a/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.ts b/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.ts index 1dcf2f49a..71f6e0257 100644 --- a/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.ts +++ b/client/src/app/site/motions/modules/motion-block/components/motion-block-list/motion-block-list.component.ts @@ -107,7 +107,6 @@ export class MotionBlockListComponent extends ListViewBaseComponent { newMotionblocks.sort((a, b) => (a > b ? 1 : -1)); this.dataSource.data = newMotionblocks; diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts index 572fa4fbe..bbc20fa63 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts @@ -18,6 +18,7 @@ import { itemVisibilityChoices } from 'app/shared/models/agenda/item'; import { LinenumberingService } from 'app/core/ui-services/linenumbering.service'; import { LocalPermissionsService } from 'app/site/motions/services/local-permissions.service'; import { Mediafile } from 'app/shared/models/mediafiles/mediafile'; +import { MediafileRepositoryService } from 'app/core/repositories/mediafiles/mediafile-repository.service'; import { Motion } from 'app/shared/models/motions/motion'; import { MotionChangeRecommendationComponentData, @@ -49,7 +50,6 @@ import { ViewStatuteParagraph } from 'app/site/motions/models/view-statute-parag import { ViewTag } from 'app/site/tags/models/view-tag'; import { ViewUnifiedChange } from 'app/shared/models/motions/view-unified-change'; import { TagRepositoryService } from 'app/core/repositories/tags/tag-repository.service'; -import { MediafileRepositoryService } from 'app/core/repositories/mediafiles/mediafile-repository.service'; import { WorkflowRepositoryService } from 'app/core/repositories/motions/workflow-repository.service'; import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-repository.service'; @@ -368,6 +368,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, * @param agendaRepo Read out agenda variables * @param changeRecoRepo Change Recommendation Repository * @param statuteRepo: Statute Paragraph Repository + * @param mediafileRepo Mediafile Repository * @param DS The DataStoreService * @param configService The configuration provider * @param sanitizer For making HTML SafeHTML @@ -863,7 +864,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, const content = this.motion.getTitle(); if (await this.promptService.open(title, content)) { await this.repo.delete(this.motion); - this.router.navigate(['./motions/']); + this.router.navigate(['../motions/']); } } @@ -1112,18 +1113,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, * then appending motion without identifiers sorted by title */ public setSurroundingMotions(): void { - // TODO: that operation is HEAVY - this.motionObserver.value.sort((a, b) => { - if (a.identifier && b.identifier) { - return a.identifier.localeCompare(b.identifier, this.translate.currentLang); - } else if (a.identifier) { - return 1; - } else if (b.identifier) { - return -1; - } else { - return a.title.localeCompare(b.title, this.translate.currentLang); - } - }); const indexOfCurrent = this.motionObserver.value.findIndex(motion => { return motion === this.motion; }); diff --git a/client/src/app/site/motions/modules/motion-list/components/motion-export-dialog/motion-export-dialog.component.ts b/client/src/app/site/motions/modules/motion-list/components/motion-export-dialog/motion-export-dialog.component.ts index 7d0fcefe0..49c7093ec 100644 --- a/client/src/app/site/motions/modules/motion-list/components/motion-export-dialog/motion-export-dialog.component.ts +++ b/client/src/app/site/motions/modules/motion-list/components/motion-export-dialog/motion-export-dialog.component.ts @@ -61,7 +61,7 @@ export class MotionExportDialogComponent implements OnInit { * @returns a list of availavble commentSections */ public get commentsToExport(): ViewMotionCommentSection[] { - return this.commentRepo.getViewModelList(); + return this.commentRepo.getSortedViewModelList(); } /** * Hold the default lnMode. Will be set by the constructor. diff --git a/client/src/app/site/motions/modules/motion-list/components/motion-list/motion-list.component.ts b/client/src/app/site/motions/modules/motion-list/components/motion-list/motion-list.component.ts index 56410ba10..47c089492 100644 --- a/client/src/app/site/motions/modules/motion-list/components/motion-list/motion-list.component.ts +++ b/client/src/app/site/motions/modules/motion-list/components/motion-list/motion-list.component.ts @@ -128,7 +128,7 @@ export class MotionListComponent extends ListViewBaseComponent('motions_recommendations_by') .subscribe(recommender => (this.recomendationEnabled = !!recommender)); this.motionBlockRepo.getViewModelListObservable().subscribe(mBs => (this.motionBlocks = mBs)); - this.categoryRepo.getSortedViewModelListObservable().subscribe(cats => (this.categories = cats)); + this.categoryRepo.getViewModelListObservable().subscribe(cats => (this.categories = cats)); this.tagRepo.getViewModelListObservable().subscribe(tags => (this.tags = tags)); this.workflowRepo.getViewModelListObservable().subscribe(wfs => (this.workflows = wfs)); this.setFulltextFilter(); diff --git a/client/src/app/site/motions/services/motion-filter-list.service.ts b/client/src/app/site/motions/services/motion-filter-list.service.ts index 600c81e9e..a992b9bf9 100644 --- a/client/src/app/site/motions/services/motion-filter-list.service.ts +++ b/client/src/app/site/motions/services/motion-filter-list.service.ts @@ -182,7 +182,7 @@ export class MotionFilterListService extends BaseFilterListService { + this.categoryRepo.getViewModelListObservable().subscribe(categories => { const categoryOptions: OsFilterOptions = categories.map(cat => ({ condition: cat.id, label: cat.prefixedName, diff --git a/client/src/app/site/motions/services/motion-multiselect.service.ts b/client/src/app/site/motions/services/motion-multiselect.service.ts index ca3be00fc..0d5c59233 100644 --- a/client/src/app/site/motions/services/motion-multiselect.service.ts +++ b/client/src/app/site/motions/services/motion-multiselect.service.ts @@ -74,7 +74,7 @@ export class MotionMultiselectService { */ public async moveToItem(motions: ViewMotion[]): Promise { const title = this.translate.instant('This will move all selected motions as childs to:'); - const choices: (Displayable & Identifiable)[] = this.agendaRepo.getViewModelList(); + const choices: (Displayable & Identifiable)[] = this.agendaRepo.getSortedViewModelList(); const selectedChoice = await this.choiceService.open(title, choices); if (selectedChoice) { const requestData = { @@ -139,7 +139,7 @@ export class MotionMultiselectService { const clearChoice = this.translate.instant('No category'); const selectedChoice = await this.choiceService.open( title, - this.categoryRepo.sortViewCategoriesByConfig(this.categoryRepo.getViewModelList()), + this.categoryRepo.getSortedViewModelList(), false, null, clearChoice @@ -164,7 +164,12 @@ export class MotionMultiselectService { 'This will add or remove the following submitters for all selected motions:' ); const choices = [this.translate.instant('Add'), this.translate.instant('Remove')]; - const selectedChoice = await this.choiceService.open(title, this.userRepo.getViewModelList(), true, choices); + const selectedChoice = await this.choiceService.open( + title, + this.userRepo.getSortedViewModelList(), + true, + choices + ); if (selectedChoice && selectedChoice.action === choices[0]) { const requestData = motions.map(motion => { let submitterIds = [...motion.sorted_submitters_id, ...(selectedChoice.items as number[])]; @@ -200,7 +205,12 @@ export class MotionMultiselectService { this.translate.instant('Remove'), this.translate.instant('Clear tags') ]; - const selectedChoice = await this.choiceService.open(title, this.tagRepo.getViewModelList(), true, choices); + const selectedChoice = await this.choiceService.open( + title, + this.tagRepo.getSortedViewModelList(), + true, + choices + ); if (selectedChoice && selectedChoice.action === choices[0]) { const requestData = motions.map(motion => { let tagIds = [...motion.tags_id, ...(selectedChoice.items as number[])]; @@ -242,7 +252,7 @@ export class MotionMultiselectService { const clearChoice = this.translate.instant('Clear motion block'); const selectedChoice = await this.choiceService.open( title, - this.motionBlockRepo.getViewModelList(), + this.motionBlockRepo.getSortedViewModelList(), false, null, clearChoice @@ -280,7 +290,7 @@ export class MotionMultiselectService { // insert after chosen const olderSibling = this.repo.getViewModel(selectedChoice.items as number); const parentId = olderSibling ? olderSibling.sort_parent_id : null; - const siblings = this.repo.getViewModelList().filter(motion => motion.sort_parent_id === parentId); + const siblings = allMotions.filter(motion => motion.sort_parent_id === parentId); const idx = siblings.findIndex(sib => sib.id === olderSibling.id); const before = siblings.slice(0, idx + 1); const after = siblings.slice(idx + 1); diff --git a/client/src/app/site/motions/services/motion-pdf.service.ts b/client/src/app/site/motions/services/motion-pdf.service.ts index 4c45738d3..4f62ecb0f 100644 --- a/client/src/app/site/motions/services/motion-pdf.service.ts +++ b/client/src/app/site/motions/services/motion-pdf.service.ts @@ -48,7 +48,7 @@ export class MotionPdfService { * * @param translate handle translations * @param motionRepo get parent motions - * @param statureRepo To get formated stature paragraphs + * @param statuteRepo To get formated stature paragraphs * @param changeRecoRepo to get the change recommendations * @param configService Read config variables * @param htmlToPdfService To convert HTML text into pdfmake doc def @@ -59,7 +59,7 @@ export class MotionPdfService { public constructor( private translate: TranslateService, private motionRepo: MotionRepositoryService, - private statureRepo: StatuteParagraphRepositoryService, + private statuteRepo: StatuteParagraphRepositoryService, private changeRecoRepo: ChangeRecommendationRepositoryService, private configService: ConfigService, private htmlToPdfService: HtmlToPdfService, @@ -123,7 +123,7 @@ export class MotionPdfService { } if (infoToExport && infoToExport.includes('allcomments')) { - commentsToExport = this.commentRepo.getViewModelList().map(vm => vm.id); + commentsToExport = this.commentRepo.getSortedViewModelList().map(vm => vm.id); } if (commentsToExport) { motionPdfContent.push(this.createComments(motion, commentsToExport)); @@ -495,7 +495,7 @@ export class MotionPdfService { } } else if (motion.isStatuteAmendment()) { // statute amendments - const statutes = this.statureRepo.getViewModelList(); + const statutes = this.statuteRepo.getViewModelList(); motionText = this.motionRepo.formatStatuteAmendment(statutes, motion, lineLength); } else { // lead motion or normal amendments diff --git a/client/src/app/site/motions/services/motion-sort-list.service.ts b/client/src/app/site/motions/services/motion-sort-list.service.ts index 082e8c4a7..c65c6f80d 100644 --- a/client/src/app/site/motions/services/motion-sort-list.service.ts +++ b/client/src/app/site/motions/services/motion-sort-list.service.ts @@ -37,6 +37,6 @@ export class MotionSortListService extends BaseSortListService { */ public constructor(translate: TranslateService, store: StorageService, config: ConfigService) { super(translate, store); - this.sortOptions.sortProperty = config.instant('motions_motions_sorting'); + this.defaultSorting = config.instant('motions_motions_sorting'); } } diff --git a/client/src/app/site/projector/components/projector-list/projector-list.component.html b/client/src/app/site/projector/components/projector-list/projector-list.component.html index 4b4468192..e9ba048c1 100644 --- a/client/src/app/site/projector/components/projector-list/projector-list.component.html +++ b/client/src/app/site/projector/components/projector-list/projector-list.component.html @@ -19,7 +19,7 @@ Reference projector for current list of speakers:   - + {{ projector.getTitle() | translate }} diff --git a/client/src/app/site/projector/components/projector-list/projector-list.component.ts b/client/src/app/site/projector/components/projector-list/projector-list.component.ts index 6a062d766..a98a951a4 100644 --- a/client/src/app/site/projector/components/projector-list/projector-list.component.ts +++ b/client/src/app/site/projector/components/projector-list/projector-list.component.ts @@ -120,6 +120,7 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit */ public ngOnInit(): void { super.setTitle('Projectors'); + this.projectors = this.repo.getViewModelList(); this.repo.getViewModelListObservable().subscribe(projectors => (this.projectors = projectors)); } diff --git a/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.ts b/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.ts index ece5642b5..043b895ac 100644 --- a/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.ts +++ b/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.ts @@ -64,7 +64,7 @@ export class ProjectorMessageListComponent extends BaseViewComponent implements */ public ngOnInit(): void { super.setTitle('Messages'); - this.messages = this.repo.getViewModelList(); + this.messages = this.repo.getSortedViewModelList(); this.repo.getViewModelListObservable().subscribe(messages => (this.messages = messages)); } diff --git a/client/src/app/site/users/components/user-detail/user-detail.component.ts b/client/src/app/site/users/components/user-detail/user-detail.component.ts index c843904f9..75be902ad 100644 --- a/client/src/app/site/users/components/user-detail/user-detail.component.ts +++ b/client/src/app/site/users/components/user-detail/user-detail.component.ts @@ -139,7 +139,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit { } this.createForm(); - this.groups = this.groupRepo.getViewModelList().filter(group => group.id !== 1); + this.groups = this.groupRepo.getSortedViewModelList().filter(group => group.id !== 1); this.groupRepo .getViewModelListObservable() .subscribe(groups => (this.groups = groups.filter(group => group.id !== 1))); diff --git a/client/src/app/site/users/components/user-list/user-list.component.ts b/client/src/app/site/users/components/user-list/user-list.component.ts index 27fac538f..f9c486eb7 100644 --- a/client/src/app/site/users/components/user-list/user-list.component.ts +++ b/client/src/app/site/users/components/user-list/user-list.component.ts @@ -167,7 +167,8 @@ export class UserListComponent extends ListViewBaseComponent imp this.setFulltextFilter(); // Initialize the groups - this.groups = this.groupRepo.getViewModelList().filter(group => group.id !== 1); + this.groups = this.groupRepo.getSortedViewModelList().filter(group => group.id !== 1); + this.groupRepo.getViewModelListObservable().subscribe(groups => (this.groups = groups)); } /** diff --git a/client/src/app/site/users/services/user-sort-list.service.ts b/client/src/app/site/users/services/user-sort-list.service.ts index 0fafcbf57..33b759340 100644 --- a/client/src/app/site/users/services/user-sort-list.service.ts +++ b/client/src/app/site/users/services/user-sort-list.service.ts @@ -36,6 +36,6 @@ export class UserSortListService extends BaseSortListService { */ public constructor(translate: TranslateService, store: StorageService, config: ConfigService) { super(translate, store); - this.sortOptions.sortProperty = config.instant('motions_motions_sorting'); + this.defaultSorting = config.instant('users_sort_by'); } }