mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-24 12:06:15 +01:00
view grouping of ciphers for a collection
This commit is contained in:
parent
991ddd8271
commit
2e9b3d0943
@ -485,6 +485,9 @@
|
|||||||
"searchFolder": {
|
"searchFolder": {
|
||||||
"message": "Search folder"
|
"message": "Search folder"
|
||||||
},
|
},
|
||||||
|
"searchCollection": {
|
||||||
|
"message": "Search collection"
|
||||||
|
},
|
||||||
"noneFolder": {
|
"noneFolder": {
|
||||||
"message": "No Folder",
|
"message": "No Folder",
|
||||||
"description": "This is the folder for uncategorized items"
|
"description": "This is the folder for uncategorized items"
|
||||||
|
@ -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_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_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_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_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_passwordGenerationService = bg_passwordGenerationService = new PasswordGenerationService(bg_cryptoService);
|
||||||
window.bg_totpService = bg_totpService = new TotpService();
|
window.bg_totpService = bg_totpService = new TotpService();
|
||||||
|
@ -110,7 +110,7 @@ require('./accounts/accountsHintController.js');
|
|||||||
require('./accounts/accountsRegisterController.js');
|
require('./accounts/accountsRegisterController.js');
|
||||||
require('./vault/vaultModule.js');
|
require('./vault/vaultModule.js');
|
||||||
require('./vault/vaultController.js');
|
require('./vault/vaultController.js');
|
||||||
require('./vault/vaultViewFolderController.js');
|
require('./vault/vaultViewGroupingController.js');
|
||||||
require('./vault/vaultAddCipherController.js');
|
require('./vault/vaultAddCipherController.js');
|
||||||
require('./vault/vaultEditCipherController.js');
|
require('./vault/vaultEditCipherController.js');
|
||||||
require('./vault/vaultViewCipherController.js');
|
require('./vault/vaultViewCipherController.js');
|
||||||
|
@ -128,10 +128,10 @@ angular
|
|||||||
component: 'tools'
|
component: 'tools'
|
||||||
})
|
})
|
||||||
|
|
||||||
.state('viewFolder', {
|
.state('viewGrouping', {
|
||||||
url: '/view-folder?folderId',
|
url: '/view-grouping?folderId&collectionId',
|
||||||
template: require('./vault/views/vaultViewFolder.html'),
|
template: require('./vault/views/vaultViewGrouping.html'),
|
||||||
controller: 'vaultViewFolderController',
|
controller: 'vaultViewGroupingController',
|
||||||
data: { authorize: true },
|
data: { authorize: true },
|
||||||
params: { animation: null, from: 'vault' }
|
params: { animation: null, from: 'vault' }
|
||||||
})
|
})
|
||||||
@ -273,7 +273,7 @@ angular
|
|||||||
|
|
||||||
if ($state.current.name.indexOf('tabs.') > -1 && toState.name.indexOf('tabs.') > -1) {
|
if ($state.current.name.indexOf('tabs.') > -1 && toState.name.indexOf('tabs.') > -1) {
|
||||||
stateService.removeState('vault');
|
stateService.removeState('vault');
|
||||||
stateService.removeState('viewFolder');
|
stateService.removeState('viewGrouping');
|
||||||
}
|
}
|
||||||
|
|
||||||
const userService = trans.injector().get('userService');
|
const userService = trans.injector().get('userService');
|
||||||
|
@ -8,7 +8,7 @@ angular
|
|||||||
$scope.addFieldType = constantsService.fieldType.text.toString();
|
$scope.addFieldType = constantsService.fieldType.text.toString();
|
||||||
$scope.selectedType = constantsService.cipherType.login.toString();
|
$scope.selectedType = constantsService.cipherType.login.toString();
|
||||||
var from = $stateParams.from,
|
var from = $stateParams.from,
|
||||||
folderId = $stateParams.folderId;
|
folderId = $stateParams.folderId && $stateParams.folderId !== '0' ? $stateParams.folderId : null;
|
||||||
|
|
||||||
$scope.cipher = {
|
$scope.cipher = {
|
||||||
folderId: folderId,
|
folderId: folderId,
|
||||||
@ -76,10 +76,9 @@ angular
|
|||||||
animation: 'out-slide-down'
|
animation: 'out-slide-down'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (from === 'folder') {
|
else if (from === 'grouping') {
|
||||||
$state.go('viewFolder', {
|
$state.go('viewGrouping', {
|
||||||
animation: 'out-slide-down',
|
animation: 'out-slide-down'
|
||||||
folderId: folderId
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -172,10 +172,11 @@ angular
|
|||||||
}, 200);
|
}, 200);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.viewGrouping = function (grouping) {
|
$scope.viewGrouping = function (grouping, folder) {
|
||||||
storeState();
|
storeState();
|
||||||
$state.go('viewFolder', {
|
$state.go('viewGrouping', {
|
||||||
folderId: grouping.id || '0',
|
folderId: (folder && grouping.id) || '0',
|
||||||
|
collectionId: (!folder && grouping.id) || '0',
|
||||||
animation: 'in-slide-left'
|
animation: 'in-slide-left'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -76,8 +76,8 @@ angular
|
|||||||
animation: 'out-slide-down'
|
animation: 'out-slide-down'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (from === 'folder') {
|
else if (from === 'grouping') {
|
||||||
$state.go('viewFolder', {
|
$state.go('viewGrouping', {
|
||||||
animation: 'out-slide-down'
|
animation: 'out-slide-down'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,34 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.vault')
|
.module('bit.vault')
|
||||||
|
|
||||||
.controller('vaultViewFolderController', function ($scope, cipherService, folderService, $q, $state, $stateParams, toastr,
|
.controller('vaultViewGroupingController', function ($scope, cipherService, folderService, $q, $state, $stateParams, toastr,
|
||||||
syncService, $analytics, i18nService, stateService, utilsService, $timeout, $window) {
|
syncService, $analytics, i18nService, stateService, utilsService, $timeout, $window, collectionService) {
|
||||||
var stateKey = 'viewFolder',
|
var stateKey = 'viewGrouping',
|
||||||
state = stateService.getState(stateKey) || {};
|
state = stateService.getState(stateKey) || {};
|
||||||
|
|
||||||
state.folderId = $stateParams.folderId || state.folderId;
|
state.folderId = $stateParams.folderId || state.folderId;
|
||||||
|
state.collectionId = $stateParams.collectionId || state.collectionId;
|
||||||
|
|
||||||
var pageSize = 100,
|
var pageSize = 100,
|
||||||
decFolder = null,
|
decGrouping = null,
|
||||||
decCiphers = [];
|
decCiphers = [];
|
||||||
|
|
||||||
$scope.folder = {
|
$scope.grouping = {
|
||||||
id: !state.folderId || state.folderId === '0' ? null : state.folderId,
|
id: null,
|
||||||
name: i18nService.noneFolder
|
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;
|
$scope.i18n = i18nService;
|
||||||
document.getElementById('search').focus();
|
document.getElementById('search').focus();
|
||||||
|
|
||||||
@ -28,32 +41,41 @@ angular
|
|||||||
function loadVault() {
|
function loadVault() {
|
||||||
var promises = [];
|
var promises = [];
|
||||||
|
|
||||||
if ($scope.folder.id) {
|
if ($scope.grouping.id && $scope.folderGrouping) {
|
||||||
var getPromise = folderService.get($scope.folder.id).then(function (folder) {
|
var getPromise = folderService.get($scope.grouping.id).then(function (folder) {
|
||||||
return folder.decrypt();
|
return folder.decrypt();
|
||||||
}).then(function (model) {
|
}).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);
|
promises.push(getPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
var cipherPromise = cipherService.getAllDecryptedForFolder($scope.folder.id).then(function (ciphers) {
|
var cipherPromise = cipherService.getAllDecryptedForGrouping($scope.grouping.id, $scope.folderGrouping)
|
||||||
if (utilsService.isEdge()) {
|
.then(function (ciphers) {
|
||||||
// Edge is super slow at sorting
|
if (utilsService.isEdge()) {
|
||||||
decCiphers = ciphers;
|
// Edge is super slow at sorting
|
||||||
}
|
decCiphers = ciphers;
|
||||||
else {
|
}
|
||||||
decCiphers = ciphers.sort(cipherSort);
|
else {
|
||||||
}
|
decCiphers = ciphers.sort(cipherSort);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
promises.push(cipherPromise);
|
promises.push(cipherPromise);
|
||||||
|
|
||||||
$q.all(promises).then(function () {
|
$q.all(promises).then(function () {
|
||||||
$scope.loaded = true;
|
$scope.loaded = true;
|
||||||
$scope.vaultCiphers = decCiphers;
|
$scope.vaultCiphers = decCiphers;
|
||||||
|
|
||||||
if (decFolder) {
|
if (decGrouping) {
|
||||||
$scope.folder.name = decFolder.name;
|
$scope.grouping.name = decGrouping.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.searchText) {
|
if (state.searchText) {
|
||||||
@ -153,8 +175,8 @@ angular
|
|||||||
storeState();
|
storeState();
|
||||||
$state.go('addCipher', {
|
$state.go('addCipher', {
|
||||||
animation: 'in-slide-up',
|
animation: 'in-slide-up',
|
||||||
from: 'folder',
|
from: 'grouping',
|
||||||
folderId: $scope.folder.id
|
folderId: state.folderId
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -178,7 +200,7 @@ angular
|
|||||||
$state.go('viewCipher', {
|
$state.go('viewCipher', {
|
||||||
cipherId: cipher.id,
|
cipherId: cipher.id,
|
||||||
animation: 'in-slide-up',
|
animation: 'in-slide-up',
|
||||||
from: 'folder'
|
from: 'grouping'
|
||||||
});
|
});
|
||||||
|
|
||||||
// clean up
|
// clean up
|
@ -39,7 +39,7 @@
|
|||||||
<span>{{vaultFolders.length}}</span>
|
<span>{{vaultFolders.length}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="list-section-items">
|
<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">
|
ng-repeat="folder in vaultFolders | orderBy: folderSort track by $index">
|
||||||
<i class="fa fa-fw text-muted"
|
<i class="fa fa-fw text-muted"
|
||||||
ng-class="{'fa-folder-open': folder.id, 'fa-folder-open-o': !folder.id}"></i>
|
ng-class="{'fa-folder-open': folder.id, 'fa-folder-open-o': !folder.id}"></i>
|
||||||
@ -55,7 +55,7 @@
|
|||||||
<span>{{vaultCollections.length}}</span>
|
<span>{{vaultCollections.length}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="list-section-items">
|
<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">
|
ng-repeat="collection in vaultCollections | orderBy: ['name'] track by $index">
|
||||||
<i class="fa fa-cube fa-fw text-muted"></i>
|
<i class="fa fa-cube fa-fw text-muted"></i>
|
||||||
{{collection.name}}
|
{{collection.name}}
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
<a ui-sref="tabs.vault({animation: 'out-slide-right'})"><i class="fa fa-chevron-left"></i> {{i18n.back}}</a>
|
<a ui-sref="tabs.vault({animation: 'out-slide-right'})"><i class="fa fa-chevron-left"></i> {{i18n.back}}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="search">
|
<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>
|
<i class="fa fa-search"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right" ng-if="folderGrouping">
|
||||||
<a href="" ng-click="addCipher()"><i class="fa fa-plus fa-lg"></i></a>
|
<a href="" ng-click="addCipher()"><i class="fa fa-plus fa-lg"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -16,7 +17,7 @@
|
|||||||
<div class="list">
|
<div class="list">
|
||||||
<div class="list-section" style="padding-bottom: 0;">
|
<div class="list-section" style="padding-bottom: 0;">
|
||||||
<div class="list-section-header">
|
<div class="list-section-header">
|
||||||
{{folder.name}}
|
{{grouping.name}}
|
||||||
<span>{{vaultCiphers.length}}</span>
|
<span>{{vaultCiphers.length}}</span>
|
||||||
</div>
|
</div>
|
||||||
<a href="#" stop-click ng-click="viewCipher(cipher)"
|
<a href="#" stop-click ng-click="viewCipher(cipher)"
|
@ -178,12 +178,14 @@ export default class CipherService {
|
|||||||
return this.decryptedCipherCache;
|
return this.decryptedCipherCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllDecryptedForFolder(folderId: string): Promise<any[]> {
|
async getAllDecryptedForGrouping(groupingId: string, folder: boolean = true): Promise<any[]> {
|
||||||
const ciphers = await this.getAllDecrypted();
|
const ciphers = await this.getAllDecrypted();
|
||||||
const ciphersToReturn: any[] = [];
|
const ciphersToReturn: any[] = [];
|
||||||
|
|
||||||
ciphers.forEach((cipher) => {
|
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);
|
ciphersToReturn.push(cipher);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import CipherService from './cipher.service';
|
import CipherService from './cipher.service';
|
||||||
|
import CollectionService from './collection.service';
|
||||||
import ConstantsService from './constants.service';
|
import ConstantsService from './constants.service';
|
||||||
import CryptoService from './crypto.service';
|
import CryptoService from './crypto.service';
|
||||||
import FolderService from './folder.service';
|
import FolderService from './folder.service';
|
||||||
@ -6,8 +7,8 @@ import UtilsService from './utils.service';
|
|||||||
|
|
||||||
export default class LockService {
|
export default class LockService {
|
||||||
constructor(private cipherService: CipherService, private folderService: FolderService,
|
constructor(private cipherService: CipherService, private folderService: FolderService,
|
||||||
private cryptoService: CryptoService, private utilsService: UtilsService,
|
private collectionService: CollectionService, private cryptoService: CryptoService,
|
||||||
private setIcon: Function, private refreshBadgeAndMenu: Function) {
|
private utilsService: UtilsService, private setIcon: Function, private refreshBadgeAndMenu: Function) {
|
||||||
this.checkLock();
|
this.checkLock();
|
||||||
setInterval(() => this.checkLock(), 10 * 1000); // check every 10 seconds
|
setInterval(() => this.checkLock(), 10 * 1000); // check every 10 seconds
|
||||||
|
|
||||||
@ -70,6 +71,7 @@ export default class LockService {
|
|||||||
this.setIcon();
|
this.setIcon();
|
||||||
this.folderService.clearCache();
|
this.folderService.clearCache();
|
||||||
this.cipherService.clearCache();
|
this.cipherService.clearCache();
|
||||||
|
this.collectionService.clearCache();
|
||||||
this.refreshBadgeAndMenu();
|
this.refreshBadgeAndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user