From 663d230561c69ea09e42a382bca302b7e8d5cec3 Mon Sep 17 00:00:00 2001 From: GabrielMeyer Date: Tue, 22 Oct 2019 15:37:49 +0200 Subject: [PATCH] Adds the 'edit-mode' to start, legal-notice and privacy-policy --- .../legal-notice-content.component.html | 17 +++- .../legal-notice-content.component.ts | 72 +++++++++++++++- .../privacy-policy-content.component.html | 17 ++-- .../privacy-policy-content.component.ts | 81 +++++++++++++++-- .../legal-notice/legal-notice.component.html | 18 +++- .../legal-notice/legal-notice.component.ts | 48 +++++++++-- .../privacy-policy.component.html | 18 +++- .../privacy-policy.component.ts | 52 ++++++++++- .../components/start/start.component.html | 37 ++++++-- .../components/start/start.component.ts | 86 +++++++++++++++++-- 10 files changed, 402 insertions(+), 44 deletions(-) diff --git a/client/src/app/shared/components/legal-notice-content/legal-notice-content.component.html b/client/src/app/shared/components/legal-notice-content/legal-notice-content.component.html index 5c3f1caf1..e673d0650 100644 --- a/client/src/app/shared/components/legal-notice-content/legal-notice-content.component.html +++ b/client/src/app/shared/components/legal-notice-content/legal-notice-content.component.html @@ -1,9 +1,18 @@
- -
- The event manager hasn't set up a legal notice yet. -
+ + +
+ The event manager hasn't set up a legal notice yet. +
+
+ +
+
+ +
+
+
diff --git a/client/src/app/shared/components/legal-notice-content/legal-notice-content.component.ts b/client/src/app/shared/components/legal-notice-content/legal-notice-content.component.ts index 9a5be7199..2a1ec7673 100644 --- a/client/src/app/shared/components/legal-notice-content/legal-notice-content.component.ts +++ b/client/src/app/shared/components/legal-notice-content/legal-notice-content.component.ts @@ -1,9 +1,14 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { MatSnackBar } from '@angular/material'; +import { Title } from '@angular/platform-browser'; +import { TranslateService } from '@ngx-translate/core'; import { environment } from 'environments/environment'; import { HttpService } from 'app/core/core-services/http.service'; import { LoginDataService } from 'app/core/ui-services/login-data.service'; +import { BaseViewComponent } from 'app/site/base/base-view'; /** * Characterize a plugin. This data is retrieved from the server @@ -64,7 +69,50 @@ interface VersionResponse { templateUrl: './legal-notice-content.component.html', styleUrls: ['./legal-notice-content.component.scss'] }) -export class LegalNoticeContentComponent implements OnInit { +export class LegalNoticeContentComponent extends BaseViewComponent implements OnInit { + /** + * Decides, whether the component can be edited at all. + * Defaults to `false`. + */ + @Input() + public canBeEdited = false; + + /** + * Sets the editing-state and updates the FormGroup with the current value. + * + * @param isEditing whether the component is currently in editing-mode. + */ + @Input() + public set isEditing(isEditing: boolean) { + this.formGroup.patchValue({ legalNotice: this.legalNotice }); + this._isEditing = isEditing; + } + + /** + * Gets the editing-state. + * + * @returns `isEditing`. + */ + public get isEditing(): boolean { + return this._isEditing; + } + + /** + * Emitter to send updated value to the parent-component. + */ + @Output() + public update = new EventEmitter(); + + /** + * FormGroup for editing value. + */ + public formGroup: FormGroup; + + /** + * State, whether this is in editing-mode. + */ + private _isEditing = false; + /** * The legal notive text for the ui. */ @@ -81,7 +129,19 @@ export class LegalNoticeContentComponent implements OnInit { * @param translate * @param http */ - public constructor(private loginDataService: LoginDataService, private http: HttpService) {} + public constructor( + title: Title, + translate: TranslateService, + matSnackbar: MatSnackBar, + private loginDataService: LoginDataService, + private http: HttpService, + fb: FormBuilder + ) { + super(title, translate, matSnackbar); + this.formGroup = fb.group({ + legalNotice: '' + }); + } /** * Subscribes for the legal notice text. @@ -100,5 +160,11 @@ export class LegalNoticeContentComponent implements OnInit { // TODO: error handling if the version info could not be loaded } ); + + if (this.canBeEdited) { + this.subscriptions.push( + this.formGroup.get('legalNotice').valueChanges.subscribe(value => this.update.emit(value)) + ); + } } } diff --git a/client/src/app/shared/components/privacy-policy-content/privacy-policy-content.component.html b/client/src/app/shared/components/privacy-policy-content/privacy-policy-content.component.html index 4e1f94960..d7f38cc38 100644 --- a/client/src/app/shared/components/privacy-policy-content/privacy-policy-content.component.html +++ b/client/src/app/shared/components/privacy-policy-content/privacy-policy-content.component.html @@ -1,6 +1,13 @@ - -
-
- The event manager hasn't set up a privacy policy yet. -
+ + +
+
+ The event manager hasn't set up a privacy policy yet. +
+
+ +
+ +
+
diff --git a/client/src/app/shared/components/privacy-policy-content/privacy-policy-content.component.ts b/client/src/app/shared/components/privacy-policy-content/privacy-policy-content.component.ts index c52c10263..1344f3390 100644 --- a/client/src/app/shared/components/privacy-policy-content/privacy-policy-content.component.ts +++ b/client/src/app/shared/components/privacy-policy-content/privacy-policy-content.component.ts @@ -1,6 +1,12 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { MatSnackBar } from '@angular/material'; +import { Title } from '@angular/platform-browser'; + +import { TranslateService } from '@ngx-translate/core'; import { LoginDataService } from 'app/core/ui-services/login-data.service'; +import { BaseViewComponent } from 'app/site/base/base-view'; /** * Shared component to hold the content of the Privacy Policy. @@ -11,18 +17,76 @@ import { LoginDataService } from 'app/core/ui-services/login-data.service'; templateUrl: './privacy-policy-content.component.html', styleUrls: ['./privacy-policy-content.component.scss'] }) -export class PrivacyPolicyContentComponent implements OnInit { +export class PrivacyPolicyContentComponent extends BaseViewComponent implements OnInit { + /** + * Decides, whether the component can be edited at all. + * Defaults to `false`. + */ + @Input() + public canBeEdited = false; + + /** + * Sets the editing-state and updates the FormGroup with the current value. + * + * @param isEditing whether the component is currently in editing-mode. + */ + @Input() + public set isEditing(isEditing: boolean) { + this.formGroup.patchValue({ privacyPolicy: this.privacyPolicy }); + this._isEditing = isEditing; + } + + /** + * Gets the editing-state. + * + * @returns `isEditing`. + */ + public get isEditing(): boolean { + return this._isEditing; + } + + /** + * Emitter to send updated value to the parent-component. + */ + @Output() + public update = new EventEmitter<{ [key: string]: string }>(); + + /** + * FormGroup for editing value. + */ + public formGroup: FormGroup; + + /** + * State, whether this is in editing-mode. + */ + private _isEditing = false; + /** * The actual privacy policy as string */ public privacyPolicy: string; /** - * Imports the loginDataService and the translation service - * @param loginDataService Login Data - * @param translate for the translation + * Constructor. + * + * @param title + * @param translate + * @param matSnackbar + * @param loginDataService + * @param fb */ - public constructor(private loginDataService: LoginDataService) {} + public constructor( + title: Title, + protected translate: TranslateService, + matSnackbar: MatSnackBar, + private loginDataService: LoginDataService, + fb: FormBuilder + ) { + super(title, translate, matSnackbar); + this.formGroup = fb.group({ + privacyPolicy: '' + }); + } /** * Subscribes for the privacy policy text @@ -31,5 +95,10 @@ export class PrivacyPolicyContentComponent implements OnInit { this.loginDataService.privacyPolicy.subscribe(privacyPolicy => { this.privacyPolicy = privacyPolicy; }); + if (this.canBeEdited) { + this.subscriptions.push( + this.formGroup.get('privacyPolicy').valueChanges.subscribe(value => this.update.emit(value)) + ); + } } } diff --git a/client/src/app/site/common/components/legal-notice/legal-notice.component.html b/client/src/app/site/common/components/legal-notice/legal-notice.component.html index 1b9d62f2c..d8e76e3e0 100644 --- a/client/src/app/site/common/components/legal-notice/legal-notice.component.html +++ b/client/src/app/site/common/components/legal-notice/legal-notice.component.html @@ -1,10 +1,24 @@ - +

Legal notice

- +
diff --git a/client/src/app/site/common/components/legal-notice/legal-notice.component.ts b/client/src/app/site/common/components/legal-notice/legal-notice.component.ts index a4b8629e5..b6ef990df 100644 --- a/client/src/app/site/common/components/legal-notice/legal-notice.component.ts +++ b/client/src/app/site/common/components/legal-notice/legal-notice.component.ts @@ -1,25 +1,47 @@ import { Component, OnInit } from '@angular/core'; +import { MatSnackBar } from '@angular/material'; import { Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; import { OpenSlidesService } from 'app/core/core-services/openslides.service'; +import { OperatorService } from 'app/core/core-services/operator.service'; +import { ConfigRepositoryService } from 'app/core/repositories/config/config-repository.service'; import { UpdateService } from 'app/core/ui-services/update.service'; +import { BaseViewComponent } from 'app/site/base/base-view'; @Component({ selector: 'os-legal-notice', templateUrl: './legal-notice.component.html' }) -export class LegalNoticeComponent implements OnInit { +export class LegalNoticeComponent extends BaseViewComponent implements OnInit { + /** + * Whether this component is in editing-mode. + */ + public isEditing = false; + + /** + * Holds the current legal-notice. + */ + public legalNotice = ''; + + /** + * Constructor. + */ public constructor( + title: Title, + protected translate: TranslateService, + matSnackbar: MatSnackBar, private openSlidesService: OpenSlidesService, private update: UpdateService, - private titleService: Title, - private translate: TranslateService - ) {} + private configRepo: ConfigRepositoryService, + private operator: OperatorService + ) { + super(title, translate, matSnackbar); + } public ngOnInit(): void { - this.titleService.setTitle(this.translate.instant('Legal notice')); + super.setTitle(this.translate.instant('Legal notice')); } public resetCache(): void { @@ -33,4 +55,20 @@ export class LegalNoticeComponent implements OnInit { public initiateUpdateCheckForAllClients(): void { this.update.initiateUpdateCheckForAllClients(); } + + /** + * Saves changes. + */ + public saveChanges(): void { + this.configRepo + .bulkUpdate([{ key: 'general_event_legal_notice', value: this.legalNotice }]) + .then(() => (this.isEditing = !this.isEditing), this.raiseError); + } + + /** + * Returns, if the current user has the necessary permissions. + */ + public canManage(): boolean { + return this.operator.hasPerms('core.can_manage_config'); + } } diff --git a/client/src/app/site/common/components/privacy-policy/privacy-policy.component.html b/client/src/app/site/common/components/privacy-policy/privacy-policy.component.html index a1065b4f1..6c832c4ec 100644 --- a/client/src/app/site/common/components/privacy-policy/privacy-policy.component.html +++ b/client/src/app/site/common/components/privacy-policy/privacy-policy.component.html @@ -1,7 +1,21 @@ - +

Privacy Policy

- + diff --git a/client/src/app/site/common/components/privacy-policy/privacy-policy.component.ts b/client/src/app/site/common/components/privacy-policy/privacy-policy.component.ts index 9700e25ca..564065f06 100644 --- a/client/src/app/site/common/components/privacy-policy/privacy-policy.component.ts +++ b/client/src/app/site/common/components/privacy-policy/privacy-policy.component.ts @@ -1,17 +1,63 @@ import { Component, OnInit } from '@angular/core'; +import { MatSnackBar } from '@angular/material'; import { Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; +import { OperatorService } from 'app/core/core-services/operator.service'; +import { ConfigRepositoryService } from 'app/core/repositories/config/config-repository.service'; +import { BaseViewComponent } from 'app/site/base/base-view'; + @Component({ selector: 'os-privacy-policy', templateUrl: './privacy-policy.component.html', styleUrls: ['./privacy-policy.component.scss'] }) -export class PrivacyPolicyComponent implements OnInit { - public constructor(private titleService: Title, private translate: TranslateService) {} +export class PrivacyPolicyComponent extends BaseViewComponent implements OnInit { + /** + * Whether the component is in editing-mode. + */ + public isEditing = false; + + /** + * Holds the current privacy-policy. + */ + public privacyProlicy = ''; + + /** + * Constructor. + * + * @param titleService + * @param translate + * @param configRepo + */ + public constructor( + title: Title, + protected translate: TranslateService, + matSnackbar: MatSnackBar, + private configRepo: ConfigRepositoryService, + private operator: OperatorService + ) { + super(title, translate, matSnackbar); + } public ngOnInit(): void { - this.titleService.setTitle(this.translate.instant('Privacy policy')); + super.setTitle(this.translate.instant('Privacy policy')); + } + + /** + * Saves changes. + */ + public saveChanges(): void { + this.configRepo + .bulkUpdate([{ key: 'general_event_privacy_policy', value: this.privacyProlicy }]) + .then(() => (this.isEditing = !this.isEditing), this.raiseError); + } + + /** + * Returns, if the current user has the necessary permissions. + */ + public canManage(): boolean { + return this.operator.hasPerms('core.can_manage_config'); } } diff --git a/client/src/app/site/common/components/start/start.component.html b/client/src/app/site/common/components/start/start.component.html index 64bfd33da..84ef87fdb 100644 --- a/client/src/app/site/common/components/start/start.component.html +++ b/client/src/app/site/common/components/start/start.component.html @@ -1,13 +1,38 @@ - +

Home

- -
-

{{ welcomeTitle | translate }}

+ + +
+

{{ startContent.general_event_welcome_title | translate }}

-
-
+
+
+ + + +
+ + + The title is required + + +
+
diff --git a/client/src/app/site/common/components/start/start.component.ts b/client/src/app/site/common/components/start/start.component.ts index 3bb886706..499341305 100644 --- a/client/src/app/site/common/components/start/start.component.ts +++ b/client/src/app/site/common/components/start/start.component.ts @@ -1,10 +1,22 @@ import { Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { MatSnackBar } from '@angular/material'; import { Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; // showcase -import { BaseComponent } from 'app/base.component'; +import { OperatorService } from 'app/core/core-services/operator.service'; +import { ConfigRepositoryService } from 'app/core/repositories/config/config-repository.service'; import { ConfigService } from 'app/core/ui-services/config.service'; +import { BaseViewComponent } from 'app/site/base/base-view'; + +/** + * Interface describes the keys for the fields at start-component. + */ +interface IStartContent { + general_event_welcome_title: string; + general_event_welcome_text: string; +} /** * The start component. Greeting page for OpenSlides @@ -14,9 +26,24 @@ import { ConfigService } from 'app/core/ui-services/config.service'; templateUrl: './start.component.html', styleUrls: ['./start.component.scss'] }) -export class StartComponent extends BaseComponent implements OnInit { - public welcomeTitle: string; - public welcomeText: string; +export class StartComponent extends BaseViewComponent implements OnInit { + /** + * Whether the user is editing the content. + */ + public isEditing = false; + + /** + * Formular for the content. + */ + public startForm: FormGroup; + + /** + * Holding the values for the content. + */ + public startContent: IStartContent = { + general_event_welcome_title: '', + general_event_welcome_text: '' + }; /** * Constructor of the StartComponent @@ -25,8 +52,20 @@ export class StartComponent extends BaseComponent implements OnInit { * @param translate to translation module * @param configService read out config values */ - public constructor(titleService: Title, translate: TranslateService, private configService: ConfigService) { - super(titleService, translate); + public constructor( + titleService: Title, + translate: TranslateService, + matSnackbar: MatSnackBar, + private configService: ConfigService, + private configRepo: ConfigRepositoryService, + private fb: FormBuilder, + private operator: OperatorService + ) { + super(titleService, translate, matSnackbar); + this.startForm = this.fb.group({ + general_event_welcome_title: ['', Validators.required], + general_event_welcome_text: '' + }); } /** @@ -40,11 +79,42 @@ export class StartComponent extends BaseComponent implements OnInit { // set the welcome title this.configService .get('general_event_welcome_title') - .subscribe(welcomeTitle => (this.welcomeTitle = welcomeTitle)); + .subscribe(welcomeTitle => (this.startContent.general_event_welcome_title = welcomeTitle)); // set the welcome text this.configService.get('general_event_welcome_text').subscribe(welcomeText => { - this.welcomeText = this.translate.instant(welcomeText); + this.startContent.general_event_welcome_text = this.translate.instant(welcomeText); }); } + + /** + * Changes to editing mode. + */ + public editStartPage(): void { + Object.keys(this.startForm.controls).forEach(control => { + this.startForm.patchValue({ [control]: this.startContent[control] }); + }); + this.isEditing = true; + } + + /** + * Saves changes and updates the content. + */ + public saveChanges(): void { + this.configRepo + .bulkUpdate( + Object.keys(this.startForm.controls).map(control => ({ + key: control, + value: this.startForm.value[control] + })) + ) + .then(() => (this.isEditing = !this.isEditing), this.raiseError); + } + + /** + * Returns, if the current user has the necessary permissions. + */ + public canManage(): boolean { + return this.operator.hasPerms('core.can_manage_config'); + } }