[PM-3538] Migrate AddOrganizationComponent Web (#6275)

Migrate add organization in provider portal to use component library.
This commit is contained in:
Oscar Hinton 2023-10-16 15:43:38 +02:00 committed by GitHub
parent ee2f2e1fb1
commit 2dc94ede97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 84 additions and 130 deletions

View File

@ -1,47 +1,25 @@
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="addTitle">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="addTitle">
{{ "addExistingOrganization" | i18n }}
</h2>
<button
type="button"
class="close"
data-dismiss="modal"
appA11yTitle="{{ 'close' | i18n }}"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="card-body text-center" *ngIf="loading">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
{{ "loading" | i18n }}
</div>
<ng-container *ngIf="!loading">
<table class="table table-hover table-list">
<tr *ngFor="let o of organizations">
<td width="30">
<bit-avatar [text]="o.name" [id]="o.id" size="small"></bit-avatar>
</td>
<td>
{{ o.name }}
</td>
<td>
<button
type="button"
class="btn btn-outline-secondary pull-right"
(click)="add(o)"
[disabled]="formPromise"
>
Add
</button>
</td>
</tr>
</table>
</ng-container>
</div>
</div>
</div>
</div>
<bit-dialog [loading]="loading">
<span bitDialogTitle>{{ "addExistingOrganization" | i18n }}</span>
<ng-container bitDialogContent>
<bit-table>
<ng-template body>
<tr bitRow *ngFor="let o of data.organizations">
<td bitCell width="30">
<bit-avatar [text]="o.name" [id]="o.id" size="small"></bit-avatar>
</td>
<td bitCell>
{{ o.name }}
</td>
<td bitCell>
<button type="button" bitButton [bitAction]="add(o)" class="tw-float-right">Add</button>
</td>
</tr>
</ng-template>
</bit-table>
</ng-container>
<ng-container bitDialogFooter>
<button type="button" bitButton bitDialogClose>
{{ "close" | i18n }}
</button>
</ng-container>
</bit-dialog>

View File

@ -1,4 +1,5 @@
import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
import { DIALOG_DATA, DialogRef } from "@angular/cdk/dialog";
import { Component, Inject, OnInit } from "@angular/core";
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
@ -10,20 +11,21 @@ import { DialogService } from "@bitwarden/components";
import { WebProviderService } from "../services/web-provider.service";
interface AddOrganizationDialogData {
providerId: string;
organizations: Organization[];
}
@Component({
selector: "provider-add-organization",
templateUrl: "add-organization.component.html",
})
export class AddOrganizationComponent implements OnInit {
@Input() providerId: string;
@Input() organizations: Organization[];
@Output() onAddedOrganization = new EventEmitter();
provider: Provider;
formPromise: Promise<any>;
loading = true;
protected provider: Provider;
protected loading = true;
constructor(
private dialogRef: DialogRef,
@Inject(DIALOG_DATA) protected data: AddOrganizationDialogData,
private providerService: ProviderService,
private webProviderService: WebProviderService,
private i18nService: I18nService,
@ -37,52 +39,53 @@ export class AddOrganizationComponent implements OnInit {
}
async load() {
if (this.providerId == null) {
if (this.data.providerId == null) {
return;
}
this.provider = await this.providerService.get(this.providerId);
this.provider = await this.providerService.get(this.data.providerId);
this.loading = false;
}
async add(organization: Organization) {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
if (this.formPromise) {
return;
}
add(organization: Organization) {
return async () => {
const confirmed = await this.dialogService.openSimpleDialog({
title: organization.name,
content: {
key: "addOrganizationConfirmation",
placeholders: [organization.name, this.provider.name],
},
type: "warning",
});
const confirmed = await this.dialogService.openSimpleDialog({
title: organization.name,
content: {
key: "addOrganizationConfirmation",
placeholders: [organization.name, this.provider.name],
},
type: "warning",
});
if (!confirmed) {
return false;
}
if (!confirmed) {
return false;
}
try {
await this.webProviderService.addOrganizationToProvider(
this.data.providerId,
organization.id
);
} catch (e) {
this.validationService.showError(e);
return;
}
try {
this.formPromise = this.webProviderService.addOrganizationToProvider(
this.providerId,
organization.id
this.platformUtilsService.showToast(
"success",
null,
this.i18nService.t("organizationJoinedProvider")
);
await this.formPromise;
} catch (e) {
this.validationService.showError(e);
return;
} finally {
this.formPromise = null;
}
this.platformUtilsService.showToast(
"success",
null,
this.i18nService.t("organizationJoinedProvider")
);
this.onAddedOrganization.emit();
this.dialogRef.close(true);
};
}
static open(dialogService: DialogService, data: AddOrganizationDialogData) {
return dialogService.open<boolean, AddOrganizationDialogData>(AddOrganizationComponent, {
data,
});
}
}

View File

@ -97,5 +97,3 @@
</table>
</ng-container>
</ng-container>
<ng-template #add></ng-template>

View File

@ -1,5 +1,6 @@
import { Component, OnInit, ViewChild, ViewContainerRef } from "@angular/core";
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { firstValueFrom } from "rxjs";
import { first } from "rxjs/operators";
import { ModalService } from "@bitwarden/angular/services/modal.service";
@ -33,8 +34,6 @@ const DisallowedPlanTypes = [
})
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
export class ClientsComponent implements OnInit {
@ViewChild("add", { read: ViewContainerRef, static: true }) addModalRef: ViewContainerRef;
providerId: string;
searchText: string;
addableOrganizations: Organization[];
@ -135,23 +134,14 @@ export class ClientsComponent implements OnInit {
}
async addExistingOrganization() {
const [modal] = await this.modalService.openViewRef(
AddOrganizationComponent,
this.addModalRef,
(comp) => {
comp.providerId = this.providerId;
comp.organizations = this.addableOrganizations;
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
comp.onAddedOrganization.subscribe(async () => {
try {
await this.load();
modal.close();
} catch (e) {
this.logService.error(`Handled exception: ${e}`);
}
});
}
);
const dialogRef = AddOrganizationComponent.open(this.dialogService, {
providerId: this.providerId,
organizations: this.addableOrganizations,
});
if (await firstValueFrom(dialogRef.closed)) {
await this.load();
}
}
async remove(organization: ProviderOrganizationOrganizationDetailsResponse) {

View File

@ -1,9 +1,8 @@
import { CommonModule } from "@angular/common";
import { ComponentFactoryResolver, NgModule } from "@angular/core";
import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import { SearchModule } from "@bitwarden/components";
import { OrganizationPlansComponent } from "@bitwarden/web-vault/app/billing";
import { OssModule } from "@bitwarden/web-vault/app/oss.module";
@ -56,11 +55,4 @@ import { SetupComponent } from "./setup/setup.component";
],
providers: [WebProviderService, ProviderPermissionsGuard],
})
export class ProvidersModule {
constructor(modalService: ModalService, componentFactoryResolver: ComponentFactoryResolver) {
modalService.registerComponentFactoryResolver(
AddOrganizationComponent,
componentFactoryResolver
);
}
}
export class ProvidersModule {}

View File

@ -88,13 +88,6 @@ export class ModalService {
return modalRef;
}
registerComponentFactoryResolver<T>(
componentType: Type<T>,
componentFactoryResolver: ComponentFactoryResolver
): void {
this.factoryResolvers.set(componentType, componentFactoryResolver);
}
resolveComponentFactory<T>(componentType: Type<T>): ComponentFactory<T> {
if (this.factoryResolvers.has(componentType)) {
return this.factoryResolvers.get(componentType).resolveComponentFactory(componentType);