Merge pull request #3890 from FinnStutzenstein/plugins3
App initialization
This commit is contained in:
commit
19d78a3361
@ -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()'>
|
</a>
|
||||||
<fa-icon icon='calendar'></fa-icon>
|
</span>
|
||||||
<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>
|
|
||||||
<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