Implements a custom sorting for categories
- If the motion-list is sorted by categories, the category is internal sorted by the `category_weight` of the motion - Adds a slot to pass a custom sorting function to the `sort-filter-bar.component`
This commit is contained in:
parent
e28f0f6685
commit
ac9bcf8539
@ -20,6 +20,7 @@ export interface OsSortingDefinition<V> {
|
|||||||
export interface OsSortingOption<V> {
|
export interface OsSortingOption<V> {
|
||||||
property: keyof V;
|
property: keyof V;
|
||||||
label?: string;
|
label?: string;
|
||||||
|
sortFn?: (itemA: V, itemB: V, ascending: boolean, intl?: Intl.Collator) => number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,7 +58,7 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
|
|||||||
/**
|
/**
|
||||||
* The sorting function according to current settings.
|
* The sorting function according to current settings.
|
||||||
*/
|
*/
|
||||||
private sortFn: (a: V, b: V) => number;
|
public sortFn?: (a: V, b: V, ascending: boolean, intl?: Intl.Collator) => number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current sorting order
|
* Set the current sorting order
|
||||||
@ -201,16 +202,6 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
|
|||||||
this.store.set('sorting_' + this.name, this.sortDefinition);
|
this.store.set('sorting_' + this.name, this.sortDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sorts an array of data synchronously, using the currently configured sorting
|
|
||||||
*
|
|
||||||
* @param data Array of ViewModels
|
|
||||||
* @returns the data, sorted with the definitions of this service
|
|
||||||
*/
|
|
||||||
public sortSync(data: V[]): V[] {
|
|
||||||
return data.sort(this.sortFn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to determine false-like values (if they are not boolean)
|
* Helper function to determine false-like values (if they are not boolean)
|
||||||
* @param property
|
* @param property
|
||||||
@ -246,42 +237,45 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
|
|||||||
const firstProperty = this.ascending ? itemA[property] : itemB[property];
|
const firstProperty = this.ascending ? itemA[property] : itemB[property];
|
||||||
const secondProperty = this.ascending ? itemB[property] : itemA[property];
|
const secondProperty = this.ascending ? itemB[property] : itemA[property];
|
||||||
|
|
||||||
switch (typeof firstProperty) {
|
if (this.sortFn) {
|
||||||
case 'boolean':
|
return this.sortFn(itemA, itemB, this.ascending, intl);
|
||||||
if (!firstProperty && secondProperty) {
|
} else {
|
||||||
return -1;
|
switch (typeof firstProperty) {
|
||||||
} else {
|
case 'boolean':
|
||||||
return 1;
|
if (!firstProperty && secondProperty) {
|
||||||
}
|
return -1;
|
||||||
case 'number':
|
} else {
|
||||||
return firstProperty > secondProperty ? 1 : -1;
|
return 1;
|
||||||
case 'string':
|
}
|
||||||
if (!!firstProperty && !secondProperty) {
|
case 'number':
|
||||||
return -1;
|
|
||||||
} else if (!firstProperty && !!secondProperty) {
|
|
||||||
return 1;
|
|
||||||
} else if ((!secondProperty && !secondProperty) || firstProperty === secondProperty) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return intl.compare(firstProperty, secondProperty);
|
|
||||||
}
|
|
||||||
case 'function':
|
|
||||||
const a = firstProperty();
|
|
||||||
const b = secondProperty();
|
|
||||||
return intl.compare(a, b);
|
|
||||||
case 'object':
|
|
||||||
if (firstProperty instanceof Date) {
|
|
||||||
return firstProperty > secondProperty ? 1 : -1;
|
return firstProperty > secondProperty ? 1 : -1;
|
||||||
} else {
|
case 'string':
|
||||||
return intl.compare(firstProperty.toString(), secondProperty.toString());
|
if (!!firstProperty && !secondProperty) {
|
||||||
}
|
return -1;
|
||||||
case 'undefined':
|
} else if (!firstProperty && !!secondProperty) {
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
} else if ((!secondProperty && !secondProperty) || firstProperty === secondProperty) {
|
||||||
return -1;
|
return 0;
|
||||||
|
} else {
|
||||||
|
return intl.compare(firstProperty, secondProperty);
|
||||||
|
}
|
||||||
|
case 'function':
|
||||||
|
const a = firstProperty();
|
||||||
|
const b = secondProperty();
|
||||||
|
return intl.compare(a, b);
|
||||||
|
case 'object':
|
||||||
|
if (firstProperty instanceof Date) {
|
||||||
|
return firstProperty > secondProperty ? 1 : -1;
|
||||||
|
} else {
|
||||||
|
return intl.compare(firstProperty.toString(), secondProperty.toString());
|
||||||
|
}
|
||||||
|
case 'undefined':
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.outputSubject.next(this.inputData);
|
this.outputSubject.next(this.inputData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,8 @@ export class SortFilterBarComponent<V extends BaseViewModel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public set sortOption(option: OsSortingOption<V>) {
|
public set sortOption(option: OsSortingOption<V>) {
|
||||||
|
// If the option has a custom sorting function
|
||||||
|
this.sortService.sortFn = option.sortFn || null;
|
||||||
this.sortService.sortProperty = option.property;
|
this.sortService.sortProperty = option.property;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ export class MotionSortListService extends BaseSortListService<ViewMotion> {
|
|||||||
{ property: 'identifier' },
|
{ property: 'identifier' },
|
||||||
{ property: 'title' },
|
{ property: 'title' },
|
||||||
{ property: 'submitters' },
|
{ property: 'submitters' },
|
||||||
{ property: 'category' },
|
{ property: 'category', sortFn: this.categorySortFn },
|
||||||
{ property: 'motion_block_id', label: 'Motion block' },
|
{ property: 'motion_block_id', label: 'Motion block' },
|
||||||
{ property: 'state' },
|
{ property: 'state' },
|
||||||
{ property: 'creationDate', label: _('Creation date') },
|
{ property: 'creationDate', label: _('Creation date') },
|
||||||
@ -71,4 +71,30 @@ export class MotionSortListService extends BaseSortListService<ViewMotion> {
|
|||||||
sortAscending: true
|
sortAscending: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom function to sort the categories internal by the `category_weight` of the motion.
|
||||||
|
*
|
||||||
|
* @param itemA The first item to sort
|
||||||
|
* @param itemB The second item to sort
|
||||||
|
* @param intl The localizer to compare strings
|
||||||
|
* @param ascending If the sorting should be in ascended or descended order
|
||||||
|
*
|
||||||
|
* @returns {number} The result of comparing.
|
||||||
|
*/
|
||||||
|
private categorySortFn(itemA: ViewMotion, itemB: ViewMotion, ascending: boolean, intl: Intl.Collator): number {
|
||||||
|
const property = 'category';
|
||||||
|
const subProperty = 'category_weight';
|
||||||
|
const firstValue = ascending ? itemA[property] : itemB[property];
|
||||||
|
const secondValue = ascending ? itemB[property] : itemA[property];
|
||||||
|
|
||||||
|
const diff = intl.compare(firstValue.toString(), secondValue.toString());
|
||||||
|
if (diff === 0) {
|
||||||
|
const firstSubValue = ascending ? itemA[subProperty] : itemB[subProperty];
|
||||||
|
const secondSubValue = ascending ? itemB[subProperty] : itemA[subProperty];
|
||||||
|
return firstSubValue > secondSubValue ? 1 : -1;
|
||||||
|
} else {
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user