1
0
mirror of https://github.com/bitwarden/browser synced 2026-03-02 11:31:44 +00:00

fix conflicts

This commit is contained in:
Brad Deibert
2026-01-21 10:03:46 -08:00
34 changed files with 595 additions and 330 deletions

View File

@@ -35,89 +35,80 @@
}
</bit-toggle-group>
}
<bit-table [dataSource]="dataSource">
<bit-table-scroll [dataSource]="dataSource" [rowSize]="75">
@if (!isAdminConsoleActive) {
<ng-container header>
<tr bitRow>
<th bitCell></th>
<th bitCell>{{ "name" | i18n }}</th>
<th bitCell>{{ "owner" | i18n }}</th>
<th bitCell></th>
</tr>
<th bitCell></th>
<th bitCell>{{ "name" | i18n }}</th>
<th bitCell>{{ "owner" | i18n }}</th>
<th bitCell></th>
</ng-container>
}
<tbody>
<ng-template body let-rows$>
<!-- prettier-ignore -->
@for (r of (rows$ | async); track r) {
<tr bitRow>
<td bitCell>
<app-vault-icon [cipher]="r"></app-vault-icon>
</td>
<td bitCell>
@if (!organization || canManageCipher(r)) {
<a
bitLink
href="#"
appStopClick
(click)="selectCipher(r)"
title="{{ 'editItemWithName' | i18n: r.name }}"
>{{ r.name }}</a
>
} @else {
<span>{{ r.name }}</span>
}
@if (!organization && r.organizationId) {
<i
class="bwi bwi-collection-shared tw-ml-1"
appStopProp
title="{{ 'shared' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "shared" | i18n }}</span>
}
@if (r.hasAttachments) {
<i
class="bwi bwi-paperclip tw-ml-1"
appStopProp
title="{{ 'attachments' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "attachments" | i18n }}</span>
}
<br />
<small>{{ r.subTitle }}</small>
</td>
<td bitCell>
@if (!organization) {
<app-org-badge
[disabled]="disabled"
[organizationId]="r.organizationId"
[organizationName]="
r.organizationId | orgNameFromId: (organizations$ | async)
"
appStopProp
>
</app-org-badge>
}
</td>
<td bitCell class="tw-text-right">
@if (cipherDocs.has(r.id)) {
<a
bitBadge
href="{{ cipherDocs.get(r.id) }}"
target="_blank"
rel="noreferrer"
>
{{ "instructions" | i18n }}</a
>
}
</td>
</tr>
<ng-template bitRowDef let-row>
<td bitCell>
<app-vault-icon [cipher]="row"></app-vault-icon>
</td>
<td bitCell>
@if (!organization || canManageCipher(row)) {
<ng-container>
<a
bitLink
href="#"
appStopClick
(click)="selectCipher(row)"
title="{{ 'editItemWithName' | i18n: row.name }}"
>{{ row.name }}</a
>
</ng-container>
} @else {
<ng-template>
<span>{{ row.name }}</span>
</ng-template>
}
</ng-template>
</tbody></bit-table
>
@if (!organization && row.organizationId) {
<ng-container>
<i
class="bwi bwi-collection-shared tw-ml-1"
appStopProp
title="{{ 'shared' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "shared" | i18n }}</span>
</ng-container>
}
@if (row.hasAttachments) {
<ng-container>
<i
class="bwi bwi-paperclip tw-ml-1"
appStopProp
title="{{ 'attachments' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "attachments" | i18n }}</span>
</ng-container>
}
<br />
<small>{{ row.subTitle }}</small>
</td>
<td bitCell>
@if (!organization) {
<app-org-badge
[disabled]="disabled"
[organizationId]="row.organizationId"
[organizationName]="row.organizationId | orgNameFromId: (organizations$ | async)"
appStopProp
/>
}
</td>
<td bitCell class="tw-text-right">
@if (cipherDocs.has(row.id)) {
<a bitBadge href="{{ cipherDocs.get(row.id) }}" target="_blank" rel="noreferrer">
{{ "instructions" | i18n }}</a
>
}
</td>
</ng-template>
</bit-table-scroll>
}
</div>
}

View File

@@ -35,75 +35,65 @@
}
</bit-toggle-group>
}
<bit-table [dataSource]="dataSource">
<bit-table-scroll [dataSource]="dataSource" [rowSize]="75">
@if (!isAdminConsoleActive) {
<ng-container header>
<tr bitRow>
<th bitCell></th>
<th bitCell>{{ "name" | i18n }}</th>
<th bitCell>{{ "owner" | i18n }}</th>
<th bitCell></th>
</tr>
<th bitCell></th>
<th bitCell>{{ "name" | i18n }}</th>
<th bitCell>{{ "owner" | i18n }}</th>
</ng-container>
}
<ng-template body let-rows$>
<!-- prettier-ignore -->
@for (r of (rows$ | async); track r) {
<tr bitRow>
<td bitCell>
<app-vault-icon [cipher]="r"></app-vault-icon>
</td>
<td bitCell>
@if (!organization || canManageCipher(r)) {
<a
bitLink
href="#"
appStopClick
(click)="selectCipher(r)"
title="{{ 'editItemWithName' | i18n: r.name }}"
>{{ r.name }}</a
>
} @else {
<span>{{ r.name }}</span>
}
@if (!organization && r.organizationId) {
<i
class="bwi bwi-collection-shared tw-ml-1"
appStopProp
title="{{ 'shared' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "shared" | i18n }}</span>
}
@if (r.hasAttachments) {
<i
class="bwi bwi-paperclip tw-ml-1"
appStopProp
title="{{ 'attachments' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "attachments" | i18n }}</span>
}
<br />
<small>{{ r.subTitle }}</small>
</td>
<td bitCell>
@if (!organization) {
<app-org-badge
[disabled]="disabled"
[organizationId]="r.organizationId"
[organizationName]="
r.organizationId | orgNameFromId: (organizations$ | async)
"
appStopProp
>
</app-org-badge>
}
</td>
</tr>
}
<ng-template bitRowDef let-row>
<td bitCell>
<app-vault-icon [cipher]="row"></app-vault-icon>
</td>
<td bitCell>
@if (!organization || canManageCipher(row)) {
<a
bitLink
href="#"
appStopClick
(click)="selectCipher(row)"
title="{{ 'editItemWithName' | i18n: row.name }}"
>{{ row.name }}</a
>
} @else {
<span>{{ row.name }}</span>
}
@if (!organization && row.organizationId) {
<i
class="bwi bwi-collection-shared tw-ml-1"
appStopProp
title="{{ 'shared' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "shared" | i18n }}</span>
}
@if (row.hasAttachments) {
<i
class="bwi bwi-paperclip tw-ml-1"
appStopProp
title="{{ 'attachments' | i18n }}"
aria-hidden="true"
></i>
<span class="tw-sr-only">{{ "attachments" | i18n }}</span>
}
<br />
<small>{{ row.subTitle }}</small>
</td>
<td bitCell>
@if (!organization) {
<app-org-badge
[disabled]="disabled"
[organizationId]="row.organizationId"
[organizationName]="row.organizationId | orgNameFromId: (organizations$ | async)"
appStopProp
>
</app-org-badge>
}
</td>
</ng-template>
</bit-table>
</bit-table-scroll>
}
</div>
}

View File

@@ -1,6 +1,6 @@
import { Component, OnDestroy } from "@angular/core";
import { Component } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { NavigationEnd, Router } from "@angular/router";
import { Subscription } from "rxjs";
import { filter } from "rxjs/operators";
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
@@ -10,20 +10,20 @@ import { filter } from "rxjs/operators";
templateUrl: "reports-layout.component.html",
standalone: false,
})
export class ReportsLayoutComponent implements OnDestroy {
export class ReportsLayoutComponent {
homepage = true;
subscription: Subscription;
constructor(router: Router) {
this.subscription = router.events
.pipe(filter((event) => event instanceof NavigationEnd))
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
const reportsHomeRoute = "/reports";
this.homepage = router.url === reportsHomeRoute;
router.events
.pipe(
takeUntilDestroyed(),
filter((event) => event instanceof NavigationEnd),
)
.subscribe((event) => {
this.homepage = (event as NavigationEnd).url == "/reports";
this.homepage = (event as NavigationEnd).url == reportsHomeRoute;
});
}
ngOnDestroy(): void {
this.subscription?.unsubscribe();
}
}

View File

@@ -86,7 +86,7 @@
@if (showActionButtons) {
<div class="tw-ml-auto">
@if (userCanArchive$ | async) {
@if ((userCanArchive$ | async) && !params.isAdminConsoleAction) {
@if (isCipherArchived) {
<button
type="button"

View File

@@ -249,6 +249,15 @@ describe("VaultItemDialogComponent", () => {
});
describe("archive button", () => {
it("should not show archive button in admin console", () => {
(component as any).userCanArchive$ = of(true);
component.setTestCipher({ canBeArchived: true });
component.setTestParams({ mode: "form", isAdminConsoleAction: true });
fixture.detectChanges();
const archiveButton = fixture.debugElement.query(By.css("[biticonbutton='bwi-archive']"));
expect(archiveButton).toBeFalsy();
});
it("should show archive button when the user can archive the item and the item can be archived", () => {
component.setTestCipher({ canBeArchived: true });
(component as any).userCanArchive$ = of(true);

View File

@@ -1271,6 +1271,7 @@ export class VaultComponent<C extends CipherViewLike> implements OnInit, OnDestr
}
restore = async (c: C): Promise<boolean> => {
let toastMessage;
if (!CipherViewLikeUtils.isDeleted(c)) {
return;
}
@@ -1284,13 +1285,19 @@ export class VaultComponent<C extends CipherViewLike> implements OnInit, OnDestr
return;
}
if (CipherViewLikeUtils.isArchived(c)) {
toastMessage = this.i18nService.t("archivedItemRestored");
} else {
toastMessage = this.i18nService.t("restoredItem");
}
try {
const activeUserId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
await this.cipherService.restoreWithServer(uuidAsString(c.id), activeUserId);
this.toastService.showToast({
variant: "success",
title: null,
message: this.i18nService.t("restoredItem"),
message: toastMessage,
});
this.refresh();
} catch (e) {
@@ -1299,11 +1306,18 @@ export class VaultComponent<C extends CipherViewLike> implements OnInit, OnDestr
};
async bulkRestore(ciphers: C[]) {
let toastMessage;
if (ciphers.some((c) => !c.edit)) {
this.showMissingPermissionsError();
return;
}
if (ciphers.some((c) => !CipherViewLikeUtils.isArchived(c))) {
toastMessage = this.i18nService.t("restoredItems");
} else {
toastMessage = this.i18nService.t("archivedItemsRestored");
}
if (!(await this.repromptCipher(ciphers))) {
return;
}
@@ -1323,7 +1337,7 @@ export class VaultComponent<C extends CipherViewLike> implements OnInit, OnDestr
this.toastService.showToast({
variant: "success",
title: null,
message: this.i18nService.t("restoredItems"),
message: toastMessage,
});
this.refresh();
}

View File

@@ -5418,6 +5418,12 @@
"restoreSelected": {
"message": "Restore selected"
},
"archivedItemRestored": {
"message": "Archived item restored"
},
"archivedItemsRestored": {
"message": "Archived items restored"
},
"restoredItem": {
"message": "Item restored"
},