mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
[PM-4209] Enable importing on browser (#6503)
* 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 browser Create import-dialog Add routing and routing animations Settings import items no longer navigates to help page but opens import page Extend messages.json to include all the necessary messages from shared components * Fix back navigation * Renamed filenames according to export rename * Make ImportWebComponent standalone, simplify routing * Pass organizationId as Input to ImportComponent * use formLoading and formDisabled outputs * add loading and disabled state to import-browser * override popup header styles * 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 browser Create import-dialog Add routing and routing animations Settings import items no longer navigates to help page but opens import page Extend messages.json to include all the necessary messages from shared components * Fix back navigation * add loading and disabled state to import-browser * override popup header styles * Add missing message for importBlockedByPolicy callout * Implement onSuccessfulImport to navigate back to settings * fix table themes on desktop & browser * fix fileSelector button styles * update selectors to use tools prefix; remove unused selectors * rename selector * 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 * Navigate to import opens in popout when navigated from the popup Make import call async and await router navigate - If the user has the popup open and selects import, it will navigate to the import page and popout into a new window. This is necessary as any focus-loss (i.e Choose file) would close the popup. - If the user is using the for example the sidebar or an already popped out window, just navigate to import page * Use SharedModule as import in import-web.component * File selector should be displayed as secondary * Update description of "importData" in messages.json * 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> * 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
cdcd1809f0
commit
87dbe8997d
@ -1656,6 +1656,9 @@
|
||||
"personalOwnershipPolicyInEffect": {
|
||||
"message": "An organization policy is affecting your ownership options."
|
||||
},
|
||||
"personalOwnershipPolicyInEffectImports": {
|
||||
"message": "An organization policy has blocked importing items into your individual vault."
|
||||
},
|
||||
"excludedDomains": {
|
||||
"message": "Excluded domains"
|
||||
},
|
||||
@ -2449,6 +2452,114 @@
|
||||
"message": "Turn off master password re-prompt to edit this field",
|
||||
"description": "Message appearing below the autofill on load message when master password reprompt is set for a vault item."
|
||||
},
|
||||
"importData": {
|
||||
"message": "Import data",
|
||||
"description": "Used for the header of the import dialog, the import button and within the file-password-prompt"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"passkeyNotCopied": {
|
||||
"message": "Passkey will not be copied"
|
||||
},
|
||||
|
@ -174,6 +174,9 @@ export const routerTransition = trigger("routerTransition", [
|
||||
transition("clone-cipher => attachments, clone-cipher => collections", inSlideLeft),
|
||||
transition("attachments => clone-cipher, collections => clone-cipher", outSlideRight),
|
||||
|
||||
transition("tabs => import", inSlideLeft),
|
||||
transition("import => tabs", outSlideRight),
|
||||
|
||||
transition("tabs => export", inSlideLeft),
|
||||
transition("export => tabs", outSlideRight),
|
||||
|
||||
|
@ -32,6 +32,7 @@ import { SendAddEditComponent } from "../tools/popup/send/send-add-edit.componen
|
||||
import { SendGroupingsComponent } from "../tools/popup/send/send-groupings.component";
|
||||
import { SendTypeComponent } from "../tools/popup/send/send-type.component";
|
||||
import { ExportComponent } from "../tools/popup/settings/export.component";
|
||||
import { ImportBrowserComponent } from "../tools/popup/settings/import/import-browser.component";
|
||||
import { Fido2Component } from "../vault/popup/components/fido2/fido2.component";
|
||||
import { AddEditComponent } from "../vault/popup/components/vault/add-edit.component";
|
||||
import { AttachmentsComponent } from "../vault/popup/components/vault/attachments.component";
|
||||
@ -222,6 +223,12 @@ const routes: Routes = [
|
||||
canActivate: [AuthGuard],
|
||||
data: { state: "generator-history" },
|
||||
},
|
||||
{
|
||||
path: "import",
|
||||
component: ImportBrowserComponent,
|
||||
canActivate: [AuthGuard],
|
||||
data: { state: "import" },
|
||||
},
|
||||
{
|
||||
path: "export",
|
||||
component: ExportComponent,
|
||||
|
@ -175,7 +175,7 @@ cdk-virtual-scroll-viewport::-webkit-scrollbar-thumb,
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
header:not(bit-callout header) {
|
||||
min-height: 44px;
|
||||
max-height: 44px;
|
||||
display: flex;
|
||||
|
@ -473,8 +473,11 @@ export class SettingsComponent implements OnInit {
|
||||
BrowserApi.createNewTab(url);
|
||||
}
|
||||
|
||||
import() {
|
||||
BrowserApi.createNewTab("https://bitwarden.com/help/import-data/");
|
||||
async import() {
|
||||
await this.router.navigate(["/import"]);
|
||||
if (await BrowserApi.isPopupOpen()) {
|
||||
this.popupUtilsService.popOut(window);
|
||||
}
|
||||
}
|
||||
|
||||
export() {
|
||||
|
@ -0,0 +1,24 @@
|
||||
<header>
|
||||
<div class="left">
|
||||
<button type="button" routerLink="/tabs/settings">
|
||||
<span class="header-icon" aria-hidden="true"><i class="bwi bwi-angle-left"></i></span>
|
||||
<span>{{ "back" | i18n }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<h1 class="center">
|
||||
<span class="title">{{ "importData" | i18n }}</span>
|
||||
</h1>
|
||||
<div class="right">
|
||||
<button form="importForm" type="submit" [disabled]="disabled">
|
||||
<span [hidden]="loading">{{ "importData" | i18n }}</span>
|
||||
<i class="bwi bwi-spinner bwi-lg bwi-spin" [hidden]="!loading" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<div tabindex="-1" class="tw-p-4">
|
||||
<tools-import
|
||||
(formDisabled)="this.disabled = $event"
|
||||
(formLoading)="this.loading = $event"
|
||||
(onSuccessfulImport)="this.onSuccessfulImport($event)"
|
||||
></tools-import>
|
||||
</div>
|
@ -0,0 +1,31 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { Component } from "@angular/core";
|
||||
import { Router, RouterLink } from "@angular/router";
|
||||
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { AsyncActionsModule, ButtonModule, DialogModule } from "@bitwarden/components";
|
||||
import { ImportComponent } from "@bitwarden/importer/ui";
|
||||
|
||||
@Component({
|
||||
templateUrl: "import-browser.component.html",
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterLink,
|
||||
JslibModule,
|
||||
DialogModule,
|
||||
AsyncActionsModule,
|
||||
ButtonModule,
|
||||
ImportComponent,
|
||||
],
|
||||
})
|
||||
export class ImportBrowserComponent {
|
||||
protected disabled = false;
|
||||
protected loading = false;
|
||||
|
||||
constructor(private router: Router) {}
|
||||
|
||||
protected async onSuccessfulImport(organizationId: string): Promise<void> {
|
||||
this.router.navigate(["/tabs/settings"]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user