1
0
mirror of https://github.com/bitwarden/web synced 2025-12-13 06:43:31 +00:00

bulk actions with move and delete

This commit is contained in:
Kyle Spearrin
2017-06-09 00:44:56 -04:00
parent c094a26cbf
commit f170157817
4 changed files with 99 additions and 11 deletions

View File

@@ -38,7 +38,9 @@
putCollections: { url: _apiUri + '/ciphers/:id/collections', method: 'POST', params: { id: '@id' } }, putCollections: { url: _apiUri + '/ciphers/:id/collections', method: 'POST', params: { id: '@id' } },
putCollectionsAdmin: { url: _apiUri + '/ciphers/:id/collections-admin', method: 'POST', params: { id: '@id' } }, putCollectionsAdmin: { url: _apiUri + '/ciphers/:id/collections-admin', method: 'POST', params: { id: '@id' } },
del: { url: _apiUri + '/ciphers/:id/delete', method: 'POST', params: { id: '@id' } }, del: { url: _apiUri + '/ciphers/:id/delete', method: 'POST', params: { id: '@id' } },
delAdmin: { url: _apiUri + '/ciphers/:id/delete-admin', method: 'POST', params: { id: '@id' } } delAdmin: { url: _apiUri + '/ciphers/:id/delete-admin', method: 'POST', params: { id: '@id' } },
delMany: { url: _apiUri + '/ciphers/delete', method: 'POST' },
moveMany: { url: _apiUri + '/ciphers/move', method: 'POST' }
}); });
_service.organizations = $resource(_apiUri + '/organizations/:id', {}, { _service.organizations = $resource(_apiUri + '/organizations/:id', {}, {

View File

@@ -312,6 +312,59 @@
return $scope.folderIdFilter === undefined || folder.id === $scope.folderIdFilter; return $scope.folderIdFilter === undefined || folder.id === $scope.folderIdFilter;
}; };
function distinct(value, index, self) {
return self.indexOf(value) === index;
}
function getSelectedLogins() {
return $('input[name="loginSelection"]:checked').map(function () {
return $(this).val();
}).get().filter(distinct);
}
function clearLoginSelections() {
$('input[name="loginSelection"]').attr('checked', false);
}
$scope.bulkMove = function () {
var ids = getSelectedLogins();
if (ids.length === 0) {
alert('You have not selected anything.');
return;
}
// TODO
};
$scope.bulkDelete = function () {
var ids = getSelectedLogins();
if (ids.length === 0) {
alert('You have not selected anything.');
return;
}
if (!confirm('Are you sure you want to delete the selected logins (total: ' + ids.length + ')?')) {
return;
}
$scope.bulkActionLoading = true;
apiService.ciphers.delMany({ ids: ids }, function () {
$analytics.eventTrack('Bulk Deleted Logins');
for (var i = 0; i < ids.length; i++) {
var login = $filter('filter')($rootScope.vaultLogins, { id: ids[i] });
if (login.length && login[0].edit) {
removeLoginFromScopes(login[0]);
}
}
clearLoginSelections();
$scope.bulkActionLoading = false;
}, function () {
$scope.bulkActionLoading = false;
});
};
function removeLoginFromScopes(login) { function removeLoginFromScopes(login) {
var index = $rootScope.vaultLogins.indexOf(login); var index = $rootScope.vaultLogins.indexOf(login);
if (index > -1) { if (index > -1) {

View File

@@ -1,4 +1,23 @@
<section class="content-header"> <section class="content-header">
<div class="btn-group pull-right">
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"
ng-disabled="bulkActionLoading">
<i class="fa fa-refresh fa-spin" ng-show="bulkActionLoading"></i>
Bulk Actions <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>
<a href="#" stop-click ng-click="bulkMove()">
<i class="fa fa-fw fa-share"></i> Move Selected
</a>
</li>
<li>
<a href="#" stop-click ng-click="bulkDelete()">
<i class="fa fa-fw fa-trash"></i> Delete Selected
</a>
</li>
</ul>
</div>
<h1> <h1>
My Vault My Vault
<small> <small>
@@ -85,6 +104,9 @@
</ul> </ul>
</div> </div>
</td> </td>
<td class="action-select">
<input type="checkbox" value="{{::login.id}}" name="loginSelection" />
</td>
<td> <td>
<a href="#" stop-click ng-click="editLogin(login)">{{login.name}}</a> <a href="#" stop-click ng-click="editLogin(login)">{{login.name}}</a>
<i class="fa fa-share-alt text-muted" title="Shared" ng-show="login.organizationId"></i> <i class="fa fa-share-alt text-muted" title="Shared" ng-show="login.organizationId"></i>
@@ -179,6 +201,9 @@
</ul> </ul>
</div> </div>
</td> </td>
<td class="action-select">
<input type="checkbox" value="{{::login.id}}" name="loginSelection" />
</td>
<td> <td>
<a href="#" stop-click ng-click="editLogin(login)">{{login.name}}</a> <a href="#" stop-click ng-click="editLogin(login)">{{login.name}}</a>
<i class="fa fa-star text-muted" title="Favorite" ng-show="login.favorite"></i> <i class="fa fa-star text-muted" title="Favorite" ng-show="login.favorite"></i>

View File

@@ -228,8 +228,17 @@ form .btn .loading-icon {
} }
} }
/* Forms */ .btn-link:active {
.box-shadow(none);
}
@media (max-width: @screen-sm-max) {
.content-header .btn-group {
display: none;
}
}
/* Forms */
.form-control { .form-control {
border-radius: 0 !important; border-radius: 0 !important;
} }
@@ -331,8 +340,15 @@ form .btn .loading-icon {
border-top: 0; border-top: 0;
} }
/* Callouts */ .table td.action-select {
text-align: center;
width: 30px;
@media (max-width: @screen-sm-max) {
display: none;
}
}
/* Callouts */
.callout.callout-default { .callout.callout-default {
background-color: #fff; background-color: #fff;
border-color: darken(@gray, 10%); border-color: darken(@gray, 10%);
@@ -364,9 +380,7 @@ form .btn .loading-icon {
color: @btn-default-color; color: @btn-default-color;
} }
} }
/* Boxes */ /* Boxes */
.box > .list-group { .box > .list-group {
margin-bottom: 0; margin-bottom: 0;
} }
@@ -423,9 +437,7 @@ form .btn .loading-icon {
} }
} }
} }
/* Toastr */ /* Toastr */
#toast-container { #toast-container {
position: absolute; position: absolute;
@@ -497,15 +509,11 @@ form .btn .loading-icon {
} }
} }
} }
/* Typography */ /* Typography */
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
margin-top: 0; margin-top: 0;
} }
/* Misc */ /* Misc */
.strike { .strike {
text-decoration: line-through; text-decoration: line-through;
color: @text-muted; color: @text-muted;