1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-06 11:43:51 +00:00

PM-23826 Implement a dialog to accept connection params

This commit is contained in:
voommen-livefront
2025-07-24 09:00:35 -05:00
parent 5c8598514e
commit cb63eb8eea
7 changed files with 133 additions and 6 deletions

View File

@@ -33,7 +33,7 @@
<p class="tw-mb-0">{{ description }}</p>
@if (canSetupConnection) {
<button type="button" class="tw-mt-3" bitButton (click)="setupConnection(name)">
<button type="button" class="tw-mt-3" bitButton (click)="setupConnection()">
<span>{{ "connectIntegrationButtonDesc" | i18n: name }}</span>
</button>
}

View File

@@ -9,13 +9,16 @@ import {
OnDestroy,
ViewChild,
} from "@angular/core";
import { Observable, Subject, combineLatest, takeUntil } from "rxjs";
import { Observable, Subject, combineLatest, lastValueFrom, takeUntil } from "rxjs";
import { SYSTEM_THEME_OBSERVABLE } from "@bitwarden/angular/services/injection-tokens";
import { ThemeType } from "@bitwarden/common/platform/enums";
import { ThemeStateService } from "@bitwarden/common/platform/theming/theme-state.service";
import { DialogService } from "@bitwarden/components";
import { SharedModule } from "../../../../../../shared/shared.module";
import { openCrowdstrikeConnectDialog } from "../integration-dialog/index";
import { Integration } from "../models";
@Component({
selector: "app-integration-card",
@@ -30,6 +33,7 @@ export class IntegrationCardComponent implements AfterViewInit, OnDestroy {
@Input() image: string;
@Input() imageDarkMode?: string;
@Input() linkURL: string;
@Input() integrationSettings: Integration;
/** Adds relevant `rel` attribute to external links */
@Input() externalURL?: boolean;
@@ -49,6 +53,7 @@ export class IntegrationCardComponent implements AfterViewInit, OnDestroy {
private themeStateService: ThemeStateService,
@Inject(SYSTEM_THEME_OBSERVABLE)
private systemTheme$: Observable<ThemeType>,
private dialogService: DialogService,
) {}
ngAfterViewInit() {
@@ -101,9 +106,17 @@ export class IntegrationCardComponent implements AfterViewInit, OnDestroy {
return this.isConnected !== undefined;
}
setupConnection(app: string) {
// This method can be used to handle the connection logic for the integration
// For example, it could open a modal or redirect to a setup page
this.isConnected = !this.isConnected; // Toggle connection state for demonstration
async setupConnection() {
// invoke the dialog to connect the integration
const dialog = openCrowdstrikeConnectDialog(this.dialogService, {
data: {
settings: this.integrationSettings,
},
});
const result = await lastValueFrom(dialog.closed);
// eslint-disable-next-line no-console
console.log(`Dialog closed with result: ${JSON.stringify(result)}`);
}
}

View File

@@ -0,0 +1,34 @@
<form [formGroup]="formGroup" [bitSubmit]="submit">
<bit-dialog dialogSize="large" [loading]="loading">
<span bitDialogTitle>
{{ "connectIntegrationButtonDesc" | i18n: connectInfo.settings.name }}
</span>
<div bitDialogContent class="tw-flex tw-flex-col tw-gap-4">
<ng-container *ngIf="loading" #spinner>
<i class="bwi bwi-spinner bwi-lg bwi-spin" aria-hidden="true"></i>
</ng-container>
<ng-container *ngIf="!loading">
<bit-form-field>
<bit-label>{{ "url" | i18n }}</bit-label>
<input bitInput formControlName="url" />
</bit-form-field>
<bit-form-field>
<bit-label>{{ "bearerToken" | i18n }}</bit-label>
<input bitInput formControlName="bearerToken" />
</bit-form-field>
<bit-form-field>
<bit-label>{{ "index" | i18n }}</bit-label>
<input bitInput formControlName="index" />
</bit-form-field>
</ng-container>
</div>
<ng-container bitDialogFooter>
<button type="submit" bitButton bitFormButton buttonType="primary" [disabled]="loading">
{{ "save" | i18n }}
</button>
<button type="button" bitButton bitDialogClose buttonType="secondary" [disabled]="loading">
{{ "cancel" | i18n }}
</button>
</ng-container>
</bit-dialog>
</form>

View File

@@ -0,0 +1,69 @@
import { Component, Inject } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
import { DIALOG_DATA, DialogConfig, DialogRef, DialogService } from "@bitwarden/components";
import { SharedModule } from "@bitwarden/web-vault/app/shared";
import { Integration } from "../../models";
export type ConnectDialogParams = {
settings: Integration;
};
export interface ConnectDialogResult {
integrationSettings: Integration;
url: string;
bearerToken: string;
index: string;
success: boolean;
error: string | null;
}
@Component({
templateUrl: "./connect-dialog.component.html",
imports: [SharedModule],
})
export class ConnectDialogComponent {
loading = false;
protected formGroup = this.formBuilder.group({
url: ["", [Validators.required, Validators.pattern("https?://.+")]],
bearerToken: ["", Validators.required],
index: ["", Validators.required],
});
constructor(
@Inject(DIALOG_DATA) protected connectInfo: ConnectDialogParams,
protected formBuilder: FormBuilder,
private dialogRef: DialogRef<ConnectDialogResult>,
) {}
protected submit = async (): Promise<void> => {
const formJson = this.formGroup.getRawValue();
// eslint-disable-next-line no-console
console.log(`Form submitted with values: ${JSON.stringify(formJson)}`);
const result: ConnectDialogResult = {
integrationSettings: this.connectInfo.settings,
url: this.formGroup.value.url,
bearerToken: this.formGroup.value.bearerToken,
index: this.formGroup.value.index,
success: true,
error: null,
};
// eslint-disable-next-line no-console
console.log(`Dialog closed with result: ${JSON.stringify(result)}`);
this.dialogRef.close(result);
return;
};
}
export function openCrowdstrikeConnectDialog(
dialogService: DialogService,
config: DialogConfig<ConnectDialogParams, DialogRef<ConnectDialogResult>>,
) {
return dialogService.open<ConnectDialogResult>(ConnectDialogComponent, config);
}

View File

@@ -0,0 +1 @@
export * from "../integration-dialog/connect-dialog/connect-dialog.component";

View File

@@ -16,6 +16,7 @@
[description]="integration.description | i18n"
[isConnected]="integration.isConnected"
[canSetupConnection]="integration.canSetupConnection"
[integrationSettings]="integration"
></app-integration-card>
</li>
</ul>

View File

@@ -9562,6 +9562,15 @@
"createNewClientToManageAsProvider": {
"message": "Create a new client organization to manage as a Provider. Additional seats will be reflected in the next billing cycle."
},
"url": {
"message": "URL"
},
"bearerToken": {
"message": "Bearer Token"
},
"index": {
"message": "Index"
},
"selectAPlan": {
"message": "Select a plan"
},