diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json
index 9a68f8bb9fb..24e1bc3ce30 100644
--- a/apps/browser/src/_locales/en/messages.json
+++ b/apps/browser/src/_locales/en/messages.json
@@ -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"
},
diff --git a/apps/browser/src/popup/app-routing.animations.ts b/apps/browser/src/popup/app-routing.animations.ts
index 2304944acb0..42baf65c270 100644
--- a/apps/browser/src/popup/app-routing.animations.ts
+++ b/apps/browser/src/popup/app-routing.animations.ts
@@ -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),
diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts
index 10159a715f0..df7b9ffb1cf 100644
--- a/apps/browser/src/popup/app-routing.module.ts
+++ b/apps/browser/src/popup/app-routing.module.ts
@@ -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,
diff --git a/apps/browser/src/popup/scss/base.scss b/apps/browser/src/popup/scss/base.scss
index 3b401d356f5..6cd99abb0d5 100644
--- a/apps/browser/src/popup/scss/base.scss
+++ b/apps/browser/src/popup/scss/base.scss
@@ -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;
diff --git a/apps/browser/src/popup/settings/settings.component.ts b/apps/browser/src/popup/settings/settings.component.ts
index 274ed871225..252a2097156 100644
--- a/apps/browser/src/popup/settings/settings.component.ts
+++ b/apps/browser/src/popup/settings/settings.component.ts
@@ -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() {
diff --git a/apps/browser/src/tools/popup/settings/import/import-browser.component.html b/apps/browser/src/tools/popup/settings/import/import-browser.component.html
new file mode 100644
index 00000000000..b305e6c395f
--- /dev/null
+++ b/apps/browser/src/tools/popup/settings/import/import-browser.component.html
@@ -0,0 +1,24 @@
+
+ {{ "importData" | i18n }}
+
+