[PM-3538] Migrate AddOrganizationComponent Web (#6275)
Migrate add organization in provider portal to use component library.
This commit is contained in:
parent
ee2f2e1fb1
commit
2dc94ede97
|
@ -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">×</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>
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,5 +97,3 @@
|
|||
</table>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-template #add></ng-template>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue