Skip to content
This repository has been archived by the owner on Jul 23, 2022. It is now read-only.

Soft delete feature #446

Merged
merged 6 commits into from
May 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/vault/ciphers.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
</ng-container>
</div>
<div class="footer">
<button appBlurClick (click)="addCipher()" (contextmenu)="addCipherOptions()" class="block primary"
appA11yTitle="{{'addItem' | i18n}}">
<button appBlurClick (click)="addCipher()" (contextmenu)="addCipherOptions()"
class="block primary" appA11yTitle="{{'addItem' | i18n}}" [disabled]="deleted">
<i class="fa fa-plus fa-lg" aria-hidden="true"></i>
</button>
</div>
5 changes: 5 additions & 0 deletions src/app/vault/groupings.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ <h2 class="sr-only">{{'filters' | i18n}}</h2>
<i class="fa fa-fw fa-star" aria-hidden="true"></i>&nbsp;{{'favorites' | i18n}}
</a>
</li>
<li [ngClass]="{active: selectedTrash}">
<a href="#" appStopClick appBlurClick (click)="selectTrash()">
<i class="fa fa-fw fa-trash-o" aria-hidden="true"></i>&nbsp;{{'trash' | i18n}}
</a>
</li>
</ul>
<h2>{{'types' | i18n}}</h2>
<ul>
Expand Down
5 changes: 3 additions & 2 deletions src/app/vault/vault.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
<app-vault-groupings id="groupings" (onAllClicked)="clearGroupingFilters()" (onFavoritesClicked)="filterFavorites()"
(onCipherTypeClicked)="filterCipherType($event)" (onFolderClicked)="filterFolder($event.id)"
(onAddFolder)="addFolder()" (onEditFolder)="editFolder($event.id)"
(onCollectionClicked)="filterCollection($event.id)">
(onCollectionClicked)="filterCollection($event.id)" (onTrashClicked)="filterDeleted()">
</app-vault-groupings>
<app-vault-ciphers id="items" [activeCipherId]="cipherId" (onCipherClicked)="viewCipher($event)"
(onCipherRightClicked)="viewCipherMenu($event)" (onAddCipher)="addCipher($event)"
(onAddCipherOptions)="addCipherOptions()">
</app-vault-ciphers>
<app-vault-view id="details" *ngIf="cipherId && action === 'view'" [cipherId]="cipherId"
(onCloneCipher)="cloneCipher($event)" (onEditCipher)="editCipher($event)"
(onViewCipherPasswordHistory)="viewCipherPasswordHistory($event)">
(onViewCipherPasswordHistory)="viewCipherPasswordHistory($event)" (onRestoredCipher)="restoredCipher($event)"
(onDeletedCipher)="deletedCipher($event)">
</app-vault-view>
<app-vault-add-edit id="details" *ngIf="action === 'add' || action === 'edit' || action === 'clone'"
[cloneMode]="action === 'clone'"
Expand Down
50 changes: 37 additions & 13 deletions src/app/vault/vault.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export class VaultComponent implements OnInit, OnDestroy {
addOrganizationId: string = null;
addCollectionIds: string[] = null;
showingModal = false;
deleted = false;

private modal: ModalComponent = null;

Expand Down Expand Up @@ -218,7 +219,10 @@ export class VaultComponent implements OnInit, OnDestroy {
await this.addCipher();
}

if (params.favorites) {
if (params.deleted) {
this.groupingsComponent.selectedTrash = true;
await this.filterDeleted();
} else if (params.favorites) {
this.groupingsComponent.selectedFavorites = true;
await this.filterFavorites();
} else if (params.type) {
Expand Down Expand Up @@ -263,18 +267,20 @@ export class VaultComponent implements OnInit, OnDestroy {
this.viewCipher(cipher);
}),
}));
menu.append(new remote.MenuItem({
label: this.i18nService.t('edit'),
click: () => this.functionWithChangeDetection(() => {
this.editCipher(cipher);
}),
}));
menu.append(new remote.MenuItem({
label: this.i18nService.t('clone'),
click: () => this.functionWithChangeDetection(() => {
this.cloneCipher(cipher);
}),
}));
if (!cipher.isDeleted) {
menu.append(new remote.MenuItem({
label: this.i18nService.t('edit'),
click: () => this.functionWithChangeDetection(() => {
this.editCipher(cipher);
}),
}));
menu.append(new remote.MenuItem({
label: this.i18nService.t('clone'),
click: () => this.functionWithChangeDetection(() => {
this.cloneCipher(cipher);
}),
}));
}

switch (cipher.type) {
case CipherType.Login:
Expand Down Expand Up @@ -402,6 +408,13 @@ export class VaultComponent implements OnInit, OnDestroy {
await this.ciphersComponent.refresh();
}

async restoredCipher(cipher: CipherView) {
this.cipherId = null;
this.action = null;
this.go();
await this.ciphersComponent.refresh();
}

editCipherAttachments(cipher: CipherView) {
if (this.modal != null) {
this.modal.close();
Expand Down Expand Up @@ -498,6 +511,15 @@ export class VaultComponent implements OnInit, OnDestroy {
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) {
this.ciphersComponent.searchPlaceholder = this.i18nService.t('searchType');
await this.ciphersComponent.reload((c) => c.type === type);
Expand Down Expand Up @@ -630,6 +652,7 @@ export class VaultComponent implements OnInit, OnDestroy {
this.addCollectionIds = null;
this.addType = null;
this.addOrganizationId = null;
this.deleted = false;
}

private go(queryParams: any = null) {
Expand All @@ -641,6 +664,7 @@ export class VaultComponent implements OnInit, OnDestroy {
type: this.type,
folderId: this.folderId,
collectionId: this.collectionId,
deleted: this.deleted ? true : null,
};
}

Expand Down
15 changes: 13 additions & 2 deletions src/app/vault/view.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,21 @@
</div>
</div>
<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>
</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>
</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>
30 changes: 29 additions & 1 deletion src/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@
"message": "Are you sure you want to delete this item?"
},
"deletedItem": {
"message": "Deleted item"
"message": "Sent item to trash"
},
"overwritePasswordConfirmation": {
"message": "Are you sure you want to overwrite the current password?"
Expand Down Expand Up @@ -1299,6 +1299,34 @@
"message": "Lock",
"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"
},
"vaultTimeoutLogOutConfirmation": {
"message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?"
},
Expand Down