Merge pull request #4067 from FinnStutzenstein/prettify

Using prettify instead of pretty-quick-wrapper
This commit is contained in:
Jochen Saalfeld 2019-01-10 13:12:02 +01:00 committed by GitHub
commit 2f7336b257
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
95 changed files with 514 additions and 504 deletions

View File

@ -68,7 +68,7 @@ matrix:
install:
- npm install
script:
- npm run prettify-all
- npm run prettify-check
- language: node_js
name: "Client: Testing"

View File

@ -18,8 +18,8 @@
"compodoc": "./node_modules/.bin/compodoc --hideGenerator -p src/tsconfig.app.json -n 'OpenSlides Documentation' -d ../Compodoc -s -w -t -o --port",
"extract": "ngx-translate-extract -i ./src -o ./src/assets/i18n/template-en.pot -clean --sort --format pot -m _",
"po2json": "./node_modules/.bin/po2json -f mf src/assets/i18n/de.po src/assets/i18n/de.json && ./node_modules/.bin/po2json -f mf src/assets/i18n/cs.po src/assets/i18n/cs.json",
"prettify-changes": "pretty-quick --staged",
"prettify-all": "pretty-quick"
"prettify-check": "prettier --config ./.prettierrc --list-different \"src/{app,environments}/**/*{.ts,.js,.json,.css,.scss}\"",
"prettify-write": "prettier --config ./.prettierrc --write \"src/{app,environments}/**/*{.ts,.js,.json,.css,.scss}\""
},
"dependencies": {
"@angular/animations": "^7.1.1",
@ -71,7 +71,6 @@
"karma-jasmine-html-reporter": "^0.2.2",
"npm-run-all": "^4.1.5",
"prettier": "^1.15.3",
"pretty-quick": "^1.8.0",
"protractor": "^5.4.1",
"ts-node": "~7.0.1",
"tslint": "~5.11.0",

View File

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

View File

@ -1,7 +1,7 @@
// import { _ } from '@biesbjerg/ngx-translate-extract';
function _(key: string | string[]): string | string[] {
return key;
return key;
}
/**
@ -19,10 +19,12 @@ function _(key: string | string[]): string | string[] {
// Core config strings
_('Presentation and assembly system');
_('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 ' +
'and controlling agenda, motions and elections of an ' +
'assembly.');
'assembly.'
);
_('General');
_('Event');
_('Short description of event');
@ -94,7 +96,6 @@ _('Public item');
_('Internal item');
_('Hidden item');
// Motions config strings
// subgroup general
_('General');
@ -115,13 +116,17 @@ _('Hide recommendation on projector');
_('Stop submitting new motions by non-staff users');
_('Allow to disable versioning');
_('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');
_('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');
// subgroup Amendments
_('Amendments');
_('Activate statute amendments')
_('Activate statute amendments');
_('Activate amendments');
_('Show amendments together with motions');
_('Prefix for the identifier for amendments');
@ -210,7 +215,6 @@ _('Called with');
_('Recommendation');
_('Motion block');
// Assignment config strings
_('Election method');
_('Automatic assign of method');
@ -220,10 +224,12 @@ _('Always Yes/No per candidate');
_('Elections');
_('Ballot and ballot papers');
_('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, ' +
'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 per candidate');
_('All valid ballots');
@ -316,7 +322,9 @@ _('Email subject');
_('Your login for {event_name}');
_('You can use {event_name} as a placeholder.');
_('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.');
// default groups

View File

@ -1,4 +1,3 @@
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
// to check if the result of the contructor (the model instance) is really a searchable.
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;
}

View File

@ -115,40 +115,44 @@ export class CsvExportService {
csvContent.push(header);
// create lines
csvContent = csvContent.concat(models.map(model => {
return columns.map(column => {
let value: string;
csvContent = csvContent.concat(
models.map(model => {
return columns.map(column => {
let value: string;
if (isPropertyDefinition(column)) {
const property: any = model[column.property];
if (typeof property === 'number') {
value = property.toString(10);
} else if (!property) {
value = '';
} else if (property === true) {
value = '1';
} else if (property === false) {
value = '0';
} else {
value = property.toString();
if (isPropertyDefinition(column)) {
const property: any = model[column.property];
if (typeof property === 'number') {
value = property.toString(10);
} else if (!property) {
value = '';
} else if (property === true) {
value = '1';
} else if (property === false) {
value = '0';
} else {
value = property.toString();
}
} else if (isMapDefinition(column)) {
value = column.map(model);
}
} else if (isMapDefinition(column)) {
value = column.map(model);
}
tsList = this.checkCsvTextSafety(value, tsList);
tsList = this.checkCsvTextSafety(value, tsList);
return value;
});
}));
return value;
});
})
);
// assemble lines, putting text separator in place
if (!tsList.length) {
throw new Error('no usable text separator left for valid csv text');
}
const csvContentAsString: string = csvContent.map(line => {
return line.map(entry => tsList[0] + entry + tsList[0]).join(columnSeparator);
}).join(lineSeparator);
const csvContentAsString: string = csvContent
.map(line => {
return line.map(entry => tsList[0] + entry + tsList[0]).join(columnSeparator);
})
.join(lineSeparator);
this.exporter.saveFile(csvContentAsString, filename);
}

View File

@ -97,7 +97,9 @@ export class DataStoreService {
/**
* 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.
@ -358,7 +360,7 @@ export class DataStoreService {
collection: collectionString,
id: +id // needs casting, because Objects.keys gives all keys as strings...
});
})
});
});
if (models && models.length) {
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 { StorageService } from './storage.service';
/**
* Describes the available filters for a listView.
* @param isActive: the current state of the filter
@ -18,7 +17,7 @@ import { StorageService } from './storage.service';
export interface OsFilter {
property: string;
label?: string;
options: (OsFilterOption | string )[];
options: (OsFilterOption | string)[];
count?: number;
}
@ -31,15 +30,12 @@ export interface OsFilterOption {
isActive?: boolean;
}
/**
* Filter for the list view. List views can subscribe to its' dataService (providing filter definitions)
* and will receive their filtered data as observable
*/
export abstract class FilterListService<M extends BaseModel, V extends BaseViewModel> {
/**
* stores the currently used raw data to be used for the filter
*/
@ -70,11 +66,14 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
* Initializes the filterService. Returns the filtered data as Observable
*/
public filter(): Observable<V[]> {
this.repo.getViewModelListObservable().pipe(auditTime(100)).subscribe( data => {
this.currentRawData = data;
this.filteredData = this.filterData(data);
this.filterDataOutput.next(this.filteredData);
});
this.repo
.getViewModelListObservable()
.pipe(auditTime(100))
.subscribe(data => {
this.currentRawData = data;
this.filteredData = this.filterData(data);
this.filterDataOutput.next(this.filteredData);
});
this.loadStorageDefinition(this.filterDefinitions);
return this.filterDataOutput;
}
@ -84,11 +83,12 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
* @param filter
*/
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) {
const filterOption = filter.options.find(o =>
(typeof o !== 'string') && o.condition === option.condition) as OsFilterOption;
if (filterOption && !filterOption.isActive){
const filterOption = filter.options.find(
o => typeof o !== 'string' && o.condition === option.condition
) as OsFilterOption;
if (filterOption && !filterOption.isActive) {
filterOption.isActive = true;
filter.count += 1;
}
@ -103,11 +103,12 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
}
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) {
const filterOption = filter.options.find(o =>
(typeof o !== 'string') && o.condition === option.condition) as OsFilterOption;
if (filterOption && filterOption.isActive){
const filterOption = filter.options.find(
o => typeof o !== 'string' && o.condition === option.condition
) as OsFilterOption;
if (filterOption && filterOption.isActive) {
filterOption.isActive = false;
filter.count -= 1;
this.filteredData = this.filterData(this.currentRawData);
@ -126,11 +127,10 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
option.isActive ? this.removeFilterOption(filterName, option) : this.addFilterOption(filterName, option);
}
public updateFilterDefinitions(filters: OsFilter[]) : void {
public updateFilterDefinitions(filters: OsFilter[]): void {
this.loadStorageDefinition(filters);
}
/**
* Retrieve the currently saved filter definition from the StorageService,
* check their match with current definitions and set the current filter
@ -141,35 +141,39 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
return;
}
const me = this;
this.store.get('filter_' + this.name).then(function(storedData: { name: string, data: OsFilter[] }): void {
const storedFilters = (storedData && storedData.data) ? storedData.data : [];
definitions.forEach(definedFilter => {
const matchingStoreFilter = storedFilters.find(f => f.property === definedFilter.property);
let count = 0;
definedFilter.options.forEach(option => {
if (typeof option === 'string'){
return;
};
if (matchingStoreFilter && matchingStoreFilter.options){
const storedOption = matchingStoreFilter.options.find(o =>
typeof o !== 'string' && o.condition === option.condition) as OsFilterOption;
if (storedOption) {
option.isActive = storedOption.isActive;
this.store.get('filter_' + this.name).then(
function(storedData: { name: string; data: OsFilter[] }): void {
const storedFilters = storedData && storedData.data ? storedData.data : [];
definitions.forEach(definedFilter => {
const matchingStoreFilter = storedFilters.find(f => f.property === definedFilter.property);
let count = 0;
definedFilter.options.forEach(option => {
if (typeof option === 'string') {
return;
}
}
if (option.isActive) {
count += 1;
}
if (matchingStoreFilter && matchingStoreFilter.options) {
const storedOption = matchingStoreFilter.options.find(
o => typeof o !== 'string' && o.condition === option.condition
) as OsFilterOption;
if (storedOption) {
option.isActive = storedOption.isActive;
}
}
if (option.isActive) {
count += 1;
}
});
definedFilter.count = count;
});
definedFilter.count = count;
});
me.filterDefinitions = definitions;
me.filteredData = me.filterData(me.currentRawData);
me.filterDataOutput.next(me.filteredData);
}, function(error: any) : void {
me.filteredData = me.filterData(me.currentRawData);
me.filterDataOutput.next(me.filteredData);
});
me.filterDefinitions = definitions;
me.filteredData = me.filterData(me.currentRawData);
me.filterDataOutput.next(me.filteredData);
},
function(error: any): void {
me.filteredData = me.filterData(me.currentRawData);
me.filterDataOutput.next(me.filteredData);
}
);
}
/**
@ -177,10 +181,11 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
*/
private setStorageDefinition(): void {
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
*/
@ -189,7 +194,7 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
if (!data) {
return filteredData;
}
if (!this.filterDefinitions || !this.filterDefinitions.length){
if (!this.filterDefinitions || !this.filterDefinitions.length) {
return data;
}
data.forEach(newItem => {
@ -200,7 +205,7 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
break;
}
}
if (!excluded){
if (!excluded) {
filteredData.push(newItem);
}
});
@ -214,27 +219,27 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
*/
private checkIncluded(item: V, filter: OsFilter): boolean {
for (const option of filter.options) {
if (typeof option === 'string' ){
if (typeof option === 'string') {
continue;
}
if (option.isActive) {
if (option.condition === null ) {
if (option.condition === null) {
return this.checkIncludedNegative(item, filter);
}
if (item[filter.property] === undefined) {
return false;
}
if (item[filter.property] instanceof BaseModel ) {
if (item[filter.property].id === option.condition){
if (item[filter.property] instanceof BaseModel) {
if (item[filter.property].id === option.condition) {
return true;
}
} else if (item[filter.property] === option.condition){
}
} else if (item[filter.property] === option.condition) {
return true;
} else if (item[filter.property].toString() === option.condition){
} else if (item[filter.property].toString() === option.condition) {
return true;
}
}
};
}
return false;
}
@ -254,7 +259,7 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
}
if (item[filter.property] === option.condition) {
return false;
} else if (item[filter.property].toString() === option.condition){
} else if (item[filter.property].toString() === option.condition) {
return false;
}
}
@ -271,20 +276,19 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
}
public get hasActiveFilters(): number {
if (!this.filterDefinitions || !this.filterDefinitions.length){
if (!this.filterDefinitions || !this.filterDefinitions.length) {
return 0;
}
let filters = 0;
for (const filter of this.filterDefinitions) {
if (filter.count){
if (filter.count) {
filters += 1;
}
};
}
return filters;
}
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
* @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
if (this.OSStatus.isInHistoryMode && method !== HTTPMethod.GET) {
throw this.handleError('You cannot make changes while in history mode');

View File

@ -8,7 +8,6 @@ import { Injectable } from '@angular/core';
providedIn: 'root'
})
export class OpenSlidesStatusService {
/**
* Saves, if OpenSlides is in the history mode.
*/
@ -37,6 +36,6 @@ export class OpenSlidesStatusService {
* Leaves the histroy mode
*/
public leaveHistroyMode(): void {
this.historyMode = false;
this.historyMode = false;
}
}

View File

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

View File

@ -52,7 +52,7 @@ export class TimeTravelService {
private DS: DataStoreService,
private OSStatus: OpenSlidesStatusService,
private OpenSlides: OpenSlidesService
) { }
) {}
/**
* Main entry point to set OpenSlides to another history point.
@ -65,11 +65,11 @@ export class TimeTravelService {
for (const historyObject of fullDataHistory) {
let collectionString: string;
let id: string;
[collectionString, id] = historyObject.element_id.split(':')
[collectionString, id] = historyObject.element_id.split(':');
if (historyObject.full_data) {
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 {
await this.DS.remove(collectionString, [+id]);
}
@ -94,7 +94,7 @@ export class TimeTravelService {
* @returns the full history on the given date
*/
private async getHistoryData(history: History): Promise<HistoryData[]> {
const historyUrl = '/core/history/'
const historyUrl = '/core/history/';
const queryParams = { timestamp: Math.ceil(+history.unixtime) };
return this.httpService.get<HistoryData[]>(environment.urlPrefix + historyUrl, null, queryParams);
}

View File

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

View File

@ -51,7 +51,7 @@ interface ChoiceDialogData {
* it will be an array of numbers and optionally an action string for multichoice
* dialogs
*/
export type ChoiceAnswer = undefined | { action?: string; items: number | number[]};
export type ChoiceAnswer = undefined | { action?: string; items: number | number[] };
/**
* A dialog with choice fields.

View File

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

View File

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

View File

@ -19,21 +19,21 @@ import { SortListService } from '../../../../core/services/sort-list.service';
styleUrls: ['./os-sort-bottom-sheet.component.scss']
})
export class OsSortBottomSheetComponent<V extends BaseViewModel> implements OnInit {
/**
* Constructor. Gets a reference to itself (for closing after interaction)
* @param data
* @param sheetRef
*/
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.
*/
public ngOnInit(): void {
if (!this.data || !this.data.sortOptions || !this.data.sortOptions.options.length){
if (!this.data || !this.data.sortOptions || !this.data.sortOptions.options.length) {
throw new Error('No sorting available for a sorting list');
}
}

View File

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

View File

@ -4,8 +4,8 @@ import { TranslateService } from '@ngx-translate/core';
import { BaseViewModel } from '../../../site/base/base-view-model';
import { OsSortBottomSheetComponent } from './os-sort-bottom-sheet/os-sort-bottom-sheet.component';
import { FilterMenuComponent} from './filter-menu/filter-menu.component';
import { OsSortingItem } from '../../../core/services/sort-list.service'
import { FilterMenuComponent } from './filter-menu/filter-menu.component';
import { OsSortingItem } from '../../../core/services/sort-list.service';
import { SortListService } from '../../../core/services/sort-list.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']
})
export class OsSortFilterBarComponent<V extends BaseViewModel> {
/**
* The currently active sorting service for the list view
*/
@ -68,7 +67,11 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
* @param vp
* @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();
}
@ -77,9 +80,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
*/
public openSortDropDown(): void {
if (this.vp.isMobile) {
const bottomSheetRef = this.bottomSheet.open(OsSortBottomSheetComponent,
{ data: this.sortService }
);
const bottomSheetRef = this.bottomSheet.open(OsSortBottomSheetComponent, { data: this.sortService });
bottomSheetRef.afterDismissed().subscribe(result => {
if (result) {
this.sortService.sortProperty = result;
@ -92,7 +93,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
* Listen to keypresses on the quick-search input
*/
public applySearch(event: KeyboardEvent, value?: string): void {
if (event.key === 'Escape' ) {
if (event.key === 'Escape') {
this.searchFieldChange.emit('');
this.isSearchBar = false;
} else {
@ -104,16 +105,16 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
* Checks if there is an active SortService present
*/
public get hasSorting(): boolean {
return (this.sortService && this.sortService.isActive);
return this.sortService && this.sortService.isActive;
}
/**
* Checks if there is an active FilterService present
*/
public get hasFilters(): boolean {
if (this.filterService && this.filterService.hasFilterOptions()){
if (this.filterService && this.filterService.hasFilterOptions()) {
return true;
};
}
return false;
}
@ -122,7 +123,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
* @param option
*/
public getSortIcon(option: OsSortingItem<V>): string {
if (this.sortService.sortProperty !== option.property){
if (this.sortService.sortProperty !== option.property) {
return '';
}
return this.sortService.ascending ? 'arrow_downward' : 'arrow_upward';
@ -133,7 +134,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
* the property is used.
* @param option
*/
public getSortLabel(option: OsSortingItem<V>) : string {
public getSortLabel(option: OsSortingItem<V>): string {
if (option.label) {
return option.label;
}
@ -146,7 +147,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
* that input applied
*/
public toggleSearchBar(): void {
if (!this.isSearchBar){
if (!this.isSearchBar) {
this.isSearchBar = true;
} else {
this.searchFieldChange.emit('');

View File

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

View File

@ -10,7 +10,12 @@ import { BehaviorSubject } from 'rxjs';
* A test model for the sorting
*/
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 {
return this.name;

View File

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

View File

@ -46,7 +46,6 @@ export abstract class AgendaBaseModel extends ProjectableBaseModel implements Ag
*/
public abstract formatForSearch(): SearchRepresentation;
/**
* Should return the URL to the detail view. Used for the agenda, that the
* 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.

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, ...)
// Just categorIES need to overwrite this...
} else {
return this._verboseName
return this._verboseName;
}
}

View File

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

View File

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

View File

@ -62,7 +62,7 @@ export class WorkflowState extends Deserializer {
* Checks if a workflowstate has no 'next state' left, and is final
*/
public get isFinalState(): boolean {
if (!this.next_states_id || !this.next_states_id.length ){
if (!this.next_states_id || !this.next_states_id.length) {
return true;
}
if (this.next_states_id.length === 1 && this.next_states_id[0] === 0) {

View File

@ -4,7 +4,10 @@ import { Topic } from '../../shared/models/topics/topic';
export const AgendaAppConfig: AppConfig = {
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: [
{
route: '/agenda',

View File

@ -12,7 +12,7 @@ import { ItemInfoDialogComponent } from './components/item-info-dialog/item-info
*/
@NgModule({
imports: [CommonModule, AgendaRoutingModule, SharedModule],
entryComponents: [ ItemInfoDialogComponent ],
entryComponents: [ItemInfoDialogComponent],
declarations: [AgendaListComponent, TopicDetailComponent, ItemInfoDialogComponent]
})
export class AgendaModule {}

View File

@ -1,5 +1,4 @@
.os-listview-table {
/** Title */
.mat-column-title {
padding-left: 26px;
@ -27,7 +26,6 @@
height: $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 { ViewItem } from '../../models/view-item';
import { AgendaCsvExportService } from '../../services/agenda-csv-export.service';
import { ItemInfoDialogComponent } from '../item-info-dialog/item-info-dialog.component';
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 op: OperatorService
) {
super(title, translate, snackBar)
super(title, translate, snackBar);
this.addSpeakerForm = new FormGroup({ user_id: new FormControl([]) });
this.getAgendaItemByUrl();
}

View File

@ -44,14 +44,14 @@ export class ViewItem extends BaseViewModel {
return '';
}
public get verboseType() : string {
public get verboseType(): string {
if (this.item && this.item.verboseType) {
return this.item.verboseType;
}
return '';
}
public get verboseCsvType() : string {
public get verboseCsvType(): string {
if (this.item) {
return this.item.verboseCsvType;
}

View File

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

View File

@ -12,7 +12,6 @@ import { ViewItem } from '../models/view-item';
providedIn: 'root'
})
export class AgendaCsvExportService {
/**
* Does nothing.
*
@ -27,10 +26,14 @@ export class AgendaCsvExportService {
* @param Agendas Agendas to export
*/
public exportItemList(items: ViewItem[]): void {
this.csvExport.export(items,
this.csvExport.export(
items,
[
{ 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: 'Comment', property: 'comment' },
{ 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 { Item, itemVisibilityChoices } from "../../../shared/models/agenda/item";
import { ViewItem } from "../models/view-item";
import { StorageService } from "app/core/services/storage.service";
import { AgendaRepositoryService } from "./agenda-repository.service";
import { FilterListService, OsFilter, OsFilterOption } from '../../../core/services/filter-list.service';
import { Item, itemVisibilityChoices } from '../../../shared/models/agenda/item';
import { ViewItem } from '../models/view-item';
import { StorageService } from 'app/core/services/storage.service';
import { AgendaRepositoryService } from './agenda-repository.service';
@Injectable({
providedIn: 'root'
})
export class AgendaFilterListService extends FilterListService<Item, ViewItem> {
protected name = 'Agenda';
public filterOptions: OsFilter[] = [];
@ -22,22 +21,22 @@ export class AgendaFilterListService extends FilterListService<Item, ViewItem> {
*/
public constructor(store: StorageService, repo: AgendaRepositoryService) {
super(store, repo);
this.filterOptions = [{
this.filterOptions = [
{
label: 'Visibility',
property: 'type',
options: this.createVisibilityFilterOptions()
}, {
},
{
label: 'Hidden Status',
property: 'done',
options: [
{label: 'Open', condition: false},
{label: 'Closed', condition: true}
]
}];
options: [{ label: 'Open', condition: false }, { label: 'Closed', condition: true }]
}
];
}
private createVisibilityFilterOptions(): OsFilterOption[] {
const options = [];
const options = [];
itemVisibilityChoices.forEach(choice => {
options.push({
condition: choice.key as number,
@ -46,6 +45,4 @@ export class AgendaFilterListService extends FilterListService<Item, ViewItem> {
});
return options;
}
}

View File

@ -187,7 +187,7 @@ export class AgendaRepositoryService extends BaseRepository<ViewItem, Item> {
* deleted (right now)
*/
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
*/
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(() =>
TestBed.configureTestingModule({
imports: [E2EImportsModule]
}));
})
);
it('should be created', () => {
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 { AssignmentSortListService } from '../services/assignment-sort-list.service';
/**
* Listview for the assignments
*
@ -22,7 +20,6 @@ import { AssignmentSortListService } from '../services/assignment-sort-list.serv
styleUrls: ['./assignment-list.component.scss']
})
export class AssignmentListComponent extends ListViewBaseComponent<ViewAssignment> implements OnInit {
/**
* Constructor.
* @param titleService

View File

@ -1,27 +1,27 @@
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 { 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';
@Injectable({
providedIn: 'root'
})
export class AssignmentFilterListService extends FilterListService<Assignment, ViewAssignment> {
protected name = 'Assignment';
public filterOptions: OsFilter[];
public constructor(store: StorageService, assignmentRepo: AssignmentRepositoryService) {
super(store, assignmentRepo);
this.filterOptions = [{
property: 'phase',
options: this.createPhaseOptions()
}];
this.filterOptions = [
{
property: 'phase',
options: this.createPhaseOptions()
}
];
}
private createPhaseOptions(): OsFilterOption[] {

View File

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

View File

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

View File

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

View File

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

View File

@ -80,7 +80,7 @@ export abstract class ListViewBaseComponent<V extends BaseViewModel> extends Bas
this.sort.sort(newSort);
}
public onFilterData(filteredDataSource: MatTableDataSource<V>) : void {
public onFilterData(filteredDataSource: MatTableDataSource<V>): void {
this.dataSource = filteredDataSource;
this.dataSource.paginator = this.paginator;
}

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 { BaseViewComponent } from '../../../base/base-view';
type SearchModelEnabled = SearchModel & { enabled: boolean; };
type SearchModelEnabled = SearchModel & { enabled: boolean };
/**
* Component for the full search text.
@ -78,16 +78,16 @@ export class SearchComponent extends BaseViewComponent implements OnInit {
super(title, translate, matSnackBar);
this.quickSearchform = new FormGroup({ query: new FormControl([]) });
this.registeredModels = this.searchService.getRegisteredModels().map(rm => ({...rm, enabled: true}));
this.registeredModels = this.searchService.getRegisteredModels().map(rm => ({ ...rm, enabled: true }));
this.DS.changedOrDeletedObservable.pipe(auditTime(1)).subscribe(() => this.search());
this.quickSearchSubject.pipe(debounceTime(250)).subscribe(query => this.search(query));
}
/**
* Take the search query from the URL and does the initial search.
*/
public ngOnInit(): void {
/**
* Take the search query from the URL and does the initial search.
*/
public ngOnInit(): void {
super.setTitle('Search');
this.query = this.activatedRoute.snapshot.queryParams.query;
this.quickSearchform.get('query').setValue(this.query);

View File

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

View File

@ -96,7 +96,7 @@ export class ViewHistory extends BaseViewModel {
* @returns the CollectionString to the model
*/
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
*/
public getModelID(): number {
return +this.element_id.split(":")[1]
return +this.element_id.split(':')[1];
}
/**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,35 +1,36 @@
import { Injectable } from "@angular/core";
import { Injectable } from '@angular/core';
import { FilterListService } from "../../../core/services/filter-list.service";
import { Mediafile } from "../../../shared/models/mediafiles/mediafile";
import { ViewMediafile } from "../models/view-mediafile";
import { StorageService } from "app/core/services/storage.service";
import { MediafileRepositoryService } from "./mediafile-repository.service";
import { FilterListService } from '../../../core/services/filter-list.service';
import { Mediafile } from '../../../shared/models/mediafiles/mediafile';
import { ViewMediafile } from '../models/view-mediafile';
import { StorageService } from 'app/core/services/storage.service';
import { MediafileRepositoryService } from './mediafile-repository.service';
@Injectable({
providedIn: 'root'
})
export class MediafileFilterListService extends FilterListService<Mediafile, ViewMediafile> {
protected name = 'Mediafile';
public filterOptions = [{
property: 'is_hidden', label: 'Hidden',
options: [
{ condition: true, label: 'is hidden' },
{ condition: false, label: 'is not hidden', isActive: true }
]
}
// , { TODO: is_pdf is not yet implemented on mediafile side
// property: 'is_pdf', isActive: false, label: 'PDF',
// options: [
// {condition: true, label: 'is a PDF'},
// {condition: false, label: 'is not a PDF'}
// ]
// }
public filterOptions = [
{
property: 'is_hidden',
label: 'Hidden',
options: [
{ condition: true, label: 'is hidden' },
{ condition: false, label: 'is not hidden', isActive: true }
]
}
// , { TODO: is_pdf is not yet implemented on mediafile side
// property: 'is_pdf', isActive: false, label: 'PDF',
// options: [
// {condition: true, label: 'is a PDF'},
// {condition: false, label: 'is not a PDF'}
// ]
// }
];
public constructor(store: StorageService, repo: MediafileRepositoryService){
public constructor(store: StorageService, repo: MediafileRepositoryService) {
super(store, repo);
}
}

View File

@ -15,7 +15,7 @@ import { HttpHeaders } from '@angular/common/http';
* Repository for MediaFiles
*/
@Injectable({
providedIn: 'root',
providedIn: 'root'
})
export class MediafileRepositoryService extends BaseRepository<ViewMediafile, Mediafile> {
/**
@ -29,7 +29,7 @@ export class MediafileRepositoryService extends BaseRepository<ViewMediafile, Me
DS: DataStoreService,
mapperService: CollectionStringModelMapperService,
private dataSend: DataSendService,
private httpService: HttpService,
private httpService: HttpService
) {
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 { ViewMediafile } from '../models/view-mediafile';
@Injectable({
providedIn: 'root'
})
export class MediafilesSortListService extends SortListService<ViewMediafile> {
public sortOptions: OsSortingDefinition<ViewMediafile> = {
sortProperty: 'title',
sortAscending: true,

View File

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

View File

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

View File

@ -4,7 +4,7 @@
font-size: 1em;
}
::ng-deep .mat-dialog-content {
overflow: visible;
overflow: visible;
}
.wide-form {
textarea {

View File

@ -9,13 +9,14 @@ import { MotionDetailOriginalChangeRecommendationsComponent } from '../motion-de
@Component({
template: `
<os-motion-detail-diff
[motion]="motion"
[changes]="changes"
(scrollToChange)="scrollToChange($event)"
(createChangeRecommendation)="createChangeRecommendation($event)"
>
</os-motion-detail-diff>`
<os-motion-detail-diff
[motion]="motion"
[changes]="changes"
(scrollToChange)="scrollToChange($event)"
(createChangeRecommendation)="createChangeRecommendation($event)"
>
</os-motion-detail-diff>
`
})
class TestHostComponent {
public motion: ViewMotion;

View File

@ -6,13 +6,14 @@ import { Component } from '@angular/core';
@Component({
template: `
<os-motion-detail-original-change-recommendations
[html]="html"
[changeRecommendations]="changeRecommendations"
(createChangeRecommendation)="createChangeRecommendation($event)"
(gotoChangeRecommendation)="gotoChangeRecommendation($event)"
>
</os-motion-detail-original-change-recommendations>`
<os-motion-detail-original-change-recommendations
[html]="html"
[changeRecommendations]="changeRecommendations"
(createChangeRecommendation)="createChangeRecommendation($event)"
(gotoChangeRecommendation)="gotoChangeRecommendation($event)"
>
</os-motion-detail-original-change-recommendations>
`
})
class TestHostComponent {
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 { WorkflowRepositoryService } from '../../services/workflow-repository.service';
/**
* 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']
})
export class MotionListComponent extends ListViewBaseComponent<ViewMotion> implements OnInit {
/**
* Use for minimal width. Please note the 'selector' row for multiSelect mode,
* 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 recomendationEnabled: boolean;
public tags: ViewTag[] = [];
public workflows: ViewWorkflow[] = [];
public categories: ViewCategory[] = [];
@ -112,11 +109,11 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion> imple
this.initTable();
this.configService.get('motions_statutes_enabled').subscribe(enabled => (this.statutesEnabled = enabled));
this.configService.get('motions_recommendations_by').subscribe(id => (this.recomendationEnabled = !!id));
this.motionBlockRepo.getViewModelListObservable().subscribe(mBs => this.motionBlocks = mBs);
this.categoryRepo.getViewModelListObservable().subscribe(cats => this.categories = cats);
this.tagRepo.getViewModelListObservable().subscribe(tags => this.tags = tags);
this.workflowRepo.getViewModelListObservable().subscribe(wfs => this.workflows = wfs);
this.filterService.filter().subscribe(filteredData => this.sortService.data = filteredData);
this.motionBlockRepo.getViewModelListObservable().subscribe(mBs => (this.motionBlocks = mBs));
this.categoryRepo.getViewModelListObservable().subscribe(cats => (this.categories = cats));
this.tagRepo.getViewModelListObservable().subscribe(tags => (this.tags = tags));
this.workflowRepo.getViewModelListObservable().subscribe(wfs => (this.workflows = wfs));
this.filterService.filter().subscribe(filteredData => (this.sortService.data = filteredData));
this.sortService.sort().subscribe(sortedData => {
this.dataSource.data = sortedData;
this.checkSelection();
@ -211,6 +208,4 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion> imple
this.raiseError(e);
}
}
}

View File

@ -34,6 +34,6 @@ export class ViewMotionBlock extends BaseViewModel {
}
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[] {
return this.motion ? this.motion.attachments_id : null
return this.motion ? this.motion.attachments_id : null;
}
public get attachments(): Mediafile[] {

View File

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

View File

@ -935,15 +935,14 @@ describe('DiffService', () => {
}
));
it('works with multiple inserted paragraphs', inject(
[DiffService],
(service: DiffService) => {
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>";
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>");
}
));
it('works with multiple inserted paragraphs', inject([DiffService], (service: DiffService) => {
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>';
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>'
);
}));
it('does not a change in a very specific case', inject([DiffService], (service: DiffService) => {
// See diff._fixWrongChangeDetection
@ -965,17 +964,21 @@ describe('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' +
'</ul>',
outHtml = '<ul class="os-split-before">\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>',
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 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>';
const diff = service.diff(inHtml, outHtml);
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 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>');
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 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>'
);
}));
});
@ -1053,10 +1056,16 @@ describe('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>",
after = "<ul>\n<li>\n<p>At vero eos et accusam et justo duo dolores et ea rebum.</p>\n</li>\n</ul>\n",
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 before =
'<ul><li>Lorem ipsum <strong>dolor sit amet</strong>, consetetur sadipscing elitr, sed diam nonumy 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',
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 diffNormalized = service.normalizeHtmlForDiff(diff).toLowerCase();
const expectedNormalized = service.normalizeHtmlForDiff(expected).toLowerCase();

View File

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

View File

@ -4,10 +4,10 @@ import { LocalPermissionsService } from './local-permissions.service';
import { E2EImportsModule } from '../../../../e2e-imports.module';
describe('LocalPermissionsService', () => {
beforeEach(() => TestBed.configureTestingModule({ imports: [E2EImportsModule] }));
beforeEach(() => TestBed.configureTestingModule({ imports: [E2EImportsModule] }));
it('should be created', () => {
const service: LocalPermissionsService = TestBed.get(LocalPermissionsService);
expect(service).toBeTruthy();
});
it('should be created', () => {
const service: LocalPermissionsService = TestBed.get(LocalPermissionsService);
expect(service).toBeTruthy();
});
});

View File

@ -3,20 +3,17 @@ import { OperatorService } from '../../../core/services/operator.service';
import { ViewMotion } from '../models/view-motion';
import { ConfigService } from '../../../core/services/config.service';
@Injectable({
providedIn: 'root'
providedIn: 'root'
})
export class LocalPermissionsService {
public configMinSupporters: number;
public constructor(
private operator: OperatorService,
private configService: ConfigService,
) {
public constructor(private operator: OperatorService, private configService: ConfigService) {
// 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.configMinSupporters > 0 &&
motion.state.allow_support &&
(motion.submitters.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)
motion.submitters.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;
default:
return false;
}

View File

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

View File

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

View File

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

View File

@ -12,7 +12,6 @@ import { ViewMotion } from '../models/view-motion';
providedIn: 'root'
})
export class MotionCsvExportService {
/**
* Does nothing.
*
@ -51,11 +50,15 @@ export class MotionCsvExportService {
this.csvExport.export(
motions,
[
{ label: 'Called', map: motion => motion.sort_parent_id ? '' : motion.identifierOrTitle },
{ label: 'Called with', 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: 'submitters', map: motion => motion.submitters.map(s => s.short_name).join(',') },
{ 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' }
],
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 { Motion } from "../../../shared/models/motions/motion";
import { ViewMotion } from "../models/view-motion";
import { CategoryRepositoryService } from "./category-repository.service";
import { WorkflowRepositoryService } from "./workflow-repository.service";
import { StorageService } from "../../../core/services/storage.service";
import { MotionRepositoryService } from "./motion-repository.service";
import { MotionBlockRepositoryService } from "./motion-block-repository.service";
import { FilterListService, OsFilter } from '../../../core/services/filter-list.service';
import { Motion } from '../../../shared/models/motions/motion';
import { ViewMotion } from '../models/view-motion';
import { CategoryRepositoryService } from './category-repository.service';
import { WorkflowRepositoryService } from './workflow-repository.service';
import { StorageService } from '../../../core/services/storage.service';
import { MotionRepositoryService } from './motion-repository.service';
import { MotionBlockRepositoryService } from './motion-block-repository.service';
@Injectable({
providedIn: 'root'
})
export class MotionFilterListService extends FilterListService<Motion, ViewMotion> {
protected name = 'Motion';
/**
* getter for the filterOptions. Note that in this case, the options are
* generated dynamically, as the options change with the datastore
*/
public get filterOptions(): OsFilter[] {
return [
this.flowFilterOptions,
this.categoryFilterOptions,
this.motionBlockFilterOptions
].concat(
this.staticFilterOptions);
return [this.flowFilterOptions, this.categoryFilterOptions, this.motionBlockFilterOptions].concat(
this.staticFilterOptions
);
}
/**
@ -54,28 +50,26 @@ export class MotionFilterListService extends FilterListService<Motion, ViewMotio
label: 'Motion block',
isActive: false,
options: []
}
};
public commentFilterOptions = {
property: 'comment',
isActive: false,
options: []
}
};
public staticFilterOptions = [
// TODO favorite (attached to user:whoamI!)
// TODO personalNote (attached to user:whoamI!)
];
public constructor(store: StorageService,
public constructor(
store: StorageService,
private workflowRepo: WorkflowRepositoryService,
private categoryRepo: CategoryRepositoryService,
private motionBlockRepo: MotionBlockRepositoryService,
// private commentRepo: MotionCommentRepositoryService
motionRepo: MotionRepositoryService,
){
motionRepo: MotionRepositoryService
) {
super(store, motionRepo);
this.subscribeWorkflows();
this.subscribeCategories();
@ -125,11 +119,11 @@ export class MotionFilterListService extends FilterListService<Motion, ViewMotio
workflows.forEach(workflow => {
workflowOptions.push(workflow.name);
workflow.states.forEach(state => {
workflowOptions.push({
condition: state.name,
label: state.name,
isActive: false
});
workflowOptions.push({
condition: state.name,
label: state.name,
isActive: false
});
});
});
workflowOptions.push('-');

View File

@ -89,11 +89,10 @@ export class MotionMultiselectService {
*/
public async setStateOfMultiple(motions: ViewMotion[]): Promise<void> {
const title = this.translate.instant('This will set the state of all selected motions to:');
const choices = this.workflowRepo.getWorkflowStatesForMotions(motions)
.map(workflowState => ({
id: workflowState.id,
label: workflowState.name
}));
const choices = this.workflowRepo.getWorkflowStatesForMotions(motions).map(workflowState => ({
id: workflowState.id,
label: workflowState.name
}));
const selectedChoice = await this.choiceService.open(title, choices);
if (selectedChoice) {
for (const motion of motions) {
@ -117,12 +116,11 @@ export class MotionMultiselectService {
label: workflowState.recommendation_label
}));
const clearChoice = 'Delete recommendation';
const selectedChoice = await this.choiceService.open(title, choices, false,
null, clearChoice);
const selectedChoice = await this.choiceService.open(title, choices, false, null, clearChoice);
if (selectedChoice) {
const requestData = motions.map(motion => ({
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', {
motions: requestData
@ -138,13 +136,19 @@ export class MotionMultiselectService {
public async setCategory(motions: ViewMotion[]): Promise<void> {
const title = this.translate.instant('This will set the category of all selected motions to:');
const clearChoice = 'No category';
const selectedChoice = await this.choiceService.open(title, this.categoryRepo.getViewModelList(),
false, null, clearChoice);
const selectedChoice = await this.choiceService.open(
title,
this.categoryRepo.getViewModelList(),
false,
null,
clearChoice
);
if (selectedChoice) {
for (const motion of motions) {
await this.repo.update(
{category_id: selectedChoice.action ? 0 : selectedChoice.items as number },
motion);
{ category_id: selectedChoice.action ? 0 : (selectedChoice.items as number) },
motion
);
}
}
}
@ -155,10 +159,11 @@ export class MotionMultiselectService {
* @param motions The motions to add/remove the sumbitters to
*/
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 selectedChoice = await this.choiceService.open(title,
this.userRepo.getViewModelList(), true, choices);
const selectedChoice = await this.choiceService.open(title, this.userRepo.getViewModelList(), true, choices);
if (selectedChoice && selectedChoice.action === choices[0]) {
const requestData = motions.map(motion => {
let submitterIds = [...motion.submitters_id, ...(selectedChoice.items as number[])];
@ -190,8 +195,7 @@ export class MotionMultiselectService {
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 choices = ['Add', 'Remove', 'Clear tags'];
const selectedChoice = await this.choiceService.open(title, this.tagRepo.getViewModelList(), true,
choices);
const selectedChoice = await this.choiceService.open(title, this.tagRepo.getViewModelList(), true, choices);
if (selectedChoice && selectedChoice.action === choices[0]) {
const requestData = motions.map(motion => {
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.
*
@ -232,12 +235,17 @@ export class MotionMultiselectService {
public async setMotionBlock(motions: ViewMotion[]): Promise<void> {
const title = this.translate.instant('This will change the motion Block for all selected motions:');
const clearChoice = 'Clear motion block';
const selectedChoice = await this.choiceService.open(title, this.motionBlockRepo.getViewModelList(),
false, null, clearChoice);
const selectedChoice = await this.choiceService.open(
title,
this.motionBlockRepo.getViewModelList(),
false,
null,
clearChoice
);
if (selectedChoice) {
for (const motion of motions) {
const blockId = selectedChoice.action ? null : selectedChoice.items as number;
await this.repo.update({motion_block_id: blockId}, motion);
const blockId = selectedChoice.action ? null : (selectedChoice.items as number);
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 { MotionBlock } from 'app/shared/models/motions/motion-block';
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)
@ -44,7 +44,6 @@ import { ConfigService } from "../../../core/services/config.service";
providedIn: 'root'
})
export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion> {
// The line length; comes from the config variable motions_line_length
private lineLength = 90;
@ -81,9 +80,9 @@ export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion>
super(DS, mapperService, Motion, [Category, User, Workflow, Item, MotionBlock, Mediafile]);
// load config variables
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_recommendation_text_mode').subscribe(mode => this.defaultCrMode = mode);
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_recommendation_text_mode').subscribe(mode => (this.defaultCrMode = mode));
}
/**
@ -106,7 +105,20 @@ export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion>
if (workflow) {
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> {
const requestData = {
motions: [{
id: viewMotion.id,
submitters: submitters.map(s => s.id),
}]
motions: [
{
id: viewMotion.id,
submitters: submitters.map(s => s.id)
}
]
};
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[] {
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 => {
const workflow = this.getViewModel(id);
states = states.concat(workflow.states);
});
return states;
}
}

View File

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

View File

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

View File

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

View File

@ -261,5 +261,4 @@ export class PasswordComponent extends BaseViewComponent implements OnInit {
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
*/
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)) {
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']
})
export class UserListComponent extends ListViewBaseComponent<ViewUser> implements OnInit {
/**
* /**
* The usual constructor for components
@ -71,10 +70,9 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
super.setTitle('Users');
this.initTable();
this.filterService.filter().subscribe(filteredData => {
this.sortService.data = filteredData;
});
this.sortService.data = filteredData;
});
this.sortService.sort().subscribe(sortedData => {
this.dataSource.data = sortedData;
this.checkSelection();
@ -148,8 +146,7 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
public async setGroupSelected(): Promise<void> {
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 selectedChoice = await this.choiceService.open(content,
this.groupRepo.getViewModelList(), true, choices);
const selectedChoice = await this.choiceService.open(content, this.groupRepo.getViewModelList(), true, choices);
if (selectedChoice) {
for (const user of this.selectedRows) {
const newGroups = [...user.groups_id];
@ -187,7 +184,7 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
* Uses selectedRows defined via multiSelect mode.
*/
public async setPresentSelected(): Promise<void> {
const content = this.translate.instant('Set the presence status for the selected users');
const content = this.translate.instant('Set the presence status for the selected users');
const options = ['Present', 'Not present'];
const selectedChoice = await this.choiceService.open(content, null, false, options);
if (selectedChoice) {
@ -203,8 +200,7 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
* Uses selectedRows defined via multiSelect mode.
*/
public async setCommitteeSelected(): Promise<void> {
const content = this.translate.instant(
'Sets/unsets the committee status for the selected users');
const content = this.translate.instant('Sets/unsets the committee status for the selected users');
const options = ['Is committee', 'Is not committee'];
const selectedChoice = await this.choiceService.open(content, null, false, options);
if (selectedChoice) {
@ -254,7 +250,5 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
public async setPresent(viewUser: ViewUser): Promise<void> {
viewUser.user.is_present = !viewUser.user.is_present;
await this.repo.update(viewUser.user, viewUser);
}
}

View File

@ -93,7 +93,7 @@ export class ViewUser extends BaseViewModel {
}
public get is_last_email_send(): boolean {
if (this.user && this.user.last_email_send){
if (this.user && this.user.last_email_send) {
return true;
}
return false;
@ -105,7 +105,6 @@ export class ViewUser extends BaseViewModel {
this._groups = groups;
}
/**
* required by BaseViewModel. Don't confuse with the users title.
*/

View File

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

View File

@ -120,7 +120,7 @@ export class UserRepositoryService extends BaseRepository<ViewUser, User> {
public async resetPassword(user: ViewUser, password: string): Promise<void> {
const path = `/rest/users/user/${user.id}/reset_password/`;
await this.httpService.post(path, { password: password });
await this.update({default_password: password}, user);
await this.update({ default_password: password }, user);
}
/**
@ -131,8 +131,8 @@ export class UserRepositoryService extends BaseRepository<ViewUser, User> {
*/
public async setNewPassword(oldPassword: string, newPassword: string): Promise<void> {
await this.httpService.post(`${environment.urlPrefix}/users/setpassword/`, {
old_password: oldPassword,
new_password: newPassword
old_password: oldPassword,
new_password: newPassword
});
}

View File

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