Skip to content

Commit da6d685

Browse files
Merge pull request #446 from Breeding-Insight/bug/BI-2691
BI-2691 - Cannot add Xuemei to Alfalfa Prosser program
2 parents fc73038 + 599d7df commit da6d685

File tree

5 files changed

+163
-40
lines changed

5 files changed

+163
-40
lines changed

src/breeding-insight/dao/UserDAO.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {BiResponse} from "@/breeding-insight/model/BiResponse";
2121
import {Role} from "@/breeding-insight/model/Role";
2222
import {PaginationQuery} from "@/breeding-insight/model/PaginationQuery";
2323
import {UserSort} from "@/breeding-insight/model/Sort";
24+
import {SearchRequest} from "@/breeding-insight/model/SearchRequest";
2425

2526
export class UserDAO {
2627

@@ -101,6 +102,40 @@ export class UserDAO {
101102

102103
}
103104

105+
static getById(id: string): Promise<BiResponse> {
106+
return new Promise<BiResponse>((resolve, reject) => {
107+
api.call({ url: `${process.env.VUE_APP_BI_API_V1_PATH}/users/${id}`, method: 'get' })
108+
.then((response: any) => {
109+
const biResponse = new BiResponse(response.data);
110+
resolve(biResponse);
111+
}).catch((error) => reject(error));
112+
});
113+
}
114+
115+
static search(searchRequest: SearchRequest, {page, pageSize}: PaginationQuery, {field, order}: UserSort): Promise<BiResponse> {
116+
117+
return new Promise<BiResponse>(((resolve, reject) => {
118+
const config = {
119+
url: `${process.env.VUE_APP_BI_API_V1_PATH}/users/search`,
120+
method: 'post',
121+
data: searchRequest,
122+
params: {
123+
sortField: field,
124+
sortOrder: order,
125+
page,
126+
pageSize
127+
}
128+
}
129+
api.call(config)
130+
.then((response: any) => {
131+
const biResponse = new BiResponse(response.data);
132+
resolve(biResponse);
133+
}).catch((error) => {
134+
reject(error);
135+
})
136+
}));
137+
}
138+
104139
static updateSystemRoles(id: string, systemRoles: Array<Role>) {
105140

106141
return new Promise<BiResponse>((resolve, reject) => {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* See the NOTICE file distributed with this work for additional information
3+
* regarding copyright ownership.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
export class FilterRequest {
19+
field: string;
20+
value: string;
21+
22+
constructor(field: string, value: string) {
23+
this.field = field;
24+
this.value = value;
25+
}
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* See the NOTICE file distributed with this work for additional information
3+
* regarding copyright ownership.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import {FilterRequest} from "@/breeding-insight/model/FilterRequest";
19+
20+
export class SearchRequest {
21+
filters: FilterRequest[] = [];
22+
23+
constructor(filters: FilterRequest[]) {
24+
this.filters = filters;
25+
}
26+
}

src/breeding-insight/service/UserService.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ import {Program} from "@/breeding-insight/model/Program";
2424
import {ProgramUser} from "@/breeding-insight/model/ProgramUser";
2525
import {PaginationQuery} from "@/breeding-insight/model/PaginationQuery";
2626
import {ProgramSort, SortOrder, UserSort, UserSortField} from "@/breeding-insight/model/Sort";
27+
import {SearchRequest} from "@/breeding-insight/model/SearchRequest";
2728

2829
export class UserService {
2930

3031
static duplicateEmailMessage : string = 'Email is already in use.';
3132
static errorCreateUser: string = 'Unable to create user';
3233
static errorDeleteUser: string = 'Unable to archive user';
33-
static errorGetUsers: string = 'Error while trying to load roles';
34+
static errorGetUsers: string = 'Error while trying to load users';
35+
static errorSearchUsers: string = 'Error while searching users';
36+
static errorGetUser: string = 'User not found';
3437
static errorDeleteUserNotFound: string = 'Unable to find user to deactivate';
3538
static errorDeleteUserNotAllowed: string = 'You are not allowed to deactivate this user.';
3639
static errorPermissionsEditUser: string = "You don't have permissions to edit the roles of this user.";
@@ -153,6 +156,45 @@ export class UserService {
153156
}));
154157
}
155158

159+
static getById(id: string): Promise<User> {
160+
return new Promise<User>((resolve, reject) => {
161+
UserDAO.getById(id).then((biResponse: BiResponse) => {
162+
const result: any = biResponse.result;
163+
const role: Role | undefined = this.parseSystemRoles(result.systemRoles);
164+
const programRoles: ProgramUser[] | undefined = this.parseProgramRoles(result.programRoles);
165+
const user = new User(result.id, result.name, result.orcid, result.email, role, programRoles);
166+
resolve(user);
167+
}).catch((error) => {
168+
error['errorMessage'] = this.errorGetUser;
169+
reject(error);
170+
});
171+
});
172+
}
173+
174+
static search(searchRequest: SearchRequest,
175+
paginationQuery: PaginationQuery = new PaginationQuery(1, 50, true),
176+
sort: UserSort = new UserSort(UserSortField.Name, SortOrder.Ascending)): Promise<[User[], Metadata]> {
177+
return new Promise<[User[], Metadata]>(((resolve, reject) => {
178+
179+
UserDAO.search(searchRequest, paginationQuery, sort).then((biResponse) => {
180+
181+
// Parse our users into the vue users param
182+
let users = biResponse.result.data.map((user: any) => {
183+
const role: Role | undefined = this.parseSystemRoles(user.systemRoles);
184+
const programRoles: ProgramUser[] | undefined = this.parseProgramRoles(user.programRoles);
185+
return new User(user.id, user.name, user.orcid, user.email, role, programRoles);
186+
});
187+
188+
resolve([users, biResponse.metadata]);
189+
190+
}).catch((error) => {
191+
error['errorMessage'] = this.errorSearchUsers;
192+
reject(error)
193+
});
194+
195+
}));
196+
}
197+
156198
static updateSystemRoles(user: User): Promise<User> {
157199

158200
return new Promise<User>((resolve, reject) => {

src/components/program/ProgramUsersTable.vue

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@
191191
import {
192192
UPDATE_PROGRAM_USER_SORT
193193
} from "@/store/sorting/mutation-types";
194+
import {SearchRequest} from "@/breeding-insight/model/SearchRequest";
195+
import {FilterRequest} from "@/breeding-insight/model/FilterRequest";
194196
195197
@Component({
196198
components: { ExpandableTable, NewDataForm, BasicInputField, BasicSelectField, TableColumn,
@@ -218,7 +220,6 @@ export default class ProgramUsersTable extends Vue {
218220
private activeProgram?: Program;
219221
private activeUser?: User;
220222
public users: ProgramUser[] = [];
221-
public systemUsers: User[] = [];
222223
223224
private deactivateActive: boolean = false;
224225
private newUserActive: boolean = false;
@@ -252,7 +253,6 @@ export default class ProgramUsersTable extends Vue {
252253
253254
mounted() {
254255
this.getRoles();
255-
this.getSystemUsers();
256256
this.paginationChanged();
257257
}
258258
@@ -333,41 +333,40 @@ export default class ProgramUsersTable extends Vue {
333333
334334
}
335335
336-
saveUser() {
336+
async saveUser() {
337337
338338
this.newUser.program = this.activeProgram;
339339
340340
try {
341-
this.newUser = this.checkExistingUserByEmail(this.newUser, this.systemUsers);
341+
this.newUser = await this.checkExistingUserByEmail(this.newUser);
342342
} catch (err) {
343343
this.$emit('show-error-notification', err);
344344
this.newUserFormState.bus.$emit(DataFormEventBusHandler.SAVE_COMPLETE_EVENT);
345345
return;
346346
}
347347
348+
// if we found a system user by email in checkExistingUserByEmail then system user exists
349+
const systemUserExisted = this.newUser.id !== undefined;
350+
348351
ProgramUserService.create(this.newUser).then((user: ProgramUser) => {
349352
this.paginationController.updatePage(1);
350353
this.paginationController.updateOnAdd();
351354
this.getUsers();
352-
this.getSystemUsers();
353355
354356
// See if the user already existed
355-
//TODO: Reconsider when user search feature is added
356-
if (this.getSystemUserById(user, this.systemUsers)) {
357+
if (systemUserExisted) {
357358
this.$emit('show-success-notification', 'Success! Existing user ' + user.name + ' added to program.');
358359
} else {
359360
this.$emit('show-success-notification', 'Success! ' + this.newUser.name + ' added.');
360361
}
361362
362363
if(this.newUser.email === this.activeUser!.email) this.updateActiveUser();
363364
364-
this.getSystemUsers();
365365
this.newUser = new ProgramUser();
366366
this.newUserActive = false;
367367
}).catch((error) => {
368368
this.$emit('show-error-notification', error.errorMessage);
369369
this.getUsers();
370-
this.getSystemUsers();
371370
}).finally(() => this.newUserFormState.bus.$emit(DataFormEventBusHandler.SAVE_COMPLETE_EVENT))
372371
373372
}
@@ -379,47 +378,42 @@ export default class ProgramUsersTable extends Vue {
379378
Vue.prototype.$ability.update(rules);
380379
}
381380
382-
//TODO: Reconsider when user search feature is added
383-
getSystemUsers() {
381+
//TODO: Do we still want this since orcid entry is removed?
382+
async checkExistingUserByEmail(user: ProgramUser): Promise<ProgramUser> {
383+
user.id = undefined;
384+
// api call to check if user exists for email
385+
// this was done on front-end before because we didn't have search endpoint at the time
386+
const filter = new FilterRequest('email', user.email);
387+
const request = new SearchRequest(filter);
384388
385-
UserService.getAll().then(([users, metadata]) => {
386-
this.systemUsers = users;
387-
}).catch((error) => {
389+
try {
390+
const [users, metadata] = await UserService.search(request);
391+
// email exists
392+
if (users.length === 1) {
393+
user.id = users[0].id;
394+
}
395+
} catch (error) {
388396
// Display error that users cannot be loaded
389397
this.$emit('show-error-notification', 'Error while trying to load system users');
390398
throw error;
391-
});
392-
393-
}
394-
395-
//TODO: Reconsider when user search feature is added
396-
//TODO: Do we still want this since orcid entry is removed?
397-
checkExistingUserByEmail(user: ProgramUser, systemUsers: User[]): ProgramUser {
398-
user.id = undefined;
399-
let usersFound = 0;
400-
for (const systemUser of systemUsers){
401-
if (user.email === systemUser.email){
402-
usersFound += 1;
403-
if (systemUser.id){
404-
user.id = systemUser.id;
405-
}
406-
}
407399
}
408400
409-
if (usersFound > 1){
410-
throw "Email matches two different users.";
411-
}
412401
413402
return user;
414403
}
415404
416-
//TODO: Reconsider when user search feature is added
417-
getSystemUserById(user: ProgramUser, systemUsers: User[]): User | undefined {
418-
for (const systemUser of systemUsers){
419-
if (user.id === systemUser.id){
420-
return systemUser;
405+
getSystemUserById(user: ProgramUser): User | undefined {
406+
407+
UserService.getById(user.id).then(([users, metadata]) => {
408+
if (users.length === 1) {
409+
return users[0];
421410
}
422-
}
411+
}).catch((error) => {
412+
// Display error that users cannot be loaded
413+
this.$emit('show-error-notification', 'Error while trying to load system user');
414+
throw error;
415+
});
416+
423417
return undefined;
424418
}
425419

0 commit comments

Comments
 (0)