mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
[PM-4197] Enable importing on deskop (#6502)
* Split up import/export into separate modules * Fix routing and apply PR feedback * Renamed OrganizationExport exports to OrganizationVaultExport * Make import dialogs standalone and move them to libs/importer * Make import.component re-usable - Move functionality which was previously present on the org-import.component into import.component - Move import.component into libs/importer Make import.component standalone Create import-web.component to represent Web UI Fix module imports and routing Remove unused org-import-files * Enable importing on deskop Create import-dialog Create file-menu entry to open import-dialog Extend messages.json to include all the necessary messages from shared components * Renamed filenames according to export rename * Make ImportWebComponent standalone, simplify routing * Pass organizationId as Input to ImportComponent * use formLoading and formDisabled outputs * use formLoading & formDisabled in desktop * Emit an event when the import succeeds Remove Angular router from base-component as other clients might not have routing (i.e. desktop) Move logic that happened on web successful import into the import-web.component * Enable importing on deskop Create import-dialog Create file-menu entry to open import-dialog Extend messages.json to include all the necessary messages from shared components * use formLoading & formDisabled in desktop * Add missing message for importBlockedByPolicy callout * Remove commented code for submit button * Implement onSuccessfulImport to close dialog on success * fix table themes on desktop & browser * fix fileSelector button styles * update selectors to use tools prefix; remove unused selectors * update selectors * Wall off UI components in libs/importer Create barrel-file for libs/importer/components Remove components and dialog exports from libs/importer/index.ts Extend libs/shared/tsconfig.libs.json to include @bitwarden/importer/ui -> libs/importer/components Extend apps/web/tsconfig.ts to include @bitwarden/importer/ui Update all usages * Rename @bitwarden/importer to @bitwarden/importer/core Create more barrel files in libs/importer/* Update imports within libs/importer Extend tsconfig files Update imports in web, desktop, browser and cli * Lazy-load the ImportWebComponent via both routes * Fix import path for ImportComponent * Use SharedModule as import in import-web.component * File selector should be displayed as secondary * Add missing messages for file-password-prompt * Add missing messages for import-error-dialog * Add missing message for import-success-dialog * Use bitSubmit to override submit preventDefault (#6607) Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com> * Use large dialogSize * PM-4398 - Add missing importWarning --------- Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com> Co-authored-by: William Martin <contact@willmartian.com>
This commit is contained in:
parent
9e290a3fed
commit
e357819251
@ -55,6 +55,7 @@ import { FolderAddEditComponent } from "../vault/app/vault/folder-add-edit.compo
|
|||||||
import { SettingsComponent } from "./accounts/settings.component";
|
import { SettingsComponent } from "./accounts/settings.component";
|
||||||
import { ExportComponent } from "./tools/export/export.component";
|
import { ExportComponent } from "./tools/export/export.component";
|
||||||
import { GeneratorComponent } from "./tools/generator.component";
|
import { GeneratorComponent } from "./tools/generator.component";
|
||||||
|
import { ImportDesktopComponent } from "./tools/import/import-desktop.component";
|
||||||
import { PasswordGeneratorHistoryComponent } from "./tools/password-generator-history.component";
|
import { PasswordGeneratorHistoryComponent } from "./tools/password-generator-history.component";
|
||||||
|
|
||||||
const BroadcasterSubscriptionId = "AppComponent";
|
const BroadcasterSubscriptionId = "AppComponent";
|
||||||
@ -328,6 +329,9 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
this.messagingService.send("scheduleNextSync");
|
this.messagingService.send("scheduleNextSync");
|
||||||
break;
|
break;
|
||||||
|
case "importVault":
|
||||||
|
await this.dialogService.open(ImportDesktopComponent);
|
||||||
|
break;
|
||||||
case "exportVault":
|
case "exportVault":
|
||||||
await this.openExportVault();
|
await this.openExportVault();
|
||||||
break;
|
break;
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
<bit-dialog #dialog dialogSize="large">
|
||||||
|
<span bitDialogTitle>{{ "importData" | i18n }}</span>
|
||||||
|
<ng-container bitDialogContent>
|
||||||
|
<tools-import
|
||||||
|
(formLoading)="this.loading = $event"
|
||||||
|
(formDisabled)="this.disabled = $event"
|
||||||
|
(onSuccessfulImport)="this.onSuccessfulImport($event)"
|
||||||
|
></tools-import>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container bitDialogFooter>
|
||||||
|
<button
|
||||||
|
[disabled]="disabled"
|
||||||
|
[loading]="loading"
|
||||||
|
form="importForm"
|
||||||
|
bitButton
|
||||||
|
type="submit"
|
||||||
|
bitFormButton
|
||||||
|
buttonType="primary"
|
||||||
|
>
|
||||||
|
{{ "importData" | i18n }}
|
||||||
|
</button>
|
||||||
|
<button type="button" bitButton bitFormButton buttonType="secondary" bitDialogClose>
|
||||||
|
{{ "cancel" | i18n }}
|
||||||
|
</button>
|
||||||
|
</ng-container>
|
||||||
|
</bit-dialog>
|
@ -0,0 +1,33 @@
|
|||||||
|
import { DialogRef } from "@angular/cdk/dialog";
|
||||||
|
import { CommonModule } from "@angular/common";
|
||||||
|
import { Component } from "@angular/core";
|
||||||
|
|
||||||
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
|
import { AsyncActionsModule, ButtonModule, DialogModule } from "@bitwarden/components";
|
||||||
|
import { ImportComponent } from "@bitwarden/importer/ui";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "import-desktop.component.html",
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
JslibModule,
|
||||||
|
DialogModule,
|
||||||
|
AsyncActionsModule,
|
||||||
|
ButtonModule,
|
||||||
|
ImportComponent,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class ImportDesktopComponent {
|
||||||
|
protected disabled = false;
|
||||||
|
protected loading = false;
|
||||||
|
|
||||||
|
constructor(public dialogRef: DialogRef) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback that is called after a successful import.
|
||||||
|
*/
|
||||||
|
protected async onSuccessfulImport(organizationId: string): Promise<void> {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
}
|
@ -1662,6 +1662,9 @@
|
|||||||
"personalOwnershipPolicyInEffect": {
|
"personalOwnershipPolicyInEffect": {
|
||||||
"message": "An organization policy is affecting your ownership options."
|
"message": "An organization policy is affecting your ownership options."
|
||||||
},
|
},
|
||||||
|
"personalOwnershipPolicyInEffectImports": {
|
||||||
|
"message": "An organization policy has blocked importing items into your individual vault."
|
||||||
|
},
|
||||||
"allSends": {
|
"allSends": {
|
||||||
"message": "All Sends",
|
"message": "All Sends",
|
||||||
"description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
"description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||||
@ -2427,5 +2430,113 @@
|
|||||||
},
|
},
|
||||||
"aliasDomain": {
|
"aliasDomain": {
|
||||||
"message": "Alias domain"
|
"message": "Alias domain"
|
||||||
|
},
|
||||||
|
"importData": {
|
||||||
|
"message": "Import data",
|
||||||
|
"description": "Used for the desktop menu item and the header of the import dialog"
|
||||||
|
},
|
||||||
|
"importError": {
|
||||||
|
"message": "Import error"
|
||||||
|
},
|
||||||
|
"importErrorDesc": {
|
||||||
|
"message": "There was a problem with the data you tried to import. Please resolve the errors listed below in your source file and try again."
|
||||||
|
},
|
||||||
|
"resolveTheErrorsBelowAndTryAgain": {
|
||||||
|
"message": "Resolve the errors below and try again."
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"message": "Description"
|
||||||
|
},
|
||||||
|
"importSuccess": {
|
||||||
|
"message": "Data successfully imported"
|
||||||
|
},
|
||||||
|
"importSuccessNumberOfItems": {
|
||||||
|
"message": "A total of $AMOUNT$ items were imported.",
|
||||||
|
"placeholders": {
|
||||||
|
"amount": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"total": {
|
||||||
|
"message": "Total"
|
||||||
|
},
|
||||||
|
"importWarning": {
|
||||||
|
"message": "You are importing data to $ORGANIZATION$. Your data may be shared with members of this organization. Do you want to proceed?",
|
||||||
|
"placeholders": {
|
||||||
|
"organization": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "My Org Name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"importFormatError": {
|
||||||
|
"message": "Data is not formatted correctly. Please check your import file and try again."
|
||||||
|
},
|
||||||
|
"importNothingError": {
|
||||||
|
"message": "Nothing was imported."
|
||||||
|
},
|
||||||
|
"importEncKeyError": {
|
||||||
|
"message": "Error decrypting the exported file. Your encryption key does not match the encryption key used export the data."
|
||||||
|
},
|
||||||
|
"importDestination": {
|
||||||
|
"message": "Import destination"
|
||||||
|
},
|
||||||
|
"learnAboutImportOptions": {
|
||||||
|
"message": "Learn about your import options"
|
||||||
|
},
|
||||||
|
"selectImportFolder": {
|
||||||
|
"message": "Select a folder"
|
||||||
|
},
|
||||||
|
"selectImportCollection": {
|
||||||
|
"message": "Select a collection"
|
||||||
|
},
|
||||||
|
"importTargetHint": {
|
||||||
|
"message": "Select this option if you want the imported file contents moved to a $DESTINATION$",
|
||||||
|
"description": "Located as a hint under the import target. Will be appended by either folder or collection, depending if the user is importing into an individual or an organizational vault.",
|
||||||
|
"placeholders": {
|
||||||
|
"destination": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "folder or collection"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"importUnassignedItemsError": {
|
||||||
|
"message": "File contains unassigned items."
|
||||||
|
},
|
||||||
|
"selectFormat": {
|
||||||
|
"message": "Select the format of the import file"
|
||||||
|
},
|
||||||
|
"selectImportFile": {
|
||||||
|
"message": "Select the import file"
|
||||||
|
},
|
||||||
|
"chooseFile": {
|
||||||
|
"message": "Choose File"
|
||||||
|
},
|
||||||
|
"noFileChosen": {
|
||||||
|
"message": "No file chosen"
|
||||||
|
},
|
||||||
|
"orCopyPasteFileContents": {
|
||||||
|
"message": "or copy/paste the import file contents"
|
||||||
|
},
|
||||||
|
"instructionsFor": {
|
||||||
|
"message": "$NAME$ Instructions",
|
||||||
|
"description": "The title for the import tool instructions.",
|
||||||
|
"placeholders": {
|
||||||
|
"name": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "LastPass (csv)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"confirmVaultImport": {
|
||||||
|
"message": "Confirm vault import"
|
||||||
|
},
|
||||||
|
"confirmVaultImportDesc": {
|
||||||
|
"message": "This file is password-protected. Please enter the file password to import data."
|
||||||
|
},
|
||||||
|
"confirmFilePassword": {
|
||||||
|
"message": "Confirm file password"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ export class FileMenu extends FirstMenu implements IMenubarMenu {
|
|||||||
this.addNewFolder,
|
this.addNewFolder,
|
||||||
this.separator,
|
this.separator,
|
||||||
this.syncVault,
|
this.syncVault,
|
||||||
|
this.importVault,
|
||||||
this.exportVault,
|
this.exportVault,
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -123,6 +124,15 @@ export class FileMenu extends FirstMenu implements IMenubarMenu {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get importVault(): MenuItemConstructorOptions {
|
||||||
|
return {
|
||||||
|
id: "importVault",
|
||||||
|
label: this.localize("importData"),
|
||||||
|
click: () => this.sendMessage("importVault"),
|
||||||
|
enabled: !this._isLocked,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private get exportVault(): MenuItemConstructorOptions {
|
private get exportVault(): MenuItemConstructorOptions {
|
||||||
return {
|
return {
|
||||||
id: "exportVault",
|
id: "exportVault",
|
||||||
|
Loading…
Reference in New Issue
Block a user