add domain feature

This commit is contained in:
_Bastler
2021-04-08 09:45:50 +02:00
parent 288bdb3956
commit 56362da724
11 changed files with 342 additions and 15 deletions
+7 -1
View File
@@ -6,7 +6,13 @@
<a mat-tab-link routerLink="profile" routerLinkActive="active">{{'profile' | i18n}}</a>
<a mat-tab-link routerLink="security" routerLinkActive="active">{{'security' | i18n}}</a>
<a mat-tab-link routerLink="voucher" routerLinkActive="active">{{'vouchers' | i18n}}</a>
<a mat-tab-link routerLink="aliases" routerLinkActive="active">{{'user.aliases' | i18n}}</a>
<a *ngIf="advancedView" mat-tab-link routerLink="aliases" routerLinkActive="active">{{'user.aliases' | i18n}}</a>
<a *ngIf="advancedView" mat-tab-link routerLink="domains" routerLinkActive="active">{{'user.domains' | i18n}}</a>
<a mat-tab-link>
<mat-slide-toggle [(ngModel)]="advancedView">
<span *ngIf="!advancedView">{{'account.advanced' | i18n}}</span>
</mat-slide-toggle>
</a>
</nav>
<router-outlet></router-outlet>
+3 -3
View File
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import {Component, OnInit} from '@angular/core';
import { AuthService } from './../../services/auth.service';
import {AuthService} from './../../services/auth.service';
@Component({
selector: 'app-account',
@@ -9,7 +9,7 @@ import { AuthService } from './../../services/auth.service';
})
export class AccountComponent implements OnInit {
advancedView: boolean = false;
auth;
constructor(private authService: AuthService) {
@@ -0,0 +1,59 @@
<h3>{{'user.domains' | i18n}}</h3>
<table mat-table matSort [dataSource]="domains" (matSortChange)="sortData($event)">
<ng-container matColumnDef="domain">
<th mat-header-cell *matHeaderCellDef mat-sort-header="domain"> {{'user.domains.domain' | i18n}} </th>
<td mat-cell *matCellDef="let domain"> {{ domain.domain}} </td>
</ng-container>
<ng-container matColumnDef="secret">
<th mat-header-cell *matHeaderCellDef mat-sort-header="secret"> {{'user.domains.secret' | i18n}} </th>
<td mat-cell *matCellDef="let domain">
<a mat-button class="secret" (click)="copySecret(domain)" matTooltip="{{'user.domains.secret.copy' | i18n}}"
matTooltipPosition="above">{{ domain.secret}}</a>
</td>
</ng-container>
<ng-container matColumnDef="validated">
<th mat-header-cell *matHeaderCellDef mat-sort-header="validated"> {{'user.domains.validated' | i18n}} </th>
<td mat-cell *matCellDef="let domain">
<mat-slide-toggle [checked]="domain.validated" disabled></mat-slide-toggle>
</td>
</ng-container>
<ng-container matColumnDef="delete">
<th mat-header-cell *matHeaderCellDef class="align-right"> {{'user.domains.delete' | i18n}} </th>
<td mat-cell *matCellDef="let domain" class="text-right">
<a mat-icon-button>
<mat-icon (click)="confirmDelete(domain)">delete</mat-icon>
</a>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="domainsColumns"></tr>
<tr mat-row *matRowDef="let myRowData; columns: domainsColumns"></tr>
</table>
<form [formGroup]="form" (ngSubmit)="create()" #formDirective="ngForm">
<mat-card>
<mat-card-content>
<p>{{'user.domains.info' | i18n}}</p>
<mat-form-field>
<input matInput placeholder="{{'user.domains.domain' | i18n}}" formControlName="domain"
[(ngModel)]="domain.domain" required>
<mat-error>
{{'user.domains.error' | i18n}}
</mat-error>
</mat-form-field>
</mat-card-content>
<mat-card-actions>
<button *ngIf="!working" mat-raised-button color="primary" [disabled]="form.invalid">
{{'user.domains.create' | i18n}}
</button>
</mat-card-actions>
</mat-card>
</form>
@@ -0,0 +1,31 @@
mat-form-field {
display: block;
}
.mat-header-cell,
.mat-cell {
&.text-right {
text-align: right;
}
}
.align-right {
display: flex;
padding: 21px 0;
justify-content: flex-end;
}
.secret {
width: 200px;
max-width: 200px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.secret:hover {
cursor: pointer;
max-width: 100%;
width: 100%;
margin-right: 25px;
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DomainsComponent } from './domains.component';
describe('DomainsComponent', () => {
let component: DomainsComponent;
let fixture: ComponentFixture<DomainsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ DomainsComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(DomainsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,132 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import {I18nService} from '../../../services/i18n.service';
import {Sort} from '@angular/material/sort';
import {UserDomainService} from '../../../services/userdomain.service';
import {FormBuilder, FormGroup, Validators, NgForm} from '@angular/forms';
import {MatDialog} from '@angular/material/dialog';
import {ConfirmDialog} from '../../../ui/confirm/confirm.component';
import {MatSnackBar} from '@angular/material/snack-bar';
@Component({
selector: 'app-account-domains',
templateUrl: './domains.component.html',
styleUrls: ['./domains.component.scss']
})
export class DomainsComponent implements OnInit {
form: FormGroup;
@ViewChild('formDirective') private formDirective: NgForm;
domains: any[] = [];
domain: any = {
visibility: "PRIVATE"
};
success: boolean;
working: boolean;
domainsColumns = ["domain", "secret", "validated", "delete"];
visibilities = ["PRIVATE", "PROTECTED", "PUBLIC"];
constructor(
private formBuilder: FormBuilder,
private userDomainService: UserDomainService,
private i18n: I18nService,
private snackBar: MatSnackBar,
public dialog: MatDialog) {}
ngOnInit(): void {
this.form = this.formBuilder.group({
domain: ['', Validators.required],
// visibility: ['', Validators.required],
});
this.update();
}
create(): void {
this.working = true;
this.userDomainService.create(this.domain).subscribe(response => {
this.update();
this.formDirective.resetForm();
this.domain = {
visibility: "PRIVATE"
};
this.working = false;
}, (error) => {
this.working = false;
if(error.status == 409) {
let errors = {};
for(let code of error.error) {
errors[code.field] = errors[code.field] || {};
errors[code.field][code.code] = true;
}
for(let code in errors) {
this.form.get(code).setErrors(errors[code]);
}
}
})
}
updateDomain(domain) {
this.userDomainService.update(domain).subscribe((response: any) => {
domain = response;
})
}
update() {
this.userDomainService.get().subscribe((data: any) => {
this.domains = data;
})
}
confirmDelete(domain) {
const dialogRef = this.dialog.open(ConfirmDialog, {
data: {
'label': 'user.domains.confirmDelete',
'args': [domain.domain]
}
})
dialogRef.afterClosed().subscribe(result => {
if(result) {
this.userDomainService.delete(domain.id).subscribe((result: any) => {
this.update();
})
}
});
}
copySecret(domain: any) {
const selBox = document.createElement('textarea');
selBox.value = domain.secret;
document.body.appendChild(selBox);
selBox.focus();
selBox.select();
document.execCommand('copy');
document.body.removeChild(selBox);
this.snackBar.open(this.i18n.get("user.domains.secret.copied", []), this.i18n.get("close", []), {
duration: 3000
});
}
sortData(sort: Sort) {
const data = this.domains.slice();
if(!sort.active || sort.direction === '') {
this.domains = data;
return;
}
this.domains = data.sort((a, b) => {
const isAsc = sort.direction === 'asc';
switch(sort.active) {
case 'domain': return this.compare(a.domain, b.domain, isAsc);
case 'validated': return this.compare(a.validated, b.validated, isAsc);
default: return 0;
}
});
}
compare(a: number | string | String, b: number | string | String, isAsc: boolean) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
}