Merge pull request #4275 from MaximilianKrambach/sortLists
sort categories (+ motions) in dropdowns etc.
This commit is contained in:
commit
76210e807f
@ -1,14 +1,17 @@
|
|||||||
import { Injectable } from '@angular/core';
|
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 { 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 { DataSendService } from '../../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 { Motion } from 'app/shared/models/motions/motion';
|
|
||||||
import { HttpService } from '../../core-services/http.service';
|
import { HttpService } from '../../core-services/http.service';
|
||||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
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';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,13 +37,17 @@ export class CategoryRepositoryService extends BaseRepository<ViewCategory, Cate
|
|||||||
* @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 httpService OpenSlides own HTTP service
|
* @param httpService OpenSlides own HTTP service
|
||||||
|
* @param configService to get the default sorting
|
||||||
|
* @param translate translationService to get the currently selected locale
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
protected DS: DataStoreService,
|
protected DS: DataStoreService,
|
||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
private dataSend: DataSendService,
|
private dataSend: DataSendService,
|
||||||
private httpService: HttpService
|
private httpService: HttpService,
|
||||||
|
private configService: ConfigService,
|
||||||
|
private translate: TranslateService
|
||||||
) {
|
) {
|
||||||
super(DS, mapperService, viewModelStoreService, Category);
|
super(DS, mapperService, viewModelStoreService, Category);
|
||||||
}
|
}
|
||||||
@ -103,4 +110,38 @@ export class CategoryRepositoryService extends BaseRepository<ViewCategory, Cate
|
|||||||
const collectionString = 'rest/motions/category/' + category.id + '/numbering/';
|
const collectionString = 'rest/motions/category/' + category.id + '/numbering/';
|
||||||
await this.httpService.post(collectionString, { motions: motionIds });
|
await this.httpService.post(collectionString, { motions: motionIds });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ returns the observable for categories sorted according to configuration
|
||||||
|
*/
|
||||||
|
public getSortedViewModelListObservable(): Observable<ViewCategory[]> {
|
||||||
|
const subject = new BehaviorSubject<ViewCategory[]>([]);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ import { BehaviorSubject } from 'rxjs';
|
|||||||
import { BaseViewModel } from '../../site/base/base-view-model';
|
import { BaseViewModel } from '../../site/base/base-view-model';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { StorageService } from '../core-services/storage.service';
|
import { StorageService } from '../core-services/storage.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the sorting columns of an associated ListView, and their state.
|
* Describes the sorting columns of an associated ListView, and their state.
|
||||||
*/
|
*/
|
||||||
|
@ -110,9 +110,8 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
super.setTitle('Category');
|
super.setTitle('Category');
|
||||||
this.repo.getViewModelListObservable().subscribe(newViewCategories => {
|
this.repo.getSortedViewModelListObservable().subscribe(newViewCategories => {
|
||||||
this.categories = 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
|
* executed on cancel button
|
||||||
* @param viewCategory
|
* @param viewCategory
|
||||||
|
@ -10,6 +10,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
||||||
import { BaseViewComponent } from '../../../base/base-view';
|
import { BaseViewComponent } from '../../../base/base-view';
|
||||||
import { Category } from 'app/shared/models/motions/category';
|
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 { ChangeRecommendationRepositoryService } from 'app/core/repositories/motions/change-recommendation-repository.service';
|
||||||
import { ChangeRecoMode, LineNumberingMode, ViewMotion } from '../../models/view-motion';
|
import { ChangeRecoMode, LineNumberingMode, ViewMotion } from '../../models/view-motion';
|
||||||
import { CreateMotion } from '../../models/create-motion';
|
import { CreateMotion } from '../../models/create-motion';
|
||||||
@ -338,6 +339,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
* @param promptService ensure safe deletion
|
* @param promptService ensure safe deletion
|
||||||
* @param pdfExport export the motion to pdf
|
* @param pdfExport export the motion to pdf
|
||||||
* @param personalNoteService: personal comments and favorite marker
|
* @param personalNoteService: personal comments and favorite marker
|
||||||
|
* @param categoryRepo
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
title: Title,
|
title: Title,
|
||||||
@ -361,14 +363,17 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
private pdfExport: MotionPdfExportService,
|
private pdfExport: MotionPdfExportService,
|
||||||
private personalNoteService: PersonalNoteService,
|
private personalNoteService: PersonalNoteService,
|
||||||
private linenumberingService: LinenumberingService,
|
private linenumberingService: LinenumberingService,
|
||||||
private viewModelStore: ViewModelStoreService
|
private viewModelStore: ViewModelStoreService,
|
||||||
|
private categoryRepo: CategoryRepositoryService
|
||||||
) {
|
) {
|
||||||
super(title, translate, matSnackBar);
|
super(title, translate, matSnackBar);
|
||||||
|
|
||||||
// Initial Filling of the Subjects
|
// Initial Filling of the Subjects
|
||||||
this.submitterObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewUser));
|
this.submitterObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewUser));
|
||||||
this.supporterObserver = 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.workflowObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewWorkflow));
|
||||||
this.blockObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewMotionBlock));
|
this.blockObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewMotionBlock));
|
||||||
this.mediafilesObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewMediafile));
|
this.mediafilesObserver = new BehaviorSubject(this.viewModelStore.getAll(ViewMediafile));
|
||||||
@ -382,7 +387,9 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
this.submitterObserver.next(this.viewModelStore.getAll(ViewUser));
|
this.submitterObserver.next(this.viewModelStore.getAll(ViewUser));
|
||||||
this.supporterObserver.next(this.viewModelStore.getAll(ViewUser));
|
this.supporterObserver.next(this.viewModelStore.getAll(ViewUser));
|
||||||
} else if (newModel instanceof Category) {
|
} 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) {
|
} else if (newModel instanceof Workflow) {
|
||||||
this.workflowObserver.next(this.viewModelStore.getAll(ViewWorkflow));
|
this.workflowObserver.next(this.viewModelStore.getAll(ViewWorkflow));
|
||||||
} else if (newModel instanceof MotionBlock) {
|
} else if (newModel instanceof MotionBlock) {
|
||||||
|
@ -127,7 +127,7 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion> imple
|
|||||||
.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.getViewModelListObservable().subscribe(cats => (this.categories = cats));
|
this.categoryRepo.getSortedViewModelListObservable().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.filterService.filter().subscribe(filteredData => (this.sortService.data = filteredData));
|
this.filterService.filter().subscribe(filteredData => (this.sortService.data = filteredData));
|
||||||
|
@ -184,7 +184,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.getViewModelListObservable().subscribe(categories => {
|
this.categoryRepo.getSortedViewModelListObservable().subscribe(categories => {
|
||||||
const categoryOptions: (OsFilterOption | string)[] = [];
|
const categoryOptions: (OsFilterOption | string)[] = [];
|
||||||
categories.forEach(cat => {
|
categories.forEach(cat => {
|
||||||
categoryOptions.push({
|
categoryOptions.push({
|
||||||
|
@ -136,7 +136,7 @@ export class MotionMultiselectService {
|
|||||||
const clearChoice = 'No category';
|
const clearChoice = 'No category';
|
||||||
const selectedChoice = await this.choiceService.open(
|
const selectedChoice = await this.choiceService.open(
|
||||||
title,
|
title,
|
||||||
this.categoryRepo.getViewModelList(),
|
this.categoryRepo.sortViewCategoriesByConfig(this.categoryRepo.getViewModelList()),
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
clearChoice
|
clearChoice
|
||||||
|
@ -2,6 +2,9 @@ import { Injectable } from '@angular/core';
|
|||||||
|
|
||||||
import { BaseSortListService, OsSortingDefinition } from 'app/core/ui-services/base-sort-list.service';
|
import { BaseSortListService, OsSortingDefinition } from 'app/core/ui-services/base-sort-list.service';
|
||||||
import { ViewMotion } from '../models/view-motion';
|
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({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -24,4 +27,16 @@ export class MotionSortListService extends BaseSortListService<ViewMotion> {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
protected name = 'Motion';
|
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<keyof ViewMotion>('motions_motions_sorting');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,34 @@ def get_config_variables():
|
|||||||
subgroup="General",
|
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
|
# Amendments
|
||||||
|
|
||||||
yield ConfigVariable(
|
yield ConfigVariable(
|
||||||
@ -184,7 +212,7 @@ def get_config_variables():
|
|||||||
default_value=False,
|
default_value=False,
|
||||||
input_type="boolean",
|
input_type="boolean",
|
||||||
label="Activate statute amendments",
|
label="Activate statute amendments",
|
||||||
weight=335,
|
weight=338,
|
||||||
group="Motions",
|
group="Motions",
|
||||||
subgroup="Amendments",
|
subgroup="Amendments",
|
||||||
)
|
)
|
||||||
@ -194,7 +222,7 @@ def get_config_variables():
|
|||||||
default_value=False,
|
default_value=False,
|
||||||
input_type="boolean",
|
input_type="boolean",
|
||||||
label="Activate amendments",
|
label="Activate amendments",
|
||||||
weight=336,
|
weight=339,
|
||||||
group="Motions",
|
group="Motions",
|
||||||
subgroup="Amendments",
|
subgroup="Amendments",
|
||||||
)
|
)
|
||||||
@ -204,7 +232,7 @@ def get_config_variables():
|
|||||||
default_value=False,
|
default_value=False,
|
||||||
input_type="boolean",
|
input_type="boolean",
|
||||||
label="Show amendments together with motions",
|
label="Show amendments together with motions",
|
||||||
weight=337,
|
weight=340,
|
||||||
group="Motions",
|
group="Motions",
|
||||||
subgroup="Amendments",
|
subgroup="Amendments",
|
||||||
)
|
)
|
||||||
@ -213,7 +241,7 @@ def get_config_variables():
|
|||||||
name="motions_amendments_prefix",
|
name="motions_amendments_prefix",
|
||||||
default_value="-",
|
default_value="-",
|
||||||
label="Prefix for the identifier for amendments",
|
label="Prefix for the identifier for amendments",
|
||||||
weight=340,
|
weight=341,
|
||||||
group="Motions",
|
group="Motions",
|
||||||
subgroup="Amendments",
|
subgroup="Amendments",
|
||||||
)
|
)
|
||||||
@ -341,26 +369,12 @@ def get_config_variables():
|
|||||||
subgroup="Export",
|
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(
|
yield ConfigVariable(
|
||||||
name="motions_export_sequential_number",
|
name="motions_export_sequential_number",
|
||||||
default_value=True,
|
default_value=True,
|
||||||
input_type="boolean",
|
input_type="boolean",
|
||||||
label="Include the sequential number in PDF and DOCX",
|
label="Include the sequential number in PDF and DOCX",
|
||||||
weight=385,
|
weight=380,
|
||||||
group="Motions",
|
group="Motions",
|
||||||
subgroup="Export",
|
subgroup="Export",
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user