mirror of
https://github.com/bitwarden/browser
synced 2026-02-12 06:23:38 +00:00
Merge branch 'main' into km/pm-27331
This commit is contained in:
2
.github/workflows/build-browser.yml
vendored
2
.github/workflows/build-browser.yml
vendored
@@ -565,7 +565,7 @@ jobs:
|
||||
uses: bitwarden/gh-actions/azure-logout@main
|
||||
|
||||
- name: Upload Sources
|
||||
uses: crowdin/github-action@60debf382ee245b21794321190ad0501db89d8c1 # v2.13.0
|
||||
uses: crowdin/github-action@b4b468cffefb50bdd99dd83e5d2eaeb63c880380 # v2.14.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
|
||||
|
||||
8
.github/workflows/build-desktop.yml
vendored
8
.github/workflows/build-desktop.yml
vendored
@@ -1007,7 +1007,7 @@ jobs:
|
||||
node-version: ${{ env._NODE_VERSION }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.14.2'
|
||||
|
||||
@@ -1247,7 +1247,7 @@ jobs:
|
||||
node-version: ${{ env._NODE_VERSION }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.14.2'
|
||||
|
||||
@@ -1522,7 +1522,7 @@ jobs:
|
||||
node-version: ${{ env._NODE_VERSION }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: '3.14.2'
|
||||
|
||||
@@ -1873,7 +1873,7 @@ jobs:
|
||||
uses: bitwarden/gh-actions/azure-logout@main
|
||||
|
||||
- name: Upload Sources
|
||||
uses: crowdin/github-action@60debf382ee245b21794321190ad0501db89d8c1 # v2.13.0
|
||||
uses: crowdin/github-action@b4b468cffefb50bdd99dd83e5d2eaeb63c880380 # v2.14.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
|
||||
|
||||
4
.github/workflows/build-web.yml
vendored
4
.github/workflows/build-web.yml
vendored
@@ -352,7 +352,7 @@ jobs:
|
||||
- name: Scan Docker image
|
||||
if: ${{ needs.setup.outputs.has_secrets == 'true' }}
|
||||
id: container-scan
|
||||
uses: anchore/scan-action@62b74fb7bb810d2c45b1865f47a77655621862a5 # v7.2.3
|
||||
uses: anchore/scan-action@0d444ed77d83ee2ba7f5ced0d90d640a1281d762 # v7.3.0
|
||||
with:
|
||||
image: ${{ steps.image-name.outputs.name }}
|
||||
fail-build: false
|
||||
@@ -408,7 +408,7 @@ jobs:
|
||||
uses: bitwarden/gh-actions/azure-logout@main
|
||||
|
||||
- name: Upload Sources
|
||||
uses: crowdin/github-action@60debf382ee245b21794321190ad0501db89d8c1 # v2.13.0
|
||||
uses: crowdin/github-action@b4b468cffefb50bdd99dd83e5d2eaeb63c880380 # v2.14.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
|
||||
|
||||
2
.github/workflows/lint-crowdin-config.yml
vendored
2
.github/workflows/lint-crowdin-config.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
uses: bitwarden/gh-actions/azure-logout@main
|
||||
|
||||
- name: Lint ${{ matrix.app.name }} config
|
||||
uses: crowdin/github-action@60debf382ee245b21794321190ad0501db89d8c1 # v2.13.0
|
||||
uses: crowdin/github-action@b4b468cffefb50bdd99dd83e5d2eaeb63c880380 # v2.14.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_PROJECT_ID: ${{ matrix.app.project_id }}
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -142,7 +142,7 @@ jobs:
|
||||
run: cargo +nightly udeps --workspace --all-features --all-targets
|
||||
|
||||
- name: Install cargo-deny
|
||||
uses: taiki-e/install-action@542cebaaed782771e619bd5609d97659d109c492 # v2.66.7
|
||||
uses: taiki-e/install-action@887bc4e03483810873d617344dd5189cd82e7b8b # v2.67.11
|
||||
with:
|
||||
tool: cargo-deny@0.18.6
|
||||
|
||||
|
||||
2
.github/workflows/publish-desktop.yml
vendored
2
.github/workflows/publish-desktop.yml
vendored
@@ -331,7 +331,7 @@ jobs:
|
||||
run: wget "https://github.com/bitwarden/clients/releases/download/${_RELEASE_TAG}/macos-build-number.json"
|
||||
|
||||
- name: Setup Ruby and Install Fastlane
|
||||
uses: ruby/setup-ruby@708024e6c902387ab41de36e1669e43b5ee7085e # v1.283.0
|
||||
uses: ruby/setup-ruby@90be1154f987f4dc0fe0dd0feedac9e473aa4ba8 # v1.286.0
|
||||
with:
|
||||
ruby-version: '3.4.7'
|
||||
bundler-cache: false
|
||||
|
||||
@@ -5966,6 +5966,9 @@
|
||||
"cardNumberLabel": {
|
||||
"message": "Card number"
|
||||
},
|
||||
"errorCannotDecrypt": {
|
||||
"message": "Error: Cannot decrypt"
|
||||
},
|
||||
"removeMasterPasswordForOrgUserKeyConnector": {
|
||||
"message": "Your organization is no longer using master passwords to log into Bitwarden. To continue, verify the organization and domain."
|
||||
},
|
||||
@@ -6127,6 +6130,10 @@
|
||||
"emailPlaceholder": {
|
||||
"message": "user@bitwarden.com , user@acme.com"
|
||||
},
|
||||
|
||||
"downloadBitwardenApps": {
|
||||
"message": "Download Bitwarden apps"
|
||||
},
|
||||
"emailProtected": {
|
||||
"message": "Email protected"
|
||||
},
|
||||
@@ -6134,4 +6141,4 @@
|
||||
"message": "Individuals will need to enter the password to view this Send",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import {
|
||||
BehaviorSubject,
|
||||
EmptyError,
|
||||
@@ -79,7 +77,7 @@ export type BrowserFido2Message = { sessionId: string } & (
|
||||
}
|
||||
| {
|
||||
type: typeof BrowserFido2MessageTypes.PickCredentialResponse;
|
||||
cipherId?: string;
|
||||
cipherId: string;
|
||||
userVerified: boolean;
|
||||
}
|
||||
| {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
BehaviorSubject,
|
||||
catchError,
|
||||
combineLatest,
|
||||
combineLatestWith,
|
||||
concatMap,
|
||||
@@ -73,9 +74,25 @@ export class BadgeService {
|
||||
map((evt) => evt.tab),
|
||||
combineLatestWith(this.stateFunctions),
|
||||
switchMap(([tab, dynamicStateFunctions]) => {
|
||||
const functions = [...Object.values(dynamicStateFunctions), defaultTabStateFunction];
|
||||
const functions = [
|
||||
...Object.entries(dynamicStateFunctions),
|
||||
["default" as string, defaultTabStateFunction] as const,
|
||||
];
|
||||
|
||||
return combineLatest(functions.map((f) => f(tab).pipe(startWith(undefined)))).pipe(
|
||||
return combineLatest(
|
||||
functions.map(([name, f]) =>
|
||||
f(tab).pipe(
|
||||
startWith(undefined),
|
||||
catchError((error: unknown) => {
|
||||
this.logService.error(
|
||||
`BadgeService: State function "${name}" threw an error`,
|
||||
error,
|
||||
);
|
||||
return of(undefined);
|
||||
}),
|
||||
),
|
||||
),
|
||||
).pipe(
|
||||
map((states) => ({
|
||||
tab,
|
||||
states: states.filter((s): s is BadgeStateSetting => s !== undefined),
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
{{ button.label | i18n }}
|
||||
</span>
|
||||
</button>
|
||||
<div *ngIf="button.showBerry" class="tw-absolute tw-top-1.5 tw-left-[calc(50%+5px)]">
|
||||
<div class="tw-bg-notification-600 tw-size-2.5 tw-rounded-full"></div>
|
||||
<div *ngIf="button.showBerry" class="tw-absolute tw-top-0 tw-left-[calc(50%+5px)]">
|
||||
<bit-berry type="status" variant="danger"></bit-berry>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { RouterModule } from "@angular/router";
|
||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||
import { BitSvg } from "@bitwarden/assets/svg";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { SvgModule, LinkModule } from "@bitwarden/components";
|
||||
import { SvgModule, LinkModule, BerryComponent } from "@bitwarden/components";
|
||||
|
||||
export type NavButton = {
|
||||
label: string;
|
||||
@@ -20,7 +20,7 @@ export type NavButton = {
|
||||
@Component({
|
||||
selector: "popup-tab-navigation",
|
||||
templateUrl: "popup-tab-navigation.component.html",
|
||||
imports: [CommonModule, LinkModule, RouterModule, JslibModule, SvgModule],
|
||||
imports: [CommonModule, LinkModule, RouterModule, JslibModule, SvgModule, BerryComponent],
|
||||
host: {
|
||||
class: "tw-block tw-size-full tw-flex tw-flex-col",
|
||||
},
|
||||
|
||||
@@ -78,13 +78,13 @@ import { ExportBrowserV2Component } from "../tools/popup/settings/export/export-
|
||||
import { ImportBrowserV2Component } from "../tools/popup/settings/import/import-browser-v2.component";
|
||||
import { SettingsV2Component } from "../tools/popup/settings/settings-v2.component";
|
||||
import { AtRiskPasswordsComponent } from "../vault/popup/components/at-risk-passwords/at-risk-passwords.component";
|
||||
import { AddEditV2Component } from "../vault/popup/components/vault-v2/add-edit/add-edit-v2.component";
|
||||
import { AssignCollections } from "../vault/popup/components/vault-v2/assign-collections/assign-collections.component";
|
||||
import { AttachmentsV2Component } from "../vault/popup/components/vault-v2/attachments/attachments-v2.component";
|
||||
import { IntroCarouselComponent } from "../vault/popup/components/vault-v2/intro-carousel/intro-carousel.component";
|
||||
import { PasswordHistoryV2Component } from "../vault/popup/components/vault-v2/vault-password-history-v2/vault-password-history-v2.component";
|
||||
import { VaultV2Component } from "../vault/popup/components/vault-v2/vault-v2.component";
|
||||
import { ViewV2Component } from "../vault/popup/components/vault-v2/view-v2/view-v2.component";
|
||||
import { AddEditComponent } from "../vault/popup/components/vault/add-edit/add-edit.component";
|
||||
import { AssignCollections } from "../vault/popup/components/vault/assign-collections/assign-collections.component";
|
||||
import { AttachmentsComponent } from "../vault/popup/components/vault/attachments/attachments.component";
|
||||
import { IntroCarouselComponent } from "../vault/popup/components/vault/intro-carousel/intro-carousel.component";
|
||||
import { PasswordHistoryComponent } from "../vault/popup/components/vault/vault-password-history/vault-password-history.component";
|
||||
import { VaultComponent } from "../vault/popup/components/vault/vault.component";
|
||||
import { ViewComponent } from "../vault/popup/components/vault/view/view.component";
|
||||
import {
|
||||
atRiskPasswordAuthGuard,
|
||||
canAccessAtRiskPasswords,
|
||||
@@ -93,13 +93,13 @@ import {
|
||||
import { clearVaultStateGuard } from "../vault/popup/guards/clear-vault-state.guard";
|
||||
import { IntroCarouselGuard } from "../vault/popup/guards/intro-carousel.guard";
|
||||
import { AdminSettingsComponent } from "../vault/popup/settings/admin-settings.component";
|
||||
import { AppearanceV2Component } from "../vault/popup/settings/appearance-v2.component";
|
||||
import { AppearanceComponent } from "../vault/popup/settings/appearance.component";
|
||||
import { ArchiveComponent } from "../vault/popup/settings/archive.component";
|
||||
import { DownloadBitwardenComponent } from "../vault/popup/settings/download-bitwarden.component";
|
||||
import { FoldersV2Component } from "../vault/popup/settings/folders-v2.component";
|
||||
import { MoreFromBitwardenPageV2Component } from "../vault/popup/settings/more-from-bitwarden-page-v2.component";
|
||||
import { FoldersComponent } from "../vault/popup/settings/folders.component";
|
||||
import { MoreFromBitwardenPageComponent } from "../vault/popup/settings/more-from-bitwarden-page.component";
|
||||
import { TrashComponent } from "../vault/popup/settings/trash.component";
|
||||
import { VaultSettingsV2Component } from "../vault/popup/settings/vault-settings-v2.component";
|
||||
import { VaultSettingsComponent } from "../vault/popup/settings/vault-settings.component";
|
||||
|
||||
import { RouteElevation } from "./app-routing.animations";
|
||||
import {
|
||||
@@ -214,7 +214,7 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: "view-cipher",
|
||||
component: ViewV2Component,
|
||||
component: ViewComponent,
|
||||
canActivate: [authGuard],
|
||||
data: {
|
||||
// Above "trash"
|
||||
@@ -223,20 +223,20 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: "cipher-password-history",
|
||||
component: PasswordHistoryV2Component,
|
||||
component: PasswordHistoryComponent,
|
||||
canActivate: [authGuard],
|
||||
data: { elevation: 4 } satisfies RouteDataProperties,
|
||||
},
|
||||
{
|
||||
path: "add-cipher",
|
||||
component: AddEditV2Component,
|
||||
component: AddEditComponent,
|
||||
canActivate: [authGuard, debounceNavigationGuard()],
|
||||
data: { elevation: 1, resetRouterCacheOnTabChange: true } satisfies RouteDataProperties,
|
||||
runGuardsAndResolvers: "always",
|
||||
},
|
||||
{
|
||||
path: "edit-cipher",
|
||||
component: AddEditV2Component,
|
||||
component: AddEditComponent,
|
||||
canActivate: [authGuard, debounceNavigationGuard()],
|
||||
data: {
|
||||
// Above "trash"
|
||||
@@ -247,7 +247,7 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: "attachments",
|
||||
component: AttachmentsV2Component,
|
||||
component: AttachmentsComponent,
|
||||
canActivate: [authGuard, filePickerPopoutGuard()],
|
||||
data: { elevation: 4 } satisfies RouteDataProperties,
|
||||
},
|
||||
@@ -301,13 +301,13 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: "vault-settings",
|
||||
component: VaultSettingsV2Component,
|
||||
component: VaultSettingsComponent,
|
||||
canActivate: [authGuard],
|
||||
data: { elevation: 1 } satisfies RouteDataProperties,
|
||||
},
|
||||
{
|
||||
path: "folders",
|
||||
component: FoldersV2Component,
|
||||
component: FoldersComponent,
|
||||
canActivate: [authGuard],
|
||||
data: { elevation: 2 } satisfies RouteDataProperties,
|
||||
},
|
||||
@@ -331,7 +331,7 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: "appearance",
|
||||
component: AppearanceV2Component,
|
||||
component: AppearanceComponent,
|
||||
canActivate: [authGuard],
|
||||
data: { elevation: 1 } satisfies RouteDataProperties,
|
||||
},
|
||||
@@ -343,7 +343,7 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: "clone-cipher",
|
||||
component: AddEditV2Component,
|
||||
component: AddEditComponent,
|
||||
canActivate: [authGuard],
|
||||
data: { elevation: 1 } satisfies RouteDataProperties,
|
||||
},
|
||||
@@ -635,7 +635,7 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: "more-from-bitwarden",
|
||||
component: MoreFromBitwardenPageV2Component,
|
||||
component: MoreFromBitwardenPageComponent,
|
||||
canActivate: [authGuard],
|
||||
data: { elevation: 2 } satisfies RouteDataProperties,
|
||||
},
|
||||
@@ -696,7 +696,7 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: "vault",
|
||||
component: VaultV2Component,
|
||||
component: VaultComponent,
|
||||
canActivate: [authGuard],
|
||||
canDeactivate: [clearVaultStateGuard],
|
||||
data: { elevation: 0 } satisfies RouteDataProperties,
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
<popup-page>
|
||||
<bit-spotlight *ngIf="!(hasPremium$ | async)" persistent>
|
||||
<span class="tw-text-xs"
|
||||
>{{ "unlockFeaturesWithPremium" | i18n }}
|
||||
<button
|
||||
bitLink
|
||||
buttonType="primary"
|
||||
class="tw-text-xs"
|
||||
type="button"
|
||||
(click)="openUpgradeDialog()"
|
||||
[title]="'upgradeNow' | i18n"
|
||||
>
|
||||
{{ "upgradeNow" | i18n }}
|
||||
</button>
|
||||
</span>
|
||||
</bit-spotlight>
|
||||
@if (!(hasPremium$ | async)) {
|
||||
<bit-spotlight persistent>
|
||||
<span class="tw-text-xs"
|
||||
>{{ "unlockFeaturesWithPremium" | i18n }}
|
||||
<button
|
||||
bitLink
|
||||
buttonType="primary"
|
||||
class="tw-text-xs"
|
||||
type="button"
|
||||
(click)="openUpgradeDialog()"
|
||||
[title]="'upgradeNow' | i18n"
|
||||
>
|
||||
{{ "upgradeNow" | i18n }}
|
||||
</button>
|
||||
</span>
|
||||
</bit-spotlight>
|
||||
}
|
||||
<popup-header slot="header" pageTitle="{{ 'settings' | i18n }}">
|
||||
<ng-container slot="end">
|
||||
<app-pop-out></app-pop-out>
|
||||
@@ -23,14 +25,14 @@
|
||||
|
||||
<bit-item-group>
|
||||
<bit-item>
|
||||
<a bit-item-content routerLink="/account-security">
|
||||
<a bit-item-content routerLink="/account-security" [truncate]="false">
|
||||
<i slot="start" class="bwi bwi-lock" aria-hidden="true"></i>
|
||||
{{ "accountSecurity" | i18n }}
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content routerLink="/autofill">
|
||||
<a bit-item-content routerLink="/autofill" [truncate]="false">
|
||||
<i slot="start" class="bwi bwi-check-circle" aria-hidden="true"></i>
|
||||
<div class="tw-flex tw-items-center tw-justify-center">
|
||||
<p class="tw-pr-2">{{ "autofill" | i18n }}</p>
|
||||
@@ -44,7 +46,7 @@
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content routerLink="/notifications">
|
||||
<a bit-item-content routerLink="/notifications" [truncate]="false">
|
||||
<i slot="start" class="bwi bwi-file-text" aria-hidden="true"></i>
|
||||
{{ "notifications" | i18n }}
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
@@ -55,6 +57,7 @@
|
||||
bit-item-content
|
||||
routerLink="/vault-settings"
|
||||
(click)="dismissBadge(NudgeType.EmptyVaultNudge)"
|
||||
[truncate]="false"
|
||||
>
|
||||
<i slot="start" class="bwi bwi-vault" aria-hidden="true"></i>
|
||||
<div class="tw-flex tw-items-center tw-justify-center">
|
||||
@@ -63,20 +66,18 @@
|
||||
Currently can be only 1 item for notification.
|
||||
Will make this dynamic when more nudges are added
|
||||
-->
|
||||
<span
|
||||
*ngIf="showVaultBadge$ | async"
|
||||
bitBadge
|
||||
variant="notification"
|
||||
[attr.aria-label]="'nudgeBadgeAria' | i18n"
|
||||
>1</span
|
||||
>
|
||||
@if (showVaultBadge$ | async) {
|
||||
<span bitBadge variant="notification" [attr.aria-label]="'nudgeBadgeAria' | i18n"
|
||||
>1</span
|
||||
>
|
||||
}
|
||||
</div>
|
||||
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content routerLink="/appearance">
|
||||
<a bit-item-content routerLink="/appearance" [truncate]="false">
|
||||
<i slot="start" class="bwi bwi-brush" aria-hidden="true"></i>
|
||||
{{ "appearance" | i18n }}
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
@@ -85,7 +86,7 @@
|
||||
|
||||
@if (showAdminSettingsLink$ | async) {
|
||||
<bit-item>
|
||||
<a bit-item-content routerLink="/admin">
|
||||
<a bit-item-content routerLink="/admin" [truncate]="false">
|
||||
<i slot="start" class="bwi bwi-business" aria-hidden="true"></i>
|
||||
<div class="tw-flex tw-items-center tw-justify-center">
|
||||
<p class="tw-pr-2">{{ "admin" | i18n }}</p>
|
||||
@@ -101,30 +102,28 @@
|
||||
}
|
||||
|
||||
<bit-item>
|
||||
<a bit-item-content routerLink="/about">
|
||||
<a bit-item-content routerLink="/about" [truncate]="false">
|
||||
<i slot="start" class="bwi bwi-info-circle" aria-hidden="true"></i>
|
||||
{{ "about" | i18n }}
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content routerLink="/download-bitwarden">
|
||||
<a bit-item-content routerLink="/download-bitwarden" [truncate]="false">
|
||||
<i slot="start" class="bwi bwi-mobile" aria-hidden="true"></i>
|
||||
<div class="tw-flex tw-items-center">
|
||||
<p class="tw-pr-2">{{ "downloadBitwardenOnAllDevices" | i18n }}</p>
|
||||
<span
|
||||
*ngIf="showDownloadBitwardenNudge$ | async"
|
||||
bitBadge
|
||||
variant="notification"
|
||||
[attr.aria-label]="'nudgeBadgeAria' | i18n"
|
||||
>1
|
||||
</span>
|
||||
<p class="tw-pr-2">{{ "downloadBitwardenApps" | i18n }}</p>
|
||||
@if (showDownloadBitwardenNudge$ | async) {
|
||||
<span bitBadge variant="notification" [attr.aria-label]="'nudgeBadgeAria' | i18n"
|
||||
>1
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
</a>
|
||||
</bit-item>
|
||||
<bit-item>
|
||||
<a bit-item-content routerLink="/more-from-bitwarden">
|
||||
<a bit-item-content routerLink="/more-from-bitwarden" [truncate]="false">
|
||||
<i slot="start" class="bwi bwi-filter" aria-hidden="true"></i>
|
||||
{{ "moreFromBitwarden" | i18n }}
|
||||
<i slot="end" class="bwi bwi-angle-right" aria-hidden="true"></i>
|
||||
|
||||
@@ -41,24 +41,6 @@
|
||||
</button>
|
||||
|
||||
<ng-container slot="end">
|
||||
@if (isEditMode) {
|
||||
@if ((archiveFlagEnabled$ | async) && isCipherArchived) {
|
||||
<button
|
||||
type="button"
|
||||
[bitAction]="unarchive"
|
||||
bitIconButton="bwi-unarchive"
|
||||
[label]="'unarchive' | i18n"
|
||||
></button>
|
||||
}
|
||||
@if ((userCanArchive$ | async) && canCipherBeArchived) {
|
||||
<button
|
||||
type="button"
|
||||
[bitAction]="archive"
|
||||
bitIconButton="bwi-archive"
|
||||
[label]="'archiveVerb' | i18n"
|
||||
></button>
|
||||
}
|
||||
}
|
||||
@if (canDeleteCipher$ | async) {
|
||||
<button
|
||||
[bitAction]="delete"
|
||||
@@ -40,16 +40,16 @@ import BrowserPopupUtils from "../../../../../platform/browser/browser-popup-uti
|
||||
import { PopupRouterCacheService } from "../../../../../platform/popup/view-cache/popup-router-cache.service";
|
||||
import { PopupCloseWarningService } from "../../../../../popup/services/popup-close-warning.service";
|
||||
|
||||
import { AddEditV2Component } from "./add-edit-v2.component";
|
||||
import { AddEditComponent } from "./add-edit.component";
|
||||
|
||||
// 'qrcode-parser' is used by `BrowserTotpCaptureService` but is an es6 module that jest can't compile.
|
||||
// Mock the entire module here to prevent jest from throwing an error. I wasn't able to find a way to mock the
|
||||
// `BrowserTotpCaptureService` where jest would not load the file in the first place.
|
||||
jest.mock("qrcode-parser", () => {});
|
||||
|
||||
describe("AddEditV2Component", () => {
|
||||
let component: AddEditV2Component;
|
||||
let fixture: ComponentFixture<AddEditV2Component>;
|
||||
describe("AddEditComponent", () => {
|
||||
let component: AddEditComponent;
|
||||
let fixture: ComponentFixture<AddEditComponent>;
|
||||
let addEditCipherInfo$: BehaviorSubject<AddEditCipherInfo | null>;
|
||||
let cipherServiceMock: MockProxy<CipherService>;
|
||||
|
||||
@@ -85,7 +85,7 @@ describe("AddEditV2Component", () => {
|
||||
});
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AddEditV2Component],
|
||||
imports: [AddEditComponent],
|
||||
providers: [
|
||||
provideNoopAnimations(),
|
||||
{ provide: PlatformUtilsService, useValue: mock<PlatformUtilsService>() },
|
||||
@@ -143,7 +143,7 @@ describe("AddEditV2Component", () => {
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(AddEditV2Component);
|
||||
fixture = TestBed.createComponent(AddEditComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
@@ -443,111 +443,6 @@ describe("AddEditV2Component", () => {
|
||||
}));
|
||||
});
|
||||
|
||||
describe("archive", () => {
|
||||
it("calls archiveCipherUtilsService service to archive the cipher", async () => {
|
||||
buildConfigResponse.originalCipher = { id: "222-333-444-5555", edit: true } as Cipher;
|
||||
queryParams$.next({ cipherId: "222-333-444-5555" });
|
||||
|
||||
await fixture.whenStable();
|
||||
await component.archive();
|
||||
|
||||
expect(component["archiveCipherUtilsService"].archiveCipher).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ id: "222-333-444-5555" }),
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("unarchive", () => {
|
||||
it("calls archiveCipherUtilsService service to unarchive the cipher", async () => {
|
||||
buildConfigResponse.originalCipher = {
|
||||
id: "222-333-444-5555",
|
||||
archivedDate: new Date(),
|
||||
edit: true,
|
||||
} as Cipher;
|
||||
queryParams$.next({ cipherId: "222-333-444-5555" });
|
||||
|
||||
await component.unarchive();
|
||||
|
||||
expect(component["archiveCipherUtilsService"].unarchiveCipher).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ id: "222-333-444-5555" }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("archive button", () => {
|
||||
beforeEach(() => {
|
||||
// prevent form from rendering
|
||||
jest.spyOn(component as any, "loading", "get").mockReturnValue(true);
|
||||
buildConfigResponse.originalCipher = { archivedDate: undefined, edit: true } as Cipher;
|
||||
});
|
||||
|
||||
it("shows the archive button when the user can archive and the cipher can be archived", fakeAsync(() => {
|
||||
cipherArchiveService.userCanArchive$.mockReturnValue(of(true));
|
||||
queryParams$.next({ cipherId: "222-333-444-5555" });
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
const archiveBtn = fixture.debugElement.query(By.css("button[biticonbutton='bwi-archive']"));
|
||||
expect(archiveBtn).toBeTruthy();
|
||||
}));
|
||||
|
||||
it("does not show the archive button when the user cannot archive", fakeAsync(() => {
|
||||
cipherArchiveService.userCanArchive$.mockReturnValue(of(false));
|
||||
queryParams$.next({ cipherId: "222-333-444-5555" });
|
||||
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
const archiveBtn = fixture.debugElement.query(By.css("button[biticonbutton='bwi-archive']"));
|
||||
expect(archiveBtn).toBeFalsy();
|
||||
}));
|
||||
|
||||
it("does not show the archive button when the cipher cannot be archived", fakeAsync(() => {
|
||||
cipherArchiveService.userCanArchive$.mockReturnValue(of(true));
|
||||
buildConfigResponse.originalCipher = { archivedDate: new Date(), edit: true } as Cipher;
|
||||
queryParams$.next({ cipherId: "222-333-444-5555" });
|
||||
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
const archiveBtn = fixture.debugElement.query(By.css("button[biticonbutton='bwi-archive']"));
|
||||
expect(archiveBtn).toBeFalsy();
|
||||
}));
|
||||
});
|
||||
|
||||
describe("unarchive button", () => {
|
||||
beforeEach(() => {
|
||||
// prevent form from rendering
|
||||
jest.spyOn(component as any, "loading", "get").mockReturnValue(true);
|
||||
buildConfigResponse.originalCipher = { edit: true } as Cipher;
|
||||
});
|
||||
|
||||
it("shows the unarchive button when the cipher is archived", fakeAsync(() => {
|
||||
buildConfigResponse.originalCipher = { archivedDate: new Date(), edit: true } as Cipher;
|
||||
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
const unarchiveBtn = fixture.debugElement.query(
|
||||
By.css("button[biticonbutton='bwi-unarchive']"),
|
||||
);
|
||||
expect(unarchiveBtn).toBeTruthy();
|
||||
}));
|
||||
|
||||
it("does not show the unarchive button when the cipher is not archived", fakeAsync(() => {
|
||||
queryParams$.next({ cipherId: "222-333-444-5555" });
|
||||
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
const unarchiveBtn = fixture.debugElement.query(
|
||||
By.css("button[biticonbutton='bwi-unarchive']"),
|
||||
);
|
||||
expect(unarchiveBtn).toBeFalsy();
|
||||
}));
|
||||
});
|
||||
|
||||
describe("delete", () => {
|
||||
it("dialogService openSimpleDialog called when deleteBtn is hit", async () => {
|
||||
const dialogSpy = jest
|
||||
@@ -157,8 +157,8 @@ export type AddEditQueryParams = Partial<Record<keyof QueryParams, string>>;
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "app-add-edit-v2",
|
||||
templateUrl: "add-edit-v2.component.html",
|
||||
selector: "app-add-edit",
|
||||
templateUrl: "add-edit.component.html",
|
||||
providers: [
|
||||
{ provide: CipherFormConfigService, useClass: DefaultCipherFormConfigService },
|
||||
{ provide: TotpCaptureService, useClass: BrowserTotpCaptureService },
|
||||
@@ -182,7 +182,7 @@ export type AddEditQueryParams = Partial<Record<keyof QueryParams, string>>;
|
||||
BadgeModule,
|
||||
],
|
||||
})
|
||||
export class AddEditV2Component implements OnInit, OnDestroy {
|
||||
export class AddEditComponent implements OnInit, OnDestroy {
|
||||
readonly cipherFormComponent = viewChild(CipherFormComponent);
|
||||
headerText: string;
|
||||
config: CipherFormConfig;
|
||||
@@ -201,14 +201,6 @@ export class AddEditV2Component implements OnInit, OnDestroy {
|
||||
return new CipherView(this.config?.originalCipher);
|
||||
}
|
||||
|
||||
get canCipherBeArchived(): boolean {
|
||||
return this.cipher?.canBeArchived;
|
||||
}
|
||||
|
||||
get isCipherArchived(): boolean {
|
||||
return this.cipher?.isArchived;
|
||||
}
|
||||
|
||||
private fido2PopoutSessionData$ = fido2PopoutSessionData$();
|
||||
private fido2PopoutSessionData: Fido2SessionData;
|
||||
|
||||
@@ -370,10 +362,6 @@ export class AddEditV2Component implements OnInit, OnDestroy {
|
||||
await BrowserApi.sendMessage("addEditCipherSubmitted");
|
||||
}
|
||||
|
||||
get isEditMode(): boolean {
|
||||
return ["edit", "partial-edit"].includes(this.config?.mode);
|
||||
}
|
||||
|
||||
subscribeToParams(): void {
|
||||
this.route.queryParams
|
||||
.pipe(
|
||||
@@ -487,40 +475,6 @@ export class AddEditV2Component implements OnInit, OnDestroy {
|
||||
return this.i18nService.t(translation[type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the cipher in the form after archiving/unarchiving.
|
||||
* @param revisionDate The new revision date.
|
||||
* @param archivedDate The new archived date (null if unarchived).
|
||||
**/
|
||||
updateCipherFromArchive = (revisionDate: Date, archivedDate: Date | null) => {
|
||||
this.cipherFormComponent().patchCipher((current) => {
|
||||
current.revisionDate = revisionDate;
|
||||
current.archivedDate = archivedDate;
|
||||
return current;
|
||||
});
|
||||
};
|
||||
|
||||
archive = async () => {
|
||||
const cipherResponse = await this.archiveCipherUtilsService.archiveCipher(this.cipher, true);
|
||||
|
||||
if (!cipherResponse) {
|
||||
return;
|
||||
}
|
||||
this.updateCipherFromArchive(
|
||||
new Date(cipherResponse.revisionDate),
|
||||
new Date(cipherResponse.archivedDate),
|
||||
);
|
||||
};
|
||||
|
||||
unarchive = async () => {
|
||||
const cipherResponse = await this.archiveCipherUtilsService.unarchiveCipher(this.cipher);
|
||||
|
||||
if (!cipherResponse) {
|
||||
return;
|
||||
}
|
||||
this.updateCipherFromArchive(new Date(cipherResponse.revisionDate), null);
|
||||
};
|
||||
|
||||
delete = async () => {
|
||||
const confirmed = await this.dialogService.openSimpleDialog({
|
||||
title: { key: "deleteItem" },
|
||||
@@ -23,7 +23,7 @@ import { PopupFooterComponent } from "../../../../../platform/popup/layout/popup
|
||||
import { PopupHeaderComponent } from "../../../../../platform/popup/layout/popup-header.component";
|
||||
import { PopupRouterCacheService } from "../../../../../platform/popup/view-cache/popup-router-cache.service";
|
||||
|
||||
import { AttachmentsV2Component } from "./attachments-v2.component";
|
||||
import { AttachmentsComponent } from "./attachments.component";
|
||||
|
||||
@Component({
|
||||
selector: "popup-header",
|
||||
@@ -44,9 +44,9 @@ class MockPopupFooterComponent {
|
||||
readonly pageTitle = input<string>();
|
||||
}
|
||||
|
||||
describe("AttachmentsV2Component", () => {
|
||||
let component: AttachmentsV2Component;
|
||||
let fixture: ComponentFixture<AttachmentsV2Component>;
|
||||
describe("AttachmentsComponent", () => {
|
||||
let component: AttachmentsComponent;
|
||||
let fixture: ComponentFixture<AttachmentsComponent>;
|
||||
const queryParams = new BehaviorSubject<{ cipherId: string }>({ cipherId: "5555-444-3333" });
|
||||
let cipherAttachment: CipherAttachmentsComponent;
|
||||
const navigate = jest.fn();
|
||||
@@ -60,7 +60,7 @@ describe("AttachmentsV2Component", () => {
|
||||
navigate.mockClear();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AttachmentsV2Component],
|
||||
imports: [AttachmentsComponent],
|
||||
providers: [
|
||||
{ provide: LogService, useValue: mock<LogService>() },
|
||||
{ provide: ConfigService, useValue: mock<ConfigService>() },
|
||||
@@ -83,7 +83,7 @@ describe("AttachmentsV2Component", () => {
|
||||
{ provide: OrganizationService, useValue: mock<OrganizationService>() },
|
||||
],
|
||||
})
|
||||
.overrideComponent(AttachmentsV2Component, {
|
||||
.overrideComponent(AttachmentsComponent, {
|
||||
remove: {
|
||||
imports: [PopupHeaderComponent, PopupFooterComponent],
|
||||
},
|
||||
@@ -95,7 +95,7 @@ describe("AttachmentsV2Component", () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AttachmentsV2Component);
|
||||
fixture = TestBed.createComponent(AttachmentsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -20,8 +20,8 @@ import { PopupRouterCacheService } from "../../../../../platform/popup/view-cach
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "app-attachments-v2",
|
||||
templateUrl: "./attachments-v2.component.html",
|
||||
selector: "app-attachments",
|
||||
templateUrl: "./attachments.component.html",
|
||||
imports: [
|
||||
CommonModule,
|
||||
ButtonModule,
|
||||
@@ -33,7 +33,7 @@ import { PopupRouterCacheService } from "../../../../../platform/popup/view-cach
|
||||
PopOutComponent,
|
||||
],
|
||||
})
|
||||
export class AttachmentsV2Component {
|
||||
export class AttachmentsComponent {
|
||||
/** The `id` tied to the underlying HTMLFormElement */
|
||||
attachmentFormId = CipherAttachmentsComponent.attachmentFormID;
|
||||
|
||||
@@ -35,7 +35,7 @@ import { PasswordRepromptService } from "@bitwarden/vault";
|
||||
|
||||
import { BrowserPremiumUpgradePromptService } from "../../../services/browser-premium-upgrade-prompt.service";
|
||||
import { VaultPopupAutofillService } from "../../../services/vault-popup-autofill.service";
|
||||
import { AddEditQueryParams } from "../add-edit/add-edit-v2.component";
|
||||
import { AddEditQueryParams } from "../add-edit/add-edit.component";
|
||||
import {
|
||||
AutofillConfirmationDialogComponent,
|
||||
AutofillConfirmationDialogResult,
|
||||
@@ -21,13 +21,13 @@ import { ButtonModule, DialogService, MenuModule, NoItemsModule } from "@bitward
|
||||
import { BrowserApi } from "../../../../../platform/browser/browser-api";
|
||||
import BrowserPopupUtils from "../../../../../platform/browser/browser-popup-utils";
|
||||
|
||||
import { NewItemDropdownV2Component, NewItemInitialValues } from "./new-item-dropdown-v2.component";
|
||||
import { NewItemDropdownComponent, NewItemInitialValues } from "./new-item-dropdown.component";
|
||||
|
||||
describe("NewItemDropdownV2Component", () => {
|
||||
let component: NewItemDropdownV2Component;
|
||||
let fixture: ComponentFixture<NewItemDropdownV2Component>;
|
||||
describe("NewItemDropdownComponent", () => {
|
||||
let component: NewItemDropdownComponent;
|
||||
let fixture: ComponentFixture<NewItemDropdownComponent>;
|
||||
let dialogServiceMock: jest.Mocked<DialogService>;
|
||||
let browserApiMock: jest.Mocked<typeof BrowserApi>;
|
||||
const browserApiMock: jest.Mocked<typeof BrowserApi> = mock<typeof BrowserApi>();
|
||||
let restrictedItemTypesServiceMock: jest.Mocked<RestrictedItemTypesService>;
|
||||
|
||||
const mockTab = { url: "https://example.com" };
|
||||
@@ -62,7 +62,7 @@ describe("NewItemDropdownV2Component", () => {
|
||||
ButtonModule,
|
||||
MenuModule,
|
||||
NoItemsModule,
|
||||
NewItemDropdownV2Component,
|
||||
NewItemDropdownComponent,
|
||||
],
|
||||
providers: [
|
||||
{ provide: I18nService, useValue: { t: (key: string) => key } },
|
||||
@@ -80,7 +80,7 @@ describe("NewItemDropdownV2Component", () => {
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NewItemDropdownV2Component);
|
||||
fixture = TestBed.createComponent(NewItemDropdownComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
@@ -15,7 +15,7 @@ import { AddEditFolderDialogComponent } from "@bitwarden/vault";
|
||||
|
||||
import { BrowserApi } from "../../../../../platform/browser/browser-api";
|
||||
import BrowserPopupUtils from "../../../../../platform/browser/browser-popup-utils";
|
||||
import { AddEditQueryParams } from "../add-edit/add-edit-v2.component";
|
||||
import { AddEditQueryParams } from "../add-edit/add-edit.component";
|
||||
|
||||
export interface NewItemInitialValues {
|
||||
folderId?: string;
|
||||
@@ -27,10 +27,10 @@ export interface NewItemInitialValues {
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "app-new-item-dropdown",
|
||||
templateUrl: "new-item-dropdown-v2.component.html",
|
||||
templateUrl: "new-item-dropdown.component.html",
|
||||
imports: [NoItemsModule, JslibModule, CommonModule, ButtonModule, RouterLink, MenuModule],
|
||||
})
|
||||
export class NewItemDropdownV2Component implements OnInit {
|
||||
export class NewItemDropdownComponent implements OnInit {
|
||||
cipherType = CipherType;
|
||||
private tab?: chrome.tabs.Tab;
|
||||
/**
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="tw-flex tw-gap-1 tw-items-center">
|
||||
<div class="tw-flex-1">
|
||||
<app-vault-v2-search></app-vault-v2-search>
|
||||
<app-vault-search></app-vault-search>
|
||||
</div>
|
||||
<div class="tw-relative">
|
||||
<button
|
||||
@@ -24,18 +24,18 @@ import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault
|
||||
import { PasswordRepromptService } from "@bitwarden/vault";
|
||||
|
||||
import { AutofillService } from "../../../../../autofill/services/abstractions/autofill.service";
|
||||
import { VaultPopupItemsService } from "../../../../../vault/popup/services/vault-popup-items.service";
|
||||
import { VaultPopupItemsService } from "../../../services/vault-popup-items.service";
|
||||
import {
|
||||
PopupListFilter,
|
||||
VaultPopupListFiltersService,
|
||||
} from "../../../../../vault/popup/services/vault-popup-list-filters.service";
|
||||
} from "../../../services/vault-popup-list-filters.service";
|
||||
import { VaultPopupLoadingService } from "../../../services/vault-popup-loading.service";
|
||||
|
||||
import { VaultHeaderV2Component } from "./vault-header-v2.component";
|
||||
import { VaultHeaderComponent } from "./vault-header.component";
|
||||
|
||||
describe("VaultHeaderV2Component", () => {
|
||||
let component: VaultHeaderV2Component;
|
||||
let fixture: ComponentFixture<VaultHeaderV2Component>;
|
||||
describe("VaultHeaderComponent", () => {
|
||||
let component: VaultHeaderComponent;
|
||||
let fixture: ComponentFixture<VaultHeaderComponent>;
|
||||
|
||||
const emptyForm: PopupListFilter = {
|
||||
organization: null,
|
||||
@@ -57,7 +57,7 @@ describe("VaultHeaderV2Component", () => {
|
||||
update.mockClear();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [VaultHeaderV2Component, CommonModule],
|
||||
imports: [VaultHeaderComponent, CommonModule],
|
||||
providers: [
|
||||
{
|
||||
provide: CipherService,
|
||||
@@ -112,7 +112,7 @@ describe("VaultHeaderV2Component", () => {
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(VaultHeaderV2Component);
|
||||
fixture = TestBed.createComponent(VaultHeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
@@ -13,17 +13,17 @@ import {
|
||||
} from "@bitwarden/components";
|
||||
|
||||
import { runInsideAngular } from "../../../../../platform/browser/run-inside-angular.operator";
|
||||
import { VaultPopupListFiltersService } from "../../../../../vault/popup/services/vault-popup-list-filters.service";
|
||||
import { VaultPopupListFiltersService } from "../../../services/vault-popup-list-filters.service";
|
||||
import { VaultListFiltersComponent } from "../vault-list-filters/vault-list-filters.component";
|
||||
import { VaultV2SearchComponent } from "../vault-search/vault-v2-search.component";
|
||||
import { VaultSearchComponent } from "../vault-search/vault-search.component";
|
||||
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "app-vault-header-v2",
|
||||
templateUrl: "vault-header-v2.component.html",
|
||||
selector: "app-vault-header",
|
||||
templateUrl: "vault-header.component.html",
|
||||
imports: [
|
||||
VaultV2SearchComponent,
|
||||
VaultSearchComponent,
|
||||
VaultListFiltersComponent,
|
||||
DisclosureComponent,
|
||||
IconButtonModule,
|
||||
@@ -32,7 +32,7 @@ import { VaultV2SearchComponent } from "../vault-search/vault-v2-search.componen
|
||||
JslibModule,
|
||||
],
|
||||
})
|
||||
export class VaultHeaderV2Component {
|
||||
export class VaultHeaderComponent {
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-903): Migrate to Signals
|
||||
// eslint-disable-next-line @angular-eslint/prefer-signals
|
||||
@ViewChild(DisclosureComponent) disclosure: DisclosureComponent;
|
||||
@@ -16,10 +16,10 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
|
||||
import { PopupRouterCacheService } from "../../../../../platform/popup/view-cache/popup-router-cache.service";
|
||||
|
||||
import { PasswordHistoryV2Component } from "./vault-password-history-v2.component";
|
||||
import { PasswordHistoryComponent } from "./vault-password-history.component";
|
||||
|
||||
describe("PasswordHistoryV2Component", () => {
|
||||
let fixture: ComponentFixture<PasswordHistoryV2Component>;
|
||||
describe("PasswordHistoryComponent", () => {
|
||||
let fixture: ComponentFixture<PasswordHistoryComponent>;
|
||||
const params$ = new Subject();
|
||||
const mockUserId = "acct-1" as UserId;
|
||||
|
||||
@@ -40,7 +40,7 @@ describe("PasswordHistoryV2Component", () => {
|
||||
getCipher.mockClear();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [PasswordHistoryV2Component],
|
||||
imports: [PasswordHistoryComponent],
|
||||
providers: [
|
||||
{ provide: WINDOW, useValue: window },
|
||||
{ provide: PlatformUtilsService, useValue: mock<PlatformUtilsService>() },
|
||||
@@ -56,7 +56,7 @@ describe("PasswordHistoryV2Component", () => {
|
||||
],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(PasswordHistoryV2Component);
|
||||
fixture = TestBed.createComponent(PasswordHistoryComponent);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
@@ -21,8 +21,8 @@ import { PopupRouterCacheService } from "../../../../../platform/popup/view-cach
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "vault-password-history-v2",
|
||||
templateUrl: "vault-password-history-v2.component.html",
|
||||
selector: "vault-password-history",
|
||||
templateUrl: "vault-password-history.component.html",
|
||||
imports: [
|
||||
JslibModule,
|
||||
PopupPageComponent,
|
||||
@@ -32,7 +32,7 @@ import { PopupRouterCacheService } from "../../../../../platform/popup/view-cach
|
||||
NgIf,
|
||||
],
|
||||
})
|
||||
export class PasswordHistoryV2Component implements OnInit {
|
||||
export class PasswordHistoryComponent implements OnInit {
|
||||
protected cipher: CipherView;
|
||||
|
||||
constructor(
|
||||
@@ -11,18 +11,18 @@ import { SearchModule } from "@bitwarden/components";
|
||||
import { VaultPopupItemsService } from "../../../services/vault-popup-items.service";
|
||||
import { VaultPopupLoadingService } from "../../../services/vault-popup-loading.service";
|
||||
|
||||
import { VaultV2SearchComponent } from "./vault-v2-search.component";
|
||||
import { VaultSearchComponent } from "./vault-search.component";
|
||||
|
||||
describe("VaultV2SearchComponent", () => {
|
||||
let component: VaultV2SearchComponent;
|
||||
let fixture: ComponentFixture<VaultV2SearchComponent>;
|
||||
describe("VaultSearchComponent", () => {
|
||||
let component: VaultSearchComponent;
|
||||
let fixture: ComponentFixture<VaultSearchComponent>;
|
||||
|
||||
const searchText$ = new BehaviorSubject("");
|
||||
const loading$ = new BehaviorSubject(false);
|
||||
const applyFilter = jest.fn();
|
||||
|
||||
const createComponent = () => {
|
||||
fixture = TestBed.createComponent(VaultV2SearchComponent);
|
||||
fixture = TestBed.createComponent(VaultSearchComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
};
|
||||
@@ -31,7 +31,7 @@ describe("VaultV2SearchComponent", () => {
|
||||
applyFilter.mockClear();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [VaultV2SearchComponent, CommonModule, SearchModule, JslibModule, FormsModule],
|
||||
imports: [VaultSearchComponent, CommonModule, SearchModule, JslibModule, FormsModule],
|
||||
providers: [
|
||||
{
|
||||
provide: VaultPopupItemsService,
|
||||
@@ -24,10 +24,10 @@ import { VaultPopupLoadingService } from "../../../services/vault-popup-loading.
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
imports: [CommonModule, SearchModule, JslibModule, FormsModule],
|
||||
selector: "app-vault-v2-search",
|
||||
templateUrl: "vault-v2-search.component.html",
|
||||
selector: "app-vault-search",
|
||||
templateUrl: "vault-search.component.html",
|
||||
})
|
||||
export class VaultV2SearchComponent {
|
||||
export class VaultSearchComponent {
|
||||
searchText: string = "";
|
||||
|
||||
private searchText$ = new Subject<string>();
|
||||
@@ -74,7 +74,7 @@
|
||||
</ul>
|
||||
</bit-spotlight>
|
||||
</div>
|
||||
<app-vault-header-v2></app-vault-header-v2>
|
||||
<app-vault-header></app-vault-header>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
@@ -50,10 +50,10 @@ import { AtRiskPasswordCalloutComponent } from "../at-risk-callout/at-risk-passw
|
||||
|
||||
import { AutofillVaultListItemsComponent } from "./autofill-vault-list-items/autofill-vault-list-items.component";
|
||||
import { BlockedInjectionBanner } from "./blocked-injection-banner/blocked-injection-banner.component";
|
||||
import { NewItemDropdownV2Component } from "./new-item-dropdown/new-item-dropdown-v2.component";
|
||||
import { VaultHeaderV2Component } from "./vault-header/vault-header-v2.component";
|
||||
import { NewItemDropdownComponent } from "./new-item-dropdown/new-item-dropdown.component";
|
||||
import { VaultHeaderComponent } from "./vault-header/vault-header.component";
|
||||
import { VaultListItemsContainerComponent } from "./vault-list-items-container/vault-list-items-container.component";
|
||||
import { VaultV2Component } from "./vault-v2.component";
|
||||
import { VaultComponent } from "./vault.component";
|
||||
|
||||
@Component({
|
||||
selector: "popup-header",
|
||||
@@ -66,12 +66,12 @@ export class PopupHeaderStubComponent {
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: "app-vault-header-v2",
|
||||
selector: "app-vault-header",
|
||||
standalone: true,
|
||||
template: "",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class VaultHeaderV2StubComponent {}
|
||||
export class VaultHeaderStubComponent {}
|
||||
|
||||
@Component({
|
||||
selector: "app-current-account",
|
||||
@@ -158,8 +158,8 @@ const autoConfirmDialogSpy = jest
|
||||
jest.spyOn(BrowserApi, "isPopupOpen").mockResolvedValue(false);
|
||||
jest.spyOn(BrowserPopupUtils, "openCurrentPagePopout").mockResolvedValue();
|
||||
|
||||
describe("VaultV2Component", () => {
|
||||
let component: VaultV2Component;
|
||||
describe("VaultComponent", () => {
|
||||
let component: VaultComponent;
|
||||
|
||||
interface FakeAccount {
|
||||
id: string;
|
||||
@@ -242,7 +242,7 @@ describe("VaultV2Component", () => {
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [VaultV2Component, RouterTestingModule],
|
||||
imports: [VaultComponent, RouterTestingModule],
|
||||
providers: [
|
||||
provideNoopAnimations(),
|
||||
{ provide: VaultPopupItemsService, useValue: itemsSvc },
|
||||
@@ -298,13 +298,13 @@ describe("VaultV2Component", () => {
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
}).compileComponents();
|
||||
|
||||
TestBed.overrideComponent(VaultV2Component, {
|
||||
TestBed.overrideComponent(VaultComponent, {
|
||||
remove: {
|
||||
imports: [
|
||||
PopupHeaderComponent,
|
||||
VaultHeaderV2Component,
|
||||
VaultHeaderComponent,
|
||||
CurrentAccountComponent,
|
||||
NewItemDropdownV2Component,
|
||||
NewItemDropdownComponent,
|
||||
PopOutComponent,
|
||||
BlockedInjectionBanner,
|
||||
AtRiskPasswordCalloutComponent,
|
||||
@@ -318,7 +318,7 @@ describe("VaultV2Component", () => {
|
||||
add: {
|
||||
imports: [
|
||||
PopupHeaderStubComponent,
|
||||
VaultHeaderV2StubComponent,
|
||||
VaultHeaderStubComponent,
|
||||
CurrentAccountStubComponent,
|
||||
NewItemDropdownStubComponent,
|
||||
PopOutStubComponent,
|
||||
@@ -331,7 +331,7 @@ describe("VaultV2Component", () => {
|
||||
},
|
||||
});
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
@@ -393,7 +393,7 @@ describe("VaultV2Component", () => {
|
||||
});
|
||||
|
||||
it("passes popup-page scroll region element to scroll position service", fakeAsync(() => {
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
const component = fixture.componentInstance;
|
||||
|
||||
const readySubject$ = component["readySubject"] as unknown as BehaviorSubject<boolean>;
|
||||
@@ -491,7 +491,7 @@ describe("VaultV2Component", () => {
|
||||
of(type === NudgeType.PremiumUpgrade),
|
||||
);
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
const component = fixture.componentInstance;
|
||||
|
||||
void component.ngOnInit();
|
||||
@@ -524,7 +524,7 @@ describe("VaultV2Component", () => {
|
||||
return of(type === NudgeType.EmptyVaultNudge);
|
||||
});
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
@@ -541,7 +541,7 @@ describe("VaultV2Component", () => {
|
||||
return of(type === NudgeType.HasVaultItems);
|
||||
});
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
@@ -559,7 +559,7 @@ describe("VaultV2Component", () => {
|
||||
return of(type === NudgeType.PremiumUpgrade);
|
||||
});
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
@@ -575,7 +575,7 @@ describe("VaultV2Component", () => {
|
||||
return of(type === NudgeType.PremiumUpgrade);
|
||||
});
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
@@ -591,7 +591,7 @@ describe("VaultV2Component", () => {
|
||||
return of(type === NudgeType.PremiumUpgrade);
|
||||
});
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
@@ -602,7 +602,7 @@ describe("VaultV2Component", () => {
|
||||
it("does not render app-autofill-vault-list-items or favorites item container when hasSearchText$ is true", () => {
|
||||
itemsSvc.hasSearchText$.next(true);
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
const readySubject$ = component["readySubject"];
|
||||
@@ -628,7 +628,7 @@ describe("VaultV2Component", () => {
|
||||
itemsSvc.hasSearchText$.next(false);
|
||||
loadingSvc.loading$.next(false);
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
const readySubject$ = component["readySubject"];
|
||||
@@ -655,7 +655,7 @@ describe("VaultV2Component", () => {
|
||||
filtersSvc.numberOfAppliedFilters$.next(0);
|
||||
loadingSvc.loading$.next(false);
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
const readySubject$ = component["readySubject"];
|
||||
@@ -679,7 +679,7 @@ describe("VaultV2Component", () => {
|
||||
itemsSvc.hasSearchText$.next(true);
|
||||
loadingSvc.loading$.next(false);
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
const readySubject$ = component["readySubject"];
|
||||
@@ -704,7 +704,7 @@ describe("VaultV2Component", () => {
|
||||
filtersSvc.numberOfAppliedFilters$.next(1);
|
||||
loadingSvc.loading$.next(false);
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
const readySubject$ = component["readySubject"];
|
||||
@@ -735,7 +735,7 @@ describe("VaultV2Component", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
const component = fixture.componentInstance;
|
||||
|
||||
void component.ngOnInit();
|
||||
@@ -754,7 +754,7 @@ describe("VaultV2Component", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
const component = fixture.componentInstance;
|
||||
|
||||
void component.ngOnInit();
|
||||
@@ -773,7 +773,7 @@ describe("VaultV2Component", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
const component = fixture.componentInstance;
|
||||
|
||||
void component.ngOnInit();
|
||||
@@ -792,7 +792,7 @@ describe("VaultV2Component", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
const fixture = TestBed.createComponent(VaultV2Component);
|
||||
const fixture = TestBed.createComponent(VaultComponent);
|
||||
const component = fixture.componentInstance;
|
||||
|
||||
void component.ngOnInit();
|
||||
@@ -71,10 +71,10 @@ import { VaultLoadingSkeletonComponent } from "../vault-loading-skeleton/vault-l
|
||||
|
||||
import { BlockedInjectionBanner } from "./blocked-injection-banner/blocked-injection-banner.component";
|
||||
import {
|
||||
NewItemDropdownV2Component,
|
||||
NewItemDropdownComponent,
|
||||
NewItemInitialValues,
|
||||
} from "./new-item-dropdown/new-item-dropdown-v2.component";
|
||||
import { VaultHeaderV2Component } from "./vault-header/vault-header-v2.component";
|
||||
} from "./new-item-dropdown/new-item-dropdown.component";
|
||||
import { VaultHeaderComponent } from "./vault-header/vault-header.component";
|
||||
|
||||
import { AutofillVaultListItemsComponent, VaultListItemsContainerComponent } from ".";
|
||||
|
||||
@@ -90,7 +90,7 @@ type VaultState = UnionOfValues<typeof VaultState>;
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "app-vault",
|
||||
templateUrl: "vault-v2.component.html",
|
||||
templateUrl: "vault.component.html",
|
||||
imports: [
|
||||
BlockedInjectionBanner,
|
||||
PopupPageComponent,
|
||||
@@ -103,9 +103,9 @@ type VaultState = UnionOfValues<typeof VaultState>;
|
||||
AutofillVaultListItemsComponent,
|
||||
VaultListItemsContainerComponent,
|
||||
ButtonModule,
|
||||
NewItemDropdownV2Component,
|
||||
NewItemDropdownComponent,
|
||||
ScrollingModule,
|
||||
VaultHeaderV2Component,
|
||||
VaultHeaderComponent,
|
||||
AtRiskPasswordCalloutComponent,
|
||||
SpotlightComponent,
|
||||
RouterModule,
|
||||
@@ -116,7 +116,7 @@ type VaultState = UnionOfValues<typeof VaultState>;
|
||||
],
|
||||
providers: [{ provide: VaultItemsTransferService, useClass: DefaultVaultItemsTransferService }],
|
||||
})
|
||||
export class VaultV2Component implements OnInit, OnDestroy {
|
||||
export class VaultComponent implements OnInit, OnDestroy {
|
||||
NudgeType = NudgeType;
|
||||
cipherType = CipherType;
|
||||
private activeUserId$ = this.accountService.activeAccount$.pipe(getUserId);
|
||||
@@ -45,19 +45,19 @@ import {
|
||||
import { BrowserApi } from "../../../../../platform/browser/browser-api";
|
||||
import BrowserPopupUtils from "../../../../../platform/browser/browser-popup-utils";
|
||||
import { PopupRouterCacheService } from "../../../../../platform/popup/view-cache/popup-router-cache.service";
|
||||
import { VaultPopupAutofillService } from "../../../services/vault-popup-autofill.service";
|
||||
import { VaultPopupScrollPositionService } from "../../../services/vault-popup-scroll-position.service";
|
||||
|
||||
import { VaultPopupAutofillService } from "./../../../services/vault-popup-autofill.service";
|
||||
import { ViewV2Component } from "./view-v2.component";
|
||||
import { ViewComponent } from "./view.component";
|
||||
|
||||
// 'qrcode-parser' is used by `BrowserTotpCaptureService` but is an es6 module that jest can't compile.
|
||||
// Mock the entire module here to prevent jest from throwing an error. I wasn't able to find a way to mock the
|
||||
// `BrowserTotpCaptureService` where jest would not load the file in the first place.
|
||||
jest.mock("qrcode-parser", () => {});
|
||||
|
||||
describe("ViewV2Component", () => {
|
||||
let component: ViewV2Component;
|
||||
let fixture: ComponentFixture<ViewV2Component>;
|
||||
describe("ViewComponent", () => {
|
||||
let component: ViewComponent;
|
||||
let fixture: ComponentFixture<ViewComponent>;
|
||||
const params$ = new Subject();
|
||||
const mockNavigate = jest.fn();
|
||||
const collect = jest.fn().mockResolvedValue(null);
|
||||
@@ -124,7 +124,7 @@ describe("ViewV2Component", () => {
|
||||
cipherArchiveService.unarchiveWithServer.mockResolvedValue({ id: "122-333-444" } as CipherData);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ViewV2Component],
|
||||
imports: [ViewComponent],
|
||||
providers: [
|
||||
{ provide: Router, useValue: { navigate: mockNavigate } },
|
||||
{ provide: CipherService, useValue: mockCipherService },
|
||||
@@ -231,7 +231,7 @@ describe("ViewV2Component", () => {
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ViewV2Component);
|
||||
fixture = TestBed.createComponent(ViewComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
(component as any).showFooter$ = of(true);
|
||||
@@ -56,17 +56,16 @@ import { sendExtensionMessage } from "../../../../../autofill/utils/index";
|
||||
import { BrowserApi } from "../../../../../platform/browser/browser-api";
|
||||
import BrowserPopupUtils from "../../../../../platform/browser/browser-popup-utils";
|
||||
import { PopOutComponent } from "../../../../../platform/popup/components/pop-out.component";
|
||||
import { PopupFooterComponent } from "../../../../../platform/popup/layout/popup-footer.component";
|
||||
import { PopupHeaderComponent } from "../../../../../platform/popup/layout/popup-header.component";
|
||||
import { PopupPageComponent } from "../../../../../platform/popup/layout/popup-page.component";
|
||||
import { PopupRouterCacheService } from "../../../../../platform/popup/view-cache/popup-router-cache.service";
|
||||
import { BrowserPremiumUpgradePromptService } from "../../../services/browser-premium-upgrade-prompt.service";
|
||||
import { BrowserViewPasswordHistoryService } from "../../../services/browser-view-password-history.service";
|
||||
import { VaultPopupAutofillService } from "../../../services/vault-popup-autofill.service";
|
||||
import { VaultPopupScrollPositionService } from "../../../services/vault-popup-scroll-position.service";
|
||||
import { closeViewVaultItemPopout, VaultPopoutType } from "../../../utils/vault-popout-window";
|
||||
import { ROUTES_AFTER_EDIT_DELETION } from "../add-edit/add-edit-v2.component";
|
||||
|
||||
import { PopupFooterComponent } from "./../../../../../platform/popup/layout/popup-footer.component";
|
||||
import { PopupHeaderComponent } from "./../../../../../platform/popup/layout/popup-header.component";
|
||||
import { PopupPageComponent } from "./../../../../../platform/popup/layout/popup-page.component";
|
||||
import { VaultPopupAutofillService } from "./../../../services/vault-popup-autofill.service";
|
||||
import { ROUTES_AFTER_EDIT_DELETION } from "../add-edit/add-edit.component";
|
||||
|
||||
/**
|
||||
* The types of actions that can be triggered when loading the view vault item popout via the
|
||||
@@ -83,8 +82,8 @@ type LoadAction =
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
selector: "app-view-v2",
|
||||
templateUrl: "view-v2.component.html",
|
||||
selector: "app-view",
|
||||
templateUrl: "view.component.html",
|
||||
imports: [
|
||||
CommonModule,
|
||||
SearchModule,
|
||||
@@ -107,7 +106,7 @@ type LoadAction =
|
||||
{ provide: ChangeLoginPasswordService, useClass: DefaultChangeLoginPasswordService },
|
||||
],
|
||||
})
|
||||
export class ViewV2Component {
|
||||
export class ViewComponent {
|
||||
private activeUserId: UserId;
|
||||
|
||||
headerText: string;
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TestBed } from "@angular/core/testing";
|
||||
import { RouterStateSnapshot } from "@angular/router";
|
||||
|
||||
import { VaultV2Component } from "../components/vault-v2/vault-v2.component";
|
||||
import { VaultComponent } from "../components/vault/vault.component";
|
||||
import { VaultPopupItemsService } from "../services/vault-popup-items.service";
|
||||
import { VaultPopupListFiltersService } from "../services/vault-popup-list-filters.service";
|
||||
|
||||
@@ -42,7 +42,7 @@ describe("clearVaultStateGuard", () => {
|
||||
const nextState = { url } as RouterStateSnapshot;
|
||||
|
||||
const result = TestBed.runInInjectionContext(() =>
|
||||
clearVaultStateGuard({} as VaultV2Component, null, null, nextState),
|
||||
clearVaultStateGuard({} as VaultComponent, null, null, nextState),
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
@@ -56,7 +56,7 @@ describe("clearVaultStateGuard", () => {
|
||||
const nextState = { url } as RouterStateSnapshot;
|
||||
|
||||
const result = TestBed.runInInjectionContext(() =>
|
||||
clearVaultStateGuard({} as VaultV2Component, null, null, nextState),
|
||||
clearVaultStateGuard({} as VaultComponent, null, null, nextState),
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
@@ -67,7 +67,7 @@ describe("clearVaultStateGuard", () => {
|
||||
|
||||
it("should not clear vault state when not changing states", () => {
|
||||
const result = TestBed.runInInjectionContext(() =>
|
||||
clearVaultStateGuard({} as VaultV2Component, null, null, null),
|
||||
clearVaultStateGuard({} as VaultComponent, null, null, null),
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { inject } from "@angular/core";
|
||||
import { CanDeactivateFn } from "@angular/router";
|
||||
|
||||
import { VaultV2Component } from "../components/vault-v2/vault-v2.component";
|
||||
import { VaultComponent } from "../components/vault/vault.component";
|
||||
import { VaultPopupItemsService } from "../services/vault-popup-items.service";
|
||||
import { VaultPopupListFiltersService } from "../services/vault-popup-list-filters.service";
|
||||
|
||||
@@ -10,8 +10,8 @@ import { VaultPopupListFiltersService } from "../services/vault-popup-list-filte
|
||||
* This ensures the search and filter state is reset when navigating between different tabs,
|
||||
* except viewing or editing a cipher.
|
||||
*/
|
||||
export const clearVaultStateGuard: CanDeactivateFn<VaultV2Component> = (
|
||||
component: VaultV2Component,
|
||||
export const clearVaultStateGuard: CanDeactivateFn<VaultComponent> = (
|
||||
component: VaultComponent,
|
||||
currentRoute,
|
||||
currentState,
|
||||
nextState,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { firstValueFrom } from "rxjs";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { CipherFormGenerationService } from "@bitwarden/vault";
|
||||
|
||||
import { VaultGeneratorDialogComponent } from "../components/vault-v2/vault-generator-dialog/vault-generator-dialog.component";
|
||||
import { VaultGeneratorDialogComponent } from "../components/vault/vault-generator-dialog/vault-generator-dialog.component";
|
||||
|
||||
@Injectable()
|
||||
export class BrowserCipherFormGenerationService implements CipherFormGenerationService {
|
||||
|
||||
@@ -69,7 +69,7 @@ describe("VaultPopupItemsService", () => {
|
||||
const accountServiceMock = mockAccountServiceWith(userId);
|
||||
const configServiceMock = mock<ConfigService>();
|
||||
const cipherArchiveServiceMock = mock<CipherArchiveService>();
|
||||
cipherArchiveServiceMock.userCanArchive$.mockReturnValue(of(true));
|
||||
cipherArchiveServiceMock.hasArchiveFlagEnabled$ = of(true);
|
||||
|
||||
const restrictedItemTypesService = {
|
||||
restricted$: new BehaviorSubject<RestrictedCipherType[]>([]),
|
||||
|
||||
@@ -135,24 +135,23 @@ export class VaultPopupItemsService {
|
||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||
);
|
||||
|
||||
private userCanArchive$ = this.activeUserId$.pipe(
|
||||
switchMap((userId) => {
|
||||
return this.cipherArchiveService.userCanArchive$(userId);
|
||||
}),
|
||||
);
|
||||
|
||||
private _activeCipherList$: Observable<PopupCipherViewLike[]> = this._allDecryptedCiphers$.pipe(
|
||||
switchMap((ciphers) =>
|
||||
combineLatest([this.organizations$, this.decryptedCollections$, this.userCanArchive$]).pipe(
|
||||
map(([organizations, collections, canArchive]) => {
|
||||
combineLatest([
|
||||
this.organizations$,
|
||||
this.decryptedCollections$,
|
||||
this.cipherArchiveService.hasArchiveFlagEnabled$,
|
||||
]).pipe(
|
||||
map(([organizations, collections, archiveFlag]) => {
|
||||
const orgMap = Object.fromEntries(organizations.map((org) => [org.id, org]));
|
||||
const collectionMap = Object.fromEntries(collections.map((col) => [col.id, col]));
|
||||
return ciphers
|
||||
.filter(
|
||||
(c) =>
|
||||
!CipherViewLikeUtils.isDeleted(c) &&
|
||||
(!canArchive || !CipherViewLikeUtils.isArchived(c)),
|
||||
(!archiveFlag || !CipherViewLikeUtils.isArchived(c)),
|
||||
)
|
||||
|
||||
.map((cipher) => {
|
||||
(cipher as PopupCipherViewLike).collections = cipher.collectionIds?.map(
|
||||
(colId) => collectionMap[colId as CollectionId],
|
||||
|
||||
@@ -20,7 +20,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co
|
||||
import { PopupSizeService } from "../../../platform/popup/layout/popup-size.service";
|
||||
import { VaultPopupCopyButtonsService } from "../services/vault-popup-copy-buttons.service";
|
||||
|
||||
import { AppearanceV2Component } from "./appearance-v2.component";
|
||||
import { AppearanceComponent } from "./appearance.component";
|
||||
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@@ -49,9 +49,9 @@ class MockPopupPageComponent {
|
||||
@Input() loading: boolean;
|
||||
}
|
||||
|
||||
describe("AppearanceV2Component", () => {
|
||||
let component: AppearanceV2Component;
|
||||
let fixture: ComponentFixture<AppearanceV2Component>;
|
||||
describe("AppearanceComponent", () => {
|
||||
let component: AppearanceComponent;
|
||||
let fixture: ComponentFixture<AppearanceComponent>;
|
||||
|
||||
const showFavicons$ = new BehaviorSubject<boolean>(true);
|
||||
const enableBadgeCounter$ = new BehaviorSubject<boolean>(true);
|
||||
@@ -80,7 +80,7 @@ describe("AppearanceV2Component", () => {
|
||||
setEnableRoutingAnimation.mockClear();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AppearanceV2Component],
|
||||
imports: [AppearanceComponent],
|
||||
providers: [
|
||||
{ provide: ConfigService, useValue: mock<ConfigService>() },
|
||||
{ provide: PlatformUtilsService, useValue: mock<PlatformUtilsService>() },
|
||||
@@ -120,7 +120,7 @@ describe("AppearanceV2Component", () => {
|
||||
},
|
||||
],
|
||||
})
|
||||
.overrideComponent(AppearanceV2Component, {
|
||||
.overrideComponent(AppearanceComponent, {
|
||||
remove: {
|
||||
imports: [PopupHeaderComponent, PopupPageComponent],
|
||||
},
|
||||
@@ -130,7 +130,7 @@ describe("AppearanceV2Component", () => {
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(AppearanceV2Component);
|
||||
fixture = TestBed.createComponent(AppearanceComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
@@ -36,7 +36,7 @@ import { VaultPopupCopyButtonsService } from "../services/vault-popup-copy-butto
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
templateUrl: "./appearance-v2.component.html",
|
||||
templateUrl: "./appearance.component.html",
|
||||
imports: [
|
||||
CommonModule,
|
||||
JslibModule,
|
||||
@@ -52,7 +52,7 @@ import { VaultPopupCopyButtonsService } from "../services/vault-popup-copy-butto
|
||||
PermitCipherDetailsPopoverComponent,
|
||||
],
|
||||
})
|
||||
export class AppearanceV2Component implements OnInit {
|
||||
export class AppearanceComponent implements OnInit {
|
||||
private compactModeService = inject(PopupCompactModeService);
|
||||
private copyButtonsService = inject(VaultPopupCopyButtonsService);
|
||||
private popupSizeService = inject(PopupSizeService);
|
||||
@@ -42,7 +42,7 @@ import {
|
||||
import { PopOutComponent } from "../../../platform/popup/components/pop-out.component";
|
||||
import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component";
|
||||
import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.component";
|
||||
import { ROUTES_AFTER_EDIT_DELETION } from "../components/vault-v2/add-edit/add-edit-v2.component";
|
||||
import { ROUTES_AFTER_EDIT_DELETION } from "../components/vault/add-edit/add-edit.component";
|
||||
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
|
||||
@@ -19,7 +19,7 @@ import { AddEditFolderDialogComponent } from "@bitwarden/vault";
|
||||
import { PopupFooterComponent } from "../../../platform/popup/layout/popup-footer.component";
|
||||
import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component";
|
||||
|
||||
import { FoldersV2Component } from "./folders-v2.component";
|
||||
import { FoldersComponent } from "./folders.component";
|
||||
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@@ -48,9 +48,9 @@ class MockPopupFooterComponent {
|
||||
@Input() pageTitle: string = "";
|
||||
}
|
||||
|
||||
describe("FoldersV2Component", () => {
|
||||
let component: FoldersV2Component;
|
||||
let fixture: ComponentFixture<FoldersV2Component>;
|
||||
describe("FoldersComponent", () => {
|
||||
let component: FoldersComponent;
|
||||
let fixture: ComponentFixture<FoldersComponent>;
|
||||
const folderViews$ = new BehaviorSubject<FolderView[]>([]);
|
||||
const open = jest.spyOn(AddEditFolderDialogComponent, "open");
|
||||
const mockDialogService = { open: jest.fn() };
|
||||
@@ -59,7 +59,7 @@ describe("FoldersV2Component", () => {
|
||||
open.mockClear();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [FoldersV2Component],
|
||||
imports: [FoldersComponent],
|
||||
providers: [
|
||||
{ provide: PlatformUtilsService, useValue: mock<PlatformUtilsService>() },
|
||||
{ provide: ConfigService, useValue: mock<ConfigService>() },
|
||||
@@ -69,7 +69,7 @@ describe("FoldersV2Component", () => {
|
||||
{ provide: AccountService, useValue: mockAccountServiceWith("UserId" as UserId) },
|
||||
],
|
||||
})
|
||||
.overrideComponent(FoldersV2Component, {
|
||||
.overrideComponent(FoldersComponent, {
|
||||
remove: {
|
||||
imports: [PopupHeaderComponent, PopupFooterComponent],
|
||||
},
|
||||
@@ -80,7 +80,7 @@ describe("FoldersV2Component", () => {
|
||||
.overrideProvider(DialogService, { useValue: mockDialogService })
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(FoldersV2Component);
|
||||
fixture = TestBed.createComponent(FoldersComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
@@ -25,7 +25,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
templateUrl: "./folders-v2.component.html",
|
||||
templateUrl: "./folders.component.html",
|
||||
imports: [
|
||||
CommonModule,
|
||||
JslibModule,
|
||||
@@ -39,7 +39,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co
|
||||
AsyncActionsModule,
|
||||
],
|
||||
})
|
||||
export class FoldersV2Component {
|
||||
export class FoldersComponent {
|
||||
folders$: Observable<FolderView[]>;
|
||||
|
||||
NoFoldersIcon = NoFolders;
|
||||
@@ -19,7 +19,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
templateUrl: "more-from-bitwarden-page-v2.component.html",
|
||||
templateUrl: "more-from-bitwarden-page.component.html",
|
||||
imports: [
|
||||
CommonModule,
|
||||
JslibModule,
|
||||
@@ -30,7 +30,7 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co
|
||||
ItemModule,
|
||||
],
|
||||
})
|
||||
export class MoreFromBitwardenPageV2Component {
|
||||
export class MoreFromBitwardenPageComponent {
|
||||
protected familySponsorshipAvailable$: Observable<boolean>;
|
||||
protected isFreeFamilyPolicyEnabled$: Observable<boolean>;
|
||||
protected hasSingleEnterpriseOrg$: Observable<boolean>;
|
||||
@@ -19,7 +19,7 @@ import { PopOutComponent } from "../../../platform/popup/components/pop-out.comp
|
||||
import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component";
|
||||
import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.component";
|
||||
|
||||
import { VaultSettingsV2Component } from "./vault-settings-v2.component";
|
||||
import { VaultSettingsComponent } from "./vault-settings.component";
|
||||
|
||||
@Component({
|
||||
selector: "popup-header",
|
||||
@@ -47,9 +47,9 @@ class MockPopOutComponent {
|
||||
readonly show = input(true);
|
||||
}
|
||||
|
||||
describe("VaultSettingsV2Component", () => {
|
||||
let component: VaultSettingsV2Component;
|
||||
let fixture: ComponentFixture<VaultSettingsV2Component>;
|
||||
describe("VaultSettingsComponent", () => {
|
||||
let component: VaultSettingsComponent;
|
||||
let fixture: ComponentFixture<VaultSettingsComponent>;
|
||||
let router: Router;
|
||||
let mockCipherArchiveService: jest.Mocked<CipherArchiveService>;
|
||||
|
||||
@@ -90,11 +90,11 @@ describe("VaultSettingsV2Component", () => {
|
||||
mockCipherArchiveService.hasArchiveFlagEnabled$ = mockHasArchiveFlagEnabled$.asObservable();
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [VaultSettingsV2Component],
|
||||
imports: [VaultSettingsComponent],
|
||||
providers: [
|
||||
provideRouter([
|
||||
{ path: "archive", component: VaultSettingsV2Component },
|
||||
{ path: "premium", component: VaultSettingsV2Component },
|
||||
{ path: "archive", component: VaultSettingsComponent },
|
||||
{ path: "premium", component: VaultSettingsComponent },
|
||||
]),
|
||||
{ provide: SyncService, useValue: mock<SyncService>() },
|
||||
{ provide: ToastService, useValue: mock<ToastService>() },
|
||||
@@ -117,7 +117,7 @@ describe("VaultSettingsV2Component", () => {
|
||||
},
|
||||
],
|
||||
})
|
||||
.overrideComponent(VaultSettingsV2Component, {
|
||||
.overrideComponent(VaultSettingsComponent, {
|
||||
remove: {
|
||||
imports: [PopupHeaderComponent, PopupPageComponent, PopOutComponent],
|
||||
},
|
||||
@@ -127,7 +127,7 @@ describe("VaultSettingsV2Component", () => {
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(VaultSettingsV2Component);
|
||||
fixture = TestBed.createComponent(VaultSettingsComponent);
|
||||
component = fixture.componentInstance;
|
||||
router = TestBed.inject(Router);
|
||||
jest.spyOn(router, "navigate");
|
||||
@@ -23,7 +23,7 @@ import { BrowserPremiumUpgradePromptService } from "../services/browser-premium-
|
||||
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
|
||||
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
|
||||
@Component({
|
||||
templateUrl: "vault-settings-v2.component.html",
|
||||
templateUrl: "vault-settings.component.html",
|
||||
imports: [
|
||||
CommonModule,
|
||||
JslibModule,
|
||||
@@ -39,7 +39,7 @@ import { BrowserPremiumUpgradePromptService } from "../services/browser-premium-
|
||||
{ provide: PremiumUpgradePromptService, useClass: BrowserPremiumUpgradePromptService },
|
||||
],
|
||||
})
|
||||
export class VaultSettingsV2Component implements OnInit, OnDestroy {
|
||||
export class VaultSettingsComponent implements OnInit, OnDestroy {
|
||||
private readonly premiumBadgeComponent = viewChild(PremiumBadgeComponent);
|
||||
|
||||
lastSync = "--";
|
||||
@@ -83,7 +83,7 @@
|
||||
"multer": "2.0.2",
|
||||
"node-fetch": "2.7.0",
|
||||
"node-forge": "1.3.2",
|
||||
"open": "11.0.0",
|
||||
"open": "8.4.2",
|
||||
"papaparse": "5.5.3",
|
||||
"proper-lockfile": "4.1.2",
|
||||
"rxjs": "7.8.1",
|
||||
|
||||
@@ -99,9 +99,6 @@ export class ArchiveCommand {
|
||||
errorMessage: "Item is in the trash, the item must be restored before archiving.",
|
||||
};
|
||||
}
|
||||
case cipher.organizationId != null: {
|
||||
return { canArchive: false, errorMessage: "Cannot archive items in an organization." };
|
||||
}
|
||||
default:
|
||||
return { canArchive: true };
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/re
|
||||
IgnorableNamespaces="uap rescap com uap10 build"
|
||||
xmlns:build="http://schemas.microsoft.com/developer/appx/2015/build">
|
||||
<!-- use single quotes to avoid double quotes escaping in the publisher value -->
|
||||
<Identity Name="${applicationId}"
|
||||
<Identity Name="${identityName}"
|
||||
ProcessorArchitecture="${arch}"
|
||||
Publisher='${publisher}'
|
||||
Version="${version}" />
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
"customManifestPath": "./custom-appx-manifest.xml",
|
||||
"applicationId": "BitwardenBeta",
|
||||
"identityName": "8bitSolutionsLLC.BitwardenBeta",
|
||||
"publisher": "CN=Bitwarden Inc., O=Bitwarden Inc., L=Santa Barbara, S=California, C=US, SERIALNUMBER=7654941, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, OID.1.3.6.1.4.1.311.60.2.1.3=US",
|
||||
"publisher": "CN=14D52771-DE3C-4886-B8BF-825BA7690418",
|
||||
"publisherDisplayName": "Bitwarden Inc",
|
||||
"languages": [
|
||||
"en-US",
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
"customManifestPath": "./custom-appx-manifest.xml",
|
||||
"applicationId": "bitwardendesktop",
|
||||
"identityName": "8bitSolutionsLLC.bitwardendesktop",
|
||||
"publisher": "CN=Bitwarden Inc., O=Bitwarden Inc., L=Santa Barbara, S=California, C=US, SERIALNUMBER=7654941, OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.2=Delaware, OID.1.3.6.1.4.1.311.60.2.1.3=US",
|
||||
"publisher": "CN=14D52771-DE3C-4886-B8BF-825BA7690418",
|
||||
"publisherDisplayName": "Bitwarden Inc",
|
||||
"languages": [
|
||||
"en-US",
|
||||
|
||||
@@ -176,6 +176,7 @@ $translationMap = @{
|
||||
'applicationId' = $builderConfig.appx.applicationId
|
||||
'displayName' = $productName
|
||||
'executable' = "app\${productName}.exe"
|
||||
'identityName' = $builderConfig.appx.identityName
|
||||
'publisher' = $builderConfig.appx.publisher
|
||||
'publisherDisplayName' = $builderConfig.appx.publisherDisplayName
|
||||
'version' = $version
|
||||
|
||||
@@ -3,7 +3,7 @@ const child_process = require("child_process");
|
||||
|
||||
exports.default = async function (configuration) {
|
||||
const ext = configuration.path.split(".").at(-1);
|
||||
if (parseInt(process.env.ELECTRON_BUILDER_SIGN) === 1 && ["exe", "appx"].includes(ext)) {
|
||||
if (parseInt(process.env.ELECTRON_BUILDER_SIGN) === 1 && ["exe"].includes(ext)) {
|
||||
console.log(`[*] Signing file: ${configuration.path}`);
|
||||
child_process.execFileSync(
|
||||
"azuresigntool",
|
||||
|
||||
@@ -273,7 +273,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
this.loading = false;
|
||||
break;
|
||||
case "lockVault":
|
||||
await this.lockService.lock(message.userId);
|
||||
await this.lockService.lock(message.userId ?? this.activeUserId);
|
||||
break;
|
||||
case "lockAllVaults": {
|
||||
await this.lockService.lockAll();
|
||||
|
||||
@@ -4486,6 +4486,9 @@
|
||||
"sessionTimeoutSettingsAction": {
|
||||
"message": "Timeout action"
|
||||
},
|
||||
"errorCannotDecrypt": {
|
||||
"message": "Error: Cannot decrypt"
|
||||
},
|
||||
"sessionTimeoutHeader": {
|
||||
"message": "Session timeout"
|
||||
},
|
||||
|
||||
@@ -55,6 +55,11 @@ export class WindowMain {
|
||||
// Perform a hard reload of the render process by crashing it. This is suboptimal but ensures that all memory gets
|
||||
// cleared, as the process itself will be completely garbage collected.
|
||||
ipcMain.on("reload-process", async () => {
|
||||
if (isDev()) {
|
||||
this.logService.info("Process reload requested, but skipping in development mode");
|
||||
return;
|
||||
}
|
||||
|
||||
this.logService.info("Reloading render process");
|
||||
// User might have changed theme, ensure the window is updated.
|
||||
this.win.setBackgroundColor(await this.getBackgroundColor());
|
||||
|
||||
@@ -263,15 +263,12 @@ export class ItemFooterComponent implements OnInit, OnChanges {
|
||||
this.userCanArchive = userCanArchive;
|
||||
|
||||
this.showArchiveButton =
|
||||
cipherCanBeArchived &&
|
||||
userCanArchive &&
|
||||
(this.action === "view" || this.action === "edit") &&
|
||||
!this.cipher.isArchived;
|
||||
cipherCanBeArchived && userCanArchive && this.action === "view" && !this.cipher.isArchived;
|
||||
|
||||
// A user should always be able to unarchive an archived item
|
||||
this.showUnarchiveButton =
|
||||
hasArchiveFlagEnabled &&
|
||||
(this.action === "view" || this.action === "edit") &&
|
||||
this.action === "view" &&
|
||||
this.cipher.isArchived &&
|
||||
!this.cipher.isDeleted;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<bit-simple-dialog hideIcon>
|
||||
<div bitDialogContent>
|
||||
<div class="tw-flex tw-justify-center">
|
||||
<div class="tw-mt-1 tw-w-[273px]">
|
||||
<bit-progress
|
||||
[showText]="false"
|
||||
size="default"
|
||||
bgColor="primary"
|
||||
[barWidth]="progressPercentage()"
|
||||
></bit-progress>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-mt-6">
|
||||
<h3 class="tw-font-semibold">
|
||||
{{ "bulkReinviteProgressTitle" | i18n: progressCount() : allCount }}
|
||||
</h3>
|
||||
<span class="tw-text-sm">
|
||||
{{ "bulkReinviteProgressSubtitle" | i18n }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</bit-simple-dialog>
|
||||
@@ -0,0 +1,46 @@
|
||||
import { DialogConfig, DialogRef } from "@angular/cdk/dialog";
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
effect,
|
||||
Inject,
|
||||
Signal,
|
||||
} from "@angular/core";
|
||||
|
||||
import { DIALOG_DATA, DialogService } from "@bitwarden/components";
|
||||
|
||||
export interface BulkProgressDialogParams {
|
||||
progress: Signal<number>;
|
||||
allCount: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: "bulk-progress-dialog.component.html",
|
||||
selector: "member-bulk-progress-dialog",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: false,
|
||||
})
|
||||
export class BulkProgressDialogComponent {
|
||||
protected allCount: string;
|
||||
protected readonly progressCount: Signal<string>;
|
||||
protected readonly progressPercentage: Signal<number>;
|
||||
private readonly progressEffect = effect(() => {
|
||||
if (this.progressPercentage() >= 100) {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
});
|
||||
|
||||
constructor(
|
||||
public dialogRef: DialogRef,
|
||||
@Inject(DIALOG_DATA) data: BulkProgressDialogParams,
|
||||
) {
|
||||
this.progressCount = computed(() => data.progress().toLocaleString());
|
||||
this.allCount = data.allCount.toLocaleString();
|
||||
this.progressPercentage = computed(() => (data.progress() / data.allCount) * 100);
|
||||
}
|
||||
|
||||
static open(dialogService: DialogService, config: DialogConfig<BulkProgressDialogParams>) {
|
||||
return dialogService.open(BulkProgressDialogComponent, config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<bit-dialog dialogSize="large">
|
||||
@let failCount = dataSource().data.length;
|
||||
<div bitDialogTitle>
|
||||
@if (failCount > 1) {
|
||||
{{ "bulkReinviteFailuresTitle" | i18n: failCount }}
|
||||
} @else {
|
||||
{{ "bulkReinviteFailureTitle" | i18n }}
|
||||
}
|
||||
</div>
|
||||
|
||||
<div bitDialogContent>
|
||||
{{ "bulkReinviteFailureDescription" | i18n: failCount : totalCount }}
|
||||
|
||||
<a bitLink href="https://bitwarden.com/contact/" target="_blank" rel="noopener noreferrer">
|
||||
{{ "contactSupportShort" | i18n | lowercase }}
|
||||
<bit-icon name="bwi-external-link"></bit-icon>
|
||||
</a>
|
||||
|
||||
<div class="tw-max-h-[304px] tw-overflow-auto tw-mt-4">
|
||||
<bit-table [dataSource]="dataSource()">
|
||||
<ng-container header>
|
||||
<tr>
|
||||
<th bitCell bitSortable="name">{{ "name" | i18n }}</th>
|
||||
</tr>
|
||||
</ng-container>
|
||||
|
||||
<ng-template body let-rows$>
|
||||
@let rows = $any(rows$ | async);
|
||||
@for (u of rows; track u.id) {
|
||||
<tr bitRow class="tw-h-16">
|
||||
<td bitCell>
|
||||
<div class="tw-flex tw-items-center">
|
||||
<bit-avatar
|
||||
size="small"
|
||||
[text]="u | userName"
|
||||
[id]="u.userId"
|
||||
[color]="u.avatarColor"
|
||||
class="tw-mr-3"
|
||||
></bit-avatar>
|
||||
<div class="tw-flex tw-flex-col">
|
||||
<div class="tw-flex tw-flex-row tw-gap-2">
|
||||
<button type="button" bitLink>
|
||||
{{ u.name ?? u.email }}
|
||||
</button>
|
||||
</div>
|
||||
@if (u.name) {
|
||||
<div class="tw-text-sm tw-text-muted">
|
||||
{{ u.email }}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</ng-template>
|
||||
</bit-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-container bitDialogFooter>
|
||||
<button bitButton buttonType="primary" type="button" (click)="resendInvitations()">
|
||||
{{ "bulkResendInvitations" | i18n }}
|
||||
</button>
|
||||
|
||||
<button bitButton buttonType="secondary" type="button" (click)="cancel()">
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
@@ -0,0 +1,62 @@
|
||||
import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
|
||||
import { ChangeDetectionStrategy, Component, Inject, signal, WritableSignal } from "@angular/core";
|
||||
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { MembersTableDataSource } from "@bitwarden/web-vault/app/admin-console/common/people-table-data-source";
|
||||
|
||||
import { OrganizationUserView } from "../../../core";
|
||||
import {
|
||||
BulkActionResult,
|
||||
MemberActionsService,
|
||||
} from "../../services/member-actions/member-actions.service";
|
||||
|
||||
export interface BulkReinviteFailureDialogParams {
|
||||
result: BulkActionResult;
|
||||
users: OrganizationUserView[];
|
||||
organization: Organization;
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: "bulk-reinvite-failure-dialog.component.html",
|
||||
selector: "member-bulk-reinvite-failure-dialog",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: false,
|
||||
})
|
||||
export class BulkReinviteFailureDialogComponent {
|
||||
private organization: Organization;
|
||||
protected totalCount: string;
|
||||
protected readonly dataSource: WritableSignal<MembersTableDataSource>;
|
||||
|
||||
constructor(
|
||||
public dialogRef: DialogRef,
|
||||
private memberActionsService: MemberActionsService,
|
||||
@Inject(DIALOG_DATA) data: BulkReinviteFailureDialogParams,
|
||||
environmentService: EnvironmentService,
|
||||
) {
|
||||
this.organization = data.organization;
|
||||
this.totalCount = (data.users.length ?? 0).toLocaleString();
|
||||
this.dataSource = signal(new MembersTableDataSource(environmentService));
|
||||
this.dataSource().data = data.result.failed.map((failedUser) => {
|
||||
const user = data.users.find((u) => u.id === failedUser.id);
|
||||
if (user == null) {
|
||||
throw new Error("Member not found");
|
||||
}
|
||||
return user;
|
||||
});
|
||||
}
|
||||
|
||||
async resendInvitations() {
|
||||
await this.memberActionsService.bulkReinvite(this.organization, this.dataSource().data);
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
async cancel() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
static open(dialogService: DialogService, config: DialogConfig<BulkReinviteFailureDialogParams>) {
|
||||
return dialogService.open(BulkReinviteFailureDialogComponent, config);
|
||||
}
|
||||
}
|
||||
@@ -444,10 +444,7 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await this.memberActionsService.bulkReinvite(
|
||||
organization,
|
||||
filteredUsers.map((user) => user.id as UserId),
|
||||
);
|
||||
const result = await this.memberActionsService.bulkReinvite(organization, filteredUsers);
|
||||
|
||||
if (!result.successful) {
|
||||
throw new Error();
|
||||
@@ -472,7 +469,10 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
|
||||
} else {
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
message: this.i18nService.t("bulkReinviteSuccessToast", invitedCount.toString()),
|
||||
message:
|
||||
invitedCount === 1
|
||||
? this.i18nService.t("reinviteSuccessToast")
|
||||
: this.i18nService.t("bulkReinviteSentToast", invitedCount.toString()),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -113,25 +113,24 @@
|
||||
<th bitCell>{{ "policies" | i18n }}</th>
|
||||
<th bitCell class="tw-w-10">
|
||||
@if (showUserManagementControls()) {
|
||||
<th bitCell>
|
||||
<div class="tw-flex tw-flex-row tw-items-center tw-justify-end tw-gap-2">
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-download"
|
||||
size="small"
|
||||
[bitAction]="exportMembers"
|
||||
[disabled]="!firstLoaded"
|
||||
label="{{ 'export' | i18n }}"
|
||||
></button>
|
||||
<button
|
||||
[bitMenuTriggerFor]="headerMenu"
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
size="small"
|
||||
label="{{ 'options' | i18n }}"
|
||||
></button>
|
||||
</div>
|
||||
</th>
|
||||
<div class="tw-flex tw-flex-row tw-items-center tw-justify-end tw-gap-2">
|
||||
<button
|
||||
type="button"
|
||||
bitIconButton="bwi-download"
|
||||
size="small"
|
||||
[bitAction]="exportMembers"
|
||||
[disabled]="!firstLoaded"
|
||||
label="{{ 'export' | i18n }}"
|
||||
></button>
|
||||
<button
|
||||
[bitMenuTriggerFor]="headerMenu"
|
||||
type="button"
|
||||
bitIconButton="bwi-ellipsis-v"
|
||||
size="small"
|
||||
label="{{ 'options' | i18n }}"
|
||||
*ngIf="showUserManagementControls()"
|
||||
></button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<bit-menu #headerMenu>
|
||||
|
||||
@@ -519,7 +519,7 @@ describe("vNextMembersComponent", () => {
|
||||
|
||||
await component.bulkReinvite(mockOrg);
|
||||
|
||||
expect(mockMemberActionsService.bulkReinvite).toHaveBeenCalledWith(mockOrg, [invitedUser.id]);
|
||||
expect(mockMemberActionsService.bulkReinvite).toHaveBeenCalledWith(mockOrg, [invitedUser]);
|
||||
expect(mockMemberDialogManager.openBulkStatusDialog).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user