Skip to content

Commit fa37773

Browse files
authored
Allow adding existing users to registrar (#2616)
1 parent 21950f7 commit fa37773

File tree

14 files changed

+417
-107
lines changed

14 files changed

+417
-107
lines changed

console-webapp/src/app/shared/services/backend.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,9 @@ export class BackendService {
166166
.pipe(catchError((err) => this.errorCatcher<User[]>(err)));
167167
}
168168

169-
createUser(registrarId: string): Observable<User> {
169+
createUser(registrarId: string, maybeUser: User | null): Observable<User> {
170170
return this.http
171-
.post<User>(`/console-api/users?registrarId=${registrarId}`, {})
171+
.post<User>(`/console-api/users?registrarId=${registrarId}`, maybeUser)
172172
.pipe(catchError((err) => this.errorCatcher<User>(err)));
173173
}
174174

console-webapp/src/app/shared/services/userData.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export interface UserData {
2727
supportEmail: string;
2828
supportPhoneNumber: string;
2929
technicalDocsUrl: string;
30+
userRoles?: Map<string, string>;
3031
}
3132

3233
@Injectable({

console-webapp/src/app/users/userEdit.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { SelectedRegistrarModule } from '../app.module';
1919
import { MaterialModule } from '../material.module';
2020
import { RegistrarService } from '../registrar/registrar.service';
2121
import { SnackBarModule } from '../snackbar.module';
22-
import { User, UsersService, roleToDescription } from './users.service';
22+
import { UsersService, roleToDescription } from './users.service';
2323
import { FormsModule } from '@angular/forms';
2424

2525
@Component({

console-webapp/src/app/users/users.component.html

Lines changed: 80 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,94 @@
33
<div class="console-app__users-spinner">
44
<mat-spinner />
55
</div>
6+
} @else if(selectingExistingUser) {
7+
8+
<div class="console-app__users">
9+
<h1 class="mat-headline-4">Add existing user</h1>
10+
11+
<p>
12+
<button
13+
mat-icon-button
14+
aria-label="Back to users list"
15+
(click)="selectingExistingUser = false"
16+
>
17+
<mat-icon>arrow_back</mat-icon>
18+
</button>
19+
</p>
20+
<h1>Select registrar from which to add a new user</h1>
21+
<p>
22+
<mat-form-field appearance="outline">
23+
<mat-label>Registrar</mat-label>
24+
<mat-select
25+
[(ngModel)]="selectedRegistrarId"
26+
name="selectedRegistrarId"
27+
(selectionChange)="onRegistrarSelectionChange($event)"
28+
>
29+
@for (registrar of registrarService.registrars(); track registrar) {
30+
<mat-option [value]="registrar.registrarId">{{
31+
registrar.registrarId
32+
}}</mat-option>
33+
}
34+
</mat-select>
35+
</mat-form-field>
36+
</p>
37+
@if(usersSelection.length) {
38+
<app-users-list
39+
[users]="usersSelection"
40+
(onSelect)="existingUserSelected($event)"
41+
/>
42+
<p class="console-app__users-add-existing">
43+
<button
44+
mat-flat-button
45+
color="primary"
46+
aria-label="Add user"
47+
(click)="submitExistingUser()"
48+
[disabled]="!selectedExistingUser"
49+
>
50+
Add user
51+
</button>
52+
<button
53+
mat-stroked-button
54+
aria-label="Cancel adding existing user"
55+
(click)="selectingExistingUser = false"
56+
>
57+
Cancel
58+
</button>
59+
</p>
60+
}
61+
</div>
662
} @else if(usersService.currentlyOpenUserEmail()) {
763
<app-user-edit></app-user-edit>
864
} @else {
965
<div class="console-app__users">
1066
<div class="console-app__users-header">
1167
<h1 class="mat-headline-4">Users</h1>
1268
<div class="spacer"></div>
13-
<button
14-
mat-flat-button
15-
(click)="createNewUser()"
16-
aria-label="Create new user"
17-
color="primary"
18-
>
19-
Create a Viewer User
20-
</button>
69+
<div class="console-app__users-header-buttons">
70+
<button
71+
class="console-app__users-header-add"
72+
mat-stroked-button
73+
(click)="addExistingUser()"
74+
aria-label="Create new user"
75+
color="primary"
76+
>
77+
<mat-icon>add</mat-icon>
78+
Add existing user
79+
</button>
80+
<button
81+
mat-flat-button
82+
(click)="createNewUser()"
83+
aria-label="Create new user"
84+
color="primary"
85+
>
86+
Create a Viewer User
87+
</button>
88+
</div>
2189
</div>
22-
<mat-table
23-
[dataSource]="dataSource"
24-
class="mat-elevation-z0"
25-
class="console-app__users-table"
26-
matSort
27-
>
28-
<ng-container
29-
*ngFor="let column of columns"
30-
[matColumnDef]="column.columnDef"
31-
>
32-
<mat-header-cell *matHeaderCellDef>
33-
{{ column.header }}
34-
</mat-header-cell>
35-
<mat-cell
36-
*matCellDef="let row"
37-
[innerHTML]="column.cell(row)"
38-
></mat-cell>
39-
</ng-container>
40-
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
41-
<mat-row
42-
*matRowDef="let row; columns: displayedColumns"
43-
(click)="openDetails(row.emailAddress)"
44-
></mat-row>
45-
</mat-table>
90+
<app-users-list
91+
[users]="usersService.users()"
92+
(onSelect)="openDetails($event)"
93+
/>
4694
</div>
4795
}
4896
</app-selected-registrar-wrapper>

console-webapp/src/app/users/users.component.scss

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,37 @@
1313
// limitations under the License.
1414

1515
.console-app {
16+
&__users {
17+
max-width: 1024px;
18+
overflow-x: auto;
19+
}
20+
1621
&__users-spinner {
1722
align-items: center;
1823
display: flex;
1924
justify-content: center;
2025
}
2126

22-
$min-width: 756px;
23-
$max-width: 1024px;
24-
25-
&__users-table {
26-
min-width: $min-width !important;
27-
max-width: $max-width;
28-
}
29-
3027
&__users-new {
3128
margin-left: 20px;
3229
}
3330

31+
&__users-add-existing {
32+
margin-top: 20px;
33+
> button {
34+
margin-right: 15px;
35+
}
36+
}
3437
&__users-header {
3538
display: flex;
3639
justify-content: space-between;
40+
flex-wrap: wrap;
41+
&-buttons {
42+
display: flex;
43+
flex-wrap: wrap;
44+
button {
45+
margin: 0 15px 15px 0;
46+
}
47+
}
3748
}
3849
}

console-webapp/src/app/users/users.component.ts

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,71 +14,64 @@
1414

1515
import { CommonModule } from '@angular/common';
1616
import { HttpErrorResponse } from '@angular/common/http';
17-
import { Component, effect, ViewChild } from '@angular/core';
17+
import { Component, effect } from '@angular/core';
1818
import { MatSnackBar } from '@angular/material/snack-bar';
19-
import { MatSort } from '@angular/material/sort';
20-
import { MatTableDataSource } from '@angular/material/table';
2119
import { SelectedRegistrarModule } from '../app.module';
2220
import { MaterialModule } from '../material.module';
2321
import { RegistrarService } from '../registrar/registrar.service';
2422
import { SnackBarModule } from '../snackbar.module';
2523
import { UserEditComponent } from './userEdit.component';
26-
import { roleToDescription, User, UsersService } from './users.service';
27-
28-
export const columns = [
29-
{
30-
columnDef: 'emailAddress',
31-
header: 'User email',
32-
cell: (record: User) => `${record.emailAddress || ''}`,
33-
},
34-
{
35-
columnDef: 'role',
36-
header: 'User role',
37-
cell: (record: User) => `${roleToDescription(record.role)}`,
38-
},
39-
];
24+
import { User, UsersService } from './users.service';
25+
import { UserDataService } from '../shared/services/userData.service';
26+
import { FormsModule } from '@angular/forms';
27+
import { UsersListComponent } from './usersList.component';
28+
import { MatSelectChange } from '@angular/material/select';
4029

4130
@Component({
4231
selector: 'app-users',
4332
templateUrl: './users.component.html',
4433
styleUrls: ['./users.component.scss'],
4534
standalone: true,
4635
imports: [
36+
FormsModule,
4737
MaterialModule,
4838
SnackBarModule,
4939
CommonModule,
5040
SelectedRegistrarModule,
41+
UsersListComponent,
5142
UserEditComponent,
5243
],
5344
providers: [UsersService],
5445
})
5546
export class UsersComponent {
56-
dataSource: MatTableDataSource<User>;
57-
columns = columns;
58-
displayedColumns = this.columns.map((c) => c.columnDef);
5947
isLoading = false;
60-
61-
@ViewChild(MatSort) sort!: MatSort;
48+
selectingExistingUser = false;
49+
selectedRegistrarId = '';
50+
usersSelection: User[] = [];
51+
selectedExistingUser: User | undefined;
6252

6353
constructor(
6454
protected registrarService: RegistrarService,
6555
protected usersService: UsersService,
56+
private userDataService: UserDataService,
6657
private _snackBar: MatSnackBar
6758
) {
68-
this.dataSource = new MatTableDataSource<User>(usersService.users());
69-
7059
effect(() => {
7160
if (registrarService.registrarId()) {
7261
this.loadUsers();
7362
}
7463
});
75-
effect(() => {
76-
this.dataSource.data = usersService.users();
77-
});
7864
}
7965

80-
ngAfterViewInit() {
81-
this.dataSource.sort = this.sort;
66+
addExistingUser() {
67+
this.selectingExistingUser = true;
68+
this.selectedRegistrarId = '';
69+
this.usersSelection = [];
70+
this.selectedExistingUser = undefined;
71+
}
72+
73+
existingUserSelected(user: User) {
74+
this.selectedExistingUser = user;
8275
}
8376

8477
loadUsers() {
@@ -96,7 +89,7 @@ export class UsersComponent {
9689

9790
createNewUser() {
9891
this.isLoading = true;
99-
this.usersService.createNewUser().subscribe({
92+
this.usersService.createOrAddNewUser(null).subscribe({
10093
error: (err: HttpErrorResponse) => {
10194
this._snackBar.open(err.error || err.message);
10295
this.isLoading = false;
@@ -107,7 +100,39 @@ export class UsersComponent {
107100
});
108101
}
109102

110-
openDetails(emailAddress: string) {
111-
this.usersService.currentlyOpenUserEmail.set(emailAddress);
103+
openDetails(user: User) {
104+
this.usersService.currentlyOpenUserEmail.set(user.emailAddress);
105+
}
106+
107+
onRegistrarSelectionChange(e: MatSelectChange) {
108+
if (e.value) {
109+
this.usersService.fetchUsersForRegistrar(e.value).subscribe({
110+
error: (err) => {
111+
this._snackBar.open(err.error || err.message);
112+
},
113+
next: (users) => {
114+
this.usersSelection = users;
115+
},
116+
});
117+
}
118+
}
119+
120+
submitExistingUser() {
121+
this.isLoading = true;
122+
if (this.selectedExistingUser) {
123+
this.usersService
124+
.createOrAddNewUser(this.selectedExistingUser)
125+
.subscribe({
126+
error: (err) => {
127+
this._snackBar.open(err.error || err.message);
128+
this.isLoading = false;
129+
},
130+
complete: () => {
131+
this.isLoading = false;
132+
this.selectingExistingUser = false;
133+
this.loadUsers();
134+
},
135+
});
136+
}
112137
}
113138
}

console-webapp/src/app/users/users.service.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ export class UsersService {
4646
private registrarService: RegistrarService
4747
) {}
4848

49+
fetchUsersForRegistrar(registrarId: string) {
50+
return this.backendService.getUsers(registrarId);
51+
}
52+
4953
fetchUsers() {
5054
return this.backendService
5155
.getUsers(this.registrarService.registrarId())
@@ -56,14 +60,16 @@ export class UsersService {
5660
);
5761
}
5862

59-
createNewUser() {
63+
createOrAddNewUser(maybeExistingUser: User | null) {
6064
return this.backendService
61-
.createUser(this.registrarService.registrarId())
65+
.createUser(this.registrarService.registrarId(), maybeExistingUser)
6266
.pipe(
6367
tap((newUser: User) => {
64-
this.users.set([...this.users(), newUser]);
65-
this.currentlyOpenUserEmail.set(newUser.emailAddress);
66-
this.isNewUser = true;
68+
if (newUser) {
69+
this.users.set([...this.users(), newUser]);
70+
this.currentlyOpenUserEmail.set(newUser.emailAddress);
71+
this.isNewUser = true;
72+
}
6773
})
6874
);
6975
}

0 commit comments

Comments
 (0)