1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-17 16:53:34 +00:00

Preserve export type across export source selections (#16922)

This commit is contained in:
John Harrington
2025-10-29 12:49:31 -07:00
committed by GitHub
parent 66052b6dd3
commit e333c0a8bc
4 changed files with 85 additions and 18 deletions

View File

@@ -35,7 +35,7 @@
<bit-form-field>
<bit-label>{{ "fileFormat" | i18n }}</bit-label>
<bit-select formControlName="format">
<bit-option *ngFor="let f of formatOptions" [value]="f.value" [label]="f.name" />
<bit-option *ngFor="let f of formatOptions$ | async" [value]="f.format" [label]="f.name" />
</bit-select>
</bit-form-field>

View File

@@ -67,7 +67,11 @@ import {
} from "@bitwarden/components";
import { GeneratorServicesModule } from "@bitwarden/generator-components";
import { CredentialGeneratorService, GenerateRequest, Type } from "@bitwarden/generator-core";
import { ExportedVault, VaultExportServiceAbstraction } from "@bitwarden/vault-export-core";
import {
ExportedVault,
ExportFormatMetadata,
VaultExportServiceAbstraction,
} from "@bitwarden/vault-export-core";
import { EncryptedExportType } from "../enums/encrypted-export-type.enum";
@@ -231,11 +235,11 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
fileEncryptionType: [EncryptedExportType.AccountEncrypted],
});
formatOptions = [
{ name: ".json", value: "json" },
{ name: ".csv", value: "csv" },
{ name: ".json (Encrypted)", value: "encrypted_json" },
];
/**
* Observable stream of available export format options
* Dynamically updates based on vault selection (My Vault vs Organization)
*/
formatOptions$: Observable<ExportFormatMetadata[]>;
private destroy$ = new Subject<void>();
private onlyManagedCollections = true;
@@ -338,17 +342,28 @@ export class ExportComponent implements OnInit, OnDestroy, AfterViewInit {
}
private observeFormSelections(): void {
this.exportForm.controls.vaultSelector.valueChanges
.pipe(takeUntil(this.destroy$))
.subscribe((value) => {
this.organizationId = value !== "myVault" ? value : undefined;
// Set up dynamic format options based on vault selection
this.formatOptions$ = this.exportForm.controls.vaultSelector.valueChanges.pipe(
startWith(this.exportForm.controls.vaultSelector.value),
map((vaultSelection) => {
const isMyVault = vaultSelection === "myVault";
// Update organizationId based on vault selection
this.organizationId = isMyVault ? undefined : vaultSelection;
return { isMyVault };
}),
switchMap((options) => this.exportService.formats$(options)),
tap((formats) => {
// Preserve the current format selection if it's still available in the new format list
const currentFormat = this.exportForm.get("format").value;
const isFormatAvailable = formats.some((f) => f.format === currentFormat);
this.formatOptions = this.formatOptions.filter((option) => option.value !== "zip");
this.exportForm.get("format").setValue("json");
if (value === "myVault") {
this.formatOptions.push({ name: ".zip (with attachments)", value: "zip" });
// Only reset to json if the current format is no longer available
if (!isFormatAvailable) {
this.exportForm.get("format").setValue("json");
}
});
}),
shareReplay({ bufferSize: 1, refCount: true }),
);
}
/**