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:
@@ -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', {}, {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user