App initialization
Used for internal apps as well as for plugins. The pluginpart is currently missing, in fact that the main OpenSlides part is more important. Apps can give their models and mainmenu entries. Routes are not enabled, because the routes have to be static for webpack to build the bundles. If we want to keep lazy loading, I see no possibility to encapsulate the routes from the site-routing module.
This commit is contained in:
parent
b6ad0d759c
commit
be9f98cfd0
@ -1,7 +1,7 @@
|
|||||||
// angular modules
|
// angular modules
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule, APP_INITIALIZER } from '@angular/core';
|
||||||
import { HttpClientModule, HttpClient, HttpClientXsrfModule } from '@angular/common/http';
|
import { HttpClientModule, HttpClient, HttpClientXsrfModule } from '@angular/common/http';
|
||||||
|
|
||||||
// Elementary App Components
|
// Elementary App Components
|
||||||
@ -13,6 +13,7 @@ import { CoreModule } from './core/core.module';
|
|||||||
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
||||||
import { PruningTranslationLoader } from './core/pruning-loader';
|
import { PruningTranslationLoader } from './core/pruning-loader';
|
||||||
import { LoginModule } from './site/login/login.module';
|
import { LoginModule } from './site/login/login.module';
|
||||||
|
import { AppLoadService } from './core/services/app-load.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For the translation module. Loads a Custom 'translation loader' and provides it as loader.
|
* For the translation module. Loads a Custom 'translation loader' and provides it as loader.
|
||||||
@ -21,6 +22,15 @@ import { LoginModule } from './site/login/login.module';
|
|||||||
export function HttpLoaderFactory(http: HttpClient): PruningTranslationLoader {
|
export function HttpLoaderFactory(http: HttpClient): PruningTranslationLoader {
|
||||||
return new PruningTranslationLoader(http);
|
return new PruningTranslationLoader(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a function that returns a promis that will be resolved, if all apps are loaded.
|
||||||
|
* @param appLoadService The service that loads the apps.
|
||||||
|
*/
|
||||||
|
export function AppLoaderFactory(appLoadService: AppLoadService): () => Promise<void> {
|
||||||
|
return () => appLoadService.loadApps();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global App Module. Keep it as clean as possible.
|
* Global App Module. Keep it as clean as possible.
|
||||||
*/
|
*/
|
||||||
@ -45,6 +55,7 @@ export function HttpLoaderFactory(http: HttpClient): PruningTranslationLoader {
|
|||||||
CoreModule,
|
CoreModule,
|
||||||
LoginModule
|
LoginModule
|
||||||
],
|
],
|
||||||
|
providers: [{ provide: APP_INITIALIZER, useFactory: AppLoaderFactory, deps: [AppLoadService], multi: true }],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
12
client/src/app/core/services/app-load.service.spec.ts
Normal file
12
client/src/app/core/services/app-load.service.spec.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
import { NotifyService } from './notify.service';
|
||||||
|
describe('NotifyService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [NotifyService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('should be created', inject([NotifyService], (service: NotifyService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
61
client/src/app/core/services/app-load.service.ts
Normal file
61
client/src/app/core/services/app-load.service.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { plugins } from '../../../plugins';
|
||||||
|
import { CommonAppConfig } from '../../site/common/common.config';
|
||||||
|
import { ModelConstructor, BaseModel } from '../../shared/models/base/base-model';
|
||||||
|
import { AppConfig } from '../../site/base/app-config';
|
||||||
|
import { CollectionStringModelMapperService } from './collectionStringModelMapper.service';
|
||||||
|
import { MediafileAppConfig } from '../../site/mediafiles/mediafile.config';
|
||||||
|
import { MotionsAppConfig } from '../../site/motions/motions.config';
|
||||||
|
import { SettingsAppConfig } from '../../site/settings/settings.config';
|
||||||
|
import { AgendaAppConfig } from '../../site/agenda/agenda.config';
|
||||||
|
import { AssignmentsAppConfig } from '../../site/assignments/assignments.config';
|
||||||
|
import { UsersAppConfig } from '../../site/users/users.config';
|
||||||
|
import { MainMenuService } from './main-menu.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of all app configurations of all delivered apps.
|
||||||
|
*/
|
||||||
|
const appConfigs: AppConfig[] = [
|
||||||
|
CommonAppConfig,
|
||||||
|
SettingsAppConfig,
|
||||||
|
AgendaAppConfig,
|
||||||
|
AssignmentsAppConfig,
|
||||||
|
MotionsAppConfig,
|
||||||
|
MediafileAppConfig,
|
||||||
|
UsersAppConfig
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles all incoming and outgoing notify messages via {@link WebsocketService}.
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class AppLoadService {
|
||||||
|
public constructor(
|
||||||
|
private modelMapper: CollectionStringModelMapperService,
|
||||||
|
private mainMenuService: MainMenuService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async loadApps(): Promise<void> {
|
||||||
|
if (plugins.length) {
|
||||||
|
console.log('plugins: ', plugins);
|
||||||
|
}
|
||||||
|
/*for (const pluginName of plugins) {
|
||||||
|
const plugin = await import('../../../../../plugins/' + pluginName + '/' + pluginName);
|
||||||
|
plugin.main();
|
||||||
|
}*/
|
||||||
|
appConfigs.forEach((config: AppConfig) => {
|
||||||
|
if (config.models) {
|
||||||
|
config.models.forEach(entry => {
|
||||||
|
this.modelMapper.registerCollectionElement(entry.collectionString, entry.model);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (config.mainMenuEntries) {
|
||||||
|
this.mainMenuService.registerEntries(config.mainMenuEntries);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerModels(models?: { collectionString: string; model: ModelConstructor<BaseModel> }[]): void {}
|
||||||
|
}
|
@ -21,7 +21,11 @@ export class AutoupdateService extends OpenSlidesComponent {
|
|||||||
* Constructor to create the AutoupdateService. Calls the constructor of the parent class.
|
* Constructor to create the AutoupdateService. Calls the constructor of the parent class.
|
||||||
* @param websocketService
|
* @param websocketService
|
||||||
*/
|
*/
|
||||||
public constructor(websocketService: WebsocketService, private DS: DataStoreService) {
|
public constructor(
|
||||||
|
websocketService: WebsocketService,
|
||||||
|
private DS: DataStoreService,
|
||||||
|
private modelMapper: CollectionStringModelMapperService
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
websocketService.getOberservable<any>('autoupdate').subscribe(response => {
|
websocketService.getOberservable<any>('autoupdate').subscribe(response => {
|
||||||
this.storeResponse(response);
|
this.storeResponse(response);
|
||||||
@ -61,7 +65,7 @@ export class AutoupdateService extends OpenSlidesComponent {
|
|||||||
|
|
||||||
// Add the objects to the DataStore.
|
// Add the objects to the DataStore.
|
||||||
Object.keys(autoupdate.changed).forEach(collection => {
|
Object.keys(autoupdate.changed).forEach(collection => {
|
||||||
const targetClass = CollectionStringModelMapperService.getModelConstructor(collection);
|
const targetClass = this.modelMapper.getModelConstructor(collection);
|
||||||
if (!targetClass) {
|
if (!targetClass) {
|
||||||
// TODO: throw an error later..
|
// TODO: throw an error later..
|
||||||
/*throw new Error*/ console.log(`Unregistered resource ${collection}`);
|
/*throw new Error*/ console.log(`Unregistered resource ${collection}`);
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
import { ModelConstructor, BaseModel } from '../../shared/models/base/base-model';
|
import { ModelConstructor, BaseModel } from '../../shared/models/base/base-model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registeres the mapping of collection strings <--> actual types. Every Model should register itself here.
|
* Registeres the mapping of collection strings <--> actual types. Every Model should register itself here.
|
||||||
*/
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
export class CollectionStringModelMapperService {
|
export class CollectionStringModelMapperService {
|
||||||
/**
|
/**
|
||||||
* Mapps collection strings to model constructors. Accessed by {@method registerCollectionElement} and
|
* Mapps collection strings to model constructors. Accessed by {@method registerCollectionElement} and
|
||||||
@ -10,26 +14,10 @@ export class CollectionStringModelMapperService {
|
|||||||
*/
|
*/
|
||||||
private static collectionStringsTypeMapping: { [collectionString: string]: ModelConstructor<BaseModel> } = {};
|
private static collectionStringsTypeMapping: { [collectionString: string]: ModelConstructor<BaseModel> } = {};
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the type to the collection string
|
|
||||||
* @param collectionString
|
|
||||||
* @param type
|
|
||||||
*/
|
|
||||||
public static registerCollectionElement(collectionString: string, type: ModelConstructor<BaseModel>): void {
|
|
||||||
CollectionStringModelMapperService.collectionStringsTypeMapping[collectionString] = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the constructor of the requested collection or undefined, if it is not registered.
|
|
||||||
* @param collectionString the requested collection
|
|
||||||
*/
|
|
||||||
public static getModelConstructor(collectionString: string): ModelConstructor<BaseModel> {
|
|
||||||
return CollectionStringModelMapperService.collectionStringsTypeMapping[collectionString];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the collection string of a given ModelConstructor or undefined, if it is not registered.
|
* Returns the collection string of a given ModelConstructor or undefined, if it is not registered.
|
||||||
* @param ctor
|
* @param ctor
|
||||||
|
* @deprecated Should inject this service and don't use the static functions.
|
||||||
*/
|
*/
|
||||||
public static getCollectionString(ctor: ModelConstructor<BaseModel>): string {
|
public static getCollectionString(ctor: ModelConstructor<BaseModel>): string {
|
||||||
return Object.keys(CollectionStringModelMapperService.collectionStringsTypeMapping).find(
|
return Object.keys(CollectionStringModelMapperService.collectionStringsTypeMapping).find(
|
||||||
@ -44,4 +32,33 @@ export class CollectionStringModelMapperService {
|
|||||||
* @param websocketService
|
* @param websocketService
|
||||||
*/
|
*/
|
||||||
public constructor() {}
|
public constructor() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the type to the collection string
|
||||||
|
* @param collectionString
|
||||||
|
* @param type
|
||||||
|
*/
|
||||||
|
public registerCollectionElement(collectionString: string, type: ModelConstructor<BaseModel>): void {
|
||||||
|
CollectionStringModelMapperService.collectionStringsTypeMapping[collectionString] = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the constructor of the requested collection or undefined, if it is not registered.
|
||||||
|
* @param collectionString the requested collection
|
||||||
|
*/
|
||||||
|
public getModelConstructor(collectionString: string): ModelConstructor<BaseModel> {
|
||||||
|
return CollectionStringModelMapperService.collectionStringsTypeMapping[collectionString];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the collection string of a given ModelConstructor or undefined, if it is not registered.
|
||||||
|
* @param ctor
|
||||||
|
*/
|
||||||
|
public getCollectionString(ctor: ModelConstructor<BaseModel>): string {
|
||||||
|
return Object.keys(CollectionStringModelMapperService.collectionStringsTypeMapping).find(
|
||||||
|
(collectionString: string) => {
|
||||||
|
return ctor === CollectionStringModelMapperService.collectionStringsTypeMapping[collectionString];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ export class DataStoreService {
|
|||||||
* Empty constructor for dataStore
|
* Empty constructor for dataStore
|
||||||
* @param cacheService use CacheService to cache the DataStore.
|
* @param cacheService use CacheService to cache the DataStore.
|
||||||
*/
|
*/
|
||||||
public constructor(private cacheService: CacheService) {
|
public constructor(private cacheService: CacheService, private modelMapper: CollectionStringModelMapperService) {
|
||||||
if (DataStoreService.wasInstantiated) {
|
if (DataStoreService.wasInstantiated) {
|
||||||
throw new Error('The Datastore should just be instantiated once!');
|
throw new Error('The Datastore should just be instantiated once!');
|
||||||
}
|
}
|
||||||
@ -158,7 +158,7 @@ export class DataStoreService {
|
|||||||
const storage: ModelStorage = {};
|
const storage: ModelStorage = {};
|
||||||
Object.keys(serializedStore).forEach(collectionString => {
|
Object.keys(serializedStore).forEach(collectionString => {
|
||||||
storage[collectionString] = {} as ModelCollection;
|
storage[collectionString] = {} as ModelCollection;
|
||||||
const target = CollectionStringModelMapperService.getModelConstructor(collectionString);
|
const target = this.modelMapper.getModelConstructor(collectionString);
|
||||||
if (target) {
|
if (target) {
|
||||||
Object.keys(serializedStore[collectionString]).forEach(id => {
|
Object.keys(serializedStore[collectionString]).forEach(id => {
|
||||||
const data = JSON.parse(serializedStore[collectionString][id]);
|
const data = JSON.parse(serializedStore[collectionString][id]);
|
||||||
@ -186,7 +186,7 @@ export class DataStoreService {
|
|||||||
if (typeof collectionType === 'string') {
|
if (typeof collectionType === 'string') {
|
||||||
return collectionType;
|
return collectionType;
|
||||||
} else {
|
} else {
|
||||||
return CollectionStringModelMapperService.getCollectionString(collectionType);
|
return this.modelMapper.getCollectionString(collectionType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
client/src/app/core/services/main-menu.service.spec.ts
Normal file
15
client/src/app/core/services/main-menu.service.spec.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MainMenuService } from './main-menu.service';
|
||||||
|
|
||||||
|
describe('MainMenuService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [MainMenuService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([MainMenuService], (service: MainMenuService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
61
client/src/app/core/services/main-menu.service.ts
Normal file
61
client/src/app/core/services/main-menu.service.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This represents one entry in the main menu
|
||||||
|
*/
|
||||||
|
export interface MainMenuEntry {
|
||||||
|
/**
|
||||||
|
* The route for the router to navigate to on click.
|
||||||
|
*/
|
||||||
|
route: string;
|
||||||
|
/**
|
||||||
|
* The display string to be shown.
|
||||||
|
*/
|
||||||
|
displayName: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The font awesom icon to display.
|
||||||
|
*/
|
||||||
|
icon: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For sorting the entries.
|
||||||
|
*/
|
||||||
|
weight: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The permission to see the entry.
|
||||||
|
*/
|
||||||
|
permission: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects main menu entries and provides them to the main menu component.
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class MainMenuService {
|
||||||
|
/**
|
||||||
|
* A list of sorted entries.
|
||||||
|
*/
|
||||||
|
private _entries: MainMenuEntry[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the entries public.
|
||||||
|
*/
|
||||||
|
public get entries(): MainMenuEntry[] {
|
||||||
|
return this._entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public constructor() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds entries to the mainmenu.
|
||||||
|
* @param entries The entries to add
|
||||||
|
*/
|
||||||
|
public registerEntries(entries: MainMenuEntry[]): void {
|
||||||
|
this._entries.push(...entries);
|
||||||
|
this._entries = this._entries.sort((a, b) => a.weight - b.weight);
|
||||||
|
}
|
||||||
|
}
|
@ -56,5 +56,3 @@ export class Item extends ProjectableBaseModel {
|
|||||||
return this.getListTitle();
|
return this.getListTitle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectableBaseModel.registerCollectionElement('agenda/item', Item);
|
|
||||||
|
@ -56,5 +56,3 @@ export class Assignment extends AgendaBaseModel {
|
|||||||
return 'TODO';
|
return 'TODO';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AgendaBaseModel.registerCollectionElement('assignments/assignment', Assignment);
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { OpenSlidesComponent } from 'app/openslides.component';
|
import { OpenSlidesComponent } from 'app/openslides.component';
|
||||||
import { Deserializable } from './deserializable';
|
import { Deserializable } from './deserializable';
|
||||||
import { CollectionStringModelMapperService } from '../../../core/services/collectionStringModelMapper.service';
|
|
||||||
import { Displayable } from './displayable';
|
import { Displayable } from './displayable';
|
||||||
import { Identifiable } from './identifiable';
|
import { Identifiable } from './identifiable';
|
||||||
|
|
||||||
@ -14,15 +13,6 @@ export interface ModelConstructor<T extends BaseModel<T>> {
|
|||||||
*/
|
*/
|
||||||
export abstract class BaseModel<T = object> extends OpenSlidesComponent
|
export abstract class BaseModel<T = object> extends OpenSlidesComponent
|
||||||
implements Deserializable, Displayable, Identifiable {
|
implements Deserializable, Displayable, Identifiable {
|
||||||
/**
|
|
||||||
* Register the collection string to the type.
|
|
||||||
* @param collectionString
|
|
||||||
* @param type
|
|
||||||
*/
|
|
||||||
public static registerCollectionElement(collectionString: string, type: any): void {
|
|
||||||
CollectionStringModelMapperService.registerCollectionElement(collectionString, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* force children of BaseModel to have a collectionString.
|
* force children of BaseModel to have a collectionString.
|
||||||
*
|
*
|
||||||
|
@ -18,5 +18,3 @@ export class ChatMessage extends BaseModel<ChatMessage> {
|
|||||||
return 'Chatmessage';
|
return 'Chatmessage';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModel.registerCollectionElement('core/chat-message', ChatMessage);
|
|
||||||
|
@ -17,5 +17,3 @@ export class Config extends BaseModel {
|
|||||||
return this.key;
|
return this.key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModel.registerCollectionElement('core/config', Config);
|
|
||||||
|
@ -19,5 +19,3 @@ export class Countdown extends ProjectableBaseModel {
|
|||||||
return this.description;
|
return this.description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectableBaseModel.registerCollectionElement('core/countdown', Countdown);
|
|
||||||
|
@ -16,5 +16,3 @@ export class ProjectorMessage extends ProjectableBaseModel {
|
|||||||
return 'Projectormessage';
|
return 'Projectormessage';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectableBaseModel.registerCollectionElement('core/projector-message', ProjectorMessage);
|
|
||||||
|
@ -23,5 +23,3 @@ export class Projector extends BaseModel<Projector> {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModel.registerCollectionElement('core/projector', Projector);
|
|
||||||
|
@ -16,5 +16,3 @@ export class Tag extends BaseModel<Tag> {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModel.registerCollectionElement('core/tag', Tag);
|
|
||||||
|
@ -28,5 +28,3 @@ export class Mediafile extends ProjectableBaseModel {
|
|||||||
return this.title;
|
return this.title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectableBaseModel.registerCollectionElement('mediafiles/mediafile', Mediafile);
|
|
||||||
|
@ -17,5 +17,3 @@ export class Category extends BaseModel<Category> {
|
|||||||
return this.prefix + ' - ' + this.name;
|
return this.prefix + ' - ' + this.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModel.registerCollectionElement('motions/category', Category);
|
|
||||||
|
@ -21,5 +21,3 @@ export class MotionBlock extends AgendaBaseModel {
|
|||||||
return 'TODO';
|
return 'TODO';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AgendaBaseModel.registerCollectionElement('motions/motion-block', MotionBlock);
|
|
||||||
|
@ -23,5 +23,3 @@ export class MotionChangeReco extends BaseModel<MotionChangeReco> {
|
|||||||
return 'Changerecommendation';
|
return 'Changerecommendation';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModel.registerCollectionElement('motions/motion-change-recommendation', MotionChangeReco);
|
|
||||||
|
@ -18,5 +18,3 @@ export class MotionCommentSection extends BaseModel<MotionCommentSection> {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModel.registerCollectionElement('motions/motion-comment-section', MotionCommentSection);
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { MotionSubmitter } from './motion-submitter';
|
import { MotionSubmitter } from './motion-submitter';
|
||||||
import { MotionLog } from './motion-log';
|
import { MotionLog } from './motion-log';
|
||||||
import { Category } from './category';
|
|
||||||
import { MotionComment } from './motion-comment';
|
import { MotionComment } from './motion-comment';
|
||||||
import { Workflow } from './workflow';
|
|
||||||
import { AgendaBaseModel } from '../base/agenda-base-model';
|
import { AgendaBaseModel } from '../base/agenda-base-model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,10 +97,3 @@ export class Motion extends AgendaBaseModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Hack to get them loaded at last
|
|
||||||
*/
|
|
||||||
AgendaBaseModel.registerCollectionElement('motions/motion', Motion);
|
|
||||||
AgendaBaseModel.registerCollectionElement('motions/category', Category);
|
|
||||||
AgendaBaseModel.registerCollectionElement('motions/workflow', Workflow);
|
|
||||||
|
@ -58,5 +58,3 @@ export class Workflow extends BaseModel<Workflow> {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModel.registerCollectionElement('motions/workflow', Workflow);
|
|
||||||
|
@ -28,5 +28,3 @@ export class Topic extends AgendaBaseModel {
|
|||||||
return 'TODO';
|
return 'TODO';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AgendaBaseModel.registerCollectionElement('topics/topic', Topic);
|
|
||||||
|
@ -17,5 +17,3 @@ export class Group extends BaseModel<Group> {
|
|||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModel.registerCollectionElement('users/group', Group);
|
|
||||||
|
@ -17,5 +17,3 @@ export class PersonalNote extends BaseModel<PersonalNote> {
|
|||||||
return 'Personal note';
|
return 'Personal note';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseModel.registerCollectionElement('users/personal-note', PersonalNote);
|
|
||||||
|
@ -89,5 +89,3 @@ export class User extends ProjectableBaseModel {
|
|||||||
return this.short_name;
|
return this.short_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectableBaseModel.registerCollectionElement('users/user', User);
|
|
||||||
|
17
client/src/app/site/agenda/agenda.config.ts
Normal file
17
client/src/app/site/agenda/agenda.config.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { AppConfig } from '../base/app-config';
|
||||||
|
import { Item } from '../../shared/models/agenda/item';
|
||||||
|
import { Topic } from '../../shared/models/topics/topic';
|
||||||
|
|
||||||
|
export const AgendaAppConfig: AppConfig = {
|
||||||
|
name: 'agenda',
|
||||||
|
models: [{ collectionString: 'agenda/item', model: Item }, { collectionString: 'topics/topic', model: Topic }],
|
||||||
|
mainMenuEntries: [
|
||||||
|
{
|
||||||
|
route: '/agenda',
|
||||||
|
displayName: 'Agenda',
|
||||||
|
icon: 'calendar',
|
||||||
|
weight: 200,
|
||||||
|
permission: 'agenda.can_see'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
16
client/src/app/site/assignments/assignments.config.ts
Normal file
16
client/src/app/site/assignments/assignments.config.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { AppConfig } from '../base/app-config';
|
||||||
|
import { Assignment } from '../../shared/models/assignments/assignment';
|
||||||
|
|
||||||
|
export const AssignmentsAppConfig: AppConfig = {
|
||||||
|
name: 'assignments',
|
||||||
|
models: [{ collectionString: 'assignments/assignment', model: Assignment }],
|
||||||
|
mainMenuEntries: [
|
||||||
|
{
|
||||||
|
route: '/assignments',
|
||||||
|
displayName: 'Elections',
|
||||||
|
icon: 'chart-pie',
|
||||||
|
weight: 400,
|
||||||
|
permission: 'assignments.can_see'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
25
client/src/app/site/base/app-config.ts
Normal file
25
client/src/app/site/base/app-config.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { ModelConstructor, BaseModel } from '../../shared/models/base/base-model';
|
||||||
|
import { MainMenuEntry } from '../../core/services/main-menu.service';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration of an app.
|
||||||
|
*/
|
||||||
|
export interface AppConfig {
|
||||||
|
/**
|
||||||
|
* The name.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All models, that should be registered.
|
||||||
|
*/
|
||||||
|
models?: {
|
||||||
|
collectionString: string;
|
||||||
|
model: ModelConstructor<BaseModel>;
|
||||||
|
}[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main menu entries.
|
||||||
|
*/
|
||||||
|
mainMenuEntries?: MainMenuEntry[];
|
||||||
|
}
|
26
client/src/app/site/common/common-routing.module.ts
Normal file
26
client/src/app/site/common/common-routing.module.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { PrivacyPolicyComponent } from './components/privacy-policy/privacy-policy.component';
|
||||||
|
import { StartComponent } from './components/start/start.component';
|
||||||
|
import { LegalNoticeComponent } from './components/legal-notice/legal-notice.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: StartComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'legalnotice',
|
||||||
|
component: LegalNoticeComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'privacypolicy',
|
||||||
|
component: PrivacyPolicyComponent
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class CommonRoutingModule {}
|
26
client/src/app/site/common/common.config.ts
Normal file
26
client/src/app/site/common/common.config.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { AppConfig } from '../base/app-config';
|
||||||
|
import { Projector } from '../../shared/models/core/projector';
|
||||||
|
import { Countdown } from '../../shared/models/core/countdown';
|
||||||
|
import { ChatMessage } from '../../shared/models/core/chat-message';
|
||||||
|
import { ProjectorMessage } from '../../shared/models/core/projector-message';
|
||||||
|
import { Tag } from '../../shared/models/core/tag';
|
||||||
|
|
||||||
|
export const CommonAppConfig: AppConfig = {
|
||||||
|
name: 'common',
|
||||||
|
models: [
|
||||||
|
{ collectionString: 'core/projector', model: Projector },
|
||||||
|
{ collectionString: 'core/chat-message', model: ChatMessage },
|
||||||
|
{ collectionString: 'core/countdown', model: Countdown },
|
||||||
|
{ collectionString: 'core/projector-message', model: ProjectorMessage },
|
||||||
|
{ collectionString: 'core/tag', model: Tag }
|
||||||
|
],
|
||||||
|
mainMenuEntries: [
|
||||||
|
{
|
||||||
|
route: '/',
|
||||||
|
displayName: 'Home',
|
||||||
|
icon: 'home',
|
||||||
|
weight: 100,
|
||||||
|
permission: 'core.can_see_frontpage'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
13
client/src/app/site/common/common.module.spec.ts
Normal file
13
client/src/app/site/common/common.module.spec.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { CommonModule } from './common.module';
|
||||||
|
|
||||||
|
describe('CommonModule', () => {
|
||||||
|
let commonModule: CommonModule;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
commonModule = new CommonModule();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create an instance', () => {
|
||||||
|
expect(commonModule).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
14
client/src/app/site/common/common.module.ts
Normal file
14
client/src/app/site/common/common.module.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule as AngularCommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { CommonRoutingModule } from './common-routing.module';
|
||||||
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
|
import { PrivacyPolicyComponent } from './components/privacy-policy/privacy-policy.component';
|
||||||
|
import { StartComponent } from './components/start/start.component';
|
||||||
|
import { LegalNoticeComponent } from './components/legal-notice/legal-notice.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [AngularCommonModule, CommonRoutingModule, SharedModule],
|
||||||
|
declarations: [PrivacyPolicyComponent, StartComponent, LegalNoticeComponent]
|
||||||
|
})
|
||||||
|
export class CommonModule {}
|
@ -7,8 +7,6 @@
|
|||||||
<h4> {{welcomeTitle | translate}} </h4>
|
<h4> {{welcomeTitle | translate}} </h4>
|
||||||
<span> {{welcomeText | translate}} </span>
|
<span> {{welcomeText | translate}} </span>
|
||||||
|
|
||||||
<button mat-button (click)="DataStoreTest()">DataStoreTest</button>
|
|
||||||
<br/>
|
|
||||||
<button mat-button (click)="TranslateTest()">Translate in console</button>
|
<button mat-button (click)="TranslateTest()">Translate in console</button>
|
||||||
<br/>
|
<br/>
|
||||||
<button mat-button (click)="giveDataStore()">print the dataStore</button>
|
<button mat-button (click)="giveDataStore()">print the dataStore</button>
|
@ -5,11 +5,10 @@ import { BaseComponent } from 'app/base.component';
|
|||||||
import { TranslateService } from '@ngx-translate/core'; // showcase
|
import { TranslateService } from '@ngx-translate/core'; // showcase
|
||||||
|
|
||||||
// for testing the DS and BaseModel
|
// for testing the DS and BaseModel
|
||||||
import { User } from 'app/shared/models/users/user';
|
import { Config } from '../../../../shared/models/core/config';
|
||||||
import { Config } from '../../shared/models/core/config';
|
import { Motion } from '../../../../shared/models/motions/motion';
|
||||||
import { Motion } from '../../shared/models/motions/motion';
|
import { MotionSubmitter } from '../../../../shared/models/motions/motion-submitter';
|
||||||
import { MotionSubmitter } from '../../shared/models/motions/motion-submitter';
|
import { DataStoreService } from '../../../../core/services/data-store.service';
|
||||||
import { DataStoreService } from '../../core/services/data-store.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'os-start',
|
selector: 'os-start',
|
||||||
@ -74,36 +73,6 @@ export class StartComponent extends BaseComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* test data store
|
|
||||||
*/
|
|
||||||
public DataStoreTest(): void {
|
|
||||||
console.log('add a user to dataStore');
|
|
||||||
this.DS.add(new User({ id: 100 }));
|
|
||||||
console.log('add three users to dataStore');
|
|
||||||
this.DS.add(new User({ id: 200 }), new User({ id: 201 }), new User({ id: 202 }));
|
|
||||||
console.log('use the spread operator "..." to add an array');
|
|
||||||
const userArray = [];
|
|
||||||
for (let i = 300; i < 400; i++) {
|
|
||||||
userArray.push(new User({ id: i }));
|
|
||||||
}
|
|
||||||
this.DS.add(...userArray);
|
|
||||||
|
|
||||||
console.log('try to get user with ID 1:');
|
|
||||||
const user1fromStore = this.DS.get<User>(User, 1);
|
|
||||||
console.log('the user: ', user1fromStore);
|
|
||||||
|
|
||||||
console.log('remove a single user:');
|
|
||||||
this.DS.remove('users/user', 100);
|
|
||||||
console.log('remove more users');
|
|
||||||
this.DS.remove('users/user', 200, 201, 202);
|
|
||||||
console.log('remove an array of users');
|
|
||||||
this.DS.remove('users/user', ...[321, 363, 399]);
|
|
||||||
|
|
||||||
console.log('test filter: ');
|
|
||||||
console.log(this.DS.filter<User>(User, user => user.id === 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* function to print datastore
|
* function to print datastore
|
||||||
*/
|
*/
|
16
client/src/app/site/mediafiles/mediafile.config.ts
Normal file
16
client/src/app/site/mediafiles/mediafile.config.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { AppConfig } from '../base/app-config';
|
||||||
|
import { Mediafile } from '../../shared/models/mediafiles/mediafile';
|
||||||
|
|
||||||
|
export const MediafileAppConfig: AppConfig = {
|
||||||
|
name: 'mediafiles',
|
||||||
|
models: [{ collectionString: 'mediafiles/mediafile', model: Mediafile }],
|
||||||
|
mainMenuEntries: [
|
||||||
|
{
|
||||||
|
route: '/mediafiles',
|
||||||
|
displayName: 'Files',
|
||||||
|
icon: 'paperclip',
|
||||||
|
weight: 600,
|
||||||
|
permission: 'mediafiles.can_see'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
28
client/src/app/site/motions/motions.config.ts
Normal file
28
client/src/app/site/motions/motions.config.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { AppConfig } from '../base/app-config';
|
||||||
|
import { Motion } from '../../shared/models/motions/motion';
|
||||||
|
import { Category } from '../../shared/models/motions/category';
|
||||||
|
import { Workflow } from '../../shared/models/motions/workflow';
|
||||||
|
import { MotionCommentSection } from '../../shared/models/motions/motion-comment-section';
|
||||||
|
import { MotionChangeReco } from '../../shared/models/motions/motion-change-reco';
|
||||||
|
import { MotionBlock } from '../../shared/models/motions/motion-block';
|
||||||
|
|
||||||
|
export const MotionsAppConfig: AppConfig = {
|
||||||
|
name: 'motions',
|
||||||
|
models: [
|
||||||
|
{ collectionString: 'motions/motion', model: Motion },
|
||||||
|
{ collectionString: 'motions/category', model: Category },
|
||||||
|
{ collectionString: 'motions/workflow', model: Workflow },
|
||||||
|
{ collectionString: 'motions/motion-comment-section', model: MotionCommentSection },
|
||||||
|
{ collectionString: 'motions/motion-change-recommendation', model: MotionChangeReco },
|
||||||
|
{ collectionString: 'motions/motion-block', model: MotionBlock }
|
||||||
|
],
|
||||||
|
mainMenuEntries: [
|
||||||
|
{
|
||||||
|
route: '/motions',
|
||||||
|
displayName: 'Motions',
|
||||||
|
icon: 'file-alt',
|
||||||
|
weight: 300,
|
||||||
|
permission: 'motions.can_see'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
16
client/src/app/site/settings/settings.config.ts
Normal file
16
client/src/app/site/settings/settings.config.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { AppConfig } from '../base/app-config';
|
||||||
|
import { Config } from '../../shared/models/core/config';
|
||||||
|
|
||||||
|
export const SettingsAppConfig: AppConfig = {
|
||||||
|
name: 'settings',
|
||||||
|
models: [{ collectionString: 'core/config', model: Config }],
|
||||||
|
mainMenuEntries: [
|
||||||
|
{
|
||||||
|
route: '/settings',
|
||||||
|
displayName: 'Settings',
|
||||||
|
icon: 'cog',
|
||||||
|
weight: 700,
|
||||||
|
permission: 'core.can_manage_config'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
@ -3,9 +3,6 @@ import { Routes, RouterModule } from '@angular/router';
|
|||||||
|
|
||||||
import { SiteComponent } from './site.component';
|
import { SiteComponent } from './site.component';
|
||||||
|
|
||||||
import { StartComponent } from './start/start.component';
|
|
||||||
import { PrivacyPolicyComponent } from './privacy-policy/privacy-policy.component';
|
|
||||||
import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
|
|
||||||
import { AuthGuard } from '../core/services/auth-guard.service';
|
import { AuthGuard } from '../core/services/auth-guard.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,15 +17,7 @@ const routes: Routes = [
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: StartComponent
|
loadChildren: './common/common.module#CommonModule'
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'legalnotice',
|
|
||||||
component: LegalNoticeComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'privacypolicy',
|
|
||||||
component: PrivacyPolicyComponent
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'agenda',
|
path: 'agenda',
|
||||||
|
@ -45,35 +45,13 @@
|
|||||||
|
|
||||||
<!-- navigation -->
|
<!-- navigation -->
|
||||||
<mat-nav-list class='main-nav'>
|
<mat-nav-list class='main-nav'>
|
||||||
<a [@navItemAnim] *osPerms="'core.can_see_frontpage'" mat-list-item routerLink='/' routerLinkActive='active' [routerLinkActiveOptions]="{exact: true}"
|
<span *ngFor="let entry of mainMenuService.entries">
|
||||||
(click)='toggleSideNav()'>
|
<a [@navItemAnim] *osPerms="entry.permission" mat-list-item (click)='toggleSideNav()'
|
||||||
<fa-icon icon='home'></fa-icon>
|
[routerLink]='entry.route' routerLinkActive='active' [routerLinkActiveOptions]="{exact: true}">
|
||||||
<span translate>Home</span>
|
<fa-icon [icon]='entry.icon'></fa-icon>
|
||||||
</a>
|
{{ entry.displayName | translate}}
|
||||||
<a [@navItemAnim] *osPerms="'agenda.can_see'" mat-list-item routerLink='/agenda' routerLinkActive='active' (click)='toggleSideNav()'>
|
|
||||||
<fa-icon icon='calendar'></fa-icon>
|
|
||||||
<span translate>Agenda</span>
|
|
||||||
</a>
|
|
||||||
<a [@navItemAnim] *osPerms="'motions.can_see'" mat-list-item routerLink='/motions' routerLinkActive='active' (click)='toggleSideNav()'>
|
|
||||||
<fa-icon icon='file-alt'></fa-icon>
|
|
||||||
<span translate>Motions</span>
|
|
||||||
</a>
|
|
||||||
<a [@navItemAnim] *osPerms="'assignments.can_see'" mat-list-item routerLink='/assignments' routerLinkActive='active' (click)='vp.isMobile ? sideNav.toggle() : null'>
|
|
||||||
<fa-icon icon='chart-pie'></fa-icon>
|
|
||||||
<span translate>Assignments</span>
|
|
||||||
</a>
|
|
||||||
<a [@navItemAnim] *osPerms="'users.can_see_name'" mat-list-item routerLink='/users' routerLinkActive='active' (click)='toggleSideNav()'>
|
|
||||||
<fa-icon icon='user'></fa-icon>
|
|
||||||
<span translate>Participants</span>
|
|
||||||
</a>
|
|
||||||
<a [@navItemAnim] *osPerms="'mediafiles.can_see'" mat-list-item routerLink='/mediafiles' routerLinkActive='active' (click)='toggleSideNav()'>
|
|
||||||
<fa-icon icon='paperclip'></fa-icon>
|
|
||||||
<span translate>Files</span>
|
|
||||||
</a>
|
|
||||||
<a [@navItemAnim] *osPerms="'core.can_manage_config'" mat-list-item routerLink='/settings' routerLinkActive='active' (click)='toggleSideNav()'>
|
|
||||||
<fa-icon icon='cog'></fa-icon>
|
|
||||||
<span translate>Settings</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
</span>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<a [@navItemAnim] *osPerms="'core.can_see_projector'" mat-list-item routerLink='/projector' routerLinkActive='active' (click)='toggleSideNav()'>
|
<a [@navItemAnim] *osPerms="'core.can_see_projector'" mat-list-item routerLink='/projector' routerLinkActive='active' (click)='toggleSideNav()'>
|
||||||
<fa-icon icon='video'></fa-icon>
|
<fa-icon icon='video'></fa-icon>
|
||||||
|
@ -9,8 +9,7 @@ import { BaseComponent } from 'app/base.component';
|
|||||||
import { pageTransition, navItemAnim } from 'app/shared/animations';
|
import { pageTransition, navItemAnim } from 'app/shared/animations';
|
||||||
import { MatDialog, MatSidenav } from '@angular/material';
|
import { MatDialog, MatSidenav } from '@angular/material';
|
||||||
import { ViewportService } from '../core/services/viewport.service';
|
import { ViewportService } from '../core/services/viewport.service';
|
||||||
import { Projector } from '../shared/models/core/projector';
|
import { MainMenuService } from '../core/services/main-menu.service';
|
||||||
import { Tag } from '../shared/models/core/tag';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'os-site',
|
selector: 'os-site',
|
||||||
@ -51,7 +50,8 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
|||||||
public operator: OperatorService,
|
public operator: OperatorService,
|
||||||
public vp: ViewportService,
|
public vp: ViewportService,
|
||||||
public translate: TranslateService,
|
public translate: TranslateService,
|
||||||
public dialog: MatDialog
|
public dialog: MatDialog,
|
||||||
|
public mainMenuService: MainMenuService // used in the component
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -75,11 +75,6 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
|||||||
// this.translate.get('Motions').subscribe((res: string) => {
|
// this.translate.get('Motions').subscribe((res: string) => {
|
||||||
// console.log('translation of motions in the target language: ' + res);
|
// console.log('translation of motions in the target language: ' + res);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// tslint:disable-next-line
|
|
||||||
const p: Projector = new Projector(); // Needed, that the Projector.ts is loaded. Can be removed, if something else creates/uses projectors.
|
|
||||||
// tslint:disable-next-line
|
|
||||||
const t: Tag = new Tag(); // Needed, that the Tag.ts is loaded. Can be removed, if something else creates/uses tags.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
import { SiteRoutingModule } from './site-routing.module';
|
|
||||||
import { SharedModule } from 'app/shared/shared.module';
|
import { SharedModule } from 'app/shared/shared.module';
|
||||||
|
|
||||||
import { SiteComponent } from './site.component';
|
import { SiteComponent } from './site.component';
|
||||||
import { StartComponent } from './start/start.component';
|
import { SiteRoutingModule } from './site-routing.module';
|
||||||
import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
|
|
||||||
import { PrivacyPolicyComponent } from './privacy-policy/privacy-policy.component';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, SharedModule, SiteRoutingModule],
|
imports: [CommonModule, SharedModule, SiteRoutingModule],
|
||||||
declarations: [SiteComponent, StartComponent, LegalNoticeComponent, PrivacyPolicyComponent]
|
declarations: [SiteComponent]
|
||||||
})
|
})
|
||||||
export class SiteModule {}
|
export class SiteModule {}
|
||||||
|
22
client/src/app/site/users/users.config.ts
Normal file
22
client/src/app/site/users/users.config.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { AppConfig } from '../base/app-config';
|
||||||
|
import { User } from '../../shared/models/users/user';
|
||||||
|
import { Group } from '../../shared/models/users/group';
|
||||||
|
import { PersonalNote } from '../../shared/models/users/personal-note';
|
||||||
|
|
||||||
|
export const UsersAppConfig: AppConfig = {
|
||||||
|
name: 'users',
|
||||||
|
models: [
|
||||||
|
{ collectionString: 'users/user', model: User },
|
||||||
|
{ collectionString: 'users/group', model: Group },
|
||||||
|
{ collectionString: 'users/personal-note', model: PersonalNote }
|
||||||
|
],
|
||||||
|
mainMenuEntries: [
|
||||||
|
{
|
||||||
|
route: '/users',
|
||||||
|
displayName: 'Participants',
|
||||||
|
icon: 'user',
|
||||||
|
weight: 500,
|
||||||
|
permission: 'users.can_see_name'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
1
client/src/plugins.ts
Normal file
1
client/src/plugins.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const plugins: string[] = [];
|
Loading…
Reference in New Issue
Block a user