mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-27 12:36:14 +01:00
[Soft Delete] - Added trash to desktop app
This commit is contained in:
parent
93e7e9d261
commit
c2eafba442
2
jslib
2
jslib
@ -1 +1 @@
|
|||||||
Subproject commit 72e3893f8eee79f1e3678839aa194f1096c343ea
|
Subproject commit e9db844285e21525f5152e782063f04e02543553
|
@ -39,8 +39,8 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<button appBlurClick (click)="addCipher()" (contextmenu)="addCipherOptions()" class="block primary"
|
<button appBlurClick (click)="(deleted ? false : addCipher())" (contextmenu)="addCipherOptions()"
|
||||||
appA11yTitle="{{'addItem' | i18n}}">
|
class="block primary" appA11yTitle="{{'addItem' | i18n}}" [disabled]="deleted">
|
||||||
<i class="fa fa-plus fa-lg" aria-hidden="true"></i>
|
<i class="fa fa-plus fa-lg" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,6 +13,11 @@
|
|||||||
<i class="fa fa-fw fa-star" aria-hidden="true"></i> {{'favorites' | i18n}}
|
<i class="fa fa-fw fa-star" aria-hidden="true"></i> {{'favorites' | i18n}}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li [ngClass]="{active: selectedTrash}">
|
||||||
|
<a href="#" appStopClick appBlurClick (click)="selectTrash()">
|
||||||
|
<i class="fa fa-fw fa-trash-o" aria-hidden="true"></i> {{'trash' | i18n}}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>{{'types' | i18n}}</h2>
|
<h2>{{'types' | i18n}}</h2>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<app-vault-groupings id="groupings" (onAllClicked)="clearGroupingFilters()" (onFavoritesClicked)="filterFavorites()"
|
<app-vault-groupings id="groupings" (onAllClicked)="clearGroupingFilters()" (onFavoritesClicked)="filterFavorites()"
|
||||||
(onCipherTypeClicked)="filterCipherType($event)" (onFolderClicked)="filterFolder($event.id)"
|
(onCipherTypeClicked)="filterCipherType($event)" (onFolderClicked)="filterFolder($event.id)"
|
||||||
(onAddFolder)="addFolder()" (onEditFolder)="editFolder($event.id)"
|
(onAddFolder)="addFolder()" (onEditFolder)="editFolder($event.id)"
|
||||||
(onCollectionClicked)="filterCollection($event.id)">
|
(onCollectionClicked)="filterCollection($event.id)" (onTrashClicked)="filterDeleted()">
|
||||||
</app-vault-groupings>
|
</app-vault-groupings>
|
||||||
<app-vault-ciphers id="items" [activeCipherId]="cipherId" (onCipherClicked)="viewCipher($event)"
|
<app-vault-ciphers id="items" [activeCipherId]="cipherId" (onCipherClicked)="viewCipher($event)"
|
||||||
(onCipherRightClicked)="viewCipherMenu($event)" (onAddCipher)="addCipher($event)"
|
(onCipherRightClicked)="viewCipherMenu($event)" (onAddCipher)="addCipher($event)"
|
||||||
@ -10,7 +10,8 @@
|
|||||||
</app-vault-ciphers>
|
</app-vault-ciphers>
|
||||||
<app-vault-view id="details" *ngIf="cipherId && action === 'view'" [cipherId]="cipherId"
|
<app-vault-view id="details" *ngIf="cipherId && action === 'view'" [cipherId]="cipherId"
|
||||||
(onCloneCipher)="cloneCipher($event)" (onEditCipher)="editCipher($event)"
|
(onCloneCipher)="cloneCipher($event)" (onEditCipher)="editCipher($event)"
|
||||||
(onViewCipherPasswordHistory)="viewCipherPasswordHistory($event)">
|
(onViewCipherPasswordHistory)="viewCipherPasswordHistory($event)" (onRestoredCipher)="restoredCipher($event)"
|
||||||
|
(onDeletedCipher)="deletedCipher($event)">
|
||||||
</app-vault-view>
|
</app-vault-view>
|
||||||
<app-vault-add-edit id="details" *ngIf="action === 'add' || action === 'edit' || action === 'clone'"
|
<app-vault-add-edit id="details" *ngIf="action === 'add' || action === 'edit' || action === 'clone'"
|
||||||
[cloneMode]="action === 'clone'"
|
[cloneMode]="action === 'clone'"
|
||||||
|
@ -76,6 +76,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
addOrganizationId: string = null;
|
addOrganizationId: string = null;
|
||||||
addCollectionIds: string[] = null;
|
addCollectionIds: string[] = null;
|
||||||
showingModal = false;
|
showingModal = false;
|
||||||
|
deleted = false;
|
||||||
|
|
||||||
private modal: ModalComponent = null;
|
private modal: ModalComponent = null;
|
||||||
|
|
||||||
@ -218,7 +219,10 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
await this.addCipher();
|
await this.addCipher();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.favorites) {
|
if (params.deleted) {
|
||||||
|
this.groupingsComponent.selectedTrash = true;
|
||||||
|
await this.filterDeleted();
|
||||||
|
} else if (params.favorites) {
|
||||||
this.groupingsComponent.selectedFavorites = true;
|
this.groupingsComponent.selectedFavorites = true;
|
||||||
await this.filterFavorites();
|
await this.filterFavorites();
|
||||||
} else if (params.type) {
|
} else if (params.type) {
|
||||||
@ -263,18 +267,20 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.viewCipher(cipher);
|
this.viewCipher(cipher);
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
menu.append(new remote.MenuItem({
|
if (!cipher.isDeleted) {
|
||||||
label: this.i18nService.t('edit'),
|
menu.append(new remote.MenuItem({
|
||||||
click: () => this.functionWithChangeDetection(() => {
|
label: this.i18nService.t('edit'),
|
||||||
this.editCipher(cipher);
|
click: () => this.functionWithChangeDetection(() => {
|
||||||
}),
|
this.editCipher(cipher);
|
||||||
}));
|
}),
|
||||||
menu.append(new remote.MenuItem({
|
}));
|
||||||
label: this.i18nService.t('clone'),
|
menu.append(new remote.MenuItem({
|
||||||
click: () => this.functionWithChangeDetection(() => {
|
label: this.i18nService.t('clone'),
|
||||||
this.cloneCipher(cipher);
|
click: () => this.functionWithChangeDetection(() => {
|
||||||
}),
|
this.cloneCipher(cipher);
|
||||||
}));
|
}),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
switch (cipher.type) {
|
switch (cipher.type) {
|
||||||
case CipherType.Login:
|
case CipherType.Login:
|
||||||
@ -402,6 +408,13 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
await this.ciphersComponent.refresh();
|
await this.ciphersComponent.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async restoredCipher(cipher: CipherView) {
|
||||||
|
this.cipherId = null;
|
||||||
|
this.action = null;
|
||||||
|
this.go();
|
||||||
|
await this.ciphersComponent.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
editCipherAttachments(cipher: CipherView) {
|
editCipherAttachments(cipher: CipherView) {
|
||||||
if (this.modal != null) {
|
if (this.modal != null) {
|
||||||
this.modal.close();
|
this.modal.close();
|
||||||
@ -498,6 +511,15 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.go();
|
this.go();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async filterDeleted() {
|
||||||
|
this.ciphersComponent.searchPlaceholder = this.i18nService.t('searchTrash');
|
||||||
|
this.ciphersComponent.deleted = true;
|
||||||
|
await this.ciphersComponent.reload(null, true);
|
||||||
|
this.clearFilters();
|
||||||
|
this.deleted = true;
|
||||||
|
this.go();
|
||||||
|
}
|
||||||
|
|
||||||
async filterCipherType(type: CipherType) {
|
async filterCipherType(type: CipherType) {
|
||||||
this.ciphersComponent.searchPlaceholder = this.i18nService.t('searchType');
|
this.ciphersComponent.searchPlaceholder = this.i18nService.t('searchType');
|
||||||
await this.ciphersComponent.reload((c) => c.type === type);
|
await this.ciphersComponent.reload((c) => c.type === type);
|
||||||
@ -630,6 +652,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
this.addCollectionIds = null;
|
this.addCollectionIds = null;
|
||||||
this.addType = null;
|
this.addType = null;
|
||||||
this.addOrganizationId = null;
|
this.addOrganizationId = null;
|
||||||
|
this.deleted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private go(queryParams: any = null) {
|
private go(queryParams: any = null) {
|
||||||
@ -641,6 +664,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
|||||||
type: this.type,
|
type: this.type,
|
||||||
folderId: this.folderId,
|
folderId: this.folderId,
|
||||||
collectionId: this.collectionId,
|
collectionId: this.collectionId,
|
||||||
|
deleted: this.deleted ? true : null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,10 +273,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<button appBlurClick class="primary" (click)="edit()" appA11yTitle="{{'edit' | i18n}}">
|
<button appBlurClick class="primary" (click)="edit()" appA11yTitle="{{'edit' | i18n}}" *ngIf="!cipher.isDeleted">
|
||||||
<i class="fa fa-pencil fa-fw fa-lg" aria-hidden="true"></i>
|
<i class="fa fa-pencil fa-fw fa-lg" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
<button appBlurClick class="primary" *ngIf="!cipher?.organizationId" (click)="clone()" appA11yTitle="{{'clone' | i18n}}">
|
<button appBlurClick class="primary" (click)="restore()" appA11yTitle="{{'restore' | i18n}}"
|
||||||
|
*ngIf="cipher.isDeleted">
|
||||||
|
<i class="fa fa-undo fa-fw fa-lg" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
<button appBlurClick class="primary" *ngIf="!cipher?.organizationId && !cipher.isDeleted" (click)="clone()"
|
||||||
|
appA11yTitle="{{'clone' | i18n}}">
|
||||||
<i class="fa fa-clone fa-fw fa-lg" aria-hidden="true"></i>
|
<i class="fa fa-clone fa-fw fa-lg" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<div class="right">
|
||||||
|
<button appBlurClick type="button" (click)="delete()" class="danger"
|
||||||
|
appA11yTitle="{{(cipher.isDeleted ? 'permanentlyDelete' : 'delete') | i18n}}">
|
||||||
|
<i class="fa fa-trash-o fa-lg fa-fw" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1292,5 +1292,33 @@
|
|||||||
"lock": {
|
"lock": {
|
||||||
"message": "Lock",
|
"message": "Lock",
|
||||||
"description": "Verb form: to make secure or inaccesible by"
|
"description": "Verb form: to make secure or inaccesible by"
|
||||||
|
},
|
||||||
|
"trash": {
|
||||||
|
"message": "Trash",
|
||||||
|
"description": "Noun: a special folder to hold deleted items"
|
||||||
|
},
|
||||||
|
"searchTrash": {
|
||||||
|
"message": "Search trash"
|
||||||
|
},
|
||||||
|
"permanentlyDeleteItem": {
|
||||||
|
"message": "Permanently Delete Item"
|
||||||
|
},
|
||||||
|
"permanentlyDeleteItemConfirmation": {
|
||||||
|
"message": "Are you sure you want to permanently delete this item?"
|
||||||
|
},
|
||||||
|
"permanentlyDeletedItem": {
|
||||||
|
"message": "Permanently Deleted item"
|
||||||
|
},
|
||||||
|
"restoreItem": {
|
||||||
|
"message": "Restore Item"
|
||||||
|
},
|
||||||
|
"restoreItemConfirmation": {
|
||||||
|
"message": "Are you sure you want to restore this item?"
|
||||||
|
},
|
||||||
|
"restoredItem": {
|
||||||
|
"message": "Restored Item"
|
||||||
|
},
|
||||||
|
"permanentlyDelete": {
|
||||||
|
"message": "Permanently Delete"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user