Merge pull request #4411 from MaximilianKrambach/sort_alternative
fix sort performance issues for dropdowns
This commit is contained in:
commit
398ffc30ea
@ -2,6 +2,8 @@ import { Injectable } from '@angular/core';
|
|||||||
import { tap, map } from 'rxjs/operators';
|
import { tap, map } from 'rxjs/operators';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
import { BaseAgendaContentObjectRepository } from '../base-agenda-content-object-repository';
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { BaseAgendaViewModel } from 'app/site/base/base-agenda-view-model';
|
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 { HttpService } from 'app/core/core-services/http.service';
|
||||||
import { Item } from 'app/shared/models/agenda/item';
|
import { Item } from 'app/shared/models/agenda/item';
|
||||||
import { OSTreeSortEvent } from 'app/shared/components/sorting-tree/sorting-tree.component';
|
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 { TreeService } from 'app/core/ui-services/tree.service';
|
||||||
import { ViewItem } from 'app/site/agenda/models/view-item';
|
import { ViewItem } from 'app/site/agenda/models/view-item';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
@ -39,15 +40,15 @@ export class ItemRepositoryService extends BaseRepository<ViewItem, Item> {
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService,
|
||||||
private httpService: HttpService,
|
private httpService: HttpService,
|
||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
private treeService: TreeService,
|
private treeService: TreeService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Item);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
@ -85,7 +86,7 @@ export class ItemRepositoryService extends BaseRepository<ViewItem, Item> {
|
|||||||
const repo = this.collectionStringMapperService.getRepository(
|
const repo = this.collectionStringMapperService.getRepository(
|
||||||
viewItem.item.content_object.collection
|
viewItem.item.content_object.collection
|
||||||
) as BaseAgendaContentObjectRepository<any, any>;
|
) as BaseAgendaContentObjectRepository<any, any>;
|
||||||
return numberPrefix + repo.getAgendaTitleWithType(viewItem);
|
return numberPrefix + repo.getAgendaTitleWithType(viewItem.title_information);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
viewItem.getListTitle = viewItem.getTitle;
|
viewItem.getListTitle = viewItem.getTitle;
|
||||||
|
@ -30,12 +30,12 @@ export class TopicRepositoryService extends BaseAgendaContentObjectRepository<Vi
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Topic, [Mediafile, Item]);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Topic, [Mediafile, Item]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAgendaTitle = (topic: Partial<Topic> | Partial<ViewTopic>) => {
|
public getAgendaTitle = (topic: Partial<Topic> | Partial<ViewTopic>) => {
|
||||||
|
@ -36,9 +36,9 @@ export class AssignmentRepositoryService extends BaseAgendaContentObjectReposito
|
|||||||
dataSend: DataSendService,
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
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<Assignment> | Partial<ViewAssignment>) => {
|
public getAgendaTitle = (assignment: Partial<Assignment> | Partial<ViewAssignment>) => {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseViewModel } from '../../site/base/base-view-model';
|
import { BaseViewModel } from '../../site/base/base-view-model';
|
||||||
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
|
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
|
||||||
import { CollectionStringMapperService } from '../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../core-services/collectionStringMapper.service';
|
||||||
@ -25,9 +27,18 @@ export abstract class BaseAgendaContentObjectRepository<
|
|||||||
dataSend: DataSendService,
|
dataSend: DataSendService,
|
||||||
collectionStringMapperService: CollectionStringMapperService,
|
collectionStringMapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
|
translate: TranslateService,
|
||||||
baseModelCtor: ModelConstructor<M>,
|
baseModelCtor: ModelConstructor<M>,
|
||||||
depsModelCtors?: ModelConstructor<BaseModel>[]
|
depsModelCtors?: ModelConstructor<BaseModel>[]
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, collectionStringMapperService, viewModelStoreService, baseModelCtor, depsModelCtors);
|
super(
|
||||||
|
DS,
|
||||||
|
dataSend,
|
||||||
|
collectionStringMapperService,
|
||||||
|
viewModelStoreService,
|
||||||
|
translate,
|
||||||
|
baseModelCtor,
|
||||||
|
depsModelCtors
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseViewModel } from '../../site/base/base-view-model';
|
import { BaseViewModel } from '../../site/base/base-view-model';
|
||||||
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
|
import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
|
||||||
@ -24,17 +25,35 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
|||||||
protected viewModelSubjects: { [modelId: number]: BehaviorSubject<V> } = {};
|
protected viewModelSubjects: { [modelId: number]: BehaviorSubject<V> } = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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<V[]> = new BehaviorSubject<V[]>([]);
|
private readonly viewModelListSubject: BehaviorSubject<V[]> = new BehaviorSubject<V[]>([]);
|
||||||
|
|
||||||
protected readonly viewModelListAuditSubject: BehaviorSubject<V[]> = new BehaviorSubject<V[]>([]);
|
/**
|
||||||
|
* 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<V[]> = new BehaviorSubject<V[]>([]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observable subject for any changes of view models.
|
* Observable subject for any changes of view models.
|
||||||
*/
|
*/
|
||||||
protected readonly generalViewModelSubject: Subject<V> = new Subject<V>();
|
protected readonly generalViewModelSubject: Subject<V> = new Subject<V>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used by the sort functions.
|
||||||
|
*/
|
||||||
|
protected languageCollator: Intl.Collator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The collection string of the managed model.
|
||||||
|
*/
|
||||||
private _collectionString: string;
|
private _collectionString: string;
|
||||||
|
|
||||||
public get collectionString(): string {
|
public get collectionString(): string {
|
||||||
@ -65,16 +84,28 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
|||||||
protected dataSend: DataSendService,
|
protected dataSend: DataSendService,
|
||||||
protected collectionStringMapperService: CollectionStringMapperService,
|
protected collectionStringMapperService: CollectionStringMapperService,
|
||||||
protected viewModelStoreService: ViewModelStoreService,
|
protected viewModelStoreService: ViewModelStoreService,
|
||||||
|
protected translate: TranslateService,
|
||||||
protected baseModelCtor: ModelConstructor<M>,
|
protected baseModelCtor: ModelConstructor<M>,
|
||||||
protected depsModelCtors?: ModelConstructor<BaseModel>[]
|
protected depsModelCtors?: ModelConstructor<BaseModel>[]
|
||||||
) {
|
) {
|
||||||
this._collectionString = baseModelCtor.COLLECTIONSTRING;
|
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 {
|
public onAfterAppsLoaded(): void {
|
||||||
this.DS.clearObservable.subscribe(() => this.clear());
|
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.
|
// Populate the local viewModelStore with ViewModel Objects.
|
||||||
this.DS.getAll(this.baseModelCtor).forEach((model: M) => {
|
this.DS.getAll(this.baseModelCtor).forEach((model: M) => {
|
||||||
@ -202,6 +233,19 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
|||||||
*/
|
*/
|
||||||
protected clear(): void {
|
protected clear(): void {
|
||||||
this.viewModelStore = {};
|
this.viewModelStore = {};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The function used for sorting the data of this repository. The defualt sorts by ID.
|
||||||
|
*/
|
||||||
|
protected viewModelSortFn: (a: V, b: V) => 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();
|
this.updateViewModelListObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,14 +257,24 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* helper function to return the viewModel as array
|
* @returns all view models stored in this repository. Sorting is not guaranteed
|
||||||
*/
|
*/
|
||||||
public getViewModelList(): V[] {
|
public getViewModelList(): V[] {
|
||||||
return Object.values(this.viewModelStore);
|
return Object.values(this.viewModelStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the current observable for one viewModel
|
* Get a sorted ViewModelList. This passes through a (1ms short) delay,
|
||||||
|
* thus may not be accurate, especially on application loading.
|
||||||
|
*
|
||||||
|
* @returns all sorted view models stored in this repository.
|
||||||
|
*/
|
||||||
|
public getSortedViewModelList(): V[] {
|
||||||
|
return this.sortedViewModelListSubject.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the current observable for one viewModel
|
||||||
*/
|
*/
|
||||||
public getViewModelObservable(id: number): Observable<V> {
|
public getViewModelObservable(id: number): Observable<V> {
|
||||||
if (!this.viewModelSubjects[id]) {
|
if (!this.viewModelSubjects[id]) {
|
||||||
@ -230,14 +284,10 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the Observable of the whole store.
|
* @returns the (sorted) Observable of the whole store.
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
public getViewModelListObservable(): Observable<V[]> {
|
public getViewModelListObservable(): Observable<V[]> {
|
||||||
return this.viewModelListSubject.asObservable().pipe(auditTime(1));
|
return this.sortedViewModelListSubject.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -247,7 +297,7 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
|||||||
* @returns A subject that holds the model list
|
* @returns A subject that holds the model list
|
||||||
*/
|
*/
|
||||||
public getViewModelListBehaviorSubject(): BehaviorSubject<V[]> {
|
public getViewModelListBehaviorSubject(): BehaviorSubject<V[]> {
|
||||||
return this.viewModelListAuditSubject;
|
return this.sortedViewModelListSubject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -268,7 +318,7 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update the observable of the list
|
* update the observable of the list. Also updates the sorting of the view model list.
|
||||||
*/
|
*/
|
||||||
protected updateViewModelListObservable(): void {
|
protected updateViewModelListObservable(): void {
|
||||||
this.viewModelListSubject.next(this.getViewModelList());
|
this.viewModelListSubject.next(this.getViewModelList());
|
||||||
|
@ -17,9 +17,9 @@ export class ChatMessageRepositoryService extends BaseRepository<ViewChatMessage
|
|||||||
dataSend: DataSendService,
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
private translate: TranslateService
|
translate: TranslateService
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, ChatMessage);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, ChatMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
|
@ -100,11 +100,11 @@ export class ConfigRepositoryService extends BaseRepository<ViewConfig, Config>
|
|||||||
dataSend: DataSendService,
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
|
translate: TranslateService,
|
||||||
private constantsService: ConstantsService,
|
private constantsService: ConstantsService,
|
||||||
private http: HttpService,
|
private http: HttpService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Config);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Config);
|
||||||
|
|
||||||
this.constantsService.get('OpenSlidesConfigVariables').subscribe(constant => {
|
this.constantsService.get('OpenSlidesConfigVariables').subscribe(constant => {
|
||||||
this.createConfigStructure(constant);
|
this.createConfigStructure(constant);
|
||||||
|
@ -35,11 +35,11 @@ export class HistoryRepositoryService extends BaseRepository<ViewHistory, Histor
|
|||||||
dataSend: DataSendService,
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
|
translate: TranslateService,
|
||||||
private httpService: HttpService,
|
private httpService: HttpService,
|
||||||
private timeTravel: TimeTravelService,
|
private timeTravel: TimeTravelService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, History, [User]);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, History, [User]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
|
@ -32,11 +32,12 @@ export class MediafileRepositoryService extends BaseRepository<ViewMediafile, Me
|
|||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
|
translate: TranslateService,
|
||||||
protected dataSend: DataSendService,
|
protected dataSend: DataSendService,
|
||||||
private httpService: HttpService,
|
private httpService: HttpService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Mediafile, [User]);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Mediafile, [User]);
|
||||||
|
this.initSorting();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
@ -69,4 +70,13 @@ export class MediafileRepositoryService extends BaseRepository<ViewMediafile, Me
|
|||||||
const emptyHeader = new HttpHeaders();
|
const emptyHeader = new HttpHeaders();
|
||||||
return this.httpService.post<Identifiable>(restPath, file, {}, emptyHeader);
|
return this.httpService.post<Identifiable>(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);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseRepository } from '../base-repository';
|
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 { ViewCategory } from 'app/site/motions/models/view-category';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
|
|
||||||
|
type SortProperty = 'prefix' | 'name';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repository Services for Categories
|
* Repository Services for Categories
|
||||||
*
|
*
|
||||||
@ -27,6 +28,8 @@ import { ViewModelStoreService } from 'app/core/core-services/view-model-store.s
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class CategoryRepositoryService extends BaseRepository<ViewCategory, Category> {
|
export class CategoryRepositoryService extends BaseRepository<ViewCategory, Category> {
|
||||||
|
private sortProperty: SortProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a CategoryRepository
|
* Creates a CategoryRepository
|
||||||
* Converts existing and incoming category to ViewCategories
|
* Converts existing and incoming category to ViewCategories
|
||||||
@ -40,15 +43,21 @@ export class CategoryRepositoryService extends BaseRepository<ViewCategory, Cate
|
|||||||
* @param translate translationService to get the currently selected locale
|
* @param translate translationService to get the currently selected locale
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
protected DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService,
|
||||||
private httpService: HttpService,
|
private httpService: HttpService,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Category);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Category);
|
||||||
|
|
||||||
|
this.sortProperty = this.configService.instant('motions_category_sorting');
|
||||||
|
this.configService.get<SortProperty>('motions_category_sorting').subscribe(conf => {
|
||||||
|
this.sortProperty = conf;
|
||||||
|
this.setConfigSortFn();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
@ -66,8 +75,7 @@ export class CategoryRepositoryService extends BaseRepository<ViewCategory, Cate
|
|||||||
* @param category_id category ID
|
* @param category_id category ID
|
||||||
*/
|
*/
|
||||||
public getCategoryByID(category_id: number): Category {
|
public getCategoryByID(category_id: number): Category {
|
||||||
const catList = this.DS.getAll(Category);
|
return this.DS.find<Category>(Category, cat => cat.id === category_id);
|
||||||
return catList.find(category => category.id === category_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,36 +89,19 @@ export class CategoryRepositoryService extends BaseRepository<ViewCategory, Cate
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ returns the observable for categories sorted according to configuration
|
* Triggers an update for the sort function responsible for the default sorting of data items
|
||||||
*/
|
*/
|
||||||
public getSortedViewModelListObservable(): Observable<ViewCategory[]> {
|
public setConfigSortFn(): void {
|
||||||
const subject = new BehaviorSubject<ViewCategory[]>([]);
|
this.setSortFunction((a: ViewCategory, b: ViewCategory) => {
|
||||||
this.getViewModelListObservable().subscribe(categories => {
|
if (a[this.sortProperty] && b[this.sortProperty]) {
|
||||||
subject.next(this.sortViewCategoriesByConfig(categories));
|
return this.languageCollator.compare(a[this.sortProperty], b[this.sortProperty]);
|
||||||
});
|
} else if (this.sortProperty === 'prefix') {
|
||||||
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') {
|
|
||||||
if (a.prefix) {
|
if (a.prefix) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (b.prefix) {
|
} else if (b.prefix) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
return a.name.localeCompare(b.name);
|
return this.languageCollator.compare(a.name, b.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -45,12 +45,12 @@ export class ChangeRecommendationRepositoryService extends BaseRepository<
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, MotionChangeRecommendation, [
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, MotionChangeRecommendation, [
|
||||||
Category,
|
Category,
|
||||||
User,
|
User,
|
||||||
Workflow
|
Workflow
|
||||||
@ -85,7 +85,7 @@ export class ChangeRecommendationRepositoryService extends BaseRepository<
|
|||||||
* return the Observable of all change recommendations belonging to the given motion
|
* return the Observable of all change recommendations belonging to the given motion
|
||||||
*/
|
*/
|
||||||
public getChangeRecosOfMotionObservable(motion_id: number): Observable<ViewMotionChangeRecommendation[]> {
|
public getChangeRecosOfMotionObservable(motion_id: number): Observable<ViewMotionChangeRecommendation[]> {
|
||||||
return this.viewModelListSubject.asObservable().pipe(
|
return this.getViewModelListObservable().pipe(
|
||||||
map((recos: ViewMotionChangeRecommendation[]) => {
|
map((recos: ViewMotionChangeRecommendation[]) => {
|
||||||
return recos.filter(reco => reco.motion_id === motion_id);
|
return recos.filter(reco => reco.motion_id === motion_id);
|
||||||
})
|
})
|
||||||
|
@ -36,14 +36,14 @@ export class MotionBlockRepositoryService extends BaseAgendaContentObjectReposit
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService,
|
||||||
private motionRepo: MotionRepositoryService,
|
private motionRepo: MotionRepositoryService,
|
||||||
private httpService: HttpService,
|
private httpService: HttpService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, MotionBlock, [Item]);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, MotionBlock, [Item]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAgendaTitle = (motionBlock: Partial<MotionBlock> | Partial<ViewMotionBlock>) => {
|
public getAgendaTitle = (motionBlock: Partial<MotionBlock> | Partial<ViewMotionBlock>) => {
|
||||||
|
@ -42,13 +42,13 @@ export class MotionCommentSectionRepositoryService extends BaseRepository<
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService,
|
||||||
private http: HttpService,
|
private http: HttpService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, MotionCommentSection, [Group]);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, MotionCommentSection, [Group]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
|
@ -7,6 +7,8 @@ import { tap, map } from 'rxjs/operators';
|
|||||||
import { Category } from 'app/shared/models/motions/category';
|
import { Category } from 'app/shared/models/motions/category';
|
||||||
import { ChangeRecoMode, ViewMotion } from 'app/site/motions/models/view-motion';
|
import { ChangeRecoMode, ViewMotion } from 'app/site/motions/models/view-motion';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
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 { DataSendService } from '../../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { DiffLinesInParagraph, DiffService, LineRange, ModificationType } from '../../ui-services/diff.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 { ViewPersonalNote } from 'app/site/users/models/view-personal-note';
|
||||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
|
|
||||||
|
type SortProperty = 'callListWeight' | 'identifier';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repository Services for motions (and potentially categories)
|
* Repository Services for motions (and potentially categories)
|
||||||
*
|
*
|
||||||
@ -56,6 +60,11 @@ import { OperatorService } from 'app/core/core-services/operator.service';
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class MotionRepositoryService extends BaseAgendaContentObjectRepository<ViewMotion, Motion> {
|
export class MotionRepositoryService extends BaseAgendaContentObjectRepository<ViewMotion, Motion> {
|
||||||
|
/**
|
||||||
|
* The property the incoming data is sorted by
|
||||||
|
*/
|
||||||
|
protected sortProperty: SortProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a MotionRepository
|
* Creates a MotionRepository
|
||||||
*
|
*
|
||||||
@ -68,20 +77,23 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
|||||||
* @param httpService OpenSlides own Http service
|
* @param httpService OpenSlides own Http service
|
||||||
* @param lineNumbering Line numbering for motion text
|
* @param lineNumbering Line numbering for motion text
|
||||||
* @param diff Display changes in motion text as diff.
|
* @param diff Display changes in motion text as diff.
|
||||||
|
* @param personalNoteService service fo personal notes
|
||||||
|
* @param config ConfigService (subscribe to sorting config)
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService,
|
||||||
|
config: ConfigService,
|
||||||
private httpService: HttpService,
|
private httpService: HttpService,
|
||||||
private readonly lineNumbering: LinenumberingService,
|
private readonly lineNumbering: LinenumberingService,
|
||||||
private readonly diff: DiffService,
|
private readonly diff: DiffService,
|
||||||
private treeService: TreeService,
|
private treeService: TreeService,
|
||||||
private translate: TranslateService,
|
|
||||||
private operator: OperatorService
|
private operator: OperatorService
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Motion, [
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Motion, [
|
||||||
Category,
|
Category,
|
||||||
User,
|
User,
|
||||||
Workflow,
|
Workflow,
|
||||||
@ -92,6 +104,10 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
|||||||
MotionChangeRecommendation,
|
MotionChangeRecommendation,
|
||||||
PersonalNote
|
PersonalNote
|
||||||
]);
|
]);
|
||||||
|
config.get<SortProperty>('motions_motions_sorting').subscribe(conf => {
|
||||||
|
this.sortProperty = conf;
|
||||||
|
this.setConfigSortFn();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTitle = (motion: Partial<Motion> | Partial<ViewMotion>) => {
|
public getTitle = (motion: Partial<Motion> | Partial<ViewMotion>) => {
|
||||||
@ -839,4 +855,30 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers an update for the sort function responsible for the default sorting of data items
|
||||||
|
*/
|
||||||
|
public setConfigSortFn(): void {
|
||||||
|
this.setSortFunction((a: ViewMotion, b: ViewMotion) => {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,12 @@ export class StatuteParagraphRepositoryService extends BaseRepository<ViewStatut
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, StatuteParagraph);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, StatuteParagraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { auditTime } from 'rxjs/operators';
|
|
||||||
|
|
||||||
import { Workflow } from 'app/shared/models/motions/workflow';
|
import { Workflow } from 'app/shared/models/motions/workflow';
|
||||||
import { ViewWorkflow } from 'app/site/motions/models/view-workflow';
|
import { ViewWorkflow } from 'app/site/motions/models/view-workflow';
|
||||||
@ -43,14 +42,15 @@ export class WorkflowRepositoryService extends BaseRepository<ViewWorkflow, Work
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService,
|
||||||
private httpService: HttpService,
|
private httpService: HttpService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Workflow);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Workflow);
|
||||||
this.viewModelListSubject.pipe(auditTime(1)).subscribe(models => {
|
|
||||||
|
this.sortedViewModelListSubject.subscribe(models => {
|
||||||
if (models && models.length > 0) {
|
if (models && models.length > 0) {
|
||||||
this.initSorting(models);
|
this.initSorting(models);
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,13 @@ import { ServertimeService } from 'app/core/core-services/servertime.service';
|
|||||||
export class CountdownRepositoryService extends BaseRepository<ViewCountdown, Countdown> {
|
export class CountdownRepositoryService extends BaseRepository<ViewCountdown, Countdown> {
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService,
|
||||||
private translate: TranslateService,
|
|
||||||
private servertimeService: ServertimeService
|
private servertimeService: ServertimeService
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Countdown);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Countdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
|
@ -14,12 +14,12 @@ import { DataSendService } from 'app/core/core-services/data-send.service';
|
|||||||
export class ProjectorMessageRepositoryService extends BaseRepository<ViewProjectorMessage, ProjectorMessage> {
|
export class ProjectorMessageRepositoryService extends BaseRepository<ViewProjectorMessage, ProjectorMessage> {
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, ProjectorMessage);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, ProjectorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
|
@ -37,13 +37,13 @@ export class ProjectorRepositoryService extends BaseRepository<ViewProjector, Pr
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService,
|
||||||
private http: HttpService,
|
private http: HttpService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Projector, [Projector]);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Projector, [Projector]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
|
@ -34,12 +34,12 @@ export class TagRepositoryService extends BaseRepository<ViewTag, Tag> {
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Tag);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
|
@ -49,13 +49,13 @@ export class GroupRepositoryService extends BaseRepository<ViewGroup, Group> {
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService,
|
||||||
private constants: ConstantsService,
|
private constants: ConstantsService
|
||||||
private translate: TranslateService
|
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, Group);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Group);
|
||||||
this.sortPermsPerApp();
|
this.sortPermsPerApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { Injectable } from '@angular/core';
|
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 { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
||||||
import { PersonalNote } from 'app/shared/models/users/personal-note';
|
import { PersonalNote } from 'app/shared/models/users/personal-note';
|
||||||
import { ViewPersonalNote } from 'app/site/users/models/view-personal-note';
|
import { ViewPersonalNote } from 'app/site/users/models/view-personal-note';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
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<ViewPersonalNo
|
|||||||
dataSend: DataSendService,
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
private translate: TranslateService
|
translate: TranslateService
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, PersonalNote);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, PersonalNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable, BehaviorSubject } from 'rxjs';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseRepository } from '../base-repository';
|
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 StringNamingSchema = 'lastCommaFirst' | 'firstSpaceLast';
|
||||||
|
|
||||||
|
type SortProperty = 'first_name' | 'last_name' | 'number';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repository service for users
|
* Repository service for users
|
||||||
*
|
*
|
||||||
@ -31,23 +33,36 @@ type StringNamingSchema = 'lastCommaFirst' | 'firstSpaceLast';
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class UserRepositoryService extends BaseRepository<ViewUser, User> {
|
export class UserRepositoryService extends BaseRepository<ViewUser, User> {
|
||||||
|
/**
|
||||||
|
* The property the incoming data is sorted by
|
||||||
|
*/
|
||||||
|
protected sortProperty: SortProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the user repo
|
* Constructor for the user repo
|
||||||
*
|
*
|
||||||
* @param DS The DataStore
|
* @param DS The DataStore
|
||||||
* @param mapperService Maps collection strings to classes
|
* @param mapperService Maps collection strings to classes
|
||||||
* @param dataSend sending changed objects
|
* @param dataSend sending changed objects
|
||||||
|
* @param translate
|
||||||
|
* @param httpService
|
||||||
|
* @param configService
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
DS: DataStoreService,
|
DS: DataStoreService,
|
||||||
|
dataSend: DataSendService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
protected dataSend: DataSendService,
|
translate: TranslateService,
|
||||||
private translate: TranslateService,
|
|
||||||
private httpService: HttpService,
|
private httpService: HttpService,
|
||||||
private configService: ConfigService
|
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<SortProperty>('users_sort_by').subscribe(conf => {
|
||||||
|
this.sortProperty = conf;
|
||||||
|
this.setConfigSortFn();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVerboseName = (plural: boolean = false) => {
|
public getVerboseName = (plural: boolean = false) => {
|
||||||
@ -219,7 +234,7 @@ export class UserRepositoryService extends BaseRepository<ViewUser, User> {
|
|||||||
* Searches and returns Users by full name
|
* Searches and returns Users by full name
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* @returns all users matching that name
|
* @returns all users matching that name (unsorted)
|
||||||
*/
|
*/
|
||||||
public getUsersByName(name: string): ViewUser[] {
|
public getUsersByName(name: string): ViewUser[] {
|
||||||
return this.getViewModelList().filter(user => {
|
return this.getViewModelList().filter(user => {
|
||||||
@ -301,43 +316,22 @@ export class UserRepositoryService extends BaseRepository<ViewUser, User> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns the observable for users sorted according to configuration
|
* Triggers an update for the sort function responsible for the default sorting of data items
|
||||||
*
|
|
||||||
* TODO: This is leading to heavy operations
|
|
||||||
*/
|
*/
|
||||||
public getSortedViewModelListObservable(): Observable<ViewUser[]> {
|
public setConfigSortFn(): void {
|
||||||
const subject = new BehaviorSubject<ViewUser[]>([]);
|
this.setSortFunction((a: ViewUser, b: ViewUser) => {
|
||||||
this.getViewModelListObservable().subscribe(users => {
|
if (a[this.sortProperty] && b[this.sortProperty]) {
|
||||||
subject.next(this.sortViewUsersByConfig(users));
|
if (a[this.sortProperty] === b[this.sortProperty]) {
|
||||||
});
|
return this.languageCollator.compare(a.short_name, b.short_name);
|
||||||
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);
|
|
||||||
} else {
|
} 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;
|
return -1;
|
||||||
} else if (b[sort]) {
|
} else if (b[this.sortProperty]) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return a.short_name.localeCompare(b.short_name);
|
return this.languageCollator.compare(a.short_name, b.short_name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ export abstract class BaseFilterListService<M extends BaseModel, V extends BaseV
|
|||||||
public filter(): Observable<V[]> {
|
public filter(): Observable<V[]> {
|
||||||
this.repo
|
this.repo
|
||||||
.getViewModelListObservable()
|
.getViewModelListObservable()
|
||||||
.pipe(auditTime(100))
|
.pipe(auditTime(10))
|
||||||
.subscribe(data => {
|
.subscribe(data => {
|
||||||
this.currentRawData = data;
|
this.currentRawData = data;
|
||||||
this.filteredData = this.filterData(data);
|
this.filteredData = this.filterData(data);
|
||||||
|
@ -50,6 +50,11 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
|
|||||||
*/
|
*/
|
||||||
private sortFn: (a: V, b: V) => number;
|
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.
|
* Constructor. Does nothing. TranslateService is used for localeCompeare.
|
||||||
*/
|
*/
|
||||||
@ -113,7 +118,7 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
|
|||||||
* get the property of the viewModel the sorting is based on.
|
* get the property of the viewModel the sorting is based on.
|
||||||
*/
|
*/
|
||||||
public get sortProperty(): string {
|
public get sortProperty(): string {
|
||||||
return this.sortOptions.sortProperty as string;
|
return this.sortOptions ? (this.sortOptions.sortProperty as string) : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public get isActive(): boolean {
|
public get isActive(): boolean {
|
||||||
@ -138,7 +143,7 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
|
|||||||
* @param option
|
* @param option
|
||||||
*/
|
*/
|
||||||
public getSortIcon(option: OsSortingItem<V>): string {
|
public getSortIcon(option: OsSortingItem<V>): string {
|
||||||
if (this.sortProperty !== (option.property as string)) {
|
if (!this.sortProperty || this.sortProperty !== (option.property as string)) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return this.ascending ? 'arrow_downward' : 'arrow_upward';
|
return this.ascending ? 'arrow_downward' : 'arrow_upward';
|
||||||
@ -156,20 +161,21 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
|
|||||||
* Retrieve the currently saved sorting definition from the borwser's
|
* Retrieve the currently saved sorting definition from the borwser's
|
||||||
* store
|
* store
|
||||||
*/
|
*/
|
||||||
private loadStorageDefinition(): void {
|
private async loadStorageDefinition(): Promise<void> {
|
||||||
const me = this;
|
const sorting: OsSortingDefinition<V> | null = await this.store.get('sorting_' + this.name);
|
||||||
this.store.get('sorting_' + this.name).then(function(sorting: OsSortingDefinition<V> | null): void {
|
|
||||||
if (sorting) {
|
if (sorting) {
|
||||||
if (sorting.sortProperty) {
|
if (sorting.sortProperty) {
|
||||||
me.sortOptions.sortProperty = sorting.sortProperty;
|
this.sortOptions.sortProperty = sorting.sortProperty;
|
||||||
if (sorting.sortAscending !== undefined) {
|
if (sorting.sortAscending !== undefined) {
|
||||||
me.sortOptions.sortAscending = sorting.sortAscending;
|
this.sortOptions.sortAscending = sorting.sortAscending;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this.sortOptions.sortProperty = this.defaultSorting;
|
||||||
|
this.sortOptions.sortAscending = true;
|
||||||
}
|
}
|
||||||
me.updateSortFn();
|
this.updateSortFn();
|
||||||
me.doAsyncSorting();
|
this.doAsyncSorting();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -197,10 +203,10 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
|
|||||||
* Recreates the sorting function. Is supposed to be called on init and
|
* Recreates the sorting function. Is supposed to be called on init and
|
||||||
* every time the sorting (property, ascending/descending) or the language changes
|
* every time the sorting (property, ascending/descending) or the language changes
|
||||||
*/
|
*/
|
||||||
private updateSortFn(): void {
|
protected updateSortFn(): void {
|
||||||
const property = this.sortProperty as string;
|
const property = this.sortProperty as string;
|
||||||
const ascending = this.ascending;
|
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 {
|
this.sortFn = function(itemA: V, itemB: V): number {
|
||||||
const firstProperty = ascending ? itemA[property] : itemB[property];
|
const firstProperty = ascending ? itemA[property] : itemB[property];
|
||||||
@ -234,16 +240,16 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
|
|||||||
if (!firstProperty) {
|
if (!firstProperty) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return firstProperty.localeCompare(secondProperty, lang);
|
return intl.compare(firstProperty, secondProperty);
|
||||||
case 'function':
|
case 'function':
|
||||||
const a = firstProperty();
|
const a = firstProperty();
|
||||||
const b = secondProperty();
|
const b = secondProperty();
|
||||||
return a.localeCompare(b, lang);
|
return intl.compare(a, b);
|
||||||
case 'object':
|
case 'object':
|
||||||
if (firstProperty instanceof Date) {
|
if (firstProperty instanceof Date) {
|
||||||
return firstProperty > secondProperty ? 1 : -1;
|
return firstProperty > secondProperty ? 1 : -1;
|
||||||
} else {
|
} else {
|
||||||
return firstProperty.toString().localeCompare(secondProperty.toString(), lang);
|
return intl.compare(firstProperty.toString(), secondProperty.toString());
|
||||||
}
|
}
|
||||||
case 'undefined':
|
case 'undefined':
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -140,7 +140,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
|||||||
this.addSpeakerForm = new FormGroup({ user_id: new FormControl([]) });
|
this.addSpeakerForm = new FormGroup({ user_id: new FormControl([]) });
|
||||||
|
|
||||||
if (this.currentListOfSpeakers) {
|
if (this.currentListOfSpeakers) {
|
||||||
this.projectors = projectorRepo.getViewModelList();
|
this.projectors = projectorRepo.getSortedViewModelList();
|
||||||
this.updateClosProjector();
|
this.updateClosProjector();
|
||||||
projectorRepo.getViewModelListObservable().subscribe(newProjectors => {
|
projectorRepo.getViewModelListObservable().subscribe(newProjectors => {
|
||||||
this.projectors = newProjectors;
|
this.projectors = newProjectors;
|
||||||
@ -160,11 +160,6 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
|||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
// load and observe users
|
// load and observe users
|
||||||
this.users = this.userRepository.getViewModelListBehaviorSubject();
|
this.users = this.userRepository.getViewModelListBehaviorSubject();
|
||||||
this.userRepository.getViewModelListBehaviorSubject().subscribe(newUsers => {
|
|
||||||
if (this.viewItem) {
|
|
||||||
this.setSpeakerList(this.viewItem.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// detect changes in the form
|
// detect changes in the form
|
||||||
this.addSpeakerForm.valueChanges.subscribe(formResult => {
|
this.addSpeakerForm.valueChanges.subscribe(formResult => {
|
||||||
|
@ -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
|
* virtual weight defined by the order in the agenda tree, representing a shortcut to sorting by
|
||||||
* weight, parent_id and the parents' weight(s)
|
* 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;
|
public agendaListWeight: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount of parents in the agenda list tree.
|
* 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;
|
public agendaListLevel: number;
|
||||||
|
|
||||||
@ -39,6 +39,10 @@ export class ViewItem extends BaseViewModel {
|
|||||||
return this.item.item_number;
|
return this.item.item_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get title_information(): object {
|
||||||
|
return this.item.title_information;
|
||||||
|
}
|
||||||
|
|
||||||
public get duration(): number {
|
public get duration(): number {
|
||||||
return this.item.duration;
|
return this.item.duration;
|
||||||
}
|
}
|
||||||
|
@ -98,9 +98,13 @@ export abstract class ListViewBaseComponent<V extends BaseViewModel, M extends B
|
|||||||
* Standard filtering function. Sufficient for most list views but can be overwritten
|
* Standard filtering function. Sufficient for most list views but can be overwritten
|
||||||
*/
|
*/
|
||||||
protected onFilter(): void {
|
protected onFilter(): void {
|
||||||
|
if (this.sortService) {
|
||||||
this.subscriptions.push(
|
this.subscriptions.push(
|
||||||
this.filterService.filter().subscribe(filteredData => (this.sortService.data = filteredData))
|
this.filterService.filter().subscribe(filteredData => (this.sortService.data = filteredData))
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
this.filterService.filter().subscribe(filteredData => (this.dataSource.data = filteredData));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,7 +101,7 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
super.setTitle('Category');
|
super.setTitle('Category');
|
||||||
this.repo.getSortedViewModelListObservable().subscribe(newViewCategories => {
|
this.repo.getViewModelListObservable().subscribe(newViewCategories => {
|
||||||
this.categories = newViewCategories;
|
this.categories = newViewCategories;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -187,21 +187,7 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
* @returns all motions in the category
|
* @returns all motions in the category
|
||||||
*/
|
*/
|
||||||
public motionsInCategory(category: Category): ViewMotion[] {
|
public motionsInCategory(category: Category): ViewMotion[] {
|
||||||
const coll = new Intl.Collator(this.translate.currentLang);
|
return this.motionRepo.getSortedViewModelList().filter(m => m.category_id === category.id);
|
||||||
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());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,7 +107,6 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
|
|||||||
|
|
||||||
this.items = this.itemRepo.getViewModelListBehaviorSubject();
|
this.items = this.itemRepo.getViewModelListBehaviorSubject();
|
||||||
|
|
||||||
// TODO: Should fall under generic sorting in PR 4411
|
|
||||||
this.repo.getViewModelListObservable().subscribe(newMotionblocks => {
|
this.repo.getViewModelListObservable().subscribe(newMotionblocks => {
|
||||||
newMotionblocks.sort((a, b) => (a > b ? 1 : -1));
|
newMotionblocks.sort((a, b) => (a > b ? 1 : -1));
|
||||||
this.dataSource.data = newMotionblocks;
|
this.dataSource.data = newMotionblocks;
|
||||||
|
@ -18,6 +18,7 @@ import { itemVisibilityChoices } from 'app/shared/models/agenda/item';
|
|||||||
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
|
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
|
||||||
import { LocalPermissionsService } from 'app/site/motions/services/local-permissions.service';
|
import { LocalPermissionsService } from 'app/site/motions/services/local-permissions.service';
|
||||||
import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
|
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 { Motion } from 'app/shared/models/motions/motion';
|
||||||
import {
|
import {
|
||||||
MotionChangeRecommendationComponentData,
|
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 { ViewTag } from 'app/site/tags/models/view-tag';
|
||||||
import { ViewUnifiedChange } from 'app/shared/models/motions/view-unified-change';
|
import { ViewUnifiedChange } from 'app/shared/models/motions/view-unified-change';
|
||||||
import { TagRepositoryService } from 'app/core/repositories/tags/tag-repository.service';
|
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 { WorkflowRepositoryService } from 'app/core/repositories/motions/workflow-repository.service';
|
||||||
import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-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 agendaRepo Read out agenda variables
|
||||||
* @param changeRecoRepo Change Recommendation Repository
|
* @param changeRecoRepo Change Recommendation Repository
|
||||||
* @param statuteRepo: Statute Paragraph Repository
|
* @param statuteRepo: Statute Paragraph Repository
|
||||||
|
* @param mediafileRepo Mediafile Repository
|
||||||
* @param DS The DataStoreService
|
* @param DS The DataStoreService
|
||||||
* @param configService The configuration provider
|
* @param configService The configuration provider
|
||||||
* @param sanitizer For making HTML SafeHTML
|
* @param sanitizer For making HTML SafeHTML
|
||||||
@ -863,7 +864,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
|
|||||||
const content = this.motion.getTitle();
|
const content = this.motion.getTitle();
|
||||||
if (await this.promptService.open(title, content)) {
|
if (await this.promptService.open(title, content)) {
|
||||||
await this.repo.delete(this.motion);
|
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
|
* then appending motion without identifiers sorted by title
|
||||||
*/
|
*/
|
||||||
public setSurroundingMotions(): void {
|
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 => {
|
const indexOfCurrent = this.motionObserver.value.findIndex(motion => {
|
||||||
return motion === this.motion;
|
return motion === this.motion;
|
||||||
});
|
});
|
||||||
|
@ -61,7 +61,7 @@ export class MotionExportDialogComponent implements OnInit {
|
|||||||
* @returns a list of availavble commentSections
|
* @returns a list of availavble commentSections
|
||||||
*/
|
*/
|
||||||
public get commentsToExport(): ViewMotionCommentSection[] {
|
public get commentsToExport(): ViewMotionCommentSection[] {
|
||||||
return this.commentRepo.getViewModelList();
|
return this.commentRepo.getSortedViewModelList();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Hold the default lnMode. Will be set by the constructor.
|
* Hold the default lnMode. Will be set by the constructor.
|
||||||
|
@ -128,7 +128,7 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion, Motio
|
|||||||
.get<string>('motions_recommendations_by')
|
.get<string>('motions_recommendations_by')
|
||||||
.subscribe(recommender => (this.recomendationEnabled = !!recommender));
|
.subscribe(recommender => (this.recomendationEnabled = !!recommender));
|
||||||
this.motionBlockRepo.getViewModelListObservable().subscribe(mBs => (this.motionBlocks = mBs));
|
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.tagRepo.getViewModelListObservable().subscribe(tags => (this.tags = tags));
|
||||||
this.workflowRepo.getViewModelListObservable().subscribe(wfs => (this.workflows = wfs));
|
this.workflowRepo.getViewModelListObservable().subscribe(wfs => (this.workflows = wfs));
|
||||||
this.setFulltextFilter();
|
this.setFulltextFilter();
|
||||||
|
@ -182,7 +182,7 @@ export class MotionFilterListService extends BaseFilterListService<Motion, ViewM
|
|||||||
* Subscibes to changing Categories, and updates the filter accordingly
|
* Subscibes to changing Categories, and updates the filter accordingly
|
||||||
*/
|
*/
|
||||||
private subscribeCategories(): void {
|
private subscribeCategories(): void {
|
||||||
this.categoryRepo.getSortedViewModelListObservable().subscribe(categories => {
|
this.categoryRepo.getViewModelListObservable().subscribe(categories => {
|
||||||
const categoryOptions: OsFilterOptions = categories.map(cat => ({
|
const categoryOptions: OsFilterOptions = categories.map(cat => ({
|
||||||
condition: cat.id,
|
condition: cat.id,
|
||||||
label: cat.prefixedName,
|
label: cat.prefixedName,
|
||||||
|
@ -74,7 +74,7 @@ export class MotionMultiselectService {
|
|||||||
*/
|
*/
|
||||||
public async moveToItem(motions: ViewMotion[]): Promise<void> {
|
public async moveToItem(motions: ViewMotion[]): Promise<void> {
|
||||||
const title = this.translate.instant('This will move all selected motions as childs to:');
|
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);
|
const selectedChoice = await this.choiceService.open(title, choices);
|
||||||
if (selectedChoice) {
|
if (selectedChoice) {
|
||||||
const requestData = {
|
const requestData = {
|
||||||
@ -139,7 +139,7 @@ export class MotionMultiselectService {
|
|||||||
const clearChoice = this.translate.instant('No category');
|
const clearChoice = this.translate.instant('No category');
|
||||||
const selectedChoice = await this.choiceService.open(
|
const selectedChoice = await this.choiceService.open(
|
||||||
title,
|
title,
|
||||||
this.categoryRepo.sortViewCategoriesByConfig(this.categoryRepo.getViewModelList()),
|
this.categoryRepo.getSortedViewModelList(),
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
clearChoice
|
clearChoice
|
||||||
@ -164,7 +164,12 @@ export class MotionMultiselectService {
|
|||||||
'This will add or remove the following submitters for all selected motions:'
|
'This will add or remove the following submitters for all selected motions:'
|
||||||
);
|
);
|
||||||
const choices = [this.translate.instant('Add'), this.translate.instant('Remove')];
|
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]) {
|
if (selectedChoice && selectedChoice.action === choices[0]) {
|
||||||
const requestData = motions.map(motion => {
|
const requestData = motions.map(motion => {
|
||||||
let submitterIds = [...motion.sorted_submitters_id, ...(selectedChoice.items as number[])];
|
let submitterIds = [...motion.sorted_submitters_id, ...(selectedChoice.items as number[])];
|
||||||
@ -200,7 +205,12 @@ export class MotionMultiselectService {
|
|||||||
this.translate.instant('Remove'),
|
this.translate.instant('Remove'),
|
||||||
this.translate.instant('Clear tags')
|
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]) {
|
if (selectedChoice && selectedChoice.action === choices[0]) {
|
||||||
const requestData = motions.map(motion => {
|
const requestData = motions.map(motion => {
|
||||||
let tagIds = [...motion.tags_id, ...(selectedChoice.items as number[])];
|
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 clearChoice = this.translate.instant('Clear motion block');
|
||||||
const selectedChoice = await this.choiceService.open(
|
const selectedChoice = await this.choiceService.open(
|
||||||
title,
|
title,
|
||||||
this.motionBlockRepo.getViewModelList(),
|
this.motionBlockRepo.getSortedViewModelList(),
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
clearChoice
|
clearChoice
|
||||||
@ -280,7 +290,7 @@ export class MotionMultiselectService {
|
|||||||
// insert after chosen
|
// insert after chosen
|
||||||
const olderSibling = this.repo.getViewModel(selectedChoice.items as number);
|
const olderSibling = this.repo.getViewModel(selectedChoice.items as number);
|
||||||
const parentId = olderSibling ? olderSibling.sort_parent_id : null;
|
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 idx = siblings.findIndex(sib => sib.id === olderSibling.id);
|
||||||
const before = siblings.slice(0, idx + 1);
|
const before = siblings.slice(0, idx + 1);
|
||||||
const after = siblings.slice(idx + 1);
|
const after = siblings.slice(idx + 1);
|
||||||
|
@ -48,7 +48,7 @@ export class MotionPdfService {
|
|||||||
*
|
*
|
||||||
* @param translate handle translations
|
* @param translate handle translations
|
||||||
* @param motionRepo get parent motions
|
* @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 changeRecoRepo to get the change recommendations
|
||||||
* @param configService Read config variables
|
* @param configService Read config variables
|
||||||
* @param htmlToPdfService To convert HTML text into pdfmake doc def
|
* @param htmlToPdfService To convert HTML text into pdfmake doc def
|
||||||
@ -59,7 +59,7 @@ export class MotionPdfService {
|
|||||||
public constructor(
|
public constructor(
|
||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
private motionRepo: MotionRepositoryService,
|
private motionRepo: MotionRepositoryService,
|
||||||
private statureRepo: StatuteParagraphRepositoryService,
|
private statuteRepo: StatuteParagraphRepositoryService,
|
||||||
private changeRecoRepo: ChangeRecommendationRepositoryService,
|
private changeRecoRepo: ChangeRecommendationRepositoryService,
|
||||||
private configService: ConfigService,
|
private configService: ConfigService,
|
||||||
private htmlToPdfService: HtmlToPdfService,
|
private htmlToPdfService: HtmlToPdfService,
|
||||||
@ -123,7 +123,7 @@ export class MotionPdfService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (infoToExport && infoToExport.includes('allcomments')) {
|
if (infoToExport && infoToExport.includes('allcomments')) {
|
||||||
commentsToExport = this.commentRepo.getViewModelList().map(vm => vm.id);
|
commentsToExport = this.commentRepo.getSortedViewModelList().map(vm => vm.id);
|
||||||
}
|
}
|
||||||
if (commentsToExport) {
|
if (commentsToExport) {
|
||||||
motionPdfContent.push(this.createComments(motion, commentsToExport));
|
motionPdfContent.push(this.createComments(motion, commentsToExport));
|
||||||
@ -495,7 +495,7 @@ export class MotionPdfService {
|
|||||||
}
|
}
|
||||||
} else if (motion.isStatuteAmendment()) {
|
} else if (motion.isStatuteAmendment()) {
|
||||||
// statute amendments
|
// statute amendments
|
||||||
const statutes = this.statureRepo.getViewModelList();
|
const statutes = this.statuteRepo.getViewModelList();
|
||||||
motionText = this.motionRepo.formatStatuteAmendment(statutes, motion, lineLength);
|
motionText = this.motionRepo.formatStatuteAmendment(statutes, motion, lineLength);
|
||||||
} else {
|
} else {
|
||||||
// lead motion or normal amendments
|
// lead motion or normal amendments
|
||||||
|
@ -37,6 +37,6 @@ export class MotionSortListService extends BaseSortListService<ViewMotion> {
|
|||||||
*/
|
*/
|
||||||
public constructor(translate: TranslateService, store: StorageService, config: ConfigService) {
|
public constructor(translate: TranslateService, store: StorageService, config: ConfigService) {
|
||||||
super(translate, store);
|
super(translate, store);
|
||||||
this.sortOptions.sortProperty = config.instant<keyof ViewMotion>('motions_motions_sorting');
|
this.defaultSorting = config.instant<keyof ViewMotion>('motions_motions_sorting');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
Reference projector for current list of speakers:
|
Reference projector for current list of speakers:
|
||||||
</span>
|
</span>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-select [disabled]="!!editId" [value]="projectors[0].reference_projector_id" (selectionChange)="onSelectReferenceProjector($event)">
|
<mat-select [disabled]="!!editId" [value]="projectors.length ? projectors[0].reference_projector_id : null" (selectionChange)="onSelectReferenceProjector($event)">
|
||||||
<mat-option *ngFor="let projector of projectors" [value]="projector.id">
|
<mat-option *ngFor="let projector of projectors" [value]="projector.id">
|
||||||
{{ projector.getTitle() | translate }}
|
{{ projector.getTitle() | translate }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
@ -120,6 +120,7 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit
|
|||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
super.setTitle('Projectors');
|
super.setTitle('Projectors');
|
||||||
|
this.projectors = this.repo.getViewModelList();
|
||||||
this.repo.getViewModelListObservable().subscribe(projectors => (this.projectors = projectors));
|
this.repo.getViewModelListObservable().subscribe(projectors => (this.projectors = projectors));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ export class ProjectorMessageListComponent extends BaseViewComponent implements
|
|||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
super.setTitle('Messages');
|
super.setTitle('Messages');
|
||||||
this.messages = this.repo.getViewModelList();
|
this.messages = this.repo.getSortedViewModelList();
|
||||||
this.repo.getViewModelListObservable().subscribe(messages => (this.messages = messages));
|
this.repo.getViewModelListObservable().subscribe(messages => (this.messages = messages));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
this.createForm();
|
this.createForm();
|
||||||
|
|
||||||
this.groups = this.groupRepo.getViewModelList().filter(group => group.id !== 1);
|
this.groups = this.groupRepo.getSortedViewModelList().filter(group => group.id !== 1);
|
||||||
this.groupRepo
|
this.groupRepo
|
||||||
.getViewModelListObservable()
|
.getViewModelListObservable()
|
||||||
.subscribe(groups => (this.groups = groups.filter(group => group.id !== 1)));
|
.subscribe(groups => (this.groups = groups.filter(group => group.id !== 1)));
|
||||||
|
@ -167,7 +167,8 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser, User> imp
|
|||||||
this.setFulltextFilter();
|
this.setFulltextFilter();
|
||||||
|
|
||||||
// Initialize the groups
|
// 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,6 +36,6 @@ export class UserSortListService extends BaseSortListService<ViewUser> {
|
|||||||
*/
|
*/
|
||||||
public constructor(translate: TranslateService, store: StorageService, config: ConfigService) {
|
public constructor(translate: TranslateService, store: StorageService, config: ConfigService) {
|
||||||
super(translate, store);
|
super(translate, store);
|
||||||
this.sortOptions.sortProperty = config.instant<keyof ViewUser>('motions_motions_sorting');
|
this.defaultSorting = config.instant<keyof ViewUser>('users_sort_by');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user