From c487d688f6d57f9000b5fca9437ba635133b1c66 Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Thu, 7 Feb 2019 12:34:31 +0100 Subject: [PATCH] sort categories in dropdowns --- .../motions/category-repository.service.ts | 51 ++++++++++++++++-- .../ui-services/base-sort-list.service.ts | 1 - .../category-list/category-list.component.ts | 10 +--- .../motion-detail/motion-detail.component.ts | 13 +++-- .../motion-list/motion-list.component.ts | 2 +- .../services/motion-filter-list.service.ts | 2 +- .../services/motion-multiselect.service.ts | 2 +- .../services/motion-sort-list.service.ts | 15 ++++++ openslides/motions/config_variables.py | 52 ++++++++++++------- 9 files changed, 108 insertions(+), 40 deletions(-) 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 8ff40175e..77f4fde24 100644 --- a/client/src/app/core/repositories/motions/category-repository.service.ts +++ b/client/src/app/core/repositories/motions/category-repository.service.ts @@ -1,14 +1,17 @@ import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { TranslateService } from '@ngx-translate/core'; +import { BaseRepository } from '../base-repository'; import { Category } from 'app/shared/models/motions/category'; -import { ViewCategory } from 'app/site/motions/models/view-category'; +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 { BaseRepository } from '../base-repository'; -import { Motion } from 'app/shared/models/motions/motion'; import { HttpService } from '../../core-services/http.service'; import { Identifiable } from 'app/shared/models/base/identifiable'; -import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service'; +import { Motion } from 'app/shared/models/motions/motion'; +import { ViewCategory } from 'app/site/motions/models/view-category'; import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service'; /** @@ -34,13 +37,17 @@ 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 + */ + 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) { + return 1; + } else if (b.prefix) { + return -1; + } else { + return a.name.localeCompare(b.name); + } + } + }); + } } 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 f4dd0a975..1f3b63861 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 @@ -3,7 +3,6 @@ import { BehaviorSubject } from 'rxjs'; import { BaseViewModel } from '../../site/base/base-view-model'; import { TranslateService } from '@ngx-translate/core'; import { StorageService } from '../core-services/storage.service'; - /** * Describes the sorting columns of an associated ListView, and their state. */ diff --git a/client/src/app/site/motions/components/category-list/category-list.component.ts b/client/src/app/site/motions/components/category-list/category-list.component.ts index ff2da676c..21bdcd4fb 100644 --- a/client/src/app/site/motions/components/category-list/category-list.component.ts +++ b/client/src/app/site/motions/components/category-list/category-list.component.ts @@ -110,9 +110,8 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit { */ public ngOnInit(): void { super.setTitle('Category'); - this.repo.getViewModelListObservable().subscribe(newViewCategories => { + this.repo.getSortedViewModelListObservable().subscribe(newViewCategories => { this.categories = newViewCategories; - this.sortDataSource(); }); } @@ -186,13 +185,6 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit { } } - /** - * sorts the categories by prefix - */ - private sortDataSource(): void { - this.categories.sort((viewCategory1, viewCategory2) => (viewCategory1 > viewCategory2 ? 1 : -1)); - } - /** * executed on cancel button * @param viewCategory diff --git a/client/src/app/site/motions/components/motion-detail/motion-detail.component.ts b/client/src/app/site/motions/components/motion-detail/motion-detail.component.ts index 194a63eae..c720475bf 100644 --- a/client/src/app/site/motions/components/motion-detail/motion-detail.component.ts +++ b/client/src/app/site/motions/components/motion-detail/motion-detail.component.ts @@ -10,6 +10,7 @@ import { TranslateService } from '@ngx-translate/core'; import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service'; import { BaseViewComponent } from '../../../base/base-view'; import { Category } from 'app/shared/models/motions/category'; +import { CategoryRepositoryService } from 'app/core/repositories/motions/category-repository.service'; import { ChangeRecommendationRepositoryService } from 'app/core/repositories/motions/change-recommendation-repository.service'; import { ChangeRecoMode, LineNumberingMode, ViewMotion } from '../../models/view-motion'; import { CreateMotion } from '../../models/create-motion'; @@ -338,6 +339,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit { * @param promptService ensure safe deletion * @param pdfExport export the motion to pdf * @param personalNoteService: personal comments and favorite marker + * @param categoryRepo */ public constructor( title: Title, @@ -361,14 +363,17 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit { private pdfExport: MotionPdfExportService, private personalNoteService: PersonalNoteService, private linenumberingService: LinenumberingService, - private viewModelStore: ViewModelStoreService + private viewModelStore: ViewModelStoreService, + private categoryRepo: CategoryRepositoryService ) { super(title, translate, matSnackBar); // Initial Filling of the Subjects this.submitterObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewUser)); this.supporterObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewUser)); - this.categoryObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewCategory)); + this.categoryObserver = new BehaviorSubject( + this.categoryRepo.sortViewCategoriesByConfig(this.viewModelStore.getAll(ViewCategory)) + ); this.workflowObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewWorkflow)); this.blockObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewMotionBlock)); this.mediafilesObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewMediafile)); @@ -381,7 +386,9 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit { this.submitterObserver.next(this.viewModelStore.getAll(ViewUser)); this.supporterObserver.next(this.viewModelStore.getAll(ViewUser)); } else if (newModel instanceof Category) { - this.categoryObserver.next(this.viewModelStore.getAll(ViewCategory)); + this.categoryObserver.next( + this.categoryRepo.sortViewCategoriesByConfig(this.viewModelStore.getAll(ViewCategory)) + ); } else if (newModel instanceof Workflow) { this.workflowObserver.next(this.viewModelStore.getAll(ViewWorkflow)); } else if (newModel instanceof MotionBlock) { diff --git a/client/src/app/site/motions/components/motion-list/motion-list.component.ts b/client/src/app/site/motions/components/motion-list/motion-list.component.ts index 72ffa9867..fe52607ec 100644 --- a/client/src/app/site/motions/components/motion-list/motion-list.component.ts +++ b/client/src/app/site/motions/components/motion-list/motion-list.component.ts @@ -127,7 +127,7 @@ export class MotionListComponent extends ListViewBaseComponent imple .get('motions_recommendations_by') .subscribe(recommender => (this.recomendationEnabled = !!recommender)); this.motionBlockRepo.getViewModelListObservable().subscribe(mBs => (this.motionBlocks = mBs)); - this.categoryRepo.getViewModelListObservable().subscribe(cats => (this.categories = cats)); + this.categoryRepo.getSortedViewModelListObservable().subscribe(cats => (this.categories = cats)); this.tagRepo.getViewModelListObservable().subscribe(tags => (this.tags = tags)); this.workflowRepo.getViewModelListObservable().subscribe(wfs => (this.workflows = wfs)); this.filterService.filter().subscribe(filteredData => (this.sortService.data = filteredData)); 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 4ca44b0f9..f65657a10 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 @@ -184,7 +184,7 @@ export class MotionFilterListService extends BaseFilterListService { + this.categoryRepo.getSortedViewModelListObservable().subscribe(categories => { const categoryOptions: (OsFilterOption | string)[] = []; categories.forEach(cat => { categoryOptions.push({ 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 5754ff3bd..ec7db499f 100644 --- a/client/src/app/site/motions/services/motion-multiselect.service.ts +++ b/client/src/app/site/motions/services/motion-multiselect.service.ts @@ -136,7 +136,7 @@ export class MotionMultiselectService { const clearChoice = 'No category'; const selectedChoice = await this.choiceService.open( title, - this.categoryRepo.getViewModelList(), + this.categoryRepo.sortViewCategoriesByConfig(this.categoryRepo.getViewModelList()), false, null, clearChoice 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 f2277ce35..7a87a3afe 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 @@ -2,6 +2,9 @@ import { Injectable } from '@angular/core'; import { BaseSortListService, OsSortingDefinition } from 'app/core/ui-services/base-sort-list.service'; import { ViewMotion } from '../models/view-motion'; +import { TranslateService } from '@ngx-translate/core'; +import { StorageService } from 'app/core/core-services/storage.service'; +import { ConfigService } from 'app/core/ui-services/config.service'; @Injectable({ providedIn: 'root' @@ -24,4 +27,16 @@ export class MotionSortListService extends BaseSortListService { ] }; protected name = 'Motion'; + + /** + * Constructor. Sets the default sorting if none is set locally + * + * @param translate + * @param store + * @param config + */ + public constructor(translate: TranslateService, store: StorageService, config: ConfigService) { + super(translate, store); + this.sortOptions.sortProperty = config.instant('motions_motions_sorting'); + } } diff --git a/openslides/motions/config_variables.py b/openslides/motions/config_variables.py index 843dfd8e2..9f59e3e19 100644 --- a/openslides/motions/config_variables.py +++ b/openslides/motions/config_variables.py @@ -177,6 +177,34 @@ def get_config_variables(): subgroup="General", ) + yield ConfigVariable( + name="motions_category_sorting", + default_value="prefix", + input_type="choice", + label="Sort categories by", + choices=( + {"value": "prefix", "display_name": "Prefix"}, + {"value": "name", "display_name": "Name"}, + ), + weight=335, + group="Motions", + subgroup="General", + ) + + yield ConfigVariable( + name="motions_motions_sorting", + default_value="identifier", + input_type="choice", + label="Sort motions by", + choices=( + {"value": "callListWeight", "display_name": "Call list"}, + {"value": "identifier", "display_name": "Identifier"}, + ), + weight=335, + group="Motions", + subgroup="General", + ) + # Amendments yield ConfigVariable( @@ -184,7 +212,7 @@ def get_config_variables(): default_value=False, input_type="boolean", label="Activate statute amendments", - weight=335, + weight=338, group="Motions", subgroup="Amendments", ) @@ -194,7 +222,7 @@ def get_config_variables(): default_value=False, input_type="boolean", label="Activate amendments", - weight=336, + weight=339, group="Motions", subgroup="Amendments", ) @@ -204,7 +232,7 @@ def get_config_variables(): default_value=False, input_type="boolean", label="Show amendments together with motions", - weight=337, + weight=340, group="Motions", subgroup="Amendments", ) @@ -213,7 +241,7 @@ def get_config_variables(): name="motions_amendments_prefix", default_value="-", label="Prefix for the identifier for amendments", - weight=340, + weight=341, group="Motions", subgroup="Amendments", ) @@ -341,26 +369,12 @@ def get_config_variables(): subgroup="Export", ) - yield ConfigVariable( - name="motions_export_category_sorting", - default_value="prefix", - input_type="choice", - label="Sort categories by", - choices=( - {"value": "prefix", "display_name": "Prefix"}, - {"value": "name", "display_name": "Name"}, - ), - weight=380, - group="Motions", - subgroup="Export", - ) - yield ConfigVariable( name="motions_export_sequential_number", default_value=True, input_type="boolean", label="Include the sequential number in PDF and DOCX", - weight=385, + weight=380, group="Motions", subgroup="Export", )