view grouping of ciphers for a collection

This commit is contained in:
Kyle Spearrin 2017-11-22 21:55:48 -05:00
parent 991ddd8271
commit 2e9b3d0943
12 changed files with 79 additions and 49 deletions

View File

@ -485,6 +485,9 @@
"searchFolder": {
"message": "Search folder"
},
"searchCollection": {
"message": "Search collection"
},
"noneFolder": {
"message": "No Folder",
"description": "This is the folder for uncategorized items"

View File

@ -109,7 +109,7 @@ var bg_isBackground = true,
window.bg_cipherService = bg_cipherService = new CipherService(bg_cryptoService, bg_userService, bg_settingsService, bg_apiService);
window.bg_folderService = bg_folderService = new FolderService(bg_cryptoService, bg_userService, bg_i18nService, bg_apiService);
window.bg_collectionService = bg_collectionService = new CollectionService(bg_cryptoService, bg_userService, bg_i18nService, bg_apiService);
window.bg_lockService = bg_lockService = new LockService(bg_cipherService, bg_folderService, bg_cryptoService, bg_utilsService, setIcon, refreshBadgeAndMenu);
window.bg_lockService = bg_lockService = new LockService(bg_cipherService, bg_folderService, bg_collectionService, bg_cryptoService, bg_utilsService, setIcon, refreshBadgeAndMenu);
window.bg_syncService = bg_syncService = new SyncService(bg_userService, bg_apiService, bg_settingsService, bg_folderService, bg_cipherService, bg_cryptoService, bg_collectionService, logout);
window.bg_passwordGenerationService = bg_passwordGenerationService = new PasswordGenerationService(bg_cryptoService);
window.bg_totpService = bg_totpService = new TotpService();

View File

@ -110,7 +110,7 @@ require('./accounts/accountsHintController.js');
require('./accounts/accountsRegisterController.js');
require('./vault/vaultModule.js');
require('./vault/vaultController.js');
require('./vault/vaultViewFolderController.js');
require('./vault/vaultViewGroupingController.js');
require('./vault/vaultAddCipherController.js');
require('./vault/vaultEditCipherController.js');
require('./vault/vaultViewCipherController.js');

View File

@ -128,10 +128,10 @@ angular
component: 'tools'
})
.state('viewFolder', {
url: '/view-folder?folderId',
template: require('./vault/views/vaultViewFolder.html'),
controller: 'vaultViewFolderController',
.state('viewGrouping', {
url: '/view-grouping?folderId&collectionId',
template: require('./vault/views/vaultViewGrouping.html'),
controller: 'vaultViewGroupingController',
data: { authorize: true },
params: { animation: null, from: 'vault' }
})
@ -273,7 +273,7 @@ angular
if ($state.current.name.indexOf('tabs.') > -1 && toState.name.indexOf('tabs.') > -1) {
stateService.removeState('vault');
stateService.removeState('viewFolder');
stateService.removeState('viewGrouping');
}
const userService = trans.injector().get('userService');

View File

@ -8,7 +8,7 @@ angular
$scope.addFieldType = constantsService.fieldType.text.toString();
$scope.selectedType = constantsService.cipherType.login.toString();
var from = $stateParams.from,
folderId = $stateParams.folderId;
folderId = $stateParams.folderId && $stateParams.folderId !== '0' ? $stateParams.folderId : null;
$scope.cipher = {
folderId: folderId,
@ -76,10 +76,9 @@ angular
animation: 'out-slide-down'
});
}
else if (from === 'folder') {
$state.go('viewFolder', {
animation: 'out-slide-down',
folderId: folderId
else if (from === 'grouping') {
$state.go('viewGrouping', {
animation: 'out-slide-down'
});
}
else {

View File

@ -172,10 +172,11 @@ angular
}, 200);
};
$scope.viewGrouping = function (grouping) {
$scope.viewGrouping = function (grouping, folder) {
storeState();
$state.go('viewFolder', {
folderId: grouping.id || '0',
$state.go('viewGrouping', {
folderId: (folder && grouping.id) || '0',
collectionId: (!folder && grouping.id) || '0',
animation: 'in-slide-left'
});
};

View File

@ -76,8 +76,8 @@ angular
animation: 'out-slide-down'
});
}
else if (from === 'folder') {
$state.go('viewFolder', {
else if (from === 'grouping') {
$state.go('viewGrouping', {
animation: 'out-slide-down'
});
}

View File

@ -1,21 +1,34 @@
angular
.module('bit.vault')
.controller('vaultViewFolderController', function ($scope, cipherService, folderService, $q, $state, $stateParams, toastr,
syncService, $analytics, i18nService, stateService, utilsService, $timeout, $window) {
var stateKey = 'viewFolder',
.controller('vaultViewGroupingController', function ($scope, cipherService, folderService, $q, $state, $stateParams, toastr,
syncService, $analytics, i18nService, stateService, utilsService, $timeout, $window, collectionService) {
var stateKey = 'viewGrouping',
state = stateService.getState(stateKey) || {};
state.folderId = $stateParams.folderId || state.folderId;
state.collectionId = $stateParams.collectionId || state.collectionId;
var pageSize = 100,
decFolder = null,
decGrouping = null,
decCiphers = [];
$scope.folder = {
id: !state.folderId || state.folderId === '0' ? null : state.folderId,
$scope.grouping = {
id: null,
name: i18nService.noneFolder
};
$scope.folderGrouping = false;
$scope.collectionGrouping = false;
if (state.folderId && state.folderId !== '0') {
$scope.grouping.id = state.folderId;
$scope.folderGrouping = true;
}
else if (state.collectionId && state.collectionId !== '0') {
$scope.grouping.id = state.collectionId;
$scope.collectionGrouping = true;
}
$scope.i18n = i18nService;
document.getElementById('search').focus();
@ -28,32 +41,41 @@ angular
function loadVault() {
var promises = [];
if ($scope.folder.id) {
var getPromise = folderService.get($scope.folder.id).then(function (folder) {
if ($scope.grouping.id && $scope.folderGrouping) {
var getPromise = folderService.get($scope.grouping.id).then(function (folder) {
return folder.decrypt();
}).then(function (model) {
decFolder = model;
decGrouping = model;
});
promises.push(getPromise);
}
else if ($scope.grouping.id && $scope.collectionGrouping) {
var getPromise = collectionService.get($scope.grouping.id).then(function (collection) {
return collection.decrypt();
}).then(function (model) {
decGrouping = model;
});
promises.push(getPromise);
}
var cipherPromise = cipherService.getAllDecryptedForFolder($scope.folder.id).then(function (ciphers) {
if (utilsService.isEdge()) {
// Edge is super slow at sorting
decCiphers = ciphers;
}
else {
decCiphers = ciphers.sort(cipherSort);
}
});
var cipherPromise = cipherService.getAllDecryptedForGrouping($scope.grouping.id, $scope.folderGrouping)
.then(function (ciphers) {
if (utilsService.isEdge()) {
// Edge is super slow at sorting
decCiphers = ciphers;
}
else {
decCiphers = ciphers.sort(cipherSort);
}
});
promises.push(cipherPromise);
$q.all(promises).then(function () {
$scope.loaded = true;
$scope.vaultCiphers = decCiphers;
if (decFolder) {
$scope.folder.name = decFolder.name;
if (decGrouping) {
$scope.grouping.name = decGrouping.name;
}
if (state.searchText) {
@ -153,8 +175,8 @@ angular
storeState();
$state.go('addCipher', {
animation: 'in-slide-up',
from: 'folder',
folderId: $scope.folder.id
from: 'grouping',
folderId: state.folderId
});
};
@ -178,7 +200,7 @@ angular
$state.go('viewCipher', {
cipherId: cipher.id,
animation: 'in-slide-up',
from: 'folder'
from: 'grouping'
});
// clean up

View File

@ -39,7 +39,7 @@
<span>{{vaultFolders.length}}</span>
</div>
<div class="list-section-items">
<a href="#" stop-click ng-click="viewGrouping(folder)" class="list-section-item"
<a href="#" stop-click ng-click="viewGrouping(folder, true)" class="list-section-item"
ng-repeat="folder in vaultFolders | orderBy: folderSort track by $index">
<i class="fa fa-fw text-muted"
ng-class="{'fa-folder-open': folder.id, 'fa-folder-open-o': !folder.id}"></i>
@ -55,7 +55,7 @@
<span>{{vaultCollections.length}}</span>
</div>
<div class="list-section-items">
<a href="#" stop-click ng-click="viewGrouping(collection)" class="list-section-item"
<a href="#" stop-click ng-click="viewGrouping(collection, false)" class="list-section-item"
ng-repeat="collection in vaultCollections | orderBy: ['name'] track by $index">
<i class="fa fa-cube fa-fw text-muted"></i>
{{collection.name}}

View File

@ -3,10 +3,11 @@
<a ui-sref="tabs.vault({animation: 'out-slide-right'})"><i class="fa fa-chevron-left"></i> {{i18n.back}}</a>
</div>
<div class="search">
<input type="search" placeholder="{{i18n.searchFolder}}" ng-model="searchText" ng-change="searchCiphers()" id="search" />
<input type="search" placeholder="{{collectionGrouping ? i18n.searchCollection : i18n.searchFolder}}"
ng-model="searchText" ng-change="searchCiphers()" id="search" />
<i class="fa fa-search"></i>
</div>
<div class="right">
<div class="right" ng-if="folderGrouping">
<a href="" ng-click="addCipher()"><i class="fa fa-plus fa-lg"></i></a>
</div>
</div>
@ -16,7 +17,7 @@
<div class="list">
<div class="list-section" style="padding-bottom: 0;">
<div class="list-section-header">
{{folder.name}}
{{grouping.name}}
<span>{{vaultCiphers.length}}</span>
</div>
<a href="#" stop-click ng-click="viewCipher(cipher)"

View File

@ -178,12 +178,14 @@ export default class CipherService {
return this.decryptedCipherCache;
}
async getAllDecryptedForFolder(folderId: string): Promise<any[]> {
async getAllDecryptedForGrouping(groupingId: string, folder: boolean = true): Promise<any[]> {
const ciphers = await this.getAllDecrypted();
const ciphersToReturn: any[] = [];
ciphers.forEach((cipher) => {
if (cipher.folderId === folderId) {
if (folder && cipher.folderId === groupingId) {
ciphersToReturn.push(cipher);
} else if (!folder && cipher.collectionIds != null && cipher.collectionIds.indexOf(groupingId) > -1) {
ciphersToReturn.push(cipher);
}
});

View File

@ -1,4 +1,5 @@
import CipherService from './cipher.service';
import CollectionService from './collection.service';
import ConstantsService from './constants.service';
import CryptoService from './crypto.service';
import FolderService from './folder.service';
@ -6,8 +7,8 @@ import UtilsService from './utils.service';
export default class LockService {
constructor(private cipherService: CipherService, private folderService: FolderService,
private cryptoService: CryptoService, private utilsService: UtilsService,
private setIcon: Function, private refreshBadgeAndMenu: Function) {
private collectionService: CollectionService, private cryptoService: CryptoService,
private utilsService: UtilsService, private setIcon: Function, private refreshBadgeAndMenu: Function) {
this.checkLock();
setInterval(() => this.checkLock(), 10 * 1000); // check every 10 seconds
@ -70,6 +71,7 @@ export default class LockService {
this.setIcon();
this.folderService.clearCache();
this.cipherService.clearCache();
this.collectionService.clearCache();
this.refreshBadgeAndMenu();
}