Add sort service for amendments

Adds the posibility to sort amendments by the parents identifier
and line number.

Patches the amendment model by their diff lines in runtime
This commit is contained in:
Sean Engelhardt 2019-09-03 15:11:54 +02:00
parent 8ff03044de
commit 91329a8338
16 changed files with 245 additions and 87 deletions

View File

@ -82,12 +82,18 @@ export class RelationManagerService {
); );
viewModel['_' + relation.ownKey] = foreignViewModels; viewModel['_' + relation.ownKey] = foreignViewModels;
this.sortByRelation(relation, viewModel); this.sortByRelation(relation, viewModel);
if (relation.afterSetRelation) {
relation.afterSetRelation(viewModel, foreignViewModels);
}
} else if (relation.type === 'M2O') { } else if (relation.type === 'M2O') {
const foreignViewModel = this.viewModelStoreService.get( const foreignViewModel = this.viewModelStoreService.get(
relation.foreignViewModel, relation.foreignViewModel,
model[relation.ownIdKey] model[relation.ownIdKey]
); );
viewModel['_' + relation.ownKey] = foreignViewModel; viewModel['_' + relation.ownKey] = foreignViewModel;
if (relation.afterSetRelation) {
relation.afterSetRelation(viewModel, foreignViewModel);
}
} }
} else if (isReverseRelationDefinition(relation) && !initialLoading) { } else if (isReverseRelationDefinition(relation) && !initialLoading) {
if (relation.type === 'M2M') { if (relation.type === 'M2M') {
@ -203,12 +209,19 @@ export class RelationManagerService {
) { ) {
const foreignViewModel = <any>this.viewModelStoreService.get(collection, changedId); const foreignViewModel = <any>this.viewModelStoreService.get(collection, changedId);
this.setForeingViewModelInOwnViewModelArray(foreignViewModel, ownViewModel, relation.ownKey); this.setForeingViewModelInOwnViewModelArray(foreignViewModel, ownViewModel, relation.ownKey);
if (relation.afterDependencyChange) {
relation.afterDependencyChange(ownViewModel, foreignViewModel);
}
return true; return true;
} }
} else if (relation.type === 'M2O') { } else if (relation.type === 'M2O') {
if (ownViewModel[relation.ownIdKey] === <any>changedId) { if (ownViewModel[relation.ownIdKey] === <any>changedId) {
// Check, if this is the matching foreign view model. // Check, if this is the matching foreign view model.
ownViewModel['_' + relation.ownKey] = <any>this.viewModelStoreService.get(collection, changedId); const foreignViewModel = this.viewModelStoreService.get(collection, changedId);
ownViewModel['_' + relation.ownKey] = <any>foreignViewModel;
if (relation.afterDependencyChange) {
relation.afterDependencyChange(ownViewModel, foreignViewModel);
}
return true; return true;
} }
} }

View File

@ -39,6 +39,8 @@ interface BaseNormalRelationDefinition<VForeign extends BaseViewModel> extends B
* the model and view model. E.g. `category_id` in a motion. * the model and view model. E.g. `category_id` in a motion.
*/ */
ownIdKey: string; ownIdKey: string;
afterDependencyChange?: (ownViewModel: BaseViewModel, foreignViewModel: BaseViewModel) => void;
} }
/** /**
@ -56,16 +58,19 @@ interface NormalM2MRelationDefinition<VForeign extends BaseViewModel>
extends BaseNormalRelationDefinition<VForeign>, extends BaseNormalRelationDefinition<VForeign>,
BaseOrderedRelation<VForeign> { BaseOrderedRelation<VForeign> {
type: 'M2M'; type: 'M2M';
afterSetRelation?: (ownViewModel: BaseViewModel, foreignViewModels: BaseViewModel[]) => void;
} }
interface NormalO2MRelationDefinition<VForeign extends BaseViewModel> interface NormalO2MRelationDefinition<VForeign extends BaseViewModel>
extends BaseNormalRelationDefinition<VForeign>, extends BaseNormalRelationDefinition<VForeign>,
BaseOrderedRelation<VForeign> { BaseOrderedRelation<VForeign> {
type: 'O2M'; type: 'O2M';
afterSetRelation?: (ownViewModel: BaseViewModel, foreignViewModels: BaseViewModel[]) => void;
} }
interface NormalM2ORelationDefinition<VForeign extends BaseViewModel> extends BaseNormalRelationDefinition<VForeign> { interface NormalM2ORelationDefinition<VForeign extends BaseViewModel> extends BaseNormalRelationDefinition<VForeign> {
type: 'M2O'; type: 'M2O';
afterSetRelation?: (ownViewModel: BaseViewModel, foreignViewModel: BaseViewModel | null) => void;
} }
export type NormalRelationDefinition<VForeign extends BaseViewModel = BaseViewModel> = export type NormalRelationDefinition<VForeign extends BaseViewModel = BaseViewModel> =

View File

@ -133,12 +133,6 @@ const MotionRelations: RelationDefinition[] = [
ownKey: 'tags', ownKey: 'tags',
foreignViewModel: ViewTag foreignViewModel: ViewTag
}, },
{
type: 'M2O',
ownIdKey: 'parent_id',
ownKey: 'parent',
foreignViewModel: ViewMotion
},
{ {
type: 'M2M', type: 'M2M',
ownIdKey: 'change_recommendations_id', ownIdKey: 'change_recommendations_id',
@ -171,6 +165,11 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
*/ */
protected sortProperty: SortProperty; protected sortProperty: SortProperty;
/**
* Line length of a motion
*/
private motionLineLength: number;
/** /**
* Creates a MotionRepository * Creates a MotionRepository
* *
@ -206,10 +205,15 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
this.sortProperty = conf; this.sortProperty = conf;
this.setConfigSortFn(); this.setConfigSortFn();
}); });
config.get<number>('motions_line_length').subscribe(lineLength => {
this.motionLineLength = lineLength;
});
} }
/** /**
* Adds the personal note custom relation to the relation definitions. * Adds the personal note custom relation to the relation definitions.
* Also adds the parent relation here to get access to methods in this repo.
*/ */
protected groupRelationsByCollections(): void { protected groupRelationsByCollections(): void {
this.relationDefinitions.push({ this.relationDefinitions.push({
@ -228,6 +232,22 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
return true; return true;
} }
}); });
this.relationDefinitions.push({
type: 'M2O',
ownIdKey: 'parent_id',
ownKey: 'parent',
foreignViewModel: ViewMotion,
afterSetRelation: (motion: ViewMotion, foreignViewModel: ViewMotion | null) => {
if (foreignViewModel) {
motion.diffLines = this.getAmendmentParagraphs(motion, this.motionLineLength, false);
}
},
afterDependencyChange: (motion: ViewMotion, parent: ViewMotion) => {
if (motion.parent) {
motion.diffLines = this.getAmendmentParagraphs(motion, this.motionLineLength, false);
}
}
});
super.groupRelationsByCollections(); super.groupRelationsByCollections();
} }
@ -284,8 +304,10 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
protected createViewModelWithTitles(model: Motion, initialLoading: boolean): ViewMotion { protected createViewModelWithTitles(model: Motion, initialLoading: boolean): ViewMotion {
const viewModel = super.createViewModelWithTitles(model, initialLoading); const viewModel = super.createViewModelWithTitles(model, initialLoading);
viewModel.getIdentifierOrTitle = () => this.getIdentifierOrTitle(viewModel); viewModel.getIdentifierOrTitle = () => this.getIdentifierOrTitle(viewModel);
viewModel.getProjectorTitle = () => this.getAgendaSlideTitle(viewModel); viewModel.getProjectorTitle = () => this.getAgendaSlideTitle(viewModel);
return viewModel; return viewModel;
} }
@ -639,16 +661,6 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
return range.to; return range.to;
} }
/**
* Given an amendment, this returns the motion affected by this amendments
*
* @param {ViewMotion} amendment
* @returns {ViewMotion}
*/
public getAmendmentBaseMotion(amendment: ViewMotion): ViewMotion {
return this.getViewModel(amendment.parent_id);
}
/** /**
* Splits a motion into paragraphs, optionally adding line numbers * Splits a motion into paragraphs, optionally adding line numbers
* *
@ -700,7 +712,7 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
lineLength: number, lineLength: number,
includeUnchanged: boolean includeUnchanged: boolean
): DiffLinesInParagraph[] { ): DiffLinesInParagraph[] {
const motion = this.getAmendmentBaseMotion(amendment); const motion = amendment.parent;
const baseParagraphs = this.getTextParagraphs(motion, true, lineLength); const baseParagraphs = this.getTextParagraphs(motion, true, lineLength);
return amendment.amendment_paragraphs return amendment.amendment_paragraphs
@ -744,7 +756,7 @@ export class MotionRepositoryService extends BaseIsAgendaItemAndListOfSpeakersCo
* @returns {ViewMotionAmendedParagraph[]} * @returns {ViewMotionAmendedParagraph[]}
*/ */
public getAmendmentAmendedParagraphs(amendment: ViewMotion, lineLength: number): ViewMotionAmendedParagraph[] { public getAmendmentAmendedParagraphs(amendment: ViewMotion, lineLength: number): ViewMotionAmendedParagraph[] {
const motion = this.getAmendmentBaseMotion(amendment); const motion = amendment.parent;
const baseParagraphs = this.getTextParagraphs(motion, true, lineLength); const baseParagraphs = this.getTextParagraphs(motion, true, lineLength);
return amendment.amendment_paragraphs return amendment.amendment_paragraphs

View File

@ -243,8 +243,6 @@ export abstract class BaseFilterListService<V extends BaseViewModel> {
if (storedFilter && storedFilter.length && newDefinitions && newDefinitions.length) { if (storedFilter && storedFilter.length && newDefinitions && newDefinitions.length) {
for (const newDef of newDefinitions) { for (const newDef of newDefinitions) {
console.log('set filter');
// for some weird angular bugs, newDef can actually be undefined // for some weird angular bugs, newDef can actually be undefined
if (newDef) { if (newDef) {
let count = 0; let count = 0;

View File

@ -55,6 +55,11 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
*/ */
private sortDefinition: OsSortingDefinition<V>; private sortDefinition: OsSortingDefinition<V>;
/**
* The key to access stored valued
*/
protected abstract readonly storageKey: string;
/** /**
* The sorting function according to current settings. * The sorting function according to current settings.
*/ */
@ -105,13 +110,15 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
* @returns wether sorting is active or not * @returns wether sorting is active or not
*/ */
public get isActive(): boolean { public get isActive(): boolean {
return this.sortDefinition && this.sortOptions.length > 0; return this.sortOptions && this.sortOptions.length > 0;
} }
/** public get sortOptions(): OsSortingOption<V>[] {
* Enforce children to implement sortOptions const sortOptions = this.getSortOptions();
*/ if (sortOptions && sortOptions.length) {
public abstract sortOptions: OsSortingOption<V>[]; return sortOptions;
}
}
/** /**
* Constructor. * Constructor.
@ -121,12 +128,16 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
* @param store to save and load sorting preferences * @param store to save and load sorting preferences
*/ */
public constructor( public constructor(
protected name: string,
protected translate: TranslateService, protected translate: TranslateService,
private store: StorageService, private store: StorageService,
private OSStatus: OpenSlidesStatusService private OSStatus: OpenSlidesStatusService
) {} ) {}
/**
* Enforce children to implement a function that returns their sorting options
*/
protected abstract getSortOptions(): OsSortingOption<V>[];
/** /**
* Enforce children to implement a method that returns the fault sorting * Enforce children to implement a method that returns the fault sorting
*/ */
@ -148,7 +159,7 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
if (this.OSStatus.isInHistoryMode) { if (this.OSStatus.isInHistoryMode) {
this.sortDefinition = null; this.sortDefinition = null;
} else { } else {
this.sortDefinition = await this.store.get<OsSortingDefinition<V> | null>('sorting_' + this.name); this.sortDefinition = await this.store.get<OsSortingDefinition<V> | null>('sorting_' + this.storageKey);
} }
if (this.sortDefinition && this.sortDefinition.sortProperty) { if (this.sortDefinition && this.sortDefinition.sortProperty) {
@ -183,11 +194,15 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
* @param option * @param option
* @returns the name of the sorting icon, fit to material icon ligatures * @returns the name of the sorting icon, fit to material icon ligatures
*/ */
public getSortIcon(option: OsSortingOption<V>): string { public getSortIcon(option: OsSortingOption<V>): string | null {
if (this.sortProperty !== option.property) { if (this.sortDefinition) {
return ''; if (this.sortProperty && this.sortProperty !== option.property) {
return '';
}
return this.ascending ? 'arrow_upward' : 'arrow_downward';
} else {
return null;
} }
return this.ascending ? 'arrow_upward' : 'arrow_downward';
} }
/** /**
@ -210,7 +225,7 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
private updateSortDefinitions(): void { private updateSortDefinitions(): void {
this.updateSortedData(); this.updateSortedData();
if (!this.OSStatus.isInHistoryMode) { if (!this.OSStatus.isInHistoryMode) {
this.store.set('sorting_' + this.name, this.sortDefinition); this.store.set('sorting_' + this.storageKey, this.sortDefinition);
} }
} }
@ -227,7 +242,7 @@ export abstract class BaseSortListService<V extends BaseViewModel> {
* every time the sorting (property, ascending/descending) or the language changes * every time the sorting (property, ascending/descending) or the language changes
*/ */
protected updateSortedData(): void { protected updateSortedData(): void {
if (this.inputData) { if (this.inputData && this.sortDefinition) {
const property = this.sortProperty as string; const property = this.sortProperty as string;
const intl = new Intl.Collator(this.translate.currentLang, { const intl = new Intl.Collator(this.translate.currentLang, {

View File

@ -208,8 +208,9 @@ export class SortFilterBarComponent<V extends BaseViewModel> {
* Retrieves the currently active icon for an option. * Retrieves the currently active icon for an option.
* @param option * @param option
*/ */
public getSortIcon(option: OsSortingOption<V>): string { public getSortIcon(option: OsSortingOption<V>): string | null {
return this.sortService.getSortIcon(option); const icon = this.sortService.getSortIcon(option);
return icon ? icon : null;
} }
/** /**

View File

@ -14,10 +14,15 @@ import { ViewAssignment } from '../models/view-assignment';
providedIn: 'root' providedIn: 'root'
}) })
export class AssignmentSortListService extends BaseSortListService<ViewAssignment> { export class AssignmentSortListService extends BaseSortListService<ViewAssignment> {
/**
* set the storage key name
*/
protected storageKey = 'AssignmentList';
/** /**
* Define the sort options * Define the sort options
*/ */
public sortOptions: OsSortingOption<ViewAssignment>[] = [ private assignmentSortOptions: OsSortingOption<ViewAssignment>[] = [
{ property: 'title', label: 'Name' }, { property: 'title', label: 'Name' },
{ property: 'phase', label: 'Phase' }, { property: 'phase', label: 'Phase' },
{ property: 'candidateAmount', label: 'Number of candidates' }, { property: 'candidateAmount', label: 'Number of candidates' },
@ -31,7 +36,14 @@ export class AssignmentSortListService extends BaseSortListService<ViewAssignmen
* @param storage required by parent * @param storage required by parent
*/ */
public constructor(translate: TranslateService, storage: StorageService, OSStatus: OpenSlidesStatusService) { public constructor(translate: TranslateService, storage: StorageService, OSStatus: OpenSlidesStatusService) {
super('Assignment', translate, storage, OSStatus); super(translate, storage, OSStatus);
}
/**
* @override
*/
protected getSortOptions(): OsSortingOption<ViewAssignment>[] {
return this.assignmentSortOptions;
} }
/** /**

View File

@ -14,7 +14,12 @@ import { ViewMediafile } from '../models/view-mediafile';
providedIn: 'root' providedIn: 'root'
}) })
export class MediafilesSortListService extends BaseSortListService<ViewMediafile> { export class MediafilesSortListService extends BaseSortListService<ViewMediafile> {
public sortOptions: OsSortingOption<ViewMediafile>[] = [ /**
* set the storage key name
*/
protected storageKey = 'MediafileList';
private mediafilesSortOptions: OsSortingOption<ViewMediafile>[] = [
{ property: 'title' }, { property: 'title' },
{ {
property: 'type', property: 'type',
@ -33,7 +38,14 @@ export class MediafilesSortListService extends BaseSortListService<ViewMediafile
* @param store required by parent * @param store required by parent
*/ */
public constructor(translate: TranslateService, store: StorageService, OSStatus: OpenSlidesStatusService) { public constructor(translate: TranslateService, store: StorageService, OSStatus: OpenSlidesStatusService) {
super('Mediafiles', translate, store, OSStatus); super(translate, store, OSStatus);
}
/**
* @override
*/
protected getSortOptions(): OsSortingOption<ViewMediafile>[] {
return this.mediafilesSortOptions;
} }
/** /**

View File

@ -1,5 +1,6 @@
import { _ } from 'app/core/translate/translation-marker'; import { _ } from 'app/core/translate/translation-marker';
import { ConfigService } from 'app/core/ui-services/config.service'; import { ConfigService } from 'app/core/ui-services/config.service';
import { DiffLinesInParagraph } from 'app/core/ui-services/diff.service';
import { SearchProperty, SearchRepresentation } from 'app/core/ui-services/search.service'; import { SearchProperty, SearchRepresentation } from 'app/core/ui-services/search.service';
import { Motion, MotionComment } from 'app/shared/models/motions/motion'; import { Motion, MotionComment } from 'app/shared/models/motions/motion';
import { PersonalNoteContent } from 'app/shared/models/users/personal-note'; import { PersonalNoteContent } from 'app/shared/models/users/personal-note';
@ -76,6 +77,7 @@ export class ViewMotion extends BaseViewModelWithAgendaItemAndListOfSpeakers<Mot
protected _parent?: ViewMotion; protected _parent?: ViewMotion;
protected _amendments?: ViewMotion[]; protected _amendments?: ViewMotion[];
protected _changeRecommendations?: ViewMotionChangeRecommendation[]; protected _changeRecommendations?: ViewMotionChangeRecommendation[];
protected _diffLines?: DiffLinesInParagraph[];
public personalNote?: PersonalNoteContent; public personalNote?: PersonalNoteContent;
public get motion(): Motion { public get motion(): Motion {
@ -342,6 +344,31 @@ export class ViewMotion extends BaseViewModelWithAgendaItemAndListOfSpeakers<Mot
return this.state ? this.state.css_class : ''; return this.state ? this.state.css_class : '';
} }
/**
* getter to access diff lines
*/
public get diffLines(): DiffLinesInParagraph[] {
if (!this.parent_id) {
throw new Error('No parent No diff');
}
return this._diffLines;
}
public set diffLines(value: DiffLinesInParagraph[]) {
this._diffLines = value;
}
/**
* Get the number of the first diff line, in case a motion is an amendment
*/
public get parentAndLineNumber(): string | null {
if (this.isParagraphBasedAmendment() && this.parent && this.diffLines && this.diffLines.length) {
return `${this.parent.identifier} ${this.diffLines[0].diffLineFrom}`;
} else {
return null;
}
}
// This is set by the repository // This is set by the repository
public getIdentifierOrTitle: () => string; public getIdentifierOrTitle: () => string;

View File

@ -18,7 +18,7 @@
<os-list-view-table <os-list-view-table
[repo]="motionRepo" [repo]="motionRepo"
[sortService]="motionSortService" [sortService]="amendmentSortService"
[filterService]="amendmentFilterService" [filterService]="amendmentFilterService"
[columns]="tableColumnDefinition" [columns]="tableColumnDefinition"
[filterProps]="filterProps" [filterProps]="filterProps"
@ -70,6 +70,7 @@
<!-- Summary --> <!-- Summary -->
<div *pblNgridCellDef="'summary'; row as motion" class="cell-slot fill"> <div *pblNgridCellDef="'summary'; row as motion" class="cell-slot fill">
<a class="detail-link" [routerLink]="motion.getDetailStateURL()"></a>
<div class="innerTable"> <div class="innerTable">
<div class="motion-text" [innerHtml]="sanitizeText(getAmendmentSummary(motion))"></div> <div class="motion-text" [innerHtml]="sanitizeText(getAmendmentSummary(motion))"></div>
</div> </div>

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
import { MatDialog, MatSnackBar } from '@angular/material'; import { MatDialog, MatSnackBar } from '@angular/material';
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser'; import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
@ -7,10 +7,9 @@ import { TranslateService } from '@ngx-translate/core';
import { PblColumnDefinition } from '@pebula/ngrid'; import { PblColumnDefinition } from '@pebula/ngrid';
import { AmendmentFilterListService } from '../../services/amendment-filter-list.service'; import { AmendmentFilterListService } from '../../services/amendment-filter-list.service';
import { AmendmentSortListService } from '../../services/amendment-sort-list.service';
import { StorageService } from 'app/core/core-services/storage.service'; import { StorageService } from 'app/core/core-services/storage.service';
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service'; import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
import { ConfigService } from 'app/core/ui-services/config.service';
import { DiffLinesInParagraph } from 'app/core/ui-services/diff.service';
import { LinenumberingService } from 'app/core/ui-services/linenumbering.service'; import { LinenumberingService } from 'app/core/ui-services/linenumbering.service';
import { ItemVisibilityChoices } from 'app/shared/models/agenda/item'; import { ItemVisibilityChoices } from 'app/shared/models/agenda/item';
import { largeDialogSettings } from 'app/shared/utils/dialog-settings'; import { largeDialogSettings } from 'app/shared/utils/dialog-settings';
@ -27,7 +26,8 @@ import { ViewMotion } from '../../models/view-motion';
selector: 'os-amendment-list', selector: 'os-amendment-list',
templateUrl: './amendment-list.component.html', templateUrl: './amendment-list.component.html',
styleUrls: ['./amendment-list.component.scss'], styleUrls: ['./amendment-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None
}) })
export class AmendmentListComponent extends BaseListViewComponent<ViewMotion> implements OnInit { export class AmendmentListComponent extends BaseListViewComponent<ViewMotion> implements OnInit {
/** /**
@ -40,11 +40,6 @@ export class AmendmentListComponent extends BaseListViewComponent<ViewMotion> im
*/ */
public itemVisibility = ItemVisibilityChoices; public itemVisibility = ItemVisibilityChoices;
/**
* To hold the motions line length
*/
private motionLineLength: number;
/** /**
* Column defintiion * Column defintiion
*/ */
@ -88,9 +83,9 @@ export class AmendmentListComponent extends BaseListViewComponent<ViewMotion> im
route: ActivatedRoute, route: ActivatedRoute,
public motionRepo: MotionRepositoryService, public motionRepo: MotionRepositoryService,
public motionSortService: MotionSortListService, public motionSortService: MotionSortListService,
public amendmentSortService: AmendmentSortListService,
public amendmentFilterService: AmendmentFilterListService, public amendmentFilterService: AmendmentFilterListService,
private sanitizer: DomSanitizer, private sanitizer: DomSanitizer,
private configService: ConfigService,
private dialog: MatDialog, private dialog: MatDialog,
private motionExport: MotionExportService, private motionExport: MotionExportService,
private linenumberingService: LinenumberingService private linenumberingService: LinenumberingService
@ -106,32 +101,7 @@ export class AmendmentListComponent extends BaseListViewComponent<ViewMotion> im
} }
} }
/** public ngOnInit(): void {}
* Observe the line length
*/
public ngOnInit(): void {
this.configService.get<number>('motions_line_length').subscribe(lineLength => {
this.motionLineLength = lineLength;
});
if (!!this.parentMotionId) {
// this.amendmentFilterService.clearAllFilters();
}
}
/**
* Helper function to get amendment paragraphs of a given motion
*
* @param amendment the get the paragraphs from
* @returns DiffLinesInParagraph-List
*/
private getDiffLines(amendment: ViewMotion): DiffLinesInParagraph[] {
if (amendment.isParagraphBasedAmendment()) {
return this.motionRepo.getAmendmentParagraphs(amendment, this.motionLineLength, false);
} else {
return null;
}
}
/** /**
* Extract the lines of the amendments * Extract the lines of the amendments
@ -141,7 +111,7 @@ export class AmendmentListComponent extends BaseListViewComponent<ViewMotion> im
* @return The lines of the amendment * @return The lines of the amendment
*/ */
public getChangeLines(amendment: ViewMotion): string { public getChangeLines(amendment: ViewMotion): string {
const diffLines = this.getDiffLines(amendment); const diffLines = amendment.diffLines;
if (!!diffLines) { if (!!diffLines) {
return diffLines return diffLines
@ -163,7 +133,7 @@ export class AmendmentListComponent extends BaseListViewComponent<ViewMotion> im
* @returns the amendments as string, if they are multiple they gonna be separated by `[...]` * @returns the amendments as string, if they are multiple they gonna be separated by `[...]`
*/ */
public getAmendmentSummary(amendment: ViewMotion): string { public getAmendmentSummary(amendment: ViewMotion): string {
const diffLines = this.getDiffLines(amendment); const diffLines = amendment.diffLines;
if (!!diffLines) { if (!!diffLines) {
return diffLines return diffLines
.map(diffLine => { .map(diffLine => {

View File

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { AmendmentSortListService } from './amendment-sort-list.service';
describe('AmendmentSortListService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: AmendmentSortListService = TestBed.get(AmendmentSortListService);
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,47 @@
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { OpenSlidesStatusService } from 'app/core/core-services/openslides-status.service';
import { StorageService } from 'app/core/core-services/storage.service';
import { OsSortingDefinition, OsSortingOption } from 'app/core/ui-services/base-sort-list.service';
import { ConfigService } from 'app/core/ui-services/config.service';
import { MotionSortListService } from './motion-sort-list.service';
import { ViewMotion } from '../models/view-motion';
@Injectable({
providedIn: 'root'
})
export class AmendmentSortListService extends MotionSortListService {
/**
* set the storage key name
*/
protected storageKey = 'AmendmentList';
private amendmentSortOptions: OsSortingOption<ViewMotion>[] = [
{
property: 'parentAndLineNumber',
label: 'Main motion and line number'
}
];
public constructor(
translate: TranslateService,
store: StorageService,
OSStatus: OpenSlidesStatusService,
config: ConfigService
) {
super(translate, store, OSStatus, config);
}
protected getSortOptions(): OsSortingOption<ViewMotion>[] {
return this.amendmentSortOptions.concat(super.getSortOptions());
}
protected async getDefaultDefinition(): Promise<OsSortingDefinition<ViewMotion>> {
return {
sortProperty: 'parentAndLineNumber',
sortAscending: true
};
}
}

View File

@ -11,7 +11,12 @@ import { ViewMotionBlock } from '../models/view-motion-block';
providedIn: 'root' providedIn: 'root'
}) })
export class MotionBlockSortService extends BaseSortListService<ViewMotionBlock> { export class MotionBlockSortService extends BaseSortListService<ViewMotionBlock> {
public sortOptions: OsSortingOption<ViewMotionBlock>[] = [ /**
* set the storage key name
*/
protected storageKey = 'MotionBlockList';
private MotionBlockSortOptions: OsSortingOption<ViewMotionBlock>[] = [
{ property: 'title' }, { property: 'title' },
{ {
property: 'motions', property: 'motions',
@ -25,7 +30,14 @@ export class MotionBlockSortService extends BaseSortListService<ViewMotionBlock>
]; ];
public constructor(translate: TranslateService, store: StorageService, OSStatus: OpenSlidesStatusService) { public constructor(translate: TranslateService, store: StorageService, OSStatus: OpenSlidesStatusService) {
super('Motion block', translate, store, OSStatus); super(translate, store, OSStatus);
}
/**
* @override
*/
protected getSortOptions(): OsSortingOption<ViewMotionBlock>[] {
return this.MotionBlockSortOptions;
} }
protected async getDefaultDefinition(): Promise<OsSortingDefinition<ViewMotionBlock>> { protected async getDefaultDefinition(): Promise<OsSortingDefinition<ViewMotionBlock>> {

View File

@ -17,6 +17,11 @@ import { ViewMotion } from '../models/view-motion';
providedIn: 'root' providedIn: 'root'
}) })
export class MotionSortListService extends BaseSortListService<ViewMotion> { export class MotionSortListService extends BaseSortListService<ViewMotion> {
/**
* set the storage key name
*/
protected storageKey = 'MotionList';
/** /**
* Hold the default motion sorting * Hold the default motion sorting
*/ */
@ -30,7 +35,7 @@ export class MotionSortListService extends BaseSortListService<ViewMotion> {
/** /**
* Define the sort options * Define the sort options
*/ */
public sortOptions: OsSortingOption<ViewMotion>[] = [ protected motionSortOptions: OsSortingOption<ViewMotion>[] = [
{ property: 'weight', label: 'Call list' }, { property: 'weight', label: 'Call list' },
{ property: 'identifier' }, { property: 'identifier' },
{ property: 'title' }, { property: 'title' },
@ -53,11 +58,11 @@ export class MotionSortListService extends BaseSortListService<ViewMotion> {
translate: TranslateService, translate: TranslateService,
store: StorageService, store: StorageService,
OSStatus: OpenSlidesStatusService, OSStatus: OpenSlidesStatusService,
private config: ConfigService config: ConfigService
) { ) {
super('Motion', translate, store, OSStatus); super(translate, store, OSStatus);
this.config.get<string>('motions_motions_sorting').subscribe(defSortProp => { config.get<string>('motions_motions_sorting').subscribe(defSortProp => {
if (defSortProp) { if (defSortProp) {
this.defaultMotionSorting = defSortProp; this.defaultMotionSorting = defSortProp;
this.defaultSortingLoaded.resolve(); this.defaultSortingLoaded.resolve();
@ -65,6 +70,10 @@ export class MotionSortListService extends BaseSortListService<ViewMotion> {
}); });
} }
protected getSortOptions(): OsSortingOption<ViewMotion>[] {
return this.motionSortOptions;
}
/** /**
* Required by parent * Required by parent
* *

View File

@ -14,10 +14,15 @@ import { ViewUser } from '../models/view-user';
providedIn: 'root' providedIn: 'root'
}) })
export class UserSortListService extends BaseSortListService<ViewUser> { export class UserSortListService extends BaseSortListService<ViewUser> {
/**
* set the storage key name
*/
protected storageKey = 'UserList';
/** /**
* Define the sort options * Define the sort options
*/ */
public sortOptions: OsSortingOption<ViewUser>[] = [ private userSortOptions: OsSortingOption<ViewUser>[] = [
{ property: 'first_name', label: 'Given name' }, { property: 'first_name', label: 'Given name' },
{ property: 'last_name', label: 'Surname' }, { property: 'last_name', label: 'Surname' },
{ property: 'is_present', label: 'Presence' }, { property: 'is_present', label: 'Presence' },
@ -36,7 +41,14 @@ export class UserSortListService extends BaseSortListService<ViewUser> {
* @param store requires by parent * @param store requires by parent
*/ */
public constructor(translate: TranslateService, store: StorageService, OSStatus: OpenSlidesStatusService) { public constructor(translate: TranslateService, store: StorageService, OSStatus: OpenSlidesStatusService) {
super('User', translate, store, OSStatus); super(translate, store, OSStatus);
}
/**
* @override
*/
protected getSortOptions(): OsSortingOption<ViewUser>[] {
return this.userSortOptions;
} }
/** /**