run prettifier

This commit is contained in:
FinnStutzenstein 2019-01-10 12:54:48 +01:00
parent 6e87a4bd80
commit 1c895fbea8
93 changed files with 511 additions and 500 deletions

View File

@ -54,7 +54,6 @@ export class AppComponent {
* TODO: Overloading can be extended to more functions. * TODO: Overloading can be extended to more functions.
*/ */
private overloadArrayToString(): void { private overloadArrayToString(): void {
Array.prototype.toString = function(): string { Array.prototype.toString = function(): string {
let string = ''; let string = '';
const iterations = Math.min(this.length, 3); const iterations = Math.min(this.length, 3);

View File

@ -19,10 +19,12 @@ function _(key: string | string[]): string | string[] {
// Core config strings // Core config strings
_('Presentation and assembly system'); _('Presentation and assembly system');
_('Event name'); _('Event name');
_('<a href="http://www.openslides.org">OpenSlides</a> is a free ' + _(
'<a href="http://www.openslides.org">OpenSlides</a> is a free ' +
'web based presentation and assembly system for visualizing ' + 'web based presentation and assembly system for visualizing ' +
'and controlling agenda, motions and elections of an ' + 'and controlling agenda, motions and elections of an ' +
'assembly.'); 'assembly.'
);
_('General'); _('General');
_('Event'); _('Event');
_('Short description of event'); _('Short description of event');
@ -94,7 +96,6 @@ _('Public item');
_('Internal item'); _('Internal item');
_('Hidden item'); _('Hidden item');
// Motions config strings // Motions config strings
// subgroup general // subgroup general
_('General'); _('General');
@ -115,13 +116,17 @@ _('Hide recommendation on projector');
_('Stop submitting new motions by non-staff users'); _('Stop submitting new motions by non-staff users');
_('Allow to disable versioning'); _('Allow to disable versioning');
_('Name of recommender'); _('Name of recommender');
_('Will be displayed as label before selected recommendation. Use an empty value to disable the recommendation system.'); _(
'Will be displayed as label before selected recommendation. Use an empty value to disable the recommendation system.'
);
_('Name of recommender for statute amendments'); _('Name of recommender for statute amendments');
_('Will be displayed as label before selected recommendation for statute amendments. Use an empty value to disable the recommendation system.'); _(
'Will be displayed as label before selected recommendation for statute amendments. Use an empty value to disable the recommendation system.'
);
_('Default text version for change recommendations'); _('Default text version for change recommendations');
// subgroup Amendments // subgroup Amendments
_('Amendments'); _('Amendments');
_('Activate statute amendments') _('Activate statute amendments');
_('Activate amendments'); _('Activate amendments');
_('Show amendments together with motions'); _('Show amendments together with motions');
_('Prefix for the identifier for amendments'); _('Prefix for the identifier for amendments');
@ -210,7 +215,6 @@ _('Called with');
_('Recommendation'); _('Recommendation');
_('Motion block'); _('Motion block');
// Assignment config strings // Assignment config strings
_('Election method'); _('Election method');
_('Automatic assign of method'); _('Automatic assign of method');
@ -220,10 +224,12 @@ _('Always Yes/No per candidate');
_('Elections'); _('Elections');
_('Ballot and ballot papers'); _('Ballot and ballot papers');
_('The 100-%-base of an election result consists of'); _('The 100-%-base of an election result consists of');
_('For Yes/No/Abstain per candidate and Yes/No per candidate the 100-%-base ' + _(
'For Yes/No/Abstain per candidate and Yes/No per candidate the 100-%-base ' +
'depends on the election method: If there is only one option per candidate, ' + 'depends on the election method: If there is only one option per candidate, ' +
'the sum of all votes of all candidates is 100 %. Otherwise for each ' + 'the sum of all votes of all candidates is 100 %. Otherwise for each ' +
'candidate the sum of all votes is 100 %.'); 'candidate the sum of all votes is 100 %.'
);
_('Yes/No/Abstain per candidate'); _('Yes/No/Abstain per candidate');
_('Yes/No per candidate'); _('Yes/No per candidate');
_('All valid ballots'); _('All valid ballots');
@ -316,7 +322,9 @@ _('Email subject');
_('Your login for {event_name}'); _('Your login for {event_name}');
_('You can use {event_name} as a placeholder.'); _('You can use {event_name} as a placeholder.');
_('Email body'); _('Email body');
_('Dear {name},\n\nthis is your OpenSlides login for the event {event_name}:\n\n {url}\n username: {username}\n password: {password}\n\nThis email was generated automatically.'); _(
'Dear {name},\n\nthis is your OpenSlides login for the event {event_name}:\n\n {url}\n username: {username}\n password: {password}\n\nThis email was generated automatically.'
);
_('Use these placeholders: {name}, {event_name}, {url}, {username}, {password}. The url referrs to the system url.'); _('Use these placeholders: {name}, {event_name}, {url}, {username}, {password}. The url referrs to the system url.');
// default groups // default groups

View File

@ -1,4 +1,3 @@
type QueryParamValue = string | number | boolean; type QueryParamValue = string | number | boolean;
/** /**

View File

@ -79,7 +79,11 @@ export class AppLoadService {
// between (ModelConstructor<BaseModel>) and (new (...args: any[]) => (BaseModel & Searchable)), we would not have // between (ModelConstructor<BaseModel>) and (new (...args: any[]) => (BaseModel & Searchable)), we would not have
// to check if the result of the contructor (the model instance) is really a searchable. // to check if the result of the contructor (the model instance) is really a searchable.
if (!isSearchable(new entry.model())) { if (!isSearchable(new entry.model())) {
throw Error(`Wrong configuration for ${entry.collectionString}: you gave a searchOrder, but the model is not searchable.`); throw Error(
`Wrong configuration for ${
entry.collectionString
}: you gave a searchOrder, but the model is not searchable.`
);
} }
return true; return true;
} }

View File

@ -115,7 +115,8 @@ export class CsvExportService {
csvContent.push(header); csvContent.push(header);
// create lines // create lines
csvContent = csvContent.concat(models.map(model => { csvContent = csvContent.concat(
models.map(model => {
return columns.map(column => { return columns.map(column => {
let value: string; let value: string;
@ -139,16 +140,19 @@ export class CsvExportService {
return value; return value;
}); });
})); })
);
// assemble lines, putting text separator in place // assemble lines, putting text separator in place
if (!tsList.length) { if (!tsList.length) {
throw new Error('no usable text separator left for valid csv text'); throw new Error('no usable text separator left for valid csv text');
} }
const csvContentAsString: string = csvContent.map(line => { const csvContentAsString: string = csvContent
.map(line => {
return line.map(entry => tsList[0] + entry + tsList[0]).join(columnSeparator); return line.map(entry => tsList[0] + entry + tsList[0]).join(columnSeparator);
}).join(lineSeparator); })
.join(lineSeparator);
this.exporter.saveFile(csvContentAsString, filename); this.exporter.saveFile(csvContentAsString, filename);
} }

View File

@ -97,7 +97,9 @@ export class DataStoreService {
/** /**
* Observable subject for changed or deleted models in the datastore. * Observable subject for changed or deleted models in the datastore.
*/ */
private readonly changedOrDeletedSubject: Subject<BaseModel | DeletedInformation> = new Subject<BaseModel | DeletedInformation>(); private readonly changedOrDeletedSubject: Subject<BaseModel | DeletedInformation> = new Subject<
BaseModel | DeletedInformation
>();
/** /**
* Observe the datastore for changes and deletions. * Observe the datastore for changes and deletions.
@ -358,7 +360,7 @@ export class DataStoreService {
collection: collectionString, collection: collectionString,
id: +id // needs casting, because Objects.keys gives all keys as strings... id: +id // needs casting, because Objects.keys gives all keys as strings...
}); });
}) });
}); });
if (models && models.length) { if (models && models.length) {
await this.add(models, newMaxChangeId); await this.add(models, newMaxChangeId);

View File

@ -5,7 +5,6 @@ import { BaseModel } from '../../shared/models/base/base-model';
import { BaseViewModel } from '../../site/base/base-view-model'; import { BaseViewModel } from '../../site/base/base-view-model';
import { StorageService } from './storage.service'; import { StorageService } from './storage.service';
/** /**
* Describes the available filters for a listView. * Describes the available filters for a listView.
* @param isActive: the current state of the filter * @param isActive: the current state of the filter
@ -31,15 +30,12 @@ export interface OsFilterOption {
isActive?: boolean; isActive?: boolean;
} }
/** /**
* Filter for the list view. List views can subscribe to its' dataService (providing filter definitions) * Filter for the list view. List views can subscribe to its' dataService (providing filter definitions)
* and will receive their filtered data as observable * and will receive their filtered data as observable
*/ */
export abstract class FilterListService<M extends BaseModel, V extends BaseViewModel> { export abstract class FilterListService<M extends BaseModel, V extends BaseViewModel> {
/** /**
* stores the currently used raw data to be used for the filter * stores the currently used raw data to be used for the filter
*/ */
@ -70,7 +66,10 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
* Initializes the filterService. Returns the filtered data as Observable * Initializes the filterService. Returns the filtered data as Observable
*/ */
public filter(): Observable<V[]> { public filter(): Observable<V[]> {
this.repo.getViewModelListObservable().pipe(auditTime(100)).subscribe( data => { this.repo
.getViewModelListObservable()
.pipe(auditTime(100))
.subscribe(data => {
this.currentRawData = data; this.currentRawData = data;
this.filteredData = this.filterData(data); this.filteredData = this.filterData(data);
this.filterDataOutput.next(this.filteredData); this.filterDataOutput.next(this.filteredData);
@ -86,8 +85,9 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
public addFilterOption(filterName: string, option: OsFilterOption): void { public addFilterOption(filterName: string, option: OsFilterOption): void {
const filter = this.filterDefinitions.find(f => f.property === filterName); const filter = this.filterDefinitions.find(f => f.property === filterName);
if (filter) { if (filter) {
const filterOption = filter.options.find(o => const filterOption = filter.options.find(
(typeof o !== 'string') && o.condition === option.condition) as OsFilterOption; o => typeof o !== 'string' && o.condition === option.condition
) as OsFilterOption;
if (filterOption && !filterOption.isActive) { if (filterOption && !filterOption.isActive) {
filterOption.isActive = true; filterOption.isActive = true;
filter.count += 1; filter.count += 1;
@ -105,8 +105,9 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
public removeFilterOption(filterName: string, option: OsFilterOption): void { public removeFilterOption(filterName: string, option: OsFilterOption): void {
const filter = this.filterDefinitions.find(f => f.property === filterName); const filter = this.filterDefinitions.find(f => f.property === filterName);
if (filter) { if (filter) {
const filterOption = filter.options.find(o => const filterOption = filter.options.find(
(typeof o !== 'string') && o.condition === option.condition) as OsFilterOption; o => typeof o !== 'string' && o.condition === option.condition
) as OsFilterOption;
if (filterOption && filterOption.isActive) { if (filterOption && filterOption.isActive) {
filterOption.isActive = false; filterOption.isActive = false;
filter.count -= 1; filter.count -= 1;
@ -130,7 +131,6 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
this.loadStorageDefinition(filters); this.loadStorageDefinition(filters);
} }
/** /**
* Retrieve the currently saved filter definition from the StorageService, * Retrieve the currently saved filter definition from the StorageService,
* check their match with current definitions and set the current filter * check their match with current definitions and set the current filter
@ -141,18 +141,20 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
return; return;
} }
const me = this; const me = this;
this.store.get('filter_' + this.name).then(function(storedData: { name: string, data: OsFilter[] }): void { this.store.get('filter_' + this.name).then(
const storedFilters = (storedData && storedData.data) ? storedData.data : []; function(storedData: { name: string; data: OsFilter[] }): void {
const storedFilters = storedData && storedData.data ? storedData.data : [];
definitions.forEach(definedFilter => { definitions.forEach(definedFilter => {
const matchingStoreFilter = storedFilters.find(f => f.property === definedFilter.property); const matchingStoreFilter = storedFilters.find(f => f.property === definedFilter.property);
let count = 0; let count = 0;
definedFilter.options.forEach(option => { definedFilter.options.forEach(option => {
if (typeof option === 'string') { if (typeof option === 'string') {
return; return;
}; }
if (matchingStoreFilter && matchingStoreFilter.options) { if (matchingStoreFilter && matchingStoreFilter.options) {
const storedOption = matchingStoreFilter.options.find(o => const storedOption = matchingStoreFilter.options.find(
typeof o !== 'string' && o.condition === option.condition) as OsFilterOption; o => typeof o !== 'string' && o.condition === option.condition
) as OsFilterOption;
if (storedOption) { if (storedOption) {
option.isActive = storedOption.isActive; option.isActive = storedOption.isActive;
} }
@ -166,10 +168,12 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
me.filterDefinitions = definitions; me.filterDefinitions = definitions;
me.filteredData = me.filterData(me.currentRawData); me.filteredData = me.filterData(me.currentRawData);
me.filterDataOutput.next(me.filteredData); me.filterDataOutput.next(me.filteredData);
}, function(error: any) : void { },
function(error: any): void {
me.filteredData = me.filterData(me.currentRawData); me.filteredData = me.filterData(me.currentRawData);
me.filterDataOutput.next(me.filteredData); me.filterDataOutput.next(me.filteredData);
}); }
);
} }
/** /**
@ -177,10 +181,11 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
*/ */
private setStorageDefinition(): void { private setStorageDefinition(): void {
this.store.set('filter_' + this.name, { this.store.set('filter_' + this.name, {
name: 'filter_' + this.name, data: this.filterDefinitions}); name: 'filter_' + this.name,
data: this.filterDefinitions
});
} }
/** /**
* Takes an array of data and applies current filters * Takes an array of data and applies current filters
*/ */
@ -234,7 +239,7 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
return true; return true;
} }
} }
}; }
return false; return false;
} }
@ -279,12 +284,11 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
if (filter.count) { if (filter.count) {
filters += 1; filters += 1;
} }
}; }
return filters; return filters;
} }
public hasFilterOptions(): boolean { public hasFilterOptions(): boolean {
return (this.filterDefinitions && this.filterDefinitions.length) ? true : false; return this.filterDefinitions && this.filterDefinitions.length ? true : false;
} }
} }

View File

@ -55,7 +55,13 @@ export class HttpService {
* @param customHeader optional custom HTTP header of required * @param customHeader optional custom HTTP header of required
* @returns a promise containing a generic * @returns a promise containing a generic
*/ */
private async send<T>(path: string, method: HTTPMethod, data?: any, queryParams?: QueryParams, customHeader?: HttpHeaders): Promise<T> { private async send<T>(
path: string,
method: HTTPMethod,
data?: any,
queryParams?: QueryParams,
customHeader?: HttpHeaders
): Promise<T> {
// end early, if we are in history mode // end early, if we are in history mode
if (this.OSStatus.isInHistoryMode && method !== HTTPMethod.GET) { if (this.OSStatus.isInHistoryMode && method !== HTTPMethod.GET) {
throw this.handleError('You cannot make changes while in history mode'); throw this.handleError('You cannot make changes while in history mode');

View File

@ -8,7 +8,6 @@ import { Injectable } from '@angular/core';
providedIn: 'root' providedIn: 'root'
}) })
export class OpenSlidesStatusService { export class OpenSlidesStatusService {
/** /**
* Saves, if OpenSlides is in the history mode. * Saves, if OpenSlides is in the history mode.
*/ */

View File

@ -4,10 +4,12 @@ import { TimeTravelService } from './time-travel.service';
import { E2EImportsModule } from 'e2e-imports.module'; import { E2EImportsModule } from 'e2e-imports.module';
describe('TimeTravelService', () => { describe('TimeTravelService', () => {
beforeEach(() => TestBed.configureTestingModule({ beforeEach(() =>
TestBed.configureTestingModule({
imports: [E2EImportsModule], imports: [E2EImportsModule],
providers: [TimeTravelService] providers: [TimeTravelService]
})); })
);
it('should be created', () => { it('should be created', () => {
const service: TimeTravelService = TestBed.get(TimeTravelService); const service: TimeTravelService = TestBed.get(TimeTravelService);

View File

@ -65,11 +65,11 @@ export class TimeTravelService {
for (const historyObject of fullDataHistory) { for (const historyObject of fullDataHistory) {
let collectionString: string; let collectionString: string;
let id: string; let id: string;
[collectionString, id] = historyObject.element_id.split(':') [collectionString, id] = historyObject.element_id.split(':');
if (historyObject.full_data) { if (historyObject.full_data) {
const targetClass = this.modelMapperService.getModelConstructor(collectionString); const targetClass = this.modelMapperService.getModelConstructor(collectionString);
await this.DS.add([new targetClass(historyObject.full_data)]) await this.DS.add([new targetClass(historyObject.full_data)]);
} else { } else {
await this.DS.remove(collectionString, [+id]); await this.DS.remove(collectionString, [+id]);
} }
@ -94,7 +94,7 @@ export class TimeTravelService {
* @returns the full history on the given date * @returns the full history on the given date
*/ */
private async getHistoryData(history: History): Promise<HistoryData[]> { private async getHistoryData(history: History): Promise<HistoryData[]> {
const historyUrl = '/core/history/' const historyUrl = '/core/history/';
const queryParams = { timestamp: Math.ceil(+history.unixtime) }; const queryParams = { timestamp: Math.ceil(+history.unixtime) };
return this.httpService.get<HistoryData[]>(environment.urlPrefix + historyUrl, null, queryParams); return this.httpService.get<HistoryData[]>(environment.urlPrefix + historyUrl, null, queryParams);
} }

View File

@ -71,11 +71,7 @@ export class WebsocketService {
* @param zone * @param zone
* @param translate * @param translate
*/ */
public constructor( public constructor(private matSnackBar: MatSnackBar, private zone: NgZone, public translate: TranslateService) {}
private matSnackBar: MatSnackBar,
private zone: NgZone,
public translate: TranslateService
) {}
/** /**
* Creates a new WebSocket connection and handles incomming events. * Creates a new WebSocket connection and handles incomming events.

View File

@ -5,19 +5,16 @@ describe('FilterMenuComponent', () => {
// TODO test won't work without a BaseViewModel // TODO test won't work without a BaseViewModel
// let component: FilterMenuComponent<V>; // let component: FilterMenuComponent<V>;
// let fixture: ComponentFixture<FilterMenuComponent<V>>; // let fixture: ComponentFixture<FilterMenuComponent<V>>;
// beforeEach(async(() => { // beforeEach(async(() => {
// TestBed.configureTestingModule({ // TestBed.configureTestingModule({
// declarations: [FilterMenuComponent] // declarations: [FilterMenuComponent]
// }).compileComponents(); // }).compileComponents();
// })); // }));
// beforeEach(() => { // beforeEach(() => {
// fixture = TestBed.createComponent(FilterMenuComponent); // fixture = TestBed.createComponent(FilterMenuComponent);
// component = fixture.componentInstance; // component = fixture.componentInstance;
// fixture.detectChanges(); // fixture.detectChanges();
// }); // });
// it('should create', () => { // it('should create', () => {
// expect(component).toBeTruthy(); // expect(component).toBeTruthy();
// }); // });

View File

@ -18,7 +18,6 @@ import { FilterListService, OsFilterOption } from '../../../../core/services/fil
styleUrls: ['./filter-menu.component.scss'] styleUrls: ['./filter-menu.component.scss']
}) })
export class FilterMenuComponent implements OnInit { export class FilterMenuComponent implements OnInit {
/** /**
* An event emitter to submit a desire to close this component * An event emitter to submit a desire to close this component
* TODO: Might be an easier way to do this * TODO: Might be an easier way to do this
@ -37,8 +36,7 @@ export class FilterMenuComponent implements OnInit {
* Constructor. Does nothing. * Constructor. Does nothing.
* @param service * @param service
*/ */
public constructor() { public constructor() {}
}
/** /**
* Directly closes again if no sorting is available * Directly closes again if no sorting is available
@ -55,10 +53,10 @@ export class FilterMenuComponent implements OnInit {
*/ */
public checkKeyEvent(event: KeyboardEvent): void { public checkKeyEvent(event: KeyboardEvent): void {
if (event.key === 'Escape') { if (event.key === 'Escape') {
this.dismissed.next(true) this.dismissed.next(true);
} }
} }
public isFilter(option: OsFilterOption): boolean { public isFilter(option: OsFilterOption): boolean {
return (typeof option === 'string') ? false : true; return typeof option === 'string' ? false : true;
} }
} }

View File

@ -3,7 +3,6 @@ import { E2EImportsModule } from 'e2e-imports.module';
import { OsSortBottomSheetComponent } from './os-sort-bottom-sheet.component'; import { OsSortBottomSheetComponent } from './os-sort-bottom-sheet.component';
describe('OsSortBottomSheetComponent', () => { describe('OsSortBottomSheetComponent', () => {
// let component: OsSortBottomSheetComponent<any>; // let component: OsSortBottomSheetComponent<any>;
let fixture: ComponentFixture<OsSortBottomSheetComponent<any>>; let fixture: ComponentFixture<OsSortBottomSheetComponent<any>>;

View File

@ -19,15 +19,15 @@ import { SortListService } from '../../../../core/services/sort-list.service';
styleUrls: ['./os-sort-bottom-sheet.component.scss'] styleUrls: ['./os-sort-bottom-sheet.component.scss']
}) })
export class OsSortBottomSheetComponent<V extends BaseViewModel> implements OnInit { export class OsSortBottomSheetComponent<V extends BaseViewModel> implements OnInit {
/** /**
* Constructor. Gets a reference to itself (for closing after interaction) * Constructor. Gets a reference to itself (for closing after interaction)
* @param data * @param data
* @param sheetRef * @param sheetRef
*/ */
public constructor( public constructor(
@Inject(MAT_BOTTOM_SHEET_DATA) public data: SortListService<V>, private sheetRef: MatBottomSheetRef ) { @Inject(MAT_BOTTOM_SHEET_DATA) public data: SortListService<V>,
} private sheetRef: MatBottomSheetRef
) {}
/** /**
* init fucntion. Closes inmediately if no sorting is available. * init fucntion. Closes inmediately if no sorting is available.

View File

@ -9,7 +9,7 @@ describe('OsSortFilterBarComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [E2EImportsModule], imports: [E2EImportsModule]
}).compileComponents(); }).compileComponents();
})); }));

View File

@ -5,7 +5,7 @@ import { TranslateService } from '@ngx-translate/core';
import { BaseViewModel } from '../../../site/base/base-view-model'; import { BaseViewModel } from '../../../site/base/base-view-model';
import { OsSortBottomSheetComponent } from './os-sort-bottom-sheet/os-sort-bottom-sheet.component'; import { OsSortBottomSheetComponent } from './os-sort-bottom-sheet/os-sort-bottom-sheet.component';
import { FilterMenuComponent } from './filter-menu/filter-menu.component'; import { FilterMenuComponent } from './filter-menu/filter-menu.component';
import { OsSortingItem } from '../../../core/services/sort-list.service' import { OsSortingItem } from '../../../core/services/sort-list.service';
import { SortListService } from '../../../core/services/sort-list.service'; import { SortListService } from '../../../core/services/sort-list.service';
import { ViewportService } from '../../../core/services/viewport.service'; import { ViewportService } from '../../../core/services/viewport.service';
@ -29,7 +29,6 @@ import { ViewportService } from '../../../core/services/viewport.service';
styleUrls: ['./os-sort-filter-bar.component.scss'] styleUrls: ['./os-sort-filter-bar.component.scss']
}) })
export class OsSortFilterBarComponent<V extends BaseViewModel> { export class OsSortFilterBarComponent<V extends BaseViewModel> {
/** /**
* The currently active sorting service for the list view * The currently active sorting service for the list view
*/ */
@ -68,7 +67,11 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
* @param vp * @param vp
* @param bottomSheet * @param bottomSheet
*/ */
public constructor(public translate: TranslateService, public vp: ViewportService, private bottomSheet: MatBottomSheet) { public constructor(
public translate: TranslateService,
public vp: ViewportService,
private bottomSheet: MatBottomSheet
) {
this.filterMenu = new FilterMenuComponent(); this.filterMenu = new FilterMenuComponent();
} }
@ -77,9 +80,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
*/ */
public openSortDropDown(): void { public openSortDropDown(): void {
if (this.vp.isMobile) { if (this.vp.isMobile) {
const bottomSheetRef = this.bottomSheet.open(OsSortBottomSheetComponent, const bottomSheetRef = this.bottomSheet.open(OsSortBottomSheetComponent, { data: this.sortService });
{ data: this.sortService }
);
bottomSheetRef.afterDismissed().subscribe(result => { bottomSheetRef.afterDismissed().subscribe(result => {
if (result) { if (result) {
this.sortService.sortProperty = result; this.sortService.sortProperty = result;
@ -104,7 +105,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
* Checks if there is an active SortService present * Checks if there is an active SortService present
*/ */
public get hasSorting(): boolean { public get hasSorting(): boolean {
return (this.sortService && this.sortService.isActive); return this.sortService && this.sortService.isActive;
} }
/** /**
@ -113,7 +114,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
public get hasFilters(): boolean { public get hasFilters(): boolean {
if (this.filterService && this.filterService.hasFilterOptions()) { if (this.filterService && this.filterService.hasFilterOptions()) {
return true; return true;
}; }
return false; return false;
} }

View File

@ -78,7 +78,7 @@ export class SortingListComponent implements OnInit, OnDestroy {
if (newValues instanceof Observable) { if (newValues instanceof Observable) {
this.inputSubscription = newValues.subscribe(values => { this.inputSubscription = newValues.subscribe(values => {
this.updateArray(values); this.updateArray(values);
}) });
} else { } else {
this.inputSubscription = null; this.inputSubscription = null;
this.updateArray(newValues); this.updateArray(newValues);

View File

@ -10,7 +10,12 @@ import { BehaviorSubject } from 'rxjs';
* A test model for the sorting * A test model for the sorting
*/ */
class TestModel implements Identifiable, Displayable { class TestModel implements Identifiable, Displayable {
public constructor(public id: number, public name: string, public weight: number, public parent_id: number | null){} public constructor(
public id: number,
public name: string,
public weight: number,
public parent_id: number | null
) {}
public getTitle(): string { public getTitle(): string {
return this.name; return this.name;

View File

@ -3,7 +3,6 @@ import { Poll } from './poll';
import { AgendaBaseModel } from '../base/agenda-base-model'; import { AgendaBaseModel } from '../base/agenda-base-model';
import { SearchRepresentation } from '../../../core/services/search.service'; import { SearchRepresentation } from '../../../core/services/search.service';
export const assignmentPhase = [ export const assignmentPhase = [
{ key: 0, name: 'Searching for candidates' }, { key: 0, name: 'Searching for candidates' },
{ key: 1, name: 'Voting' }, { key: 1, name: 'Voting' },

View File

@ -46,7 +46,6 @@ export abstract class AgendaBaseModel extends ProjectableBaseModel implements Ag
*/ */
public abstract formatForSearch(): SearchRepresentation; public abstract formatForSearch(): SearchRepresentation;
/** /**
* Should return the URL to the detail view. Used for the agenda, that the * Should return the URL to the detail view. Used for the agenda, that the
* user can navigate to the content object. * user can navigate to the content object.

View File

@ -1,4 +1,4 @@
import { DetailNavigable } from "./detail-navigable"; import { DetailNavigable } from './detail-navigable';
/** /**
* An Interface for all extra information needed for content objects of items. * An Interface for all extra information needed for content objects of items.

View File

@ -98,7 +98,7 @@ export abstract class BaseModel<T = object> extends OpenSlidesComponent
// topicS, motionS, (media)fileS, motion blockS, commentS, personal noteS, projectorS, messageS, countdownS, ...) // topicS, motionS, (media)fileS, motion blockS, commentS, personal noteS, projectorS, messageS, countdownS, ...)
// Just categorIES need to overwrite this... // Just categorIES need to overwrite this...
} else { } else {
return this._verboseName return this._verboseName;
} }
} }

View File

@ -1,4 +1,3 @@
import { BaseModel } from '../base/base-model'; import { BaseModel } from '../base/base-model';
/** /**

View File

@ -86,7 +86,7 @@ export class Motion extends AgendaBaseModel {
* @override * @override
*/ */
public formatForSearch(): SearchRepresentation { public formatForSearch(): SearchRepresentation {
let searchValues = [this.title, this.text, this.reason] let searchValues = [this.title, this.text, this.reason];
if (this.amendment_paragraphs) { if (this.amendment_paragraphs) {
searchValues = searchValues.concat(this.amendment_paragraphs.filter(x => !!x)); searchValues = searchValues.concat(this.amendment_paragraphs.filter(x => !!x));
} }

View File

@ -4,7 +4,10 @@ import { Topic } from '../../shared/models/topics/topic';
export const AgendaAppConfig: AppConfig = { export const AgendaAppConfig: AppConfig = {
name: 'agenda', name: 'agenda',
models: [{ collectionString: 'agenda/item', model: Item }, { collectionString: 'topics/topic', model: Topic, searchOrder: 1 }], models: [
{ collectionString: 'agenda/item', model: Item },
{ collectionString: 'topics/topic', model: Topic, searchOrder: 1 }
],
mainMenuEntries: [ mainMenuEntries: [
{ {
route: '/agenda', route: '/agenda',

View File

@ -1,5 +1,4 @@
.os-listview-table { .os-listview-table {
/** Title */ /** Title */
.mat-column-title { .mat-column-title {
padding-left: 26px; padding-left: 26px;
@ -27,7 +26,6 @@
height: $icon-size; height: $icon-size;
width: $icon-size; width: $icon-size;
} }
} }
} }

View File

@ -10,7 +10,6 @@ import { ListViewBaseComponent } from 'app/site/base/list-view-base';
import { PromptService } from '../../../../core/services/prompt.service'; import { PromptService } from '../../../../core/services/prompt.service';
import { ViewItem } from '../../models/view-item'; import { ViewItem } from '../../models/view-item';
import { AgendaCsvExportService } from '../../services/agenda-csv-export.service'; import { AgendaCsvExportService } from '../../services/agenda-csv-export.service';
import { ItemInfoDialogComponent } from '../item-info-dialog/item-info-dialog.component'; import { ItemInfoDialogComponent } from '../item-info-dialog/item-info-dialog.component';
import { ViewportService } from 'app/core/services/viewport.service'; import { ViewportService } from 'app/core/services/viewport.service';

View File

@ -73,7 +73,7 @@ export class SpeakerListComponent extends BaseViewComponent implements OnInit {
private itemRepo: AgendaRepositoryService, private itemRepo: AgendaRepositoryService,
private op: OperatorService private op: OperatorService
) { ) {
super(title, translate, snackBar) super(title, translate, snackBar);
this.addSpeakerForm = new FormGroup({ user_id: new FormControl([]) }); this.addSpeakerForm = new FormGroup({ user_id: new FormControl([]) });
this.getAgendaItemByUrl(); this.getAgendaItemByUrl();
} }

View File

@ -11,10 +11,7 @@ describe('AgendaCsvExportService', () => {
}); });
}); });
it('should be created', inject( it('should be created', inject([AgendaCsvExportService], (service: AgendaCsvExportService) => {
[AgendaCsvExportService],
(service: AgendaCsvExportService) => {
expect(service).toBeTruthy(); expect(service).toBeTruthy();
} }));
));
}); });

View File

@ -12,7 +12,6 @@ import { ViewItem } from '../models/view-item';
providedIn: 'root' providedIn: 'root'
}) })
export class AgendaCsvExportService { export class AgendaCsvExportService {
/** /**
* Does nothing. * Does nothing.
* *
@ -27,10 +26,14 @@ export class AgendaCsvExportService {
* @param Agendas Agendas to export * @param Agendas Agendas to export
*/ */
public exportItemList(items: ViewItem[]): void { public exportItemList(items: ViewItem[]): void {
this.csvExport.export(items, this.csvExport.export(
items,
[ [
{ label: 'Title', map: viewItem => viewItem.getTitle() }, { label: 'Title', map: viewItem => viewItem.getTitle() },
{ label: 'Text', map: viewItem => viewItem.contentObject ? viewItem.contentObject.getCSVExportText() : '' }, {
label: 'Text',
map: viewItem => (viewItem.contentObject ? viewItem.contentObject.getCSVExportText() : '')
},
{ label: 'Duration', property: 'duration' }, { label: 'Duration', property: 'duration' },
{ label: 'Comment', property: 'comment' }, { label: 'Comment', property: 'comment' },
{ label: 'Item type', property: 'verboseCsvType' } { label: 'Item type', property: 'verboseCsvType' }

View File

@ -1,16 +1,15 @@
import { Injectable } from "@angular/core"; import { Injectable } from '@angular/core';
import { FilterListService, OsFilter, OsFilterOption } from "../../../core/services/filter-list.service"; import { FilterListService, OsFilter, OsFilterOption } from '../../../core/services/filter-list.service';
import { Item, itemVisibilityChoices } from "../../../shared/models/agenda/item"; import { Item, itemVisibilityChoices } from '../../../shared/models/agenda/item';
import { ViewItem } from "../models/view-item"; import { ViewItem } from '../models/view-item';
import { StorageService } from "app/core/services/storage.service"; import { StorageService } from 'app/core/services/storage.service';
import { AgendaRepositoryService } from "./agenda-repository.service"; import { AgendaRepositoryService } from './agenda-repository.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class AgendaFilterListService extends FilterListService<Item, ViewItem> { export class AgendaFilterListService extends FilterListService<Item, ViewItem> {
protected name = 'Agenda'; protected name = 'Agenda';
public filterOptions: OsFilter[] = []; public filterOptions: OsFilter[] = [];
@ -22,18 +21,18 @@ export class AgendaFilterListService extends FilterListService<Item, ViewItem> {
*/ */
public constructor(store: StorageService, repo: AgendaRepositoryService) { public constructor(store: StorageService, repo: AgendaRepositoryService) {
super(store, repo); super(store, repo);
this.filterOptions = [{ this.filterOptions = [
{
label: 'Visibility', label: 'Visibility',
property: 'type', property: 'type',
options: this.createVisibilityFilterOptions() options: this.createVisibilityFilterOptions()
}, { },
{
label: 'Hidden Status', label: 'Hidden Status',
property: 'done', property: 'done',
options: [ options: [{ label: 'Open', condition: false }, { label: 'Closed', condition: true }]
{label: 'Open', condition: false}, }
{label: 'Closed', condition: true} ];
]
}];
} }
private createVisibilityFilterOptions(): OsFilterOption[] { private createVisibilityFilterOptions(): OsFilterOption[] {
@ -46,6 +45,4 @@ export class AgendaFilterListService extends FilterListService<Item, ViewItem> {
}); });
return options; return options;
} }
} }

View File

@ -187,7 +187,7 @@ export class AgendaRepositoryService extends BaseRepository<ViewItem, Item> {
* deleted (right now) * deleted (right now)
*/ */
public delete(item: ViewItem): Promise<void> { public delete(item: ViewItem): Promise<void> {
throw new Error("Method not implemented."); throw new Error('Method not implemented.');
} }
/** /**
@ -196,7 +196,7 @@ export class AgendaRepositoryService extends BaseRepository<ViewItem, Item> {
* Agenda items are created implicitly and do not have on create functions * Agenda items are created implicitly and do not have on create functions
*/ */
public async create(item: Item): Promise<Identifiable> { public async create(item: Item): Promise<Identifiable> {
throw new Error("Method not implemented."); throw new Error('Method not implemented.');
} }
/** /**

View File

@ -7,7 +7,8 @@ describe('TopicRepositoryService', () => {
beforeEach(() => beforeEach(() =>
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [E2EImportsModule] imports: [E2EImportsModule]
})); })
);
it('should be created', () => { it('should be created', () => {
const service: TopicRepositoryService = TestBed.get(TopicRepositoryService); const service: TopicRepositoryService = TestBed.get(TopicRepositoryService);

View File

@ -10,8 +10,6 @@ import { PromptService } from '../../../core/services/prompt.service';
import { ViewAssignment } from '../models/view-assignment'; import { ViewAssignment } from '../models/view-assignment';
import { AssignmentSortListService } from '../services/assignment-sort-list.service'; import { AssignmentSortListService } from '../services/assignment-sort-list.service';
/** /**
* Listview for the assignments * Listview for the assignments
* *
@ -22,7 +20,6 @@ import { AssignmentSortListService } from '../services/assignment-sort-list.serv
styleUrls: ['./assignment-list.component.scss'] styleUrls: ['./assignment-list.component.scss']
}) })
export class AssignmentListComponent extends ListViewBaseComponent<ViewAssignment> implements OnInit { export class AssignmentListComponent extends ListViewBaseComponent<ViewAssignment> implements OnInit {
/** /**
* Constructor. * Constructor.
* @param titleService * @param titleService

View File

@ -1,27 +1,27 @@
import { Injectable } from "@angular/core"; import { Injectable } from '@angular/core';
import { AssignmentRepositoryService } from "./assignment-repository.service";
import { Assignment, assignmentPhase } from "../../../shared/models/assignments/assignment";
import { FilterListService, OsFilter, OsFilterOption } from "../../../core/services/filter-list.service";
import { StorageService } from "app/core/services/storage.service";
import { ViewAssignment } from "../models/view-assignment";
import { AssignmentRepositoryService } from './assignment-repository.service';
import { Assignment, assignmentPhase } from '../../../shared/models/assignments/assignment';
import { FilterListService, OsFilter, OsFilterOption } from '../../../core/services/filter-list.service';
import { StorageService } from 'app/core/services/storage.service';
import { ViewAssignment } from '../models/view-assignment';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class AssignmentFilterListService extends FilterListService<Assignment, ViewAssignment> { export class AssignmentFilterListService extends FilterListService<Assignment, ViewAssignment> {
protected name = 'Assignment'; protected name = 'Assignment';
public filterOptions: OsFilter[]; public filterOptions: OsFilter[];
public constructor(store: StorageService, assignmentRepo: AssignmentRepositoryService) { public constructor(store: StorageService, assignmentRepo: AssignmentRepositoryService) {
super(store, assignmentRepo); super(store, assignmentRepo);
this.filterOptions = [{ this.filterOptions = [
{
property: 'phase', property: 'phase',
options: this.createPhaseOptions() options: this.createPhaseOptions()
}]; }
];
} }
private createPhaseOptions(): OsFilterOption[] { private createPhaseOptions(): OsFilterOption[] {

View File

@ -24,10 +24,7 @@ export class AssignmentRepositoryService extends BaseRepository<ViewAssignment,
* @param DS The DataStore * @param DS The DataStore
* @param mapperService Maps collection strings to classes * @param mapperService Maps collection strings to classes
*/ */
public constructor( public constructor(DS: DataStoreService, mapperService: CollectionStringModelMapperService) {
DS: DataStoreService,
mapperService: CollectionStringModelMapperService
) {
super(DS, mapperService, Assignment, [User, Item, Tag]); super(DS, mapperService, Assignment, [User, Item, Tag]);
} }

View File

@ -6,7 +6,6 @@ import { ViewAssignment } from '../models/view-assignment';
providedIn: 'root' providedIn: 'root'
}) })
export class AssignmentSortListService extends SortListService<ViewAssignment> { export class AssignmentSortListService extends SortListService<ViewAssignment> {
public sortOptions: OsSortingDefinition<ViewAssignment> = { public sortOptions: OsSortingDefinition<ViewAssignment> = {
sortProperty: 'assignment', sortProperty: 'assignment',
sortAscending: true, sortAscending: true,
@ -18,5 +17,4 @@ export class AssignmentSortListService extends SortListService<ViewAssignment> {
] ]
}; };
protected name = 'Assignment'; protected name = 'Assignment';
} }

View File

@ -9,7 +9,7 @@ export interface ModelEntry {
export interface SearchableModelEntry { export interface SearchableModelEntry {
collectionString: string; collectionString: string;
model: new (...args: any[]) => (BaseModel & Searchable); model: new (...args: any[]) => BaseModel & Searchable;
searchOrder: number; searchOrder: number;
} }

View File

@ -37,7 +37,7 @@ export abstract class BaseRepository<V extends BaseViewModel, M extends BaseMode
protected DS: DataStoreService, protected DS: DataStoreService,
protected collectionStringModelMapperService: CollectionStringModelMapperService, protected collectionStringModelMapperService: CollectionStringModelMapperService,
protected baseModelCtor: ModelConstructor<M>, protected baseModelCtor: ModelConstructor<M>,
protected depsModelCtors?: ModelConstructor<BaseModel>[], protected depsModelCtors?: ModelConstructor<BaseModel>[]
) { ) {
super(); super();
this.setup(); this.setup();

View File

@ -12,7 +12,7 @@ import { DataStoreService } from 'app/core/services/data-store.service';
import { SearchService, SearchModel, SearchResult } from 'app/core/services/search.service'; import { SearchService, SearchModel, SearchResult } from 'app/core/services/search.service';
import { BaseViewComponent } from '../../../base/base-view'; import { BaseViewComponent } from '../../../base/base-view';
type SearchModelEnabled = SearchModel & { enabled: boolean; }; type SearchModelEnabled = SearchModel & { enabled: boolean };
/** /**
* Component for the full search text. * Component for the full search text.

View File

@ -4,9 +4,11 @@ import { DurationService } from './duration.service';
import { E2EImportsModule } from 'e2e-imports.module'; import { E2EImportsModule } from 'e2e-imports.module';
describe('DurationService', () => { describe('DurationService', () => {
beforeEach(() => TestBed.configureTestingModule({ beforeEach(() =>
TestBed.configureTestingModule({
imports: [E2EImportsModule] imports: [E2EImportsModule]
})); })
);
it('should be created', () => { it('should be created', () => {
const service: DurationService = TestBed.get(DurationService); const service: DurationService = TestBed.get(DurationService);

View File

@ -96,7 +96,7 @@ export class ViewHistory extends BaseViewModel {
* @returns the CollectionString to the model * @returns the CollectionString to the model
*/ */
public getCollectionString(): string { public getCollectionString(): string {
return this.element_id.split(":")[0] return this.element_id.split(':')[0];
} }
/** /**
@ -104,7 +104,7 @@ export class ViewHistory extends BaseViewModel {
* @returns a model id * @returns a model id
*/ */
public getModelID(): number { public getModelID(): number {
return +this.element_id.split(":")[1] return +this.element_id.split(':')[1];
} }
/** /**

View File

@ -93,7 +93,8 @@ export class LoginMaskComponent extends BaseComponent implements OnInit, OnDestr
// Get the login data. Save information to the login data service. If there is an // Get the login data. Save information to the login data service. If there is an
// error, ignore it. // error, ignore it.
// TODO: This has to be caught by the offline service // TODO: This has to be caught by the offline service
this.http.get<any>(environment.urlPrefix + '/users/login/').then(response => { this.http.get<any>(environment.urlPrefix + '/users/login/').then(
response => {
if (response.info_text) { if (response.info_text) {
this.installationNotice = this.matSnackBar.open(response.info_text, this.translate.instant('OK'), { this.installationNotice = this.matSnackBar.open(response.info_text, this.translate.instant('OK'), {
duration: 5000 duration: 5000
@ -101,7 +102,9 @@ export class LoginMaskComponent extends BaseComponent implements OnInit, OnDestr
} }
this.loginDataService.setPrivacyPolicy(response.privacy_policy); this.loginDataService.setPrivacyPolicy(response.privacy_policy);
this.loginDataService.setLegalNotice(response.legal_notice); this.loginDataService.setLegalNotice(response.legal_notice);
}, () => {}); },
() => {}
);
} }
public ngOnDestroy(): void { public ngOnDestroy(): void {

View File

@ -15,11 +15,9 @@ describe('ResetPasswordConfirmComponent', () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [E2EImportsModule], imports: [E2EImportsModule],
providers: [ providers: [{ provide: MatSnackBar, useValue: spy }]
{provide: MatSnackBar, useValue: spy}
]
}).compileComponents(); }).compileComponents();
matSnackBarSpy = TestBed.get(MatSnackBar) matSnackBarSpy = TestBed.get(MatSnackBar);
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -10,7 +10,7 @@ describe('MediaUploadComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [E2EImportsModule], imports: [E2EImportsModule],
declarations: [MediaUploadComponent], declarations: [MediaUploadComponent]
}).compileComponents(); }).compileComponents();
})); }));

View File

@ -27,7 +27,7 @@ interface FileData {
@Component({ @Component({
selector: 'os-media-upload', selector: 'os-media-upload',
templateUrl: './media-upload.component.html', templateUrl: './media-upload.component.html',
styleUrls: ['./media-upload.component.scss'], styleUrls: ['./media-upload.component.scss']
}) })
export class MediaUploadComponent extends BaseViewComponent implements OnInit { export class MediaUploadComponent extends BaseViewComponent implements OnInit {
/** /**
@ -168,7 +168,7 @@ export class MediaUploadComponent extends BaseViewComponent implements OnInit {
filename: file.name, filename: file.name,
title: file.name, title: file.name,
uploader_id: this.op.user.id, uploader_id: this.op.user.id,
hidden: false, hidden: false
}; };
this.uploadList.data.push(newFile); this.uploadList.data.push(newFile);

View File

@ -26,7 +26,6 @@
white-space: pre-line !important; white-space: pre-line !important;
} }
.edit-file-form { .edit-file-form {
mat-form-field + mat-form-field { mat-form-field + mat-form-field {
margin: 1em; margin: 1em;

View File

@ -16,16 +16,13 @@ import { MediafileFilterListService } from '../../services/mediafile-filter.serv
import { MediafilesSortListService } from '../../services/mediafiles-sort-list.service'; import { MediafilesSortListService } from '../../services/mediafiles-sort-list.service';
import { ViewportService } from 'app/core/services/viewport.service'; import { ViewportService } from 'app/core/services/viewport.service';
/** /**
* Lists all the uploaded files. * Lists all the uploaded files.
*/ */
@Component({ @Component({
selector: 'os-mediafile-list', selector: 'os-mediafile-list',
templateUrl: './mediafile-list.component.html', templateUrl: './mediafile-list.component.html',
styleUrls: ['./mediafile-list.component.scss'], styleUrls: ['./mediafile-list.component.scss']
}) })
export class MediafileListComponent extends ListViewBaseComponent<ViewMediafile> implements OnInit { export class MediafileListComponent extends ListViewBaseComponent<ViewMediafile> implements OnInit {
/** /**
@ -106,7 +103,7 @@ export class MediafileListComponent extends ListViewBaseComponent<ViewMediafile>
this.fileEditForm = new FormGroup({ this.fileEditForm = new FormGroup({
title: new FormControl('', Validators.required), title: new FormControl('', Validators.required),
hidden: new FormControl(), hidden: new FormControl()
}); });
this.filterService.filter().subscribe(filteredData => { this.filterService.filter().subscribe(filteredData => {
@ -163,7 +160,7 @@ export class MediafileListComponent extends ListViewBaseComponent<ViewMediafile>
} }
const updateData = new Mediafile({ const updateData = new Mediafile({
title: this.fileEditForm.value.title, title: this.fileEditForm.value.title,
hidden: this.fileEditForm.value.hidden, hidden: this.fileEditForm.value.hidden
}); });
this.repo.update(updateData, this.fileToEdit).then(() => { this.repo.update(updateData, this.fileToEdit).then(() => {

View File

@ -5,11 +5,11 @@ import { MediaUploadComponent } from './components/media-upload/media-upload.com
const routes: Routes = [ const routes: Routes = [
{ path: '', component: MediafileListComponent }, { path: '', component: MediafileListComponent },
{ path: 'upload', component: MediaUploadComponent }, { path: 'upload', component: MediaUploadComponent }
]; ];
@NgModule({ @NgModule({
imports: [RouterModule.forChild(routes)], imports: [RouterModule.forChild(routes)],
exports: [RouterModule], exports: [RouterModule]
}) })
export class MediafilesRoutingModule {} export class MediafilesRoutingModule {}

View File

@ -122,5 +122,4 @@ export class ViewMediafile extends BaseViewModel {
public is_hidden(): boolean { public is_hidden(): boolean {
return this._mediafile.hidden; return this._mediafile.hidden;
} }
} }

View File

@ -8,7 +8,7 @@ import { ViewMediafile } from '../models/view-mediafile';
* The structure of an image config object * The structure of an image config object
*/ */
interface ImageConfigObject { interface ImageConfigObject {
display_name: string display_name: string;
key: string; key: string;
path: string; path: string;
} }
@ -17,7 +17,7 @@ interface ImageConfigObject {
* The structure of a font config * The structure of a font config
*/ */
interface FontConfigObject { interface FontConfigObject {
display_name: string display_name: string;
default: string; default: string;
path: string; path: string;
} }
@ -26,10 +26,10 @@ interface FontConfigObject {
* Holds the required structure of the manage payload * Holds the required structure of the manage payload
*/ */
interface ManagementPayload { interface ManagementPayload {
id: number, id: number;
key?: string, key?: string;
default?: string, default?: string;
value: ImageConfigObject | FontConfigObject value: ImageConfigObject | FontConfigObject;
} }
/** /**
@ -38,7 +38,7 @@ interface ManagementPayload {
* Declaring images as logos (web, projector, pdf, ...) is handles here. * Declaring images as logos (web, projector, pdf, ...) is handles here.
*/ */
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root'
}) })
export class MediaManageService { export class MediaManageService {
/** /**
@ -61,7 +61,7 @@ export class MediaManageService {
const restPath = `rest/core/config/${action}`; const restPath = `rest/core/config/${action}`;
const config = this.getMediaConfig(action); const config = this.getMediaConfig(action);
const path = (config.path !== file.downloadUrl) ? file.downloadUrl : ''; const path = config.path !== file.downloadUrl ? file.downloadUrl : '';
// Create the payload that the server requires to manage a mediafile // Create the payload that the server requires to manage a mediafile
const payload: ManagementPayload = { const payload: ManagementPayload = {
@ -74,7 +74,7 @@ export class MediaManageService {
default: (config as FontConfigObject).default, default: (config as FontConfigObject).default,
path: path path: path
} }
} };
return this.httpService.put<void>(restPath, payload); return this.httpService.put<void>(restPath, payload);
} }

View File

@ -1,20 +1,21 @@
import { Injectable } from "@angular/core"; import { Injectable } from '@angular/core';
import { FilterListService } from "../../../core/services/filter-list.service"; import { FilterListService } from '../../../core/services/filter-list.service';
import { Mediafile } from "../../../shared/models/mediafiles/mediafile"; import { Mediafile } from '../../../shared/models/mediafiles/mediafile';
import { ViewMediafile } from "../models/view-mediafile"; import { ViewMediafile } from '../models/view-mediafile';
import { StorageService } from "app/core/services/storage.service"; import { StorageService } from 'app/core/services/storage.service';
import { MediafileRepositoryService } from "./mediafile-repository.service"; import { MediafileRepositoryService } from './mediafile-repository.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class MediafileFilterListService extends FilterListService<Mediafile, ViewMediafile> { export class MediafileFilterListService extends FilterListService<Mediafile, ViewMediafile> {
protected name = 'Mediafile'; protected name = 'Mediafile';
public filterOptions = [{ public filterOptions = [
property: 'is_hidden', label: 'Hidden', {
property: 'is_hidden',
label: 'Hidden',
options: [ options: [
{ condition: true, label: 'is hidden' }, { condition: true, label: 'is hidden' },
{ condition: false, label: 'is not hidden', isActive: true } { condition: false, label: 'is not hidden', isActive: true }

View File

@ -15,7 +15,7 @@ import { HttpHeaders } from '@angular/common/http';
* Repository for MediaFiles * Repository for MediaFiles
*/ */
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root'
}) })
export class MediafileRepositoryService extends BaseRepository<ViewMediafile, Mediafile> { export class MediafileRepositoryService extends BaseRepository<ViewMediafile, Mediafile> {
/** /**
@ -29,7 +29,7 @@ export class MediafileRepositoryService extends BaseRepository<ViewMediafile, Me
DS: DataStoreService, DS: DataStoreService,
mapperService: CollectionStringModelMapperService, mapperService: CollectionStringModelMapperService,
private dataSend: DataSendService, private dataSend: DataSendService,
private httpService: HttpService, private httpService: HttpService
) { ) {
super(DS, mapperService, Mediafile, [User]); super(DS, mapperService, Mediafile, [User]);
} }

View File

@ -2,12 +2,10 @@ import { Injectable } from '@angular/core';
import { SortListService, OsSortingDefinition } from '../../../core/services/sort-list.service'; import { SortListService, OsSortingDefinition } from '../../../core/services/sort-list.service';
import { ViewMediafile } from '../models/view-mediafile'; import { ViewMediafile } from '../models/view-mediafile';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class MediafilesSortListService extends SortListService<ViewMediafile> { export class MediafilesSortListService extends SortListService<ViewMediafile> {
public sortOptions: OsSortingDefinition<ViewMediafile> = { public sortOptions: OsSortingDefinition<ViewMediafile> = {
sortProperty: 'title', sortProperty: 'title',
sortAscending: true, sortAscending: true,

View File

@ -94,7 +94,7 @@ export class CategoryListComponent extends BaseViewComponent implements OnInit {
* @param viewCategory * @param viewCategory
*/ */
public keyDownFunction(event: KeyboardEvent, viewCategory?: ViewCategory): void { public keyDownFunction(event: KeyboardEvent, viewCategory?: ViewCategory): void {
if (event.key === "Enter") { if (event.key === 'Enter') {
if (viewCategory) { if (viewCategory) {
this.onSaveButton(viewCategory); this.onSaveButton(viewCategory);
} else { } else {

View File

@ -6,7 +6,6 @@ import { ViewChild, Component } from '@angular/core';
import { ViewMotion } from '../../models/view-motion'; import { ViewMotion } from '../../models/view-motion';
describe('ManageSubmittersComponent', () => { describe('ManageSubmittersComponent', () => {
@Component({ @Component({
selector: 'os-host-component', selector: 'os-host-component',
template: '<os-manage-submitters></os-manage-submitters>' template: '<os-manage-submitters></os-manage-submitters>'

View File

@ -15,7 +15,8 @@ import { MotionDetailOriginalChangeRecommendationsComponent } from '../motion-de
(scrollToChange)="scrollToChange($event)" (scrollToChange)="scrollToChange($event)"
(createChangeRecommendation)="createChangeRecommendation($event)" (createChangeRecommendation)="createChangeRecommendation($event)"
> >
</os-motion-detail-diff>` </os-motion-detail-diff>
`
}) })
class TestHostComponent { class TestHostComponent {
public motion: ViewMotion; public motion: ViewMotion;

View File

@ -12,7 +12,8 @@ import { Component } from '@angular/core';
(createChangeRecommendation)="createChangeRecommendation($event)" (createChangeRecommendation)="createChangeRecommendation($event)"
(gotoChangeRecommendation)="gotoChangeRecommendation($event)" (gotoChangeRecommendation)="gotoChangeRecommendation($event)"
> >
</os-motion-detail-original-change-recommendations>` </os-motion-detail-original-change-recommendations>
`
}) })
class TestHostComponent { class TestHostComponent {
public html = '<p>Test123</p>'; public html = '<p>Test123</p>';

View File

@ -21,7 +21,6 @@ import { ViewCategory } from '../../models/view-category';
import { ViewMotionBlock } from '../../models/view-motion-block'; import { ViewMotionBlock } from '../../models/view-motion-block';
import { WorkflowRepositoryService } from '../../services/workflow-repository.service'; import { WorkflowRepositoryService } from '../../services/workflow-repository.service';
/** /**
* Component that displays all the motions in a Table using DataSource. * Component that displays all the motions in a Table using DataSource.
*/ */
@ -31,7 +30,6 @@ import { WorkflowRepositoryService } from '../../services/workflow-repository.se
styleUrls: ['./motion-list.component.scss'] styleUrls: ['./motion-list.component.scss']
}) })
export class MotionListComponent extends ListViewBaseComponent<ViewMotion> implements OnInit { export class MotionListComponent extends ListViewBaseComponent<ViewMotion> implements OnInit {
/** /**
* Use for minimal width. Please note the 'selector' row for multiSelect mode, * Use for minimal width. Please note the 'selector' row for multiSelect mode,
* to be able to display an indicator for the state of selection * to be able to display an indicator for the state of selection
@ -52,7 +50,6 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion> imple
public statutesEnabled: boolean; public statutesEnabled: boolean;
public recomendationEnabled: boolean; public recomendationEnabled: boolean;
public tags: ViewTag[] = []; public tags: ViewTag[] = [];
public workflows: ViewWorkflow[] = []; public workflows: ViewWorkflow[] = [];
public categories: ViewCategory[] = []; public categories: ViewCategory[] = [];
@ -112,11 +109,11 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion> imple
this.initTable(); this.initTable();
this.configService.get('motions_statutes_enabled').subscribe(enabled => (this.statutesEnabled = enabled)); this.configService.get('motions_statutes_enabled').subscribe(enabled => (this.statutesEnabled = enabled));
this.configService.get('motions_recommendations_by').subscribe(id => (this.recomendationEnabled = !!id)); this.configService.get('motions_recommendations_by').subscribe(id => (this.recomendationEnabled = !!id));
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.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.filterService.filter().subscribe(filteredData => this.sortService.data = filteredData); this.filterService.filter().subscribe(filteredData => (this.sortService.data = filteredData));
this.sortService.sort().subscribe(sortedData => { this.sortService.sort().subscribe(sortedData => {
this.dataSource.data = sortedData; this.dataSource.data = sortedData;
this.checkSelection(); this.checkSelection();
@ -211,6 +208,4 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion> imple
this.raiseError(e); this.raiseError(e);
} }
} }
} }

View File

@ -34,6 +34,6 @@ export class ViewMotionBlock extends BaseViewModel {
} }
public getTitle(): string { public getTitle(): string {
return this.title return this.title;
} }
} }

View File

@ -226,7 +226,7 @@ export class ViewMotion extends BaseViewModel {
} }
public get attachments_id(): number[] { public get attachments_id(): number[] {
return this.motion ? this.motion.attachments_id : null return this.motion ? this.motion.attachments_id : null;
} }
public get attachments(): Mediafile[] { public get attachments(): Mediafile[] {

View File

@ -10,7 +10,6 @@ import { BaseViewModel } from '../../base/base-view-model';
* @ignore * @ignore
*/ */
export class ViewWorkflow extends BaseViewModel { export class ViewWorkflow extends BaseViewModel {
private _workflow: Workflow; private _workflow: Workflow;
public constructor(workflow?: Workflow) { public constructor(workflow?: Workflow) {

View File

@ -935,15 +935,14 @@ describe('DiffService', () => {
} }
)); ));
it('works with multiple inserted paragraphs', inject( it('works with multiple inserted paragraphs', inject([DiffService], (service: DiffService) => {
[DiffService],
(service: DiffService) => {
const before = '<p>This is the text before</p>', const before = '<p>This is the text before</p>',
after = "<p>This is the text before</p>\n<p>This is one added line</p>\n<p>Another added line</p>"; after = '<p>This is the text before</p>\n<p>This is one added line</p>\n<p>Another added line</p>';
const diff = service.diff(before, after); const diff = service.diff(before, after);
expect(diff).toBe("<p>This is the text before</p>\n<p class=\"insert\">This is one added line</p>\n<p class=\"insert\">Another added line</p>"); expect(diff).toBe(
} '<p>This is the text before</p>\n<p class="insert">This is one added line</p>\n<p class="insert">Another added line</p>'
)); );
}));
it('does not a change in a very specific case', inject([DiffService], (service: DiffService) => { it('does not a change in a very specific case', inject([DiffService], (service: DiffService) => {
// See diff._fixWrongChangeDetection // See diff._fixWrongChangeDetection
@ -965,17 +964,21 @@ describe('DiffService', () => {
})); }));
it('does not delete a paragraph before an inserted one', inject([DiffService], (service: DiffService) => { it('does not delete a paragraph before an inserted one', inject([DiffService], (service: DiffService) => {
const inHtml = '<ul class="os-split-before"><li>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</li>\n' + const inHtml =
'<ul class="os-split-before"><li>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</li>\n' +
'</ul>', '</ul>',
outHtml = '<ul class="os-split-before">\n' + outHtml =
'<ul class="os-split-before">\n' +
'<li>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</li>\n' + '<li>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</li>\n' +
'<li class="testclass">At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</li>\n' + '<li class="testclass">At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</li>\n' +
'</ul>'; '</ul>';
const diff = service.diff(inHtml, outHtml); const diff = service.diff(inHtml, outHtml);
expect(diff).toBe('<ul class="os-split-before">' + expect(diff).toBe(
'<ul class="os-split-before">' +
'<li>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</li>' + '<li>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</li>' +
'<li class="testclass insert">At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</li>' + '<li class="testclass insert">At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</li>' +
'</ul>'); '</ul>'
);
})); }));
}); });
@ -1053,10 +1056,16 @@ describe('DiffService', () => {
)); ));
it('works with a replaced list item', inject([DiffService], (service: DiffService) => { it('works with a replaced list item', inject([DiffService], (service: DiffService) => {
const before = "<ul><li>Lorem ipsum <strong>dolor sit amet</strong>, consetetur sadipscing elitr, sed diam nonumy eirmod tempor.</li></ul>", const before =
after = "<ul>\n<li>\n<p>At vero eos et accusam et justo duo dolores et ea rebum.</p>\n</li>\n</ul>\n", '<ul><li>Lorem ipsum <strong>dolor sit amet</strong>, consetetur sadipscing elitr, sed diam nonumy eirmod tempor.</li></ul>',
expected = '<UL class="delete"><LI>' + noMarkup(1) + 'Lorem ipsum <STRONG>dolor sit amet</STRONG>, consetetur sadipscing elitr, sed diam nonumy ' + brMarkup(2) + 'eirmod tempor.</LI></UL>' + after = '<ul>\n<li>\n<p>At vero eos et accusam et justo duo dolores et ea rebum.</p>\n</li>\n</ul>\n',
"<UL class=\"insert\">\n<LI>\n<P>At vero eos et accusam et justo duo dolores et ea rebum.</P>\n</LI>\n</UL>"; expected =
'<UL class="delete"><LI>' +
noMarkup(1) +
'Lorem ipsum <STRONG>dolor sit amet</STRONG>, consetetur sadipscing elitr, sed diam nonumy ' +
brMarkup(2) +
'eirmod tempor.</LI></UL>' +
'<UL class="insert">\n<LI>\n<P>At vero eos et accusam et justo duo dolores et ea rebum.</P>\n</LI>\n</UL>';
const diff = service.diff(before, after, 80, 1); const diff = service.diff(before, after, 80, 1);
const diffNormalized = service.normalizeHtmlForDiff(diff).toLowerCase(); const diffNormalized = service.normalizeHtmlForDiff(diff).toLowerCase();
const expectedNormalized = service.normalizeHtmlForDiff(expected).toLowerCase(); const expectedNormalized = service.normalizeHtmlForDiff(expected).toLowerCase();

View File

@ -491,12 +491,12 @@ describe('LinenumberingService', () => {
expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml);
})); }));
it('does not count within .insert nodes', inject( it('does not count within .insert nodes', inject([LinenumberingService], (service: LinenumberingService) => {
[LinenumberingService], const inHtml = '<p>1234</p><ul class="insert"><li>1234</li></ul><p>1234 1234</p>';
(service: LinenumberingService) => {
const inHtml = "<p>1234</p><ul class=\"insert\"><li>1234</li></ul><p>1234 1234</p>";
const outHtml = service.insertLineNumbers(inHtml, 10); const outHtml = service.insertLineNumbers(inHtml, 10);
expect(outHtml).toBe('<p>' + noMarkup(1) + '1234</p><ul class="insert"><li>1234</li></ul><p>' + noMarkup(2) + '1234 1234</p>'); expect(outHtml).toBe(
'<p>' + noMarkup(1) + '1234</p><ul class="insert"><li>1234</li></ul><p>' + noMarkup(2) + '1234 1234</p>'
);
expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.stripLineNumbers(outHtml)).toBe(inHtml);
expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml);
})); }));

View File

@ -3,20 +3,17 @@ import { OperatorService } from '../../../core/services/operator.service';
import { ViewMotion } from '../models/view-motion'; import { ViewMotion } from '../models/view-motion';
import { ConfigService } from '../../../core/services/config.service'; import { ConfigService } from '../../../core/services/config.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class LocalPermissionsService { export class LocalPermissionsService {
public configMinSupporters: number; public configMinSupporters: number;
public constructor( public constructor(private operator: OperatorService, private configService: ConfigService) {
private operator: OperatorService,
private configService: ConfigService,
) {
// load config variables // load config variables
this.configService.get('motions_min_supporters').subscribe(supporters => (this.configMinSupporters = supporters)); this.configService
.get('motions_min_supporters')
.subscribe(supporters => (this.configMinSupporters = supporters));
} }
/** /**
@ -36,13 +33,11 @@ export class LocalPermissionsService {
this.operator.hasPerms('motions.can_support') && this.operator.hasPerms('motions.can_support') &&
this.configMinSupporters > 0 && this.configMinSupporters > 0 &&
motion.state.allow_support && motion.state.allow_support &&
(motion.submitters.indexOf(this.operator.user) === -1) && motion.submitters.indexOf(this.operator.user) === -1 &&
(motion.supporters.indexOf(this.operator.user) === -1)); motion.supporters.indexOf(this.operator.user) === -1
case 'unsupport':
return (
motion.state.allow_support &&
(motion.supporters.indexOf(this.operator.user) !== -1)
); );
case 'unsupport':
return motion.state.allow_support && motion.supporters.indexOf(this.operator.user) !== -1;
default: default:
return false; return false;
} }

View File

@ -4,9 +4,11 @@ import { MotionBlockRepositoryService } from './motion-block-repository.service'
import { E2EImportsModule } from 'e2e-imports.module'; import { E2EImportsModule } from 'e2e-imports.module';
describe('MotionBlockRepositoryService', () => { describe('MotionBlockRepositoryService', () => {
beforeEach(() => TestBed.configureTestingModule({ beforeEach(() =>
TestBed.configureTestingModule({
imports: [E2EImportsModule] imports: [E2EImportsModule]
})); })
);
it('should be created', () => { it('should be created', () => {
const service: MotionBlockRepositoryService = TestBed.get(MotionBlockRepositoryService); const service: MotionBlockRepositoryService = TestBed.get(MotionBlockRepositoryService);

View File

@ -32,7 +32,7 @@ export class MotionBlockRepositoryService extends BaseRepository<ViewMotionBlock
DS: DataStoreService, DS: DataStoreService,
mapperService: CollectionStringModelMapperService, mapperService: CollectionStringModelMapperService,
private dataSend: DataSendService, private dataSend: DataSendService,
private motionRepo: MotionRepositoryService, private motionRepo: MotionRepositoryService
) { ) {
super(DS, mapperService, MotionBlock); super(DS, mapperService, MotionBlock);
} }

View File

@ -11,10 +11,7 @@ describe('MotionCsvExportService', () => {
}); });
}); });
it('should be created', inject( it('should be created', inject([MotionCsvExportService], (service: MotionCsvExportService) => {
[MotionCsvExportService],
(service: MotionCsvExportService) => {
expect(service).toBeTruthy(); expect(service).toBeTruthy();
} }));
));
}); });

View File

@ -12,7 +12,6 @@ import { ViewMotion } from '../models/view-motion';
providedIn: 'root' providedIn: 'root'
}) })
export class MotionCsvExportService { export class MotionCsvExportService {
/** /**
* Does nothing. * Does nothing.
* *
@ -51,11 +50,15 @@ export class MotionCsvExportService {
this.csvExport.export( this.csvExport.export(
motions, motions,
[ [
{ label: 'Called', map: motion => motion.sort_parent_id ? '' : motion.identifierOrTitle }, { label: 'Called', map: motion => (motion.sort_parent_id ? '' : motion.identifierOrTitle) },
{ label: 'Called with', map: motion => !motion.sort_parent_id ? '' : motion.identifierOrTitle }, { label: 'Called with', map: motion => (!motion.sort_parent_id ? '' : motion.identifierOrTitle) },
{ label: 'submitters', map: motion => motion.submitters.map(s => s.short_name).join(',') }, { label: 'submitters', map: motion => motion.submitters.map(s => s.short_name).join(',') },
{ property: 'title' }, { property: 'title' },
{ label: 'recommendation', map: motion => motion.recommendation ? this.translate.instant(motion.recommendation.recommendation_label) : '' }, {
label: 'recommendation',
map: motion =>
motion.recommendation ? this.translate.instant(motion.recommendation.recommendation_label) : ''
},
{ property: 'motion_block', label: 'Motion block' } { property: 'motion_block', label: 'Motion block' }
], ],
this.translate.instant('Call list') + '.csv' this.translate.instant('Call list') + '.csv'

View File

@ -1,31 +1,27 @@
import { Injectable } from "@angular/core"; import { Injectable } from '@angular/core';
import { FilterListService, OsFilter } from "../../../core/services/filter-list.service"; import { FilterListService, OsFilter } from '../../../core/services/filter-list.service';
import { Motion } from "../../../shared/models/motions/motion"; import { Motion } from '../../../shared/models/motions/motion';
import { ViewMotion } from "../models/view-motion"; import { ViewMotion } from '../models/view-motion';
import { CategoryRepositoryService } from "./category-repository.service"; import { CategoryRepositoryService } from './category-repository.service';
import { WorkflowRepositoryService } from "./workflow-repository.service"; import { WorkflowRepositoryService } from './workflow-repository.service';
import { StorageService } from "../../../core/services/storage.service"; import { StorageService } from '../../../core/services/storage.service';
import { MotionRepositoryService } from "./motion-repository.service"; import { MotionRepositoryService } from './motion-repository.service';
import { MotionBlockRepositoryService } from "./motion-block-repository.service"; import { MotionBlockRepositoryService } from './motion-block-repository.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class MotionFilterListService extends FilterListService<Motion, ViewMotion> { export class MotionFilterListService extends FilterListService<Motion, ViewMotion> {
protected name = 'Motion'; protected name = 'Motion';
/** /**
* getter for the filterOptions. Note that in this case, the options are * getter for the filterOptions. Note that in this case, the options are
* generated dynamically, as the options change with the datastore * generated dynamically, as the options change with the datastore
*/ */
public get filterOptions(): OsFilter[] { public get filterOptions(): OsFilter[] {
return [ return [this.flowFilterOptions, this.categoryFilterOptions, this.motionBlockFilterOptions].concat(
this.flowFilterOptions, this.staticFilterOptions
this.categoryFilterOptions, );
this.motionBlockFilterOptions
].concat(
this.staticFilterOptions);
} }
/** /**
@ -54,27 +50,25 @@ export class MotionFilterListService extends FilterListService<Motion, ViewMotio
label: 'Motion block', label: 'Motion block',
isActive: false, isActive: false,
options: [] options: []
} };
public commentFilterOptions = { public commentFilterOptions = {
property: 'comment', property: 'comment',
isActive: false, isActive: false,
options: [] options: []
} };
public staticFilterOptions = [ public staticFilterOptions = [
// TODO favorite (attached to user:whoamI!) // TODO favorite (attached to user:whoamI!)
// TODO personalNote (attached to user:whoamI!) // TODO personalNote (attached to user:whoamI!)
]; ];
public constructor(store: StorageService, public constructor(
store: StorageService,
private workflowRepo: WorkflowRepositoryService, private workflowRepo: WorkflowRepositoryService,
private categoryRepo: CategoryRepositoryService, private categoryRepo: CategoryRepositoryService,
private motionBlockRepo: MotionBlockRepositoryService, private motionBlockRepo: MotionBlockRepositoryService,
// private commentRepo: MotionCommentRepositoryService // private commentRepo: MotionCommentRepositoryService
motionRepo: MotionRepositoryService, motionRepo: MotionRepositoryService
) { ) {
super(store, motionRepo); super(store, motionRepo);
this.subscribeWorkflows(); this.subscribeWorkflows();

View File

@ -89,8 +89,7 @@ export class MotionMultiselectService {
*/ */
public async setStateOfMultiple(motions: ViewMotion[]): Promise<void> { public async setStateOfMultiple(motions: ViewMotion[]): Promise<void> {
const title = this.translate.instant('This will set the state of all selected motions to:'); const title = this.translate.instant('This will set the state of all selected motions to:');
const choices = this.workflowRepo.getWorkflowStatesForMotions(motions) const choices = this.workflowRepo.getWorkflowStatesForMotions(motions).map(workflowState => ({
.map(workflowState => ({
id: workflowState.id, id: workflowState.id,
label: workflowState.name label: workflowState.name
})); }));
@ -117,12 +116,11 @@ export class MotionMultiselectService {
label: workflowState.recommendation_label label: workflowState.recommendation_label
})); }));
const clearChoice = 'Delete recommendation'; const clearChoice = 'Delete recommendation';
const selectedChoice = await this.choiceService.open(title, choices, false, const selectedChoice = await this.choiceService.open(title, choices, false, null, clearChoice);
null, clearChoice);
if (selectedChoice) { if (selectedChoice) {
const requestData = motions.map(motion => ({ const requestData = motions.map(motion => ({
id: motion.id, id: motion.id,
recommendation: selectedChoice.action ? 0 : selectedChoice.items as number recommendation: selectedChoice.action ? 0 : (selectedChoice.items as number)
})); }));
await this.httpService.post('/rest/motions/motion/manage_multiple_recommendation', { await this.httpService.post('/rest/motions/motion/manage_multiple_recommendation', {
motions: requestData motions: requestData
@ -138,13 +136,19 @@ export class MotionMultiselectService {
public async setCategory(motions: ViewMotion[]): Promise<void> { public async setCategory(motions: ViewMotion[]): Promise<void> {
const title = this.translate.instant('This will set the category of all selected motions to:'); const title = this.translate.instant('This will set the category of all selected motions to:');
const clearChoice = 'No category'; const clearChoice = 'No category';
const selectedChoice = await this.choiceService.open(title, this.categoryRepo.getViewModelList(), const selectedChoice = await this.choiceService.open(
false, null, clearChoice); title,
this.categoryRepo.getViewModelList(),
false,
null,
clearChoice
);
if (selectedChoice) { if (selectedChoice) {
for (const motion of motions) { for (const motion of motions) {
await this.repo.update( await this.repo.update(
{category_id: selectedChoice.action ? 0 : selectedChoice.items as number }, { category_id: selectedChoice.action ? 0 : (selectedChoice.items as number) },
motion); motion
);
} }
} }
} }
@ -155,10 +159,11 @@ export class MotionMultiselectService {
* @param motions The motions to add/remove the sumbitters to * @param motions The motions to add/remove the sumbitters to
*/ */
public async changeSubmitters(motions: ViewMotion[]): Promise<void> { public async changeSubmitters(motions: ViewMotion[]): Promise<void> {
const title = this.translate.instant('This will add or remove the following submitters for all selected motions:'); const title = this.translate.instant(
'This will add or remove the following submitters for all selected motions:'
);
const choices = ['Add', 'Remove']; const choices = ['Add', 'Remove'];
const selectedChoice = await this.choiceService.open(title, const selectedChoice = await this.choiceService.open(title, this.userRepo.getViewModelList(), true, choices);
this.userRepo.getViewModelList(), 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.submitters_id, ...(selectedChoice.items as number[])]; let submitterIds = [...motion.submitters_id, ...(selectedChoice.items as number[])];
@ -190,8 +195,7 @@ export class MotionMultiselectService {
public async changeTags(motions: ViewMotion[]): Promise<void> { public async changeTags(motions: ViewMotion[]): Promise<void> {
const title = this.translate.instant('This will add or remove the following tags for all selected motions:'); const title = this.translate.instant('This will add or remove the following tags for all selected motions:');
const choices = ['Add', 'Remove', 'Clear tags']; const choices = ['Add', 'Remove', 'Clear tags'];
const selectedChoice = await this.choiceService.open(title, this.tagRepo.getViewModelList(), true, const selectedChoice = await this.choiceService.open(title, this.tagRepo.getViewModelList(), true, choices);
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[])];
@ -223,7 +227,6 @@ export class MotionMultiselectService {
} }
} }
/** /**
* Opens a dialog and changes the motionBlock for all given motions. * Opens a dialog and changes the motionBlock for all given motions.
* *
@ -232,11 +235,16 @@ export class MotionMultiselectService {
public async setMotionBlock(motions: ViewMotion[]): Promise<void> { public async setMotionBlock(motions: ViewMotion[]): Promise<void> {
const title = this.translate.instant('This will change the motion Block for all selected motions:'); const title = this.translate.instant('This will change the motion Block for all selected motions:');
const clearChoice = 'Clear motion block'; const clearChoice = 'Clear motion block';
const selectedChoice = await this.choiceService.open(title, this.motionBlockRepo.getViewModelList(), const selectedChoice = await this.choiceService.open(
false, null, clearChoice); title,
this.motionBlockRepo.getViewModelList(),
false,
null,
clearChoice
);
if (selectedChoice) { if (selectedChoice) {
for (const motion of motions) { for (const motion of motions) {
const blockId = selectedChoice.action ? null : selectedChoice.items as number; const blockId = selectedChoice.action ? null : (selectedChoice.items as number);
await this.repo.update({ motion_block_id: blockId }, motion); await this.repo.update({ motion_block_id: blockId }, motion);
} }
} }

View File

@ -28,7 +28,7 @@ import { ViewMotionAmendedParagraph } from '../models/view-motion-amended-paragr
import { CreateMotion } from '../models/create-motion'; import { CreateMotion } from '../models/create-motion';
import { MotionBlock } from 'app/shared/models/motions/motion-block'; import { MotionBlock } from 'app/shared/models/motions/motion-block';
import { Mediafile } from 'app/shared/models/mediafiles/mediafile'; import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
import { ConfigService } from "../../../core/services/config.service"; import { ConfigService } from '../../../core/services/config.service';
/** /**
* Repository Services for motions (and potentially categories) * Repository Services for motions (and potentially categories)
@ -44,7 +44,6 @@ import { ConfigService } from "../../../core/services/config.service";
providedIn: 'root' providedIn: 'root'
}) })
export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion> { export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion> {
// The line length; comes from the config variable motions_line_length // The line length; comes from the config variable motions_line_length
private lineLength = 90; private lineLength = 90;
@ -81,9 +80,9 @@ export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion>
super(DS, mapperService, Motion, [Category, User, Workflow, Item, MotionBlock, Mediafile]); super(DS, mapperService, Motion, [Category, User, Workflow, Item, MotionBlock, Mediafile]);
// load config variables // load config variables
this.configService.get('motions_line_length').subscribe(lineLength => this.lineLength = lineLength); this.configService.get('motions_line_length').subscribe(lineLength => (this.lineLength = lineLength));
this.configService.get('motions_default_line_numbering').subscribe(mode => this.defaultLineNumbering = mode); this.configService.get('motions_default_line_numbering').subscribe(mode => (this.defaultLineNumbering = mode));
this.configService.get('motions_recommendation_text_mode').subscribe(mode => this.defaultCrMode = mode); this.configService.get('motions_recommendation_text_mode').subscribe(mode => (this.defaultCrMode = mode));
} }
/** /**
@ -106,7 +105,20 @@ export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion>
if (workflow) { if (workflow) {
state = workflow.getStateById(motion.state_id); state = workflow.getStateById(motion.state_id);
} }
return new ViewMotion(motion, category, submitters, supporters, workflow, state, item, block, attachments, this.lineLength, this.defaultLineNumbering, this.defaultCrMode); return new ViewMotion(
motion,
category,
submitters,
supporters,
workflow,
state,
item,
block,
attachments,
this.lineLength,
this.defaultLineNumbering,
this.defaultCrMode
);
} }
/** /**
@ -220,10 +232,12 @@ export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion>
*/ */
public async setSubmitters(viewMotion: ViewMotion, submitters: User[]): Promise<void> { public async setSubmitters(viewMotion: ViewMotion, submitters: User[]): Promise<void> {
const requestData = { const requestData = {
motions: [{ motions: [
{
id: viewMotion.id, id: viewMotion.id,
submitters: submitters.map(s => s.id), submitters: submitters.map(s => s.id)
}] }
]
}; };
this.httpService.post('/rest/motions/motion/manage_multiple_submitters/', requestData); this.httpService.post('/rest/motions/motion/manage_multiple_submitters/', requestData);
} }

View File

@ -79,12 +79,13 @@ export class WorkflowRepositoryService extends BaseRepository<ViewWorkflow, Work
*/ */
public getWorkflowStatesForMotions(motions: ViewMotion[]): WorkflowState[] { public getWorkflowStatesForMotions(motions: ViewMotion[]): WorkflowState[] {
let states: WorkflowState[] = []; let states: WorkflowState[] = [];
const workflowIds = motions.map(motion => motion.workflow_id).filter((value, index, self) => self.indexOf(value) === index); const workflowIds = motions
.map(motion => motion.workflow_id)
.filter((value, index, self) => self.indexOf(value) === index);
workflowIds.forEach(id => { workflowIds.forEach(id => {
const workflow = this.getViewModel(id); const workflow = this.getViewModel(id);
states = states.concat(workflow.states); states = states.concat(workflow.states);
}); });
return states; return states;
} }
} }

View File

@ -51,7 +51,6 @@ const routes: Routes = [
path: 'history', path: 'history',
loadChildren: './history/history.module#HistoryModule' loadChildren: './history/history.module#HistoryModule'
} }
], ],
canActivateChild: [AuthGuard] canActivateChild: [AuthGuard]
} }

View File

@ -141,7 +141,7 @@ export class TagListComponent extends ListViewBaseComponent<ViewTag> implements
if (event.key === 'Enter' && event.shiftKey) { if (event.key === 'Enter' && event.shiftKey) {
this.submitNewTag(); this.submitNewTag();
} }
if (event.key === "Escape") { if (event.key === 'Escape') {
this.cancelEditing(); this.cancelEditing();
} }
} }

View File

@ -198,7 +198,7 @@ export class GroupListComponent extends BaseViewComponent implements OnInit {
* Clicking escape while in #newGroupForm should toggle newGroup. * Clicking escape while in #newGroupForm should toggle newGroup.
*/ */
public keyDownFunction(event: KeyboardEvent): void { public keyDownFunction(event: KeyboardEvent): void {
if (event.key === "Escape") { if (event.key === 'Escape') {
this.newGroup = false; this.newGroup = false;
} }
} }

View File

@ -261,5 +261,4 @@ export class PasswordComponent extends BaseViewComponent implements OnInit {
this.hide_user_password = !this.hide_user_password; this.hide_user_password = !this.hide_user_password;
} }
} }
} }

View File

@ -321,7 +321,9 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
* click on the delete user button * click on the delete user button
*/ */
public async deleteUserButton(): Promise<void> { public async deleteUserButton(): Promise<void> {
const content = this.translate.instant('Do you want to delete this participant?') + `<p><strong>${this.user.full_name}</strong>`; const content =
this.translate.instant('Do you want to delete this participant?') +
`<p><strong>${this.user.full_name}</strong>`;
if (await this.promptService.open(this.translate.instant('Are you sure?'), content)) { if (await this.promptService.open(this.translate.instant('Are you sure?'), content)) {
this.repo.delete(this.user).then(() => this.router.navigate(['./users/']), this.raiseError); this.repo.delete(this.user).then(() => this.router.navigate(['./users/']), this.raiseError);
} }

View File

@ -24,7 +24,6 @@ import { UserSortListService } from '../../services/user-sort-list.service';
styleUrls: ['./user-list.component.scss'] styleUrls: ['./user-list.component.scss']
}) })
export class UserListComponent extends ListViewBaseComponent<ViewUser> implements OnInit { export class UserListComponent extends ListViewBaseComponent<ViewUser> implements OnInit {
/** /**
* /** * /**
* The usual constructor for components * The usual constructor for components
@ -71,7 +70,6 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
super.setTitle('Users'); super.setTitle('Users');
this.initTable(); this.initTable();
this.filterService.filter().subscribe(filteredData => { this.filterService.filter().subscribe(filteredData => {
this.sortService.data = filteredData; this.sortService.data = filteredData;
}); });
@ -148,8 +146,7 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
public async setGroupSelected(): Promise<void> { public async setGroupSelected(): Promise<void> {
const content = this.translate.instant('This will add or remove the following groups for all selected users:'); const content = this.translate.instant('This will add or remove the following groups for all selected users:');
const choices = ['Add group(s)', 'Remove group(s)']; const choices = ['Add group(s)', 'Remove group(s)'];
const selectedChoice = await this.choiceService.open(content, const selectedChoice = await this.choiceService.open(content, this.groupRepo.getViewModelList(), true, choices);
this.groupRepo.getViewModelList(), true, choices);
if (selectedChoice) { if (selectedChoice) {
for (const user of this.selectedRows) { for (const user of this.selectedRows) {
const newGroups = [...user.groups_id]; const newGroups = [...user.groups_id];
@ -203,8 +200,7 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
* Uses selectedRows defined via multiSelect mode. * Uses selectedRows defined via multiSelect mode.
*/ */
public async setCommitteeSelected(): Promise<void> { public async setCommitteeSelected(): Promise<void> {
const content = this.translate.instant( const content = this.translate.instant('Sets/unsets the committee status for the selected users');
'Sets/unsets the committee status for the selected users');
const options = ['Is committee', 'Is not committee']; const options = ['Is committee', 'Is not committee'];
const selectedChoice = await this.choiceService.open(content, null, false, options); const selectedChoice = await this.choiceService.open(content, null, false, options);
if (selectedChoice) { if (selectedChoice) {
@ -254,7 +250,5 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
public async setPresent(viewUser: ViewUser): Promise<void> { public async setPresent(viewUser: ViewUser): Promise<void> {
viewUser.user.is_present = !viewUser.user.is_present; viewUser.user.is_present = !viewUser.user.is_present;
await this.repo.update(viewUser.user, viewUser); await this.repo.update(viewUser.user, viewUser);
} }
} }

View File

@ -105,7 +105,6 @@ export class ViewUser extends BaseViewModel {
this._groups = groups; this._groups = groups;
} }
/** /**
* required by BaseViewModel. Don't confuse with the users title. * required by BaseViewModel. Don't confuse with the users title.
*/ */

View File

@ -8,7 +8,8 @@ describe('GroupRepositoryService', () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [E2EImportsModule], imports: [E2EImportsModule],
providers: [GroupRepositoryService] providers: [GroupRepositoryService]
})); })
);
it('should be created', inject([GroupRepositoryService], (service: GroupRepositoryService) => { it('should be created', inject([GroupRepositoryService], (service: GroupRepositoryService) => {
expect(service).toBeTruthy(); expect(service).toBeTruthy();

View File

@ -1,17 +1,16 @@
import { Injectable } from "@angular/core"; import { Injectable } from '@angular/core';
import { FilterListService, OsFilter } from "../../../core/services/filter-list.service"; import { FilterListService, OsFilter } from '../../../core/services/filter-list.service';
import { StorageService } from "../../../core/services/storage.service"; import { StorageService } from '../../../core/services/storage.service';
import { User } from "../../../shared/models/users/user"; import { User } from '../../../shared/models/users/user';
import { ViewUser } from "../models/view-user"; import { ViewUser } from '../models/view-user';
import { GroupRepositoryService } from "./group-repository.service"; import { GroupRepositoryService } from './group-repository.service';
import { UserRepositoryService } from "./user-repository.service"; import { UserRepositoryService } from './user-repository.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class UserFilterListService extends FilterListService<User, ViewUser> { export class UserFilterListService extends FilterListService<User, ViewUser> {
protected name = 'User'; protected name = 'User';
private userGroupFilterOptions = { private userGroupFilterOptions = {
@ -26,30 +25,25 @@ export class UserFilterListService extends FilterListService<User, ViewUser> {
property: 'is_present', property: 'is_present',
label: 'Presence', label: 'Presence',
isActive: false, isActive: false,
options: [ options: [{ condition: true, label: 'Is present' }, { condition: false, label: 'Is not present' }]
{ condition: true, label: 'Is present'}, },
{ condition: false, label: 'Is not present'}] {
}, {
property: 'is_active', property: 'is_active',
label: 'Active', label: 'Active',
isActive: false, isActive: false,
options: [ options: [{ condition: true, label: 'Is active' }, { condition: false, label: 'Is not active' }]
{ condition: true, label: 'Is active' }, },
{ condition: false, label: 'Is not active' }] {
}, {
property: 'is_committee', property: 'is_committee',
label: 'Committee', label: 'Committee',
isActive: false, isActive: false,
options: [ options: [{ condition: true, label: 'Is a committee' }, { condition: false, label: 'Is not a committee' }]
{ condition: true, label: 'Is a committee' }, },
{ condition: false, label: 'Is not a committee'}] {
}, {
property: 'is_last_email_send', property: 'is_last_email_send',
label: 'Last email send', label: 'Last email send',
isActive: false, isActive: false,
options: [ options: [{ condition: true, label: 'Got an email' }, { condition: false, label: "Didn't get an email" }]
{ condition: true, label: 'Got an email' },
{ condition: false, label: 'Didn\'t get an email' }]
} }
]; ];
@ -61,8 +55,7 @@ export class UserFilterListService extends FilterListService<User, ViewUser> {
return [this.userGroupFilterOptions].concat(this.staticFilterOptions); return [this.userGroupFilterOptions].concat(this.staticFilterOptions);
} }
public constructor(store: StorageService, private groupRepo: GroupRepositoryService, public constructor(store: StorageService, private groupRepo: GroupRepositoryService, repo: UserRepositoryService) {
repo: UserRepositoryService){
super(store, repo); super(store, repo);
this.subscribeGroups(); this.subscribeGroups();
} }
@ -79,6 +72,6 @@ export class UserFilterListService extends FilterListService<User, ViewUser> {
}); });
this.userGroupFilterOptions.options = groupOptions; this.userGroupFilterOptions.options = groupOptions;
this.updateFilterDefinitions(this.filterOptions); this.updateFilterDefinitions(this.filterOptions);
}) });
} }
} }

View File

@ -6,7 +6,6 @@ import { ViewUser } from '../models/view-user';
providedIn: 'root' providedIn: 'root'
}) })
export class UserSortListService extends SortListService<ViewUser> { export class UserSortListService extends SortListService<ViewUser> {
public sortOptions: OsSortingDefinition<ViewUser> = { public sortOptions: OsSortingDefinition<ViewUser> = {
sortProperty: 'first_name', sortProperty: 'first_name',
sortAscending: true, sortAscending: true,