feat(console): message and login texts, privacy policy (#2016)

* message texts wrapper components

* message-text sub, i18n, grid

* fix routing

* pack

* pack

* update material

* audit

* fix mgmt service for labelplcy

* map conv

* edit text from map

* request map

* fetch data, mgmt admin service

* warn box, i18n

* resetbtn

* login texts

* login text requests

* reset, default, i18n

* disabled, features, message text setter, service

* locale switcher

* policy grid

* password reset, domain claimed i18n

* lint files

* fix admin service, i18n, lang setter

* fix scss duplicate

* privacy policy, cleanup grid, fix message, login texts (#2031)

* policy grid everywhere 🦒

* cleanup home

* log login text request

* patch all data

* refresh toggle

* fix: add dialog for unsaved changes (#2057)

* logintexts dialog

* check for dialog on pairwise operation

* fix: patch value to local state after save

* fix: i18n and custom login texts (#2060)

* fix: i18n and custom login texts

* fix: tos and privacy texts

* fix frontend

* fix: tos and privacy texts and tests

* fix: i18n, tos and privacy texts and tests

* fix frontend maps

* i18n

* add ResetCustomLoginTextToDefault in admin api and fix template remove in handlers

* resetlogintexttodefault

Co-authored-by: Livio Amstutz <[email protected]>
This commit is contained in:
Max Peintner
2021-07-26 12:44:45 +02:00
committed by GitHub
co-authored by Livio Amstutz
parent 26e4e607bc
commit 2e684684de
100 changed files with 4500 additions and 2259 deletions
@@ -0,0 +1,31 @@
<div *ngIf="currentMap">
<form [formGroup]="form" >
<ng-container *ngFor="let key of (current$ | async) | keyvalue">
<div class="block">
<div class="flex" *ngIf="(default$ | async) as defaultmap">
<cnsl-form-field class="formfield" >
<cnsl-label>{{key.key}}</cnsl-label>
<textarea class="text" cnslInput [formControlName]="key.key" [placeholder]="defaultmap[key.key]" [name]="key.key" [ngClass]="{'defaulttext': form.get(key.key)?.value === ''}"></textarea>
<div class="chips" *ngIf="warnText[key.key] == undefined">
<ng-container *ngFor="let chip of chips" >
<div class="chip" appCopyToClipboard [valueToCopy]="chip.value" (copiedValue)="copied = $event" (click)="addChip(key.key, chip.value)">
<span class="key">{{chip.key | translate}}</span>
<span class="value">{{chip.value}}</span>
<i *ngIf="copied != chip.value" class="las la-clipboard"></i>
<i *ngIf="copied == chip.value" class="las la-clipboard-check"></i>
</div>
</ng-container>
</div>
</cnsl-form-field>
<div class="actions">
<button matTooltip="{{'ACTIONS.RESETDEFAULT'| translate }}" mat-icon-button [disabled]="form.get(key.key)?.value == defaultmap[key.key] || disabled" (click)="form.get(key.key)?.setValue(defaultmap[key.key])" (mouseenter) = "form.get(key.key)?.value != defaultmap[key.key] && setWarnText(key.key, defaultmap[key.key])" (mouseleave) ="setWarnText(key.key, undefined)"><i class="las la-history"></i></button>
<button matTooltip="{{'ACTIONS.RESETCURRENT'| translate }}" mat-icon-button [disabled]="form.get(key.key)?.value == currentMap[key.key] || disabled" (click)="form.get(key.key)?.setValue(currentMap[key.key])" (mouseenter) = "form.get(key.key)?.value != currentMap[key.key] && setWarnText(key.key, currentMap[key.key])" (mouseleave) ="setWarnText(key.key, undefined)"><i class="las la-undo"></i></button>
</div>
</div>
</div>
<cnsl-info-section *ngIf="warnText[key.key] !== undefined" class="info" type="WARN">{{'ACTIONS.RESETTO'| translate }} <cite>'{{warnText[key.key]}}'</cite></cnsl-info-section>
</ng-container>
</form>
</div>
@@ -0,0 +1,96 @@
.block {
display: block;
.flex {
display: flex;
.formfield {
flex: 1;
.text {
min-height: 80px;
}
&.hovering {
background-color: red;
}
.chips {
display: flex;
flex-wrap: wrap;
opacity: 0;
margin: 0 -.25rem;
transition: all .2s ease;
.chip {
border-radius: 50vw;
padding: 4px .5rem;
font-size: 12px;
background: #5282c1;
color: white;
margin: .25rem;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
* {
transition: all .2s ease;
}
i {
opacity: .5;
font-size: 1.1rem;
margin-left: .5rem;
}
.key {
display: inline-block;
}
.value {
display: none;
}
&:hover {
i {
opacity: 1;
}
.key {
display: none;
}
.value {
display: inline-block;
}
}
}
}
&.cnsl-focused {
.chips {
opacity: 1;
cursor: copy;
}
}
.chips:hover {
visibility: visible;
}
}
.actions {
display: flex;
flex-direction: column;
align-self: flex-start;
margin-top: 30px;
}
}
}
.info {
display: block;
margin-right: 40px;
margin-bottom: 1.5rem;
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { EditTextComponent } from './edit-text.component';
describe('EditTextComponent', () => {
let component: EditTextComponent;
let fixture: ComponentFixture<EditTextComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [EditTextComponent],
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(EditTextComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,54 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'cnsl-edit-text',
templateUrl: './edit-text.component.html',
styleUrls: ['./edit-text.component.scss'],
})
export class EditTextComponent implements OnInit, OnDestroy {
@Input() label: string = '';
@Input() current$!: Observable<{ [key: string]: any | string; }>;
@Input() default$!: Observable<{ [key: string]: any | string; }>;
@Input() currentlyDragged: string = '';
@Output() changedValues: EventEmitter<{ [key: string]: string; }> = new EventEmitter();
public currentMap: { [key: string]: string; } = {};
private destroy$: Subject<void> = new Subject();
public form!: FormGroup;
public warnText: { [key: string]: string | undefined; } = {};
@Input() public chips: any[] = [];
@Input() public disabled: boolean = true;
public copied: string = '';
public ngOnInit(): void {
this.current$.pipe(takeUntil(this.destroy$)).subscribe(value => {
this.currentMap = value;
this.form = new FormGroup({});
Object.keys(value).map(key => {
const control = new FormControl({ value: value[key], disabled: this.disabled });
this.form.addControl(key, control);
});
this.form.valueChanges.pipe(takeUntil(this.destroy$)).subscribe(values => this.changedValues.emit(values));
});
}
public ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
public setWarnText(key: string, text: string | undefined): void {
this.warnText[key] = text;
}
public addChip(key: string, value: string): void {
const c = this.form.get(key)?.value;
this.form.get(key)?.setValue(`${c} ${value}`);
}
}
@@ -0,0 +1,39 @@
import { TextFieldModule } from '@angular/cdk/text-field';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import { CopyToClipboardModule } from 'src/app/directives/copy-to-clipboard/copy-to-clipboard.module';
import { InputModule } from 'src/app/modules/input/input.module';
import { FormFieldModule } from '../form-field/form-field.module';
import { InfoSectionModule } from '../info-section/info-section.module';
import { EditTextComponent } from './edit-text.component';
@NgModule({
declarations: [
EditTextComponent,
],
imports: [
CommonModule,
InfoSectionModule,
ReactiveFormsModule,
FormsModule,
InputModule,
FormFieldModule,
MatButtonModule,
MatIconModule,
MatTooltipModule,
TranslateModule,
MatTooltipModule,
TextFieldModule,
CopyToClipboardModule,
],
exports: [
EditTextComponent,
],
})
export class EditTextModule { }