Bulk re-invite of org users (#961)
* Add support for bulk re-invite of org users * Add selectAll, resolve review comments
This commit is contained in:
parent
3ac2ce079a
commit
51f3fee75d
2
jslib
2
jslib
|
@ -1 +1 @@
|
|||
Subproject commit 8244971026ffefb962e235a79c5cb219163bead9
|
||||
Subproject commit 1e2c56cacf975eab4527cb3c1a63cf8136b58bd4
|
|
@ -25,6 +25,27 @@
|
|||
<input type="search" class="form-control form-control-sm" id="search" placeholder="{{'search' | i18n}}"
|
||||
[(ngModel)]="searchText">
|
||||
</div>
|
||||
<div class="dropdown ml-3" appListDropdown>
|
||||
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" id="bulkActionsButton"
|
||||
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" appA11yTitle="{{'options' | i18n}}">
|
||||
<i class="fa fa-cog" aria-hidden="true"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="bulkActionsButton">
|
||||
<button class="dropdown-item" appStopClick (click)="bulkReinvite()">
|
||||
<i class="fa fa-fw fa-envelope-o" aria-hidden="true"></i>
|
||||
{{'reinviteSelected' | i18n}}
|
||||
</button>
|
||||
<div class="dropdown-divider"></div>
|
||||
<button class="dropdown-item" appStopClick (click)="selectAll(true)">
|
||||
<i class="fa fa-fw fa-check-square-o" aria-hidden="true"></i>
|
||||
{{'selectAll' | i18n}}
|
||||
</button>
|
||||
<button class="dropdown-item" appStopClick (click)="selectAll(false)">
|
||||
<i class="fa fa-fw fa-minus-square-o" aria-hidden="true"></i>
|
||||
{{'unselectAll' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary ml-3" (click)="invite()">
|
||||
<i class="fa fa-plus fa-fw" aria-hidden="true"></i>
|
||||
{{'inviteUser' | i18n}}
|
||||
|
@ -46,6 +67,9 @@
|
|||
[infiniteScrollDisabled]="!isPaging()" (scrolled)="loadMore()">
|
||||
<tbody>
|
||||
<tr *ngFor="let u of searchedUsers">
|
||||
<td (click)="checkUser(u)" class="table-list-checkbox">
|
||||
<input type="checkbox" [(ngModel)]="u.checked" appStopProp>
|
||||
</td>
|
||||
<td width="30">
|
||||
<app-avatar [data]="u.name || u.email" [email]="u.email" size="25" [circle]="true"
|
||||
[fontSize]="14"></app-avatar>
|
||||
|
|
|
@ -25,6 +25,7 @@ import { UserService } from 'jslib/abstractions/user.service';
|
|||
|
||||
import { OrganizationUserConfirmRequest } from 'jslib/models/request/organizationUserConfirmRequest';
|
||||
|
||||
import { UserBulkReinviteRequest } from 'jslib/models/request/userBulkReinviteRequest';
|
||||
import { OrganizationUserUserDetailsResponse } from 'jslib/models/response/organizationUserResponse';
|
||||
|
||||
import { OrganizationUserStatusType } from 'jslib/enums/organizationUserStatusType';
|
||||
|
@ -38,6 +39,8 @@ import { UserAddEditComponent } from './user-add-edit.component';
|
|||
import { UserConfirmComponent } from './user-confirm.component';
|
||||
import { UserGroupsComponent } from './user-groups.component';
|
||||
|
||||
const MaxCheckedCount = 500;
|
||||
|
||||
@Component({
|
||||
selector: 'app-org-people',
|
||||
templateUrl: 'people.component.html',
|
||||
|
@ -125,6 +128,8 @@ export class PeopleComponent implements OnInit {
|
|||
} else {
|
||||
this.users = this.allUsers;
|
||||
}
|
||||
// Reset checkbox selecton
|
||||
this.selectAll(false);
|
||||
this.resetPaging();
|
||||
}
|
||||
|
||||
|
@ -246,6 +251,30 @@ export class PeopleComponent implements OnInit {
|
|||
this.actionPromise = null;
|
||||
}
|
||||
|
||||
async bulkReinvite() {
|
||||
if (this.actionPromise != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const users = this.getCheckedUsers().filter(u => u.status === OrganizationUserStatusType.Invited);
|
||||
|
||||
if (users.length <= 0) {
|
||||
this.toasterService.popAsync('error', this.i18nService.t('errorOccurred'),
|
||||
this.i18nService.t('noSelectedUsersApplicable'));
|
||||
return;
|
||||
}
|
||||
|
||||
const request = new UserBulkReinviteRequest(users.map(user => user.id));
|
||||
this.actionPromise = this.apiService.postManyOrganizationUserReinvite(this.organizationId, request);
|
||||
try {
|
||||
await this.actionPromise;
|
||||
this.toasterService.popAsync('success', null, this.i18nService.t('usersHasBeenReinvited'));
|
||||
} catch (e) {
|
||||
this.validationService.showError(e);
|
||||
}
|
||||
this.actionPromise = null;
|
||||
}
|
||||
|
||||
async confirm(user: OrganizationUserUserDetailsResponse) {
|
||||
function updateUser(self: PeopleComponent) {
|
||||
user.status = OrganizationUserStatusType.Confirmed;
|
||||
|
@ -358,6 +387,22 @@ export class PeopleComponent implements OnInit {
|
|||
return !searching && this.users && this.users.length > this.pageSize;
|
||||
}
|
||||
|
||||
checkUser(user: OrganizationUserUserDetailsResponse, select?: boolean) {
|
||||
(user as any).checked = select == null ? !(user as any).checked : select;
|
||||
}
|
||||
|
||||
selectAll(select: boolean) {
|
||||
if (select) {
|
||||
this.selectAll(false);
|
||||
}
|
||||
const selectCount = select && this.users.length > MaxCheckedCount
|
||||
? MaxCheckedCount
|
||||
: this.users.length;
|
||||
for (let i = 0; i < selectCount; i++) {
|
||||
this.checkUser(this.users[i], select);
|
||||
}
|
||||
}
|
||||
|
||||
private async doConfirmation(user: OrganizationUserUserDetailsResponse, publicKey: Uint8Array) {
|
||||
const orgKey = await this.cryptoService.getOrgKey(this.organizationId);
|
||||
const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey.buffer);
|
||||
|
@ -391,4 +436,8 @@ export class PeopleComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getCheckedUsers() {
|
||||
return this.users.filter(u => (u as any).checked);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3890,5 +3890,14 @@
|
|||
},
|
||||
"passwordConfirmationDesc": {
|
||||
"message": "This action is protected. To continue, please re-enter your master password to verify your identity."
|
||||
},
|
||||
"reinviteSelected": {
|
||||
"message": "Resend Invitations"
|
||||
},
|
||||
"noSelectedUsersApplicable": {
|
||||
"message": "This action is not applicable to any of the selected users."
|
||||
},
|
||||
"usersHasBeenReinvited": {
|
||||
"message": "The selected users have been reinvited."
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue