Refresh clients cache when the database was migrated
This commit is contained in:
parent
e9a60a54fd
commit
a715c0e432
@ -4,13 +4,14 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { take, filter } from 'rxjs/operators';
|
import { take, filter } from 'rxjs/operators';
|
||||||
|
|
||||||
import { ConfigService } from './core/ui-services/config.service';
|
import { ConfigService } from './core/ui-services/config.service';
|
||||||
import { ConstantsService } from './core/ui-services/constants.service';
|
import { ConstantsService } from './core/core-services/constants.service';
|
||||||
import { CountUsersService } from './core/ui-services/count-users.service';
|
import { CountUsersService } from './core/ui-services/count-users.service';
|
||||||
import { LoadFontService } from './core/ui-services/load-font.service';
|
import { LoadFontService } from './core/ui-services/load-font.service';
|
||||||
import { LoginDataService } from './core/ui-services/login-data.service';
|
import { LoginDataService } from './core/ui-services/login-data.service';
|
||||||
import { OperatorService } from './core/core-services/operator.service';
|
import { OperatorService } from './core/core-services/operator.service';
|
||||||
import { ServertimeService } from './core/core-services/servertime.service';
|
import { ServertimeService } from './core/core-services/servertime.service';
|
||||||
import { ThemeService } from './core/ui-services/theme.service';
|
import { ThemeService } from './core/ui-services/theme.service';
|
||||||
|
import { DataStoreUpgradeService } from './core/core-services/data-store-upgrade.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Angular's global App Component
|
* Angular's global App Component
|
||||||
@ -48,7 +49,8 @@ export class AppComponent {
|
|||||||
themeService: ThemeService,
|
themeService: ThemeService,
|
||||||
countUsersService: CountUsersService, // Needed to register itself.
|
countUsersService: CountUsersService, // Needed to register itself.
|
||||||
configService: ConfigService,
|
configService: ConfigService,
|
||||||
loadFontService: LoadFontService
|
loadFontService: LoadFontService,
|
||||||
|
dataStoreUpgradeService: DataStoreUpgradeService // to start it.
|
||||||
) {
|
) {
|
||||||
// manually add the supported languages
|
// manually add the supported languages
|
||||||
translate.addLangs(['en', 'de', 'cs']);
|
translate.addLangs(['en', 'de', 'cs']);
|
||||||
|
@ -145,4 +145,22 @@ export class AutoupdateService {
|
|||||||
console.log('requesting changed objects with DS max change id', this.DS.maxChangeId + 1);
|
console.log('requesting changed objects with DS max change id', this.DS.maxChangeId + 1);
|
||||||
this.websocketService.send('getElements', { change_id: this.DS.maxChangeId + 1 });
|
this.websocketService.send('getElements', { change_id: this.DS.maxChangeId + 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does a full update: Requests all data from the server and sets the DS to the fresh data.
|
||||||
|
*/
|
||||||
|
public async doFullUpdate(): Promise<void> {
|
||||||
|
const response = await this.websocketService.sendAndGetResponse<{}, AutoupdateFormat>('getElements', {});
|
||||||
|
|
||||||
|
let allModels: BaseModel[] = [];
|
||||||
|
for (const collection of Object.keys(response.changed)) {
|
||||||
|
if (this.modelMapper.isCollectionRegistered(collection)) {
|
||||||
|
allModels = allModels.concat(this.mapObjectsToBaseModels(collection, response.changed[collection]));
|
||||||
|
} else {
|
||||||
|
console.error(`Unregistered collection "${collection}". Ignore it.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.DS.set(allModels, response.to_change_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { WebsocketService } from '../core-services/websocket.service';
|
import { WebsocketService } from './websocket.service';
|
||||||
import { Observable, of, Subject } from 'rxjs';
|
import { Observable, of, Subject } from 'rxjs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,7 +15,7 @@ interface Constants {
|
|||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* this.constantsService.get('OpenSlidesSettings').subscribe(constant => {
|
* this.constantsService.get('Settings').subscribe(constant => {
|
||||||
* console.log(constant);
|
* console.log(constant);
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
@ -0,0 +1,17 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { E2EImportsModule } from '../../../e2e-imports.module';
|
||||||
|
import { DataStoreUpgradeService } from './data-store-upgrade.service';
|
||||||
|
|
||||||
|
describe('DataStoreUpgradeService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [E2EImportsModule],
|
||||||
|
providers: [DataStoreUpgradeService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([DataStoreUpgradeService], (service: DataStoreUpgradeService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
@ -0,0 +1,34 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { ConstantsService } from './constants.service';
|
||||||
|
import { AutoupdateService } from './autoupdate.service';
|
||||||
|
import { StorageService } from './storage.service';
|
||||||
|
|
||||||
|
const MIGRATIONVERSION = 'MigrationVersion';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages upgrading the DataStore, if the migration version from the server is higher than the current one.
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class DataStoreUpgradeService {
|
||||||
|
/**
|
||||||
|
* @param autoupdateService
|
||||||
|
* @param constantsService
|
||||||
|
* @param storageService
|
||||||
|
*/
|
||||||
|
public constructor(
|
||||||
|
autoupdateService: AutoupdateService,
|
||||||
|
constantsService: ConstantsService,
|
||||||
|
storageService: StorageService
|
||||||
|
) {
|
||||||
|
constantsService.get<number>(MIGRATIONVERSION).subscribe(async version => {
|
||||||
|
const currentVersion = await storageService.get<number>(MIGRATIONVERSION);
|
||||||
|
await storageService.set(MIGRATIONVERSION, version);
|
||||||
|
if (currentVersion && currentVersion !== version) {
|
||||||
|
autoupdateService.doFullUpdate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -10,12 +10,26 @@ import { formatQueryParams, QueryParams } from '../query-params';
|
|||||||
/**
|
/**
|
||||||
* The generic message format in which messages are send and recieved by the server.
|
* The generic message format in which messages are send and recieved by the server.
|
||||||
*/
|
*/
|
||||||
interface WebsocketMessage {
|
interface BaseWebsocketMessage {
|
||||||
type: string;
|
type: string;
|
||||||
content: any;
|
content: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outgoing messages must have an id.
|
||||||
|
*/
|
||||||
|
interface OutgoingWebsocketMessage extends BaseWebsocketMessage {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Incomming messages may have an `in_response`, if they are an answer to a previously
|
||||||
|
* submitted request.
|
||||||
|
*/
|
||||||
|
interface IncommingWebsocketMessage extends BaseWebsocketMessage {
|
||||||
|
in_response?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service that handles WebSocket connections. Other services can register themselfs
|
* Service that handles WebSocket connections. Other services can register themselfs
|
||||||
* with {@method getOberservable} for a specific type of messages. The content will be published.
|
* with {@method getOberservable} for a specific type of messages. The content will be published.
|
||||||
@ -89,6 +103,8 @@ export class WebsocketService {
|
|||||||
*/
|
*/
|
||||||
private subjects: { [type: string]: Subject<any> } = {};
|
private subjects: { [type: string]: Subject<any> } = {};
|
||||||
|
|
||||||
|
private responseCallbacks: { [id: string]: [(val: any) => boolean, (error: string) => void | null] } = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves, if the WS Connection should be closed (e.g. after an explicit `close()`). Prohibits
|
* Saves, if the WS Connection should be closed (e.g. after an explicit `close()`). Prohibits
|
||||||
* retry connection attempts.
|
* retry connection attempts.
|
||||||
@ -180,16 +196,7 @@ export class WebsocketService {
|
|||||||
|
|
||||||
this.websocket.onmessage = (event: MessageEvent) => {
|
this.websocket.onmessage = (event: MessageEvent) => {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
const message: WebsocketMessage = JSON.parse(event.data);
|
this.handleMessage(event.data);
|
||||||
const type: string = message.type;
|
|
||||||
if (type === 'error') {
|
|
||||||
console.error('Websocket error', message.content);
|
|
||||||
} else if (this.subjects[type]) {
|
|
||||||
// Pass the content to the registered subscribers.
|
|
||||||
this.subjects[type].next(message.content);
|
|
||||||
} else {
|
|
||||||
console.log(`Got unknown websocket message type "${type}" with content`, message.content);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -234,6 +241,48 @@ export class WebsocketService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles an incomming message.
|
||||||
|
*
|
||||||
|
* @param data The message
|
||||||
|
*/
|
||||||
|
private handleMessage(data: string): void {
|
||||||
|
const message: IncommingWebsocketMessage = JSON.parse(data);
|
||||||
|
const type = message.type;
|
||||||
|
const inResponse = message.in_response;
|
||||||
|
const callbacks = this.responseCallbacks[inResponse];
|
||||||
|
if (callbacks) {
|
||||||
|
delete this.responseCallbacks[inResponse];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'error') {
|
||||||
|
console.error('Websocket error', message.content);
|
||||||
|
if (inResponse && callbacks && callbacks[1]) {
|
||||||
|
callbacks[1](message.content as string);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to fire a response callback directly. If it returnes true, the message is handeled
|
||||||
|
// and not distributed further
|
||||||
|
if (inResponse && callbacks && callbacks[0](message.content)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.subjects[type]) {
|
||||||
|
// Pass the content to the registered subscribers.
|
||||||
|
this.subjects[type].next(message.content);
|
||||||
|
} else {
|
||||||
|
console.warn(
|
||||||
|
`Got unknown websocket message type "${type}" (inResponse: ${inResponse}) with content`,
|
||||||
|
message.content
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the connection error notice
|
||||||
|
*/
|
||||||
private dismissConnectionErrorNotice(): void {
|
private dismissConnectionErrorNotice(): void {
|
||||||
if (this.connectionErrorNotice) {
|
if (this.connectionErrorNotice) {
|
||||||
this.connectionErrorNotice.dismiss();
|
this.connectionErrorNotice.dismiss();
|
||||||
@ -269,13 +318,23 @@ export class WebsocketService {
|
|||||||
*
|
*
|
||||||
* @param type the message type
|
* @param type the message type
|
||||||
* @param content the actual content
|
* @param content the actual content
|
||||||
|
* @param success an optional success callback for a response
|
||||||
|
* @param error an optional error callback for a response
|
||||||
|
* @param id an optional id for the message. If not given, a random id will be generated and returned.
|
||||||
|
* @returns the message id
|
||||||
*/
|
*/
|
||||||
public send<T>(type: string, content: T, id?: string): void {
|
public send<T, R>(
|
||||||
|
type: string,
|
||||||
|
content: T,
|
||||||
|
success?: (val: R) => boolean,
|
||||||
|
error?: (error: string) => void,
|
||||||
|
id?: string
|
||||||
|
): string {
|
||||||
if (!this.websocket) {
|
if (!this.websocket) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const message: WebsocketMessage = {
|
const message: OutgoingWebsocketMessage = {
|
||||||
type: type,
|
type: type,
|
||||||
content: content,
|
content: content,
|
||||||
id: id
|
id: id
|
||||||
@ -290,6 +349,10 @@ export class WebsocketService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
this.responseCallbacks[message.id] = [success, error];
|
||||||
|
}
|
||||||
|
|
||||||
// Either send directly or add to queue, if not connected.
|
// Either send directly or add to queue, if not connected.
|
||||||
const jsonMessage = JSON.stringify(message);
|
const jsonMessage = JSON.stringify(message);
|
||||||
if (this.isConnected) {
|
if (this.isConnected) {
|
||||||
@ -297,5 +360,29 @@ export class WebsocketService {
|
|||||||
} else {
|
} else {
|
||||||
this.sendQueueWhileNotConnected.push(jsonMessage);
|
this.sendQueueWhileNotConnected.push(jsonMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return message.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a message and waits for the response
|
||||||
|
*
|
||||||
|
* @param type the message type
|
||||||
|
* @param content the actual content
|
||||||
|
* @param id an optional id for the message. If not given, a random id will be generated and returned.
|
||||||
|
*/
|
||||||
|
public sendAndGetResponse<T, R>(type: string, content: T, id?: string): Promise<R> {
|
||||||
|
return new Promise<R>((resolve, reject) => {
|
||||||
|
this.send<T, R>(
|
||||||
|
type,
|
||||||
|
content,
|
||||||
|
val => {
|
||||||
|
resolve(val);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
reject,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { Observable, BehaviorSubject } from 'rxjs';
|
import { Observable, BehaviorSubject } from 'rxjs';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { BaseRepository } from 'app/core/repositories/base-repository';
|
import { BaseRepository } from 'app/core/repositories/base-repository';
|
||||||
import { Config } from 'app/shared/models/core/config';
|
import { Config } from 'app/shared/models/core/config';
|
||||||
import { DataSendService } from 'app/core/core-services/data-send.service';
|
import { DataSendService } from 'app/core/core-services/data-send.service';
|
||||||
import { DataStoreService } from 'app/core/core-services/data-store.service';
|
import { DataStoreService } from 'app/core/core-services/data-store.service';
|
||||||
import { ConstantsService } from 'app/core/ui-services/constants.service';
|
import { ConstantsService } from 'app/core/core-services/constants.service';
|
||||||
import { HttpService } from 'app/core/core-services/http.service';
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
import { Identifiable } from 'app/shared/models/base/identifiable';
|
||||||
import { CollectionStringMapperService } from 'app/core/core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from 'app/core/core-services/collectionStringMapper.service';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
import { ViewConfig } from 'app/site/config/models/view-config';
|
import { ViewConfig } from 'app/site/config/models/view-config';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds a single config item.
|
* Holds a single config item.
|
||||||
@ -107,7 +107,7 @@ export class ConfigRepositoryService extends BaseRepository<ViewConfig, Config>
|
|||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, translate, Config);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Config);
|
||||||
|
|
||||||
this.constantsService.get('OpenSlidesConfigVariables').subscribe(constant => {
|
this.constantsService.get('ConfigVariables').subscribe(constant => {
|
||||||
this.createConfigStructure(constant);
|
this.createConfigStructure(constant);
|
||||||
this.updateConfigStructure(...Object.values(this.viewModelStore));
|
this.updateConfigStructure(...Object.values(this.viewModelStore));
|
||||||
this.updateConfigListObservable();
|
this.updateConfigListObservable();
|
||||||
|
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
|||||||
|
|
||||||
import { BaseRepository } from '../base-repository';
|
import { BaseRepository } from '../base-repository';
|
||||||
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
import { CollectionStringMapperService } from '../../core-services/collectionStringMapper.service';
|
||||||
import { ConstantsService } from '../../ui-services/constants.service';
|
import { ConstantsService } from '../../core-services/constants.service';
|
||||||
import { DataSendService } from '../../core-services/data-send.service';
|
import { DataSendService } from '../../core-services/data-send.service';
|
||||||
import { DataStoreService } from '../../core-services/data-store.service';
|
import { DataStoreService } from '../../core-services/data-store.service';
|
||||||
import { Group } from 'app/shared/models/users/group';
|
import { Group } from 'app/shared/models/users/group';
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { Observable, BehaviorSubject } from 'rxjs';
|
import { Observable, BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
import { Config } from '../../shared/models/core/config';
|
import { Config } from '../../shared/models/core/config';
|
||||||
import { DataStoreService } from '../core-services/data-store.service';
|
import { DataStoreService } from '../core-services/data-store.service';
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ interface ContentObject {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine visibility states for agenda items
|
* Determine visibility states for agenda items
|
||||||
* Coming from "OpenSlidesConfigVariables" property "agenda_hide_internal_items_on_projector"
|
* Coming from "ConfigVariables" property "agenda_hide_internal_items_on_projector"
|
||||||
*/
|
*/
|
||||||
export const itemVisibilityChoices = [
|
export const itemVisibilityChoices = [
|
||||||
{ key: 1, name: 'Public item', csvName: '' },
|
{ key: 1, name: 'Public item', csvName: '' },
|
||||||
|
@ -11,7 +11,7 @@ import { Assignment } from 'app/shared/models/assignments/assignment';
|
|||||||
import { AssignmentPollService } from '../../services/assignment-poll.service';
|
import { AssignmentPollService } from '../../services/assignment-poll.service';
|
||||||
import { AssignmentRepositoryService } from 'app/core/repositories/assignments/assignment-repository.service';
|
import { AssignmentRepositoryService } from 'app/core/repositories/assignments/assignment-repository.service';
|
||||||
import { BaseViewComponent } from 'app/site/base/base-view';
|
import { BaseViewComponent } from 'app/site/base/base-view';
|
||||||
import { ConstantsService } from 'app/core/ui-services/constants.service';
|
import { ConstantsService } from 'app/core/core-services/constants.service';
|
||||||
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
||||||
import { LocalPermissionsService } from 'app/site/motions/services/local-permissions.service';
|
import { LocalPermissionsService } from 'app/site/motions/services/local-permissions.service';
|
||||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
|
@ -5,7 +5,7 @@ import { Assignment } from 'app/shared/models/assignments/assignment';
|
|||||||
import { BaseFilterListService, OsFilter } from 'app/core/ui-services/base-filter-list.service';
|
import { BaseFilterListService, OsFilter } from 'app/core/ui-services/base-filter-list.service';
|
||||||
import { StorageService } from 'app/core/core-services/storage.service';
|
import { StorageService } from 'app/core/core-services/storage.service';
|
||||||
import { ViewAssignment, AssignmentPhase } from '../models/view-assignment';
|
import { ViewAssignment, AssignmentPhase } from '../models/view-assignment';
|
||||||
import { ConstantsService } from 'app/core/ui-services/constants.service';
|
import { ConstantsService } from 'app/core/core-services/constants.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
@ -4,7 +4,7 @@ import { MatDialog } from '@angular/material';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { CalculablePollKey } from 'app/core/ui-services/poll.service';
|
import { CalculablePollKey } from 'app/core/ui-services/poll.service';
|
||||||
import { ConstantsService } from 'app/core/ui-services/constants.service';
|
import { ConstantsService } from 'app/core/core-services/constants.service';
|
||||||
import { LocalPermissionsService } from 'app/site/motions/services/local-permissions.service';
|
import { LocalPermissionsService } from 'app/site/motions/services/local-permissions.service';
|
||||||
import { MotionPoll } from 'app/shared/models/motions/motion-poll';
|
import { MotionPoll } from 'app/shared/models/motions/motion-poll';
|
||||||
import { MotionPollDialogComponent } from './motion-poll-dialog.component';
|
import { MotionPollDialogComponent } from './motion-poll-dialog.component';
|
||||||
@ -209,7 +209,7 @@ export class MotionPollComponent implements OnInit {
|
|||||||
* Subscribe to the available majority choices as given in the server-side constants
|
* Subscribe to the available majority choices as given in the server-side constants
|
||||||
*/
|
*/
|
||||||
private subscribeMajorityChoices(): void {
|
private subscribeMajorityChoices(): void {
|
||||||
this.constants.get<any>('OpenSlidesConfigVariables').subscribe(constants => {
|
this.constants.get<any>('ConfigVariables').subscribe(constants => {
|
||||||
const motionconst = constants.find(c => c.name === 'Motions');
|
const motionconst = constants.find(c => c.name === 'Motions');
|
||||||
if (motionconst) {
|
if (motionconst) {
|
||||||
const ballotConst = motionconst.subgroups.find(s => s.name === 'Voting and ballot papers');
|
const ballotConst = motionconst.subgroups.find(s => s.name === 'Voting and ballot papers');
|
||||||
|
@ -3,9 +3,9 @@ import { Injectable } from '@angular/core';
|
|||||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
import { ViewMotion } from '../models/view-motion';
|
import { ViewMotion } from '../models/view-motion';
|
||||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||||
import { ConstantsService } from 'app/core/ui-services/constants.service';
|
import { ConstantsService } from 'app/core/core-services/constants.service';
|
||||||
|
|
||||||
interface OpenSlidesSettings {
|
interface Settings {
|
||||||
MOTIONS_ALLOW_AMENDMENTS_OF_AMENDMENTS: boolean;
|
MOTIONS_ALLOW_AMENDMENTS_OF_AMENDMENTS: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ export class LocalPermissionsService {
|
|||||||
.get<boolean>('motions_amendments_enabled')
|
.get<boolean>('motions_amendments_enabled')
|
||||||
.subscribe(enabled => (this.amendmentEnabled = enabled));
|
.subscribe(enabled => (this.amendmentEnabled = enabled));
|
||||||
this.constants
|
this.constants
|
||||||
.get<OpenSlidesSettings>('OpenSlidesSettings')
|
.get<Settings>('Settings')
|
||||||
.subscribe(settings => (this.amendmentOfAmendment = settings.MOTIONS_ALLOW_AMENDMENTS_OF_AMENDMENTS));
|
.subscribe(settings => (this.amendmentOfAmendment = settings.MOTIONS_ALLOW_AMENDMENTS_OF_AMENDMENTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ from typing import Any, Dict, List, Set
|
|||||||
|
|
||||||
from django.apps import AppConfig
|
from django.apps import AppConfig
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.db.models import Max
|
||||||
from django.db.models.signals import post_migrate, pre_delete
|
from django.db.models.signals import post_migrate, pre_delete
|
||||||
|
|
||||||
|
|
||||||
@ -155,7 +156,7 @@ class CoreAppConfig(AppConfig):
|
|||||||
# Settings key does not exist. Do nothing. The client will
|
# Settings key does not exist. Do nothing. The client will
|
||||||
# treat this as undefined.
|
# treat this as undefined.
|
||||||
pass
|
pass
|
||||||
constants["OpenSlidesSettings"] = client_settings_dict
|
constants["Settings"] = client_settings_dict
|
||||||
|
|
||||||
# Config variables
|
# Config variables
|
||||||
config_groups: List[Any] = []
|
config_groups: List[Any] = []
|
||||||
@ -181,7 +182,14 @@ class CoreAppConfig(AppConfig):
|
|||||||
)
|
)
|
||||||
# Add the config variable to the current group and subgroup.
|
# Add the config variable to the current group and subgroup.
|
||||||
config_groups[-1]["subgroups"][-1]["items"].append(config_variable.data)
|
config_groups[-1]["subgroups"][-1]["items"].append(config_variable.data)
|
||||||
constants["OpenSlidesConfigVariables"] = config_groups
|
constants["ConfigVariables"] = config_groups
|
||||||
|
|
||||||
|
# get max migration id -> the "version" of the DB
|
||||||
|
from django.db.migrations.recorder import MigrationRecorder
|
||||||
|
|
||||||
|
constants["MigrationVersion"] = MigrationRecorder.Migration.objects.aggregate(
|
||||||
|
Max("id")
|
||||||
|
)["id__max"]
|
||||||
|
|
||||||
return constants
|
return constants
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user