1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-18 01:03:35 +00:00

re-factor vault listings

This commit is contained in:
Kyle Spearrin
2018-03-17 11:42:35 -04:00
parent bbb69bba26
commit dcb0416fd6
19 changed files with 368 additions and 479 deletions

View File

@@ -5,24 +5,27 @@
cipherService, $q, $localStorage, $timeout, $rootScope, $state, $analytics, constants, validationService) {
$scope.loading = true;
$scope.ciphers = [];
$scope.folderCount = 0;
$scope.collectionCount = 0;
$scope.firstCollectionId = null;
$scope.folders = [];
$scope.collections = [];
$scope.constants = constants;
$scope.favoriteCollapsed = $localStorage.collapsedFolders && 'favorite' in $localStorage.collapsedFolders;
$scope.groupingIdFilter = undefined;
$scope.typeFilter = undefined;
$scope.filter = undefined;
$scope.selectedType = undefined;
$scope.selectedFolder = undefined;
$scope.selectedCollection = undefined;
$scope.selectedFavorites = false;
$scope.selectedAll = true;
$scope.selectedTitle = 'All';
$scope.selectedIcon = 'fa-th';
if ($state.params.refreshFromServer) {
$rootScope.vaultGroupings = $rootScope.vaultCiphers = null;
$rootScope.vaultFolders = $rootScope.vaultCollections = $rootScope.vaultCiphers = null;
}
$scope.$on('$viewContentLoaded', function () {
$("#search").focus();
if ($rootScope.vaultGroupings && $rootScope.vaultCiphers) {
if (($rootScope.vaultFolders || $rootScope.vaultCollections) && $rootScope.vaultCiphers) {
$scope.loading = false;
loadGroupingData($rootScope.vaultGroupings);
loadCipherData($rootScope.vaultCiphers);
return;
}
@@ -31,30 +34,30 @@
});
function loadDataFromServer() {
var decGroupings = [{
var decFolders = [{
id: null,
name: 'No Folder',
folder: true
name: 'No Folder'
}];
var decCollections = [];
var collectionPromise = apiService.collections.listMe({ writeOnly: false }, function (collections) {
for (var i = 0; i < collections.Data.length; i++) {
var decCollection = cipherService.decryptCollection(collections.Data[i], null, true);
decCollection.collection = true;
decGroupings.push(decCollection);
decCollections.push(decCollection);
}
}).$promise;
var folderPromise = apiService.folders.list({}, function (folders) {
for (var i = 0; i < folders.Data.length; i++) {
var decFolder = cipherService.decryptFolderPreview(folders.Data[i]);
decFolder.folder = true;
decGroupings.push(decFolder);
decFolders.push(decFolder);
}
}).$promise;
var groupingPromise = $q.all([collectionPromise, folderPromise]).then(function () {
loadGroupingData(decGroupings);
$rootScope.vaultCollections = decCollections;
$rootScope.vaultFolders = decFolders;
});
var cipherPromise = apiService.ciphers.list({}, function (ciphers) {
@@ -75,34 +78,7 @@
});
}
function loadGroupingData(decGroupings) {
$rootScope.vaultGroupings = $filter('orderBy')(decGroupings, ['folder', groupingSort]);
var collections = $filter('filter')($rootScope.vaultGroupings, { collection: true });
$scope.collectionCount = collections.length;
$scope.folderCount = decGroupings.length - collections.length - 1;
if (collections && collections.length) {
$scope.firstCollectionId = collections[0].id;
}
}
function loadCipherData(decCiphers) {
angular.forEach($rootScope.vaultGroupings, function (grouping, groupingIndex) {
grouping.collapsed = $localStorage.collapsedFolders &&
(grouping.id || 'none') in $localStorage.collapsedFolders;
angular.forEach(decCiphers, function (cipherValue) {
if (cipherValue.favorite) {
cipherValue.sort = -1;
}
else if (grouping.folder && cipherValue.folderId == grouping.id) {
cipherValue.sort = groupingIndex;
}
else if (grouping.collection && cipherValue.collectionIds.indexOf(grouping.id) > -1) {
cipherValue.sort = groupingIndex;
}
});
});
$rootScope.vaultCiphers = $scope.ciphers = $filter('orderBy')(decCiphers, ['sort', 'name', 'subTitle']);
var chunks = chunk($rootScope.vaultCiphers, 400);
@@ -136,61 +112,19 @@
return chunks;
}
function groupingSort(item) {
$scope.groupingSort = function (item) {
if (!item.id) {
return '';
}
return item.name.toLowerCase();
}
};
$scope.clipboardError = function (e) {
alert('Your web browser does not support easy clipboard copying. ' +
'Edit the item and copy it manually instead.');
};
$scope.collapseExpand = function (grouping, favorite) {
if (!$localStorage.collapsedFolders) {
$localStorage.collapsedFolders = {};
}
var id = favorite ? 'favorite' : (grouping.id || 'none');
if (id in $localStorage.collapsedFolders) {
delete $localStorage.collapsedFolders[id];
}
else {
$localStorage.collapsedFolders[id] = true;
}
};
$scope.collapseAll = function () {
if (!$localStorage.collapsedFolders) {
$localStorage.collapsedFolders = {};
}
$localStorage.collapsedFolders.none = true;
$localStorage.collapsedFolders.favorite = true;
if ($rootScope.vaultGroupings) {
for (var i = 0; i < $rootScope.vaultGroupings.length; i++) {
$localStorage.collapsedFolders[$rootScope.vaultGroupings[i].id] = true;
}
}
$('.box').addClass('collapsed-box');
$('.box .box-header button i.fa-minus').removeClass('fa-minus').addClass('fa-plus');
};
$scope.expandAll = function () {
if ($localStorage.collapsedFolders) {
delete $localStorage.collapsedFolders;
}
$('.box').removeClass('collapsed-box');
$('.box-body').show();
$('.box .box-header button i.fa-plus').removeClass('fa-plus').addClass('fa-minus');
};
$scope.editCipher = function (cipher) {
var editModel = $uibModal.open({
animation: true,
@@ -225,14 +159,15 @@
$scope.addCipher();
});
$scope.addCipher = function (grouping, favorite) {
$scope.addCipher = function () {
var addModel = $uibModal.open({
animation: true,
templateUrl: 'app/vault/views/vaultAddCipher.html',
controller: 'vaultAddCipherController',
resolve: {
selectedFolder: function () { return grouping && grouping.folder ? grouping : null; },
checkedFavorite: function () { return favorite; }
selectedFolder: function () { return $scope.selectedFolder; },
selectedType: function () { return $scope.selectedType; },
checkedFavorite: function () { return $scope.selectedFavorites; }
}
});
@@ -332,36 +267,26 @@
});
addModel.result.then(function (addedFolder) {
addedFolder.folder = true;
$rootScope.vaultGroupings.push(addedFolder);
loadGroupingData($rootScope.vaultGroupings);
$rootScope.vaultFolders.push(addedFolder);
});
};
$scope.deleteFolder = function (folder) {
if (!confirm('Are you sure you want to delete this folder (' + folder.name + ')?')) {
if (!confirm('Are you sure you want to delete this folder (' + folder.name + ')? ' +
'Any items will be moved to "No Folder".')) {
return;
}
apiService.folders.del({ id: folder.id }, function () {
$analytics.eventTrack('Deleted Folder');
var index = $rootScope.vaultGroupings.indexOf(folder);
var index = $rootScope.vaultFolders.indexOf(folder);
if (index > -1) {
$rootScope.vaultGroupings.splice(index, 1);
$scope.folderCount--;
$rootScope.vaultFolders.splice(index, 1);
$scope.filterAll();
}
});
};
$scope.canDeleteFolder = function (folder) {
if (!folder || !folder.id || !$rootScope.vaultCiphers) {
return false;
}
var ciphers = $filter('filter')($rootScope.vaultCiphers, { folderId: folder.id });
return ciphers && ciphers.length === 0;
};
$scope.share = function (cipher) {
var modal = $uibModal.open({
animation: true,
@@ -397,52 +322,94 @@
});
};
$scope.filterGrouping = function (grouping) {
$scope.groupingIdFilter = grouping.id;
$scope.filterCollection = function (col) {
resetSelected();
$scope.selectedCollection = col;
$scope.selectedIcon = 'fa-cube';
$scope.filter = function (c) {
return c.collectionIds && c.collectionIds.indexOf(col.id) > -1;
};
fixLayout();
};
$scope.filterFolder = function (f) {
resetSelected();
$scope.selectedFolder = f;
$scope.selectedIcon = 'fa-folder-open' + (!f.id ? '-o' : '');
$scope.filter = function (c) {
return c.folderId === f.id;
};
fixLayout();
};
$scope.filterType = function (t) {
resetSelected();
$scope.selectedType = t;
switch (t) {
case constants.cipherType.login:
$scope.selectedTitle = 'Login';
$scope.selectedIcon = 'fa-globe';
break;
case constants.cipherType.card:
$scope.selectedTitle = 'Card';
$scope.selectedIcon = 'fa-credit-card';
break;
case constants.cipherType.identity:
$scope.selectedTitle = 'Identity';
$scope.selectedIcon = 'fa-id-card-o';
break;
case constants.cipherType.secureNote:
$scope.selectedTitle = 'Secure Note';
$scope.selectedIcon = 'fa-sticky-note-o';
break;
default:
break;
}
$scope.filter = function (c) {
return c.type === t;
};
fixLayout();
};
$scope.filterFavorites = function () {
resetSelected();
$scope.selectedFavorites = true;
$scope.selectedTitle = 'Favorites';
$scope.selectedIcon = 'fa-star';
$scope.filter = function (c) {
return !!c.favorite;
};
fixLayout();
};
$scope.filterAll = function () {
resetSelected();
$scope.selectedAll = true;
$scope.selectedTitle = 'All';
$scope.selectedIcon = 'fa-th';
$scope.filter = null;
fixLayout();
};
function resetSelected() {
$scope.selectedFolder = undefined;
$scope.selectedCollection = undefined;
$scope.selectedType = undefined;
$scope.selectedFavorites = false;
$scope.selectedAll = false;
}
function fixLayout() {
if ($.AdminLTE && $.AdminLTE.layout) {
$timeout(function () {
$.AdminLTE.layout.fix();
}, 0);
}
};
}
$scope.filterType = function (type) {
$scope.typeFilter = type;
if ($.AdminLTE && $.AdminLTE.layout) {
$timeout(function () {
$.AdminLTE.layout.fix();
}, 0);
}
};
$scope.clearFilters = function () {
$scope.groupingIdFilter = undefined;
$scope.typeFilter = undefined;
if ($.AdminLTE && $.AdminLTE.layout) {
$timeout(function () {
$.AdminLTE.layout.fix();
}, 0);
}
};
$scope.groupingFilter = function (grouping) {
return $scope.groupingIdFilter === undefined || grouping.id === $scope.groupingIdFilter;
};
$scope.cipherFilter = function (grouping) {
$scope.cipherFilter = function () {
return function (cipher) {
var matchesGrouping = grouping === null;
if (!matchesGrouping && grouping.folder && cipher.folderId === grouping.id) {
matchesGrouping = true;
}
else if (!matchesGrouping && grouping.collection && cipher.collectionIds.indexOf(grouping.id) > -1) {
matchesGrouping = true;
}
return matchesGrouping && ($scope.typeFilter === undefined || cipher.type === $scope.typeFilter);
return !$scope.filter || $scope.filter(cipher);
};
};
@@ -450,14 +417,8 @@
selectAll(false);
};
$scope.selectFolder = function (folder, $event) {
var checkbox = $($event.currentTarget).closest('.box').find('input[name="cipherSelection"]');
checkbox.prop('checked', true);
};
$scope.select = function ($event) {
var checkbox = $($event.currentTarget).closest('tr').find('input[name="cipherSelection"]');
checkbox.prop('checked', !checkbox.prop('checked'));
$scope.selectAll = function () {
selectAll(true);
};
function distinct(value, index, self) {