1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-22 11:45:59 +01:00

migrating domain rules component (#8745)

This commit is contained in:
vinith-kovan 2024-05-22 19:34:02 +05:30 committed by GitHub
parent 6ca836f31d
commit 780ab28e40
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 87 additions and 90 deletions

View File

@ -1,109 +1,89 @@
<app-header></app-header> <app-header></app-header>
<bit-container> <bit-container>
<p>{{ "domainRulesDesc" | i18n }}</p> <p bitTypography="body1">{{ "domainRulesDesc" | i18n }}</p>
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate> <form [formGroup]="formGroup" [bitSubmit]="submit">
<h2>{{ "customEqDomains" | i18n }}</h2> <h2 bitTypography="h2">{{ "customEqDomains" | i18n }}</h2>
<p *ngIf="loading"> <p bitTypography="body1" *ngIf="loading">
<i <i
class="bwi bwi-spinner bwi-spin text-muted" class="bwi bwi-spinner bwi-spin tw-text-muted"
title="{{ 'loading' | i18n }}" title="{{ 'loading' | i18n }}"
aria-hidden="true" aria-hidden="true"
></i> ></i>
<span class="sr-only">{{ "loading" | i18n }}</span> <span class="tw-sr-only">{{ "loading" | i18n }}</span>
</p> </p>
<ng-container *ngIf="!loading"> <ng-container formArrayName="customDomain" *ngIf="!loading">
<div class="form-group d-flex" *ngFor="let d of custom; let i = index; trackBy: indexTrackBy"> <div
<div class="flex-fill"> class="tw-flex tw-items-center tw-gap-2 tw-mb-6"
<label for="customDomain_{{ i }}" class="sr-only">{{ *ngFor="let d of custom; let i = index; trackBy: indexTrackBy"
"customDomainX" | i18n: i + 1 >
}}</label> <bit-form-field class="tw-flex-1 !tw-mb-0" formGroupName="{{ i }}">
<bit-label class="tw-sr-only">{{ "customDomainX" | i18n: i + 1 }} </bit-label>
<textarea <textarea
class="form-control" rows="2"
name="CustomDomain[{{ i }}]" bitInput
id="customDomain_{{ i }}" [value]="d"
[(ngModel)]="custom[i]" formControlName="domain"
placeholder="{{ 'ex' | i18n }} google.com, gmail.com" placeholder="{{ 'ex' | i18n }} google.com, gmail.com"
required
></textarea> ></textarea>
</div> </bit-form-field>
<button <button
bitIconButton="bwi-minus-circle"
type="button" type="button"
class="btn btn-link text-danger ml-2" buttonType="danger"
(click)="remove(i)" (click)="remove(i)"
appA11yTitle="{{ 'remove' | i18n }}" appA11yTitle="{{ 'remove' | i18n }}"
> ></button>
<i class="bwi bwi-minus-circle bwi-lg" aria-hidden="true"></i>
</button>
</div> </div>
<button type="button" (click)="add()" class="btn btn-outline-secondary btn-sm mb-2"> <button bitButton type="button" (click)="add()" buttonType="secondary" class="tw-mb-2">
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i> {{ "newCustomDomain" | i18n }} <i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i> {{ "newCustomDomain" | i18n }}
</button> </button>
<small class="text-muted d-block mb-3">{{ "newCustomDomainDesc" | i18n }}</small> <small class="tw-text-muted tw-block tw-mb-3">{{ "newCustomDomainDesc" | i18n }}</small>
</ng-container> </ng-container>
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading"> <button type="submit" bitButton bitFormButton buttonType="primary">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i> {{ "save" | i18n }}
<span>{{ "save" | i18n }}</span>
</button> </button>
<h2 class="spaced-header">{{ "globalEqDomains" | i18n }}</h2> <h2 bitTypography="h2" class="spaced-header">{{ "globalEqDomains" | i18n }}</h2>
<p *ngIf="loading"> <p bitTypography="body1" *ngIf="loading">
<i <i
class="bwi bwi-spinner bwi-spin text-muted" class="bwi bwi-spinner bwi-spin tw-text-muted"
title="{{ 'loading' | i18n }}" title="{{ 'loading' | i18n }}"
aria-hidden="true" aria-hidden="true"
></i> ></i>
<span class="sr-only">{{ "loading" | i18n }}</span> <span class="tw-sr-only">{{ "loading" | i18n }}</span>
</p> </p>
<table class="table table-hover table-list" *ngIf="!loading && global.length > 0"> <bit-table *ngIf="!loading && global.length > 0">
<tbody> <ng-template body>
<tr *ngFor="let d of global"> <tr bitRow *ngFor="let d of global" class="tw-group">
<td [ngClass]="{ 'table-list-strike': d.excluded }">{{ d.domains }}</td> <td bitCell [ngClass]="{ 'table-list-strike': d.excluded }">{{ d.domains }}</td>
<td class="table-list-options"> <td bitCell>
<div class="dropdown" appListDropdown> <button
<button type="button"
class="btn btn-outline-secondary dropdown-toggle" bitIconButton="bwi-cog"
type="button" buttonType="secondary"
data-toggle="dropdown" [bitMenuTriggerFor]="appListDropdown"
aria-haspopup="true" class="tw-border-0 tw-bg-transparent tw-p-0"
aria-expanded="false" ></button>
appA11yTitle="{{ 'options' | i18n }}" <bit-menu #appListDropdown>
> <a href="#" bitMenuItem appStopClick (click)="toggleExcluded(d)" *ngIf="!d.excluded">
<i class="bwi bwi-cog bwi-lg" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-close" aria-hidden="true"></i>
</button> {{ "exclude" | i18n }}
<div class="dropdown-menu dropdown-menu-right"> </a>
<a <a href="#" bitMenuItem appStopClick (click)="toggleExcluded(d)" *ngIf="d.excluded">
class="dropdown-item" <i class="bwi bwi-fw bwi-plus" aria-hidden="true"></i>
href="#" {{ "include" | i18n }}
appStopClick </a>
(click)="toggleExcluded(d)" <a href="#" bitMenuItem appStopClick (click)="customize(d)">
*ngIf="!d.excluded" <i class="bwi bwi-fw bwi-cut" aria-hidden="true"></i>
> {{ "customize" | i18n }}
<i class="bwi bwi-fw bwi-close" aria-hidden="true"></i> </a>
{{ "exclude" | i18n }} </bit-menu>
</a>
<a
class="dropdown-item"
href="#"
appStopClick
(click)="toggleExcluded(d)"
*ngIf="d.excluded"
>
<i class="bwi bwi-fw bwi-plus" aria-hidden="true"></i>
{{ "include" | i18n }}
</a>
<a class="dropdown-item" href="#" appStopClick (click)="customize(d)">
<i class="bwi bwi-fw bwi-cut" aria-hidden="true"></i>
{{ "customize" | i18n }}
</a>
</div>
</div>
</td> </td>
</tr> </tr>
</tbody> </ng-template>
</table> </bit-table>
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading"> <button type="submit" bitButton buttonType="primary">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i> {{ "save" | i18n }}
<span>{{ "save" | i18n }}</span>
</button> </button>
</form> </form>
</bit-container> </bit-container>

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from "@angular/core"; import { Component, OnInit } from "@angular/core";
import { FormArray, FormBuilder, FormControl, FormGroup } from "@angular/forms";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { UpdateDomainsRequest } from "@bitwarden/common/models/request/update-domains.request"; import { UpdateDomainsRequest } from "@bitwarden/common/models/request/update-domains.request";
@ -15,12 +16,15 @@ export class DomainRulesComponent implements OnInit {
custom: string[] = []; custom: string[] = [];
global: any[] = []; global: any[] = [];
formPromise: Promise<any>; formPromise: Promise<any>;
formGroup: FormGroup<{ customDomain: FormArray<FormControl<any>> }> = this.formBuilder.group({
customDomain: this.formBuilder.array([]),
});
constructor( constructor(
private apiService: ApiService, private apiService: ApiService,
private i18nService: I18nService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,
private logService: LogService, private logService: LogService,
private formBuilder: FormBuilder,
) {} ) {}
async ngOnInit() { async ngOnInit() {
@ -38,8 +42,21 @@ export class DomainRulesComponent implements OnInit {
}; };
}); });
} }
this.patch();
}
patch() {
const control = <FormArray>this.formGroup.get("customDomain");
control.clear();
this.custom.forEach((val, index) => {
control.insert(index, this.patchValues(val));
});
this.formGroup.updateValueAndValidity();
}
patchValues(customDomain: string) {
return this.formBuilder.group({
domain: [customDomain],
});
} }
toggleExcluded(globalDomain: any) { toggleExcluded(globalDomain: any) {
globalDomain.excluded = !globalDomain.excluded; globalDomain.excluded = !globalDomain.excluded;
} }
@ -47,17 +64,22 @@ export class DomainRulesComponent implements OnInit {
customize(globalDomain: any) { customize(globalDomain: any) {
globalDomain.excluded = true; globalDomain.excluded = true;
this.custom.push(globalDomain.domains); this.custom.push(globalDomain.domains);
this.patch();
} }
remove(index: number) { remove(index: number) {
this.custom.splice(index, 1); this.custom.splice(index, 1);
this.patch();
} }
add() { add() {
this.custom.push(""); this.custom.push("");
this.patch();
} }
async submit() { submit = async () => {
const customDomainValues = this.formGroup.get("customDomain").value;
this.custom = customDomainValues.map((d) => d.domain);
const request = new UpdateDomainsRequest(); const request = new UpdateDomainsRequest();
request.excludedGlobalEquivalentDomains = this.global request.excludedGlobalEquivalentDomains = this.global
.filter((d) => d.excluded) .filter((d) => d.excluded)
@ -72,14 +94,9 @@ export class DomainRulesComponent implements OnInit {
request.equivalentDomains = null; request.equivalentDomains = null;
} }
try { await this.apiService.putSettingsDomains(request);
this.formPromise = this.apiService.putSettingsDomains(request); this.platformUtilsService.showToast("success", null, this.i18nService.t("domainsUpdated"));
await this.formPromise; };
this.platformUtilsService.showToast("success", null, this.i18nService.t("domainsUpdated"));
} catch (e) {
this.logService.error(e);
}
}
indexTrackBy(index: number, obj: any): any { indexTrackBy(index: number, obj: any): any {
return index; return index;