Merge pull request #4067 from FinnStutzenstein/prettify
Using prettify instead of pretty-quick-wrapper
This commit is contained in:
commit
2f7336b257
@ -68,7 +68,7 @@ matrix:
|
|||||||
install:
|
install:
|
||||||
- npm install
|
- npm install
|
||||||
script:
|
script:
|
||||||
- npm run prettify-all
|
- npm run prettify-check
|
||||||
|
|
||||||
- language: node_js
|
- language: node_js
|
||||||
name: "Client: Testing"
|
name: "Client: Testing"
|
||||||
|
@ -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",
|
"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 _",
|
"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",
|
"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-check": "prettier --config ./.prettierrc --list-different \"src/{app,environments}/**/*{.ts,.js,.json,.css,.scss}\"",
|
||||||
"prettify-all": "pretty-quick"
|
"prettify-write": "prettier --config ./.prettierrc --write \"src/{app,environments}/**/*{.ts,.js,.json,.css,.scss}\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^7.1.1",
|
"@angular/animations": "^7.1.1",
|
||||||
@ -71,7 +71,6 @@
|
|||||||
"karma-jasmine-html-reporter": "^0.2.2",
|
"karma-jasmine-html-reporter": "^0.2.2",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^1.15.3",
|
"prettier": "^1.15.3",
|
||||||
"pretty-quick": "^1.8.0",
|
|
||||||
"protractor": "^5.4.1",
|
"protractor": "^5.4.1",
|
||||||
"ts-node": "~7.0.1",
|
"ts-node": "~7.0.1",
|
||||||
"tslint": "~5.11.0",
|
"tslint": "~5.11.0",
|
||||||
|
@ -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);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// import { _ } from '@biesbjerg/ngx-translate-extract';
|
// import { _ } from '@biesbjerg/ngx-translate-extract';
|
||||||
|
|
||||||
function _(key: string | string[]): string | string[] {
|
function _(key: string | string[]): string | string[] {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
type QueryParamValue = string | number | boolean;
|
type QueryParamValue = string | number | boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -115,40 +115,44 @@ export class CsvExportService {
|
|||||||
csvContent.push(header);
|
csvContent.push(header);
|
||||||
|
|
||||||
// create lines
|
// create lines
|
||||||
csvContent = csvContent.concat(models.map(model => {
|
csvContent = csvContent.concat(
|
||||||
return columns.map(column => {
|
models.map(model => {
|
||||||
let value: string;
|
return columns.map(column => {
|
||||||
|
let value: string;
|
||||||
|
|
||||||
if (isPropertyDefinition(column)) {
|
if (isPropertyDefinition(column)) {
|
||||||
const property: any = model[column.property];
|
const property: any = model[column.property];
|
||||||
if (typeof property === 'number') {
|
if (typeof property === 'number') {
|
||||||
value = property.toString(10);
|
value = property.toString(10);
|
||||||
} else if (!property) {
|
} else if (!property) {
|
||||||
value = '';
|
value = '';
|
||||||
} else if (property === true) {
|
} else if (property === true) {
|
||||||
value = '1';
|
value = '1';
|
||||||
} else if (property === false) {
|
} else if (property === false) {
|
||||||
value = '0';
|
value = '0';
|
||||||
} else {
|
} else {
|
||||||
value = property.toString();
|
value = property.toString();
|
||||||
|
}
|
||||||
|
} else if (isMapDefinition(column)) {
|
||||||
|
value = column.map(model);
|
||||||
}
|
}
|
||||||
} else if (isMapDefinition(column)) {
|
tsList = this.checkCsvTextSafety(value, tsList);
|
||||||
value = column.map(model);
|
|
||||||
}
|
|
||||||
tsList = this.checkCsvTextSafety(value, tsList);
|
|
||||||
|
|
||||||
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
|
||||||
return line.map(entry => tsList[0] + entry + tsList[0]).join(columnSeparator);
|
.map(line => {
|
||||||
}).join(lineSeparator);
|
return line.map(entry => tsList[0] + entry + tsList[0]).join(columnSeparator);
|
||||||
|
})
|
||||||
|
.join(lineSeparator);
|
||||||
this.exporter.saveFile(csvContentAsString, filename);
|
this.exporter.saveFile(csvContentAsString, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
@ -18,7 +17,7 @@ import { StorageService } from './storage.service';
|
|||||||
export interface OsFilter {
|
export interface OsFilter {
|
||||||
property: string;
|
property: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
options: (OsFilterOption | string )[];
|
options: (OsFilterOption | string)[];
|
||||||
count?: number;
|
count?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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,11 +66,14 @@ 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
|
||||||
this.currentRawData = data;
|
.getViewModelListObservable()
|
||||||
this.filteredData = this.filterData(data);
|
.pipe(auditTime(100))
|
||||||
this.filterDataOutput.next(this.filteredData);
|
.subscribe(data => {
|
||||||
});
|
this.currentRawData = data;
|
||||||
|
this.filteredData = this.filterData(data);
|
||||||
|
this.filterDataOutput.next(this.filteredData);
|
||||||
|
});
|
||||||
this.loadStorageDefinition(this.filterDefinitions);
|
this.loadStorageDefinition(this.filterDefinitions);
|
||||||
return this.filterDataOutput;
|
return this.filterDataOutput;
|
||||||
}
|
}
|
||||||
@ -84,11 +83,12 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
|||||||
* @param filter
|
* @param filter
|
||||||
*/
|
*/
|
||||||
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
|
||||||
if (filterOption && !filterOption.isActive){
|
) as OsFilterOption;
|
||||||
|
if (filterOption && !filterOption.isActive) {
|
||||||
filterOption.isActive = true;
|
filterOption.isActive = true;
|
||||||
filter.count += 1;
|
filter.count += 1;
|
||||||
}
|
}
|
||||||
@ -103,11 +103,12 @@ 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
|
||||||
if (filterOption && filterOption.isActive){
|
) as OsFilterOption;
|
||||||
|
if (filterOption && filterOption.isActive) {
|
||||||
filterOption.isActive = false;
|
filterOption.isActive = false;
|
||||||
filter.count -= 1;
|
filter.count -= 1;
|
||||||
this.filteredData = this.filterData(this.currentRawData);
|
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);
|
option.isActive ? this.removeFilterOption(filterName, option) : this.addFilterOption(filterName, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateFilterDefinitions(filters: OsFilter[]) : void {
|
public updateFilterDefinitions(filters: OsFilter[]): void {
|
||||||
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,35 +141,39 @@ 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 {
|
||||||
definitions.forEach(definedFilter => {
|
const storedFilters = storedData && storedData.data ? storedData.data : [];
|
||||||
const matchingStoreFilter = storedFilters.find(f => f.property === definedFilter.property);
|
definitions.forEach(definedFilter => {
|
||||||
let count = 0;
|
const matchingStoreFilter = storedFilters.find(f => f.property === definedFilter.property);
|
||||||
definedFilter.options.forEach(option => {
|
let count = 0;
|
||||||
if (typeof option === 'string'){
|
definedFilter.options.forEach(option => {
|
||||||
return;
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
if (matchingStoreFilter && matchingStoreFilter.options) {
|
||||||
if (option.isActive) {
|
const storedOption = matchingStoreFilter.options.find(
|
||||||
count += 1;
|
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.filterDefinitions = definitions;
|
me.filterDataOutput.next(me.filteredData);
|
||||||
me.filteredData = me.filterData(me.currentRawData);
|
},
|
||||||
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
|
||||||
*/
|
*/
|
||||||
@ -189,7 +194,7 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
return filteredData;
|
return filteredData;
|
||||||
}
|
}
|
||||||
if (!this.filterDefinitions || !this.filterDefinitions.length){
|
if (!this.filterDefinitions || !this.filterDefinitions.length) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
data.forEach(newItem => {
|
data.forEach(newItem => {
|
||||||
@ -200,7 +205,7 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!excluded){
|
if (!excluded) {
|
||||||
filteredData.push(newItem);
|
filteredData.push(newItem);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -214,27 +219,27 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
|||||||
*/
|
*/
|
||||||
private checkIncluded(item: V, filter: OsFilter): boolean {
|
private checkIncluded(item: V, filter: OsFilter): boolean {
|
||||||
for (const option of filter.options) {
|
for (const option of filter.options) {
|
||||||
if (typeof option === 'string' ){
|
if (typeof option === 'string') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (option.isActive) {
|
if (option.isActive) {
|
||||||
if (option.condition === null ) {
|
if (option.condition === null) {
|
||||||
return this.checkIncludedNegative(item, filter);
|
return this.checkIncludedNegative(item, filter);
|
||||||
}
|
}
|
||||||
if (item[filter.property] === undefined) {
|
if (item[filter.property] === undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (item[filter.property] instanceof BaseModel ) {
|
if (item[filter.property] instanceof BaseModel) {
|
||||||
if (item[filter.property].id === option.condition){
|
if (item[filter.property].id === option.condition) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (item[filter.property] === option.condition){
|
} else if (item[filter.property] === option.condition) {
|
||||||
return true;
|
return true;
|
||||||
} else if (item[filter.property].toString() === option.condition){
|
} else if (item[filter.property].toString() === option.condition) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +259,7 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
|||||||
}
|
}
|
||||||
if (item[filter.property] === option.condition) {
|
if (item[filter.property] === option.condition) {
|
||||||
return false;
|
return false;
|
||||||
} else if (item[filter.property].toString() === option.condition){
|
} else if (item[filter.property].toString() === option.condition) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,20 +276,19 @@ export abstract class FilterListService<M extends BaseModel, V extends BaseViewM
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get hasActiveFilters(): number {
|
public get hasActiveFilters(): number {
|
||||||
if (!this.filterDefinitions || !this.filterDefinitions.length){
|
if (!this.filterDefinitions || !this.filterDefinitions.length) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
let filters = 0;
|
let filters = 0;
|
||||||
for (const filter of this.filterDefinitions) {
|
for (const filter of this.filterDefinitions) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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');
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
@ -37,6 +36,6 @@ export class OpenSlidesStatusService {
|
|||||||
* Leaves the histroy mode
|
* Leaves the histroy mode
|
||||||
*/
|
*/
|
||||||
public leaveHistroyMode(): void {
|
public leaveHistroyMode(): void {
|
||||||
this.historyMode = false;
|
this.historyMode = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(() =>
|
||||||
imports: [E2EImportsModule],
|
TestBed.configureTestingModule({
|
||||||
providers: [TimeTravelService]
|
imports: [E2EImportsModule],
|
||||||
}));
|
providers: [TimeTravelService]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
const service: TimeTravelService = TestBed.get(TimeTravelService);
|
const service: TimeTravelService = TestBed.get(TimeTravelService);
|
||||||
|
@ -52,7 +52,7 @@ export class TimeTravelService {
|
|||||||
private DS: DataStoreService,
|
private DS: DataStoreService,
|
||||||
private OSStatus: OpenSlidesStatusService,
|
private OSStatus: OpenSlidesStatusService,
|
||||||
private OpenSlides: OpenSlidesService
|
private OpenSlides: OpenSlidesService
|
||||||
) { }
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main entry point to set OpenSlides to another history point.
|
* Main entry point to set OpenSlides to another history point.
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -51,7 +51,7 @@ interface ChoiceDialogData {
|
|||||||
* it will be an array of numbers and optionally an action string for multichoice
|
* it will be an array of numbers and optionally an action string for multichoice
|
||||||
* dialogs
|
* dialogs
|
||||||
*/
|
*/
|
||||||
export type ChoiceAnswer = undefined | { action?: string; items: number | number[]};
|
export type ChoiceAnswer = undefined | { action?: string; items: number | number[] };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A dialog with choice fields.
|
* A dialog with choice fields.
|
||||||
|
@ -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();
|
||||||
// });
|
// });
|
||||||
|
@ -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
|
||||||
@ -53,12 +51,12 @@ export class FilterMenuComponent implements OnInit {
|
|||||||
* Tests for escape key (to colose the sidebar)
|
* Tests for escape key (to colose the sidebar)
|
||||||
* @param event
|
* @param event
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>>;
|
||||||
|
@ -19,21 +19,21 @@ 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.
|
||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
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');
|
throw new Error('No sorting available for a sorting list');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ describe('OsSortFilterBarComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [E2EImportsModule],
|
imports: [E2EImportsModule]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@ 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;
|
||||||
@ -92,7 +93,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
|
|||||||
* Listen to keypresses on the quick-search input
|
* Listen to keypresses on the quick-search input
|
||||||
*/
|
*/
|
||||||
public applySearch(event: KeyboardEvent, value?: string): void {
|
public applySearch(event: KeyboardEvent, value?: string): void {
|
||||||
if (event.key === 'Escape' ) {
|
if (event.key === 'Escape') {
|
||||||
this.searchFieldChange.emit('');
|
this.searchFieldChange.emit('');
|
||||||
this.isSearchBar = false;
|
this.isSearchBar = false;
|
||||||
} else {
|
} else {
|
||||||
@ -104,16 +105,16 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if there is an active FilterService present
|
* Checks if there is an active FilterService present
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +123,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
|
|||||||
* @param option
|
* @param option
|
||||||
*/
|
*/
|
||||||
public getSortIcon(option: OsSortingItem<V>): string {
|
public getSortIcon(option: OsSortingItem<V>): string {
|
||||||
if (this.sortService.sortProperty !== option.property){
|
if (this.sortService.sortProperty !== option.property) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return this.sortService.ascending ? 'arrow_downward' : 'arrow_upward';
|
return this.sortService.ascending ? 'arrow_downward' : 'arrow_upward';
|
||||||
@ -133,7 +134,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
|
|||||||
* the property is used.
|
* the property is used.
|
||||||
* @param option
|
* @param option
|
||||||
*/
|
*/
|
||||||
public getSortLabel(option: OsSortingItem<V>) : string {
|
public getSortLabel(option: OsSortingItem<V>): string {
|
||||||
if (option.label) {
|
if (option.label) {
|
||||||
return option.label;
|
return option.label;
|
||||||
}
|
}
|
||||||
@ -146,7 +147,7 @@ export class OsSortFilterBarComponent<V extends BaseViewModel> {
|
|||||||
* that input applied
|
* that input applied
|
||||||
*/
|
*/
|
||||||
public toggleSearchBar(): void {
|
public toggleSearchBar(): void {
|
||||||
if (!this.isSearchBar){
|
if (!this.isSearchBar) {
|
||||||
this.isSearchBar = true;
|
this.isSearchBar = true;
|
||||||
} else {
|
} else {
|
||||||
this.searchFieldChange.emit('');
|
this.searchFieldChange.emit('');
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -3,11 +3,10 @@ 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' },
|
||||||
{key: 2, name: 'Finished'}
|
{ key: 2, name: 'Finished' }
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import { BaseModel } from '../base/base-model';
|
import { BaseModel } from '../base/base-model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ export class WorkflowState extends Deserializer {
|
|||||||
* Checks if a workflowstate has no 'next state' left, and is final
|
* Checks if a workflowstate has no 'next state' left, and is final
|
||||||
*/
|
*/
|
||||||
public get isFinalState(): boolean {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
if (this.next_states_id.length === 1 && this.next_states_id[0] === 0) {
|
if (this.next_states_id.length === 1 && this.next_states_id[0] === 0) {
|
||||||
|
@ -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',
|
||||||
|
@ -12,7 +12,7 @@ import { ItemInfoDialogComponent } from './components/item-info-dialog/item-info
|
|||||||
*/
|
*/
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, AgendaRoutingModule, SharedModule],
|
imports: [CommonModule, AgendaRoutingModule, SharedModule],
|
||||||
entryComponents: [ ItemInfoDialogComponent ],
|
entryComponents: [ItemInfoDialogComponent],
|
||||||
declarations: [AgendaListComponent, TopicDetailComponent, ItemInfoDialogComponent]
|
declarations: [AgendaListComponent, TopicDetailComponent, ItemInfoDialogComponent]
|
||||||
})
|
})
|
||||||
export class AgendaModule {}
|
export class AgendaModule {}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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';
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -44,14 +44,14 @@ export class ViewItem extends BaseViewModel {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public get verboseType() : string {
|
public get verboseType(): string {
|
||||||
if (this.item && this.item.verboseType) {
|
if (this.item && this.item.verboseType) {
|
||||||
return this.item.verboseType;
|
return this.item.verboseType;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public get verboseCsvType() : string {
|
public get verboseCsvType(): string {
|
||||||
if (this.item) {
|
if (this.item) {
|
||||||
return this.item.verboseCsvType;
|
return this.item.verboseCsvType;
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,7 @@ describe('AgendaCsvExportService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be created', inject(
|
it('should be created', inject([AgendaCsvExportService], (service: AgendaCsvExportService) => {
|
||||||
[AgendaCsvExportService],
|
expect(service).toBeTruthy();
|
||||||
(service: AgendaCsvExportService) => {
|
}));
|
||||||
expect(service).toBeTruthy();
|
|
||||||
}
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
|
@ -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' }
|
||||||
|
@ -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,22 +21,22 @@ 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[] {
|
||||||
const options = [];
|
const options = [];
|
||||||
itemVisibilityChoices.forEach(choice => {
|
itemVisibilityChoices.forEach(choice => {
|
||||||
options.push({
|
options.push({
|
||||||
condition: choice.key as number,
|
condition: choice.key as number,
|
||||||
@ -46,6 +45,4 @@ export class AgendaFilterListService extends FilterListService<Item, ViewItem> {
|
|||||||
});
|
});
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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',
|
{
|
||||||
options: this.createPhaseOptions()
|
property: 'phase',
|
||||||
}];
|
options: this.createPhaseOptions()
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private createPhaseOptions(): OsFilterOption[] {
|
private createPhaseOptions(): OsFilterOption[] {
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -80,7 +80,7 @@ export abstract class ListViewBaseComponent<V extends BaseViewModel> extends Bas
|
|||||||
this.sort.sort(newSort);
|
this.sort.sort(newSort);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onFilterData(filteredDataSource: MatTableDataSource<V>) : void {
|
public onFilterData(filteredDataSource: MatTableDataSource<V>): void {
|
||||||
this.dataSource = filteredDataSource;
|
this.dataSource = filteredDataSource;
|
||||||
this.dataSource.paginator = this.paginator;
|
this.dataSource.paginator = this.paginator;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
@ -78,16 +78,16 @@ export class SearchComponent extends BaseViewComponent implements OnInit {
|
|||||||
super(title, translate, matSnackBar);
|
super(title, translate, matSnackBar);
|
||||||
this.quickSearchform = new FormGroup({ query: new FormControl([]) });
|
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.DS.changedOrDeletedObservable.pipe(auditTime(1)).subscribe(() => this.search());
|
||||||
this.quickSearchSubject.pipe(debounceTime(250)).subscribe(query => this.search(query));
|
this.quickSearchSubject.pipe(debounceTime(250)).subscribe(query => this.search(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take the search query from the URL and does the initial search.
|
* Take the search query from the URL and does the initial search.
|
||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
super.setTitle('Search');
|
super.setTitle('Search');
|
||||||
this.query = this.activatedRoute.snapshot.queryParams.query;
|
this.query = this.activatedRoute.snapshot.queryParams.query;
|
||||||
this.quickSearchform.get('query').setValue(this.query);
|
this.quickSearchform.get('query').setValue(this.query);
|
||||||
|
@ -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(() =>
|
||||||
imports: [E2EImportsModule]
|
TestBed.configureTestingModule({
|
||||||
}));
|
imports: [E2EImportsModule]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
const service: DurationService = TestBed.get(DurationService);
|
const service: DurationService = TestBed.get(DurationService);
|
||||||
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
// 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(
|
||||||
if (response.info_text) {
|
response => {
|
||||||
this.installationNotice = this.matSnackBar.open(response.info_text, this.translate.instant('OK'), {
|
if (response.info_text) {
|
||||||
duration: 5000
|
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.loginDataService.setPrivacyPolicy(response.privacy_policy);
|
||||||
}, () => {});
|
this.loginDataService.setLegalNotice(response.legal_notice);
|
||||||
|
},
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnDestroy(): void {
|
public ngOnDestroy(): void {
|
||||||
|
@ -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(() => {
|
||||||
|
@ -10,7 +10,7 @@ describe('MediaUploadComponent', () => {
|
|||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [E2EImportsModule],
|
imports: [E2EImportsModule],
|
||||||
declarations: [MediaUploadComponent],
|
declarations: [MediaUploadComponent]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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(() => {
|
||||||
@ -269,7 +266,7 @@ export class MediafileListComponent extends ListViewBaseComponent<ViewMediafile>
|
|||||||
*/
|
*/
|
||||||
public getColumnDefinition(): string[] {
|
public getColumnDefinition(): string[] {
|
||||||
const columns = this.vp.isMobile ? this.displayedColumnsMobile : this.displayedColumnsDesktop;
|
const columns = this.vp.isMobile ? this.displayedColumnsMobile : this.displayedColumnsDesktop;
|
||||||
if (this.isMultiSelect){
|
if (this.isMultiSelect) {
|
||||||
return ['selector'].concat(columns);
|
return ['selector'].concat(columns);
|
||||||
}
|
}
|
||||||
return columns;
|
return columns;
|
||||||
|
@ -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 {}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -1,35 +1,36 @@
|
|||||||
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',
|
{
|
||||||
options: [
|
property: 'is_hidden',
|
||||||
{ condition: true, label: 'is hidden' },
|
label: 'Hidden',
|
||||||
{ condition: false, label: 'is not hidden', isActive: true }
|
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: [
|
// , { TODO: is_pdf is not yet implemented on mediafile side
|
||||||
// {condition: true, label: 'is a PDF'},
|
// property: 'is_pdf', isActive: false, label: 'PDF',
|
||||||
// {condition: false, label: 'is not a 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);
|
super(store, repo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
@ -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>'
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
::ng-deep .mat-dialog-content {
|
::ng-deep .mat-dialog-content {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
.wide-form {
|
.wide-form {
|
||||||
textarea {
|
textarea {
|
||||||
|
@ -9,13 +9,14 @@ import { MotionDetailOriginalChangeRecommendationsComponent } from '../motion-de
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
<os-motion-detail-diff
|
<os-motion-detail-diff
|
||||||
[motion]="motion"
|
[motion]="motion"
|
||||||
[changes]="changes"
|
[changes]="changes"
|
||||||
(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;
|
||||||
|
@ -6,13 +6,14 @@ import { Component } from '@angular/core';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
<os-motion-detail-original-change-recommendations
|
<os-motion-detail-original-change-recommendations
|
||||||
[html]="html"
|
[html]="html"
|
||||||
[changeRecommendations]="changeRecommendations"
|
[changeRecommendations]="changeRecommendations"
|
||||||
(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>';
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,6 @@ export class ViewMotionBlock extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getTitle(): string {
|
public getTitle(): string {
|
||||||
return this.title
|
return this.title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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[] {
|
||||||
|
@ -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) {
|
||||||
|
@ -935,15 +935,14 @@ describe('DiffService', () => {
|
|||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
it('works with multiple inserted paragraphs', inject(
|
it('works with multiple inserted paragraphs', inject([DiffService], (service: DiffService) => {
|
||||||
[DiffService],
|
const before = '<p>This is the text before</p>',
|
||||||
(service: DiffService) => {
|
after = '<p>This is the text before</p>\n<p>This is one added line</p>\n<p>Another added line</p>';
|
||||||
const before = '<p>This is the text before</p>',
|
const diff = service.diff(before, after);
|
||||||
after = "<p>This is the text before</p>\n<p>This is one added line</p>\n<p>Another added line</p>";
|
expect(diff).toBe(
|
||||||
const diff = service.diff(before, after);
|
'<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>',
|
'<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' +
|
||||||
outHtml = '<ul class="os-split-before">\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>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(
|
||||||
'<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>' +
|
'<ul class="os-split-before">' +
|
||||||
'<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>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>' +
|
||||||
'</ul>');
|
'<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) => {
|
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();
|
||||||
|
@ -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);
|
||||||
}));
|
}));
|
||||||
|
@ -4,10 +4,10 @@ import { LocalPermissionsService } from './local-permissions.service';
|
|||||||
import { E2EImportsModule } from '../../../../e2e-imports.module';
|
import { E2EImportsModule } from '../../../../e2e-imports.module';
|
||||||
|
|
||||||
describe('LocalPermissionsService', () => {
|
describe('LocalPermissionsService', () => {
|
||||||
beforeEach(() => TestBed.configureTestingModule({ imports: [E2EImportsModule] }));
|
beforeEach(() => TestBed.configureTestingModule({ imports: [E2EImportsModule] }));
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
const service: LocalPermissionsService = TestBed.get(LocalPermissionsService);
|
const service: LocalPermissionsService = TestBed.get(LocalPermissionsService);
|
||||||
expect(service).toBeTruthy();
|
expect(service).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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(() =>
|
||||||
imports: [E2EImportsModule]
|
TestBed.configureTestingModule({
|
||||||
}));
|
imports: [E2EImportsModule]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
it('should be created', () => {
|
it('should be created', () => {
|
||||||
const service: MotionBlockRepositoryService = TestBed.get(MotionBlockRepositoryService);
|
const service: MotionBlockRepositoryService = TestBed.get(MotionBlockRepositoryService);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,7 @@ describe('MotionCsvExportService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be created', inject(
|
it('should be created', inject([MotionCsvExportService], (service: MotionCsvExportService) => {
|
||||||
[MotionCsvExportService],
|
expect(service).toBeTruthy();
|
||||||
(service: MotionCsvExportService) => {
|
}));
|
||||||
expect(service).toBeTruthy();
|
|
||||||
}
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
|
@ -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'
|
||||||
|
@ -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,28 +50,26 @@ 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();
|
||||||
this.subscribeCategories();
|
this.subscribeCategories();
|
||||||
@ -125,11 +119,11 @@ export class MotionFilterListService extends FilterListService<Motion, ViewMotio
|
|||||||
workflows.forEach(workflow => {
|
workflows.forEach(workflow => {
|
||||||
workflowOptions.push(workflow.name);
|
workflowOptions.push(workflow.name);
|
||||||
workflow.states.forEach(state => {
|
workflow.states.forEach(state => {
|
||||||
workflowOptions.push({
|
workflowOptions.push({
|
||||||
condition: state.name,
|
condition: state.name,
|
||||||
label: state.name,
|
label: state.name,
|
||||||
isActive: false
|
isActive: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
workflowOptions.push('-');
|
workflowOptions.push('-');
|
||||||
|
@ -89,11 +89,10 @@ 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
|
}));
|
||||||
}));
|
|
||||||
const selectedChoice = await this.choiceService.open(title, choices);
|
const selectedChoice = await this.choiceService.open(title, choices);
|
||||||
if (selectedChoice) {
|
if (selectedChoice) {
|
||||||
for (const motion of motions) {
|
for (const motion of motions) {
|
||||||
@ -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,12 +235,17 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
{
|
||||||
submitters: submitters.map(s => s.id),
|
id: viewMotion.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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,10 +70,9 @@ 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;
|
||||||
});
|
});
|
||||||
this.sortService.sort().subscribe(sortedData => {
|
this.sortService.sort().subscribe(sortedData => {
|
||||||
this.dataSource.data = sortedData;
|
this.dataSource.data = sortedData;
|
||||||
this.checkSelection();
|
this.checkSelection();
|
||||||
@ -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];
|
||||||
@ -187,7 +184,7 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
|
|||||||
* Uses selectedRows defined via multiSelect mode.
|
* Uses selectedRows defined via multiSelect mode.
|
||||||
*/
|
*/
|
||||||
public async setPresentSelected(): Promise<void> {
|
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 options = ['Present', 'Not present'];
|
||||||
const selectedChoice = await this.choiceService.open(content, null, false, options);
|
const selectedChoice = await this.choiceService.open(content, null, false, options);
|
||||||
if (selectedChoice) {
|
if (selectedChoice) {
|
||||||
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ export class ViewUser extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get is_last_email_send(): boolean {
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ export class UserRepositoryService extends BaseRepository<ViewUser, User> {
|
|||||||
public async resetPassword(user: ViewUser, password: string): Promise<void> {
|
public async resetPassword(user: ViewUser, password: string): Promise<void> {
|
||||||
const path = `/rest/users/user/${user.id}/reset_password/`;
|
const path = `/rest/users/user/${user.id}/reset_password/`;
|
||||||
await this.httpService.post(path, { password: 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> {
|
public async setNewPassword(oldPassword: string, newPassword: string): Promise<void> {
|
||||||
await this.httpService.post(`${environment.urlPrefix}/users/setpassword/`, {
|
await this.httpService.post(`${environment.urlPrefix}/users/setpassword/`, {
|
||||||
old_password: oldPassword,
|
old_password: oldPassword,
|
||||||
new_password: newPassword
|
new_password: newPassword
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user