diff --git a/client/src/app/core/repositories/assignments/assignment-repository.service.ts b/client/src/app/core/repositories/assignments/assignment-repository.service.ts index 764a181d7..aafd8cc90 100644 --- a/client/src/app/core/repositories/assignments/assignment-repository.service.ts +++ b/client/src/app/core/repositories/assignments/assignment-repository.service.ts @@ -130,9 +130,9 @@ export class AssignmentRepositoryService extends BaseIsAgendaItemAndListOfSpeake * of the candidate. Else, the candidate will be added if not on the list, * and removed if on the list */ - public async changeCandidate(user: ViewUser, assignment: ViewAssignment, adding?: boolean): Promise { - const data = { user: user.id }; - if (assignment.candidates.some(candidate => candidate.id === user.id) && adding !== true) { + public async changeCandidate(userId: number, assignment: ViewAssignment, adding?: boolean): Promise { + const data = { user: userId }; + if (assignment.candidates.some(candidate => candidate.id === userId) && adding !== true) { await this.httpService.delete(this.restPath + assignment.id + this.candidatureOtherPath, data); } else if (adding !== false) { await this.httpService.post(this.restPath + assignment.id + this.candidatureOtherPath, data); diff --git a/client/src/app/core/repositories/users/user-repository.service.ts b/client/src/app/core/repositories/users/user-repository.service.ts index db2f865b7..5f0f56e47 100644 --- a/client/src/app/core/repositories/users/user-repository.service.ts +++ b/client/src/app/core/repositories/users/user-repository.service.ts @@ -22,6 +22,11 @@ export interface MassImportResult { errors: { [id: number]: string }; } +export interface NewUser { + id: number; + name: string; +} + /** * type for determining the user name from a string during import. * See {@link parseUserString} for implementations @@ -370,10 +375,10 @@ export class UserRepositoryService extends BaseRepository { + public async createFromString(user: string): Promise { const newUser = this.parseUserString(user); const createdUser = await this.create(newUser); - return { id: createdUser.id, name: user }; + return { id: createdUser.id, name: user } as NewUser; } /** diff --git a/client/src/app/shared/components/sorting-list/sorting-list.component.html b/client/src/app/shared/components/sorting-list/sorting-list.component.html index bd4660240..93d277810 100644 --- a/client/src/app/shared/components/sorting-list/sorting-list.component.html +++ b/client/src/app/shared/components/sorting-list/sorting-list.component.html @@ -15,7 +15,7 @@
{{ i + 1 }}.  - {{ item.getTitle() }} + {{ item?.getTitle() }}
diff --git a/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.ts b/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.ts index a33669541..1cb050d20 100644 --- a/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.ts +++ b/client/src/app/site/agenda/components/list-of-speakers/list-of-speakers.component.ts @@ -512,11 +512,11 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit * * @param username The name of the new user. */ - public onCreateUser(username: string): void { - this.userRepository.createFromString(username).then(result => { - this.addNewSpeaker(result.id); - }); + public async onCreateUser(username: string): Promise { + const newUser = await this.userRepository.createFromString(username); + this.addNewSpeaker(newUser.id); } + /** * Triggers an update of the filter for the list of available potential speakers * (triggered on an update of users or config) diff --git a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html index 31a97a121..6ac71094f 100644 --- a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html +++ b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.html @@ -186,7 +186,14 @@ [multiple]="false" placeholder="{{ 'Select a new candidate' | translate }}" [inputListValues]="filteredCandidates" - > + [showNotFoundButton]="true" + (clickNotFound)="createNewCandidate($event)" + > + + add + {{ 'Create user' | translate }} + +
diff --git a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts index 199757ebb..736ad9944 100644 --- a/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts +++ b/client/src/app/site/assignments/components/assignment-detail/assignment-detail.component.ts @@ -338,9 +338,8 @@ export class AssignmentDetailComponent extends BaseViewComponent implements OnIn * @param userId the id of a ViewUser */ public async addUser(userId: number): Promise { - const user = this.userRepo.getViewModel(userId); - if (user) { - await this.repo.changeCandidate(user, this.assignment, true).catch(this.raiseError); + if (userId) { + await this.repo.changeCandidate(userId, this.assignment, true).catch(this.raiseError); } } @@ -350,7 +349,15 @@ export class AssignmentDetailComponent extends BaseViewComponent implements OnIn * @param candidate A ViewAssignmentUser currently in the list of related users */ public async removeUser(candidate: ViewAssignmentRelatedUser): Promise { - await this.repo.changeCandidate(candidate.user, this.assignment, false).catch(this.raiseError); + await this.repo.changeCandidate(candidate.user.id, this.assignment, false).catch(this.raiseError); + } + + /** + * Creates unfound candidate on the fly and add the the list + */ + public async createNewCandidate(username: string): Promise { + const newUserObj = await this.userRepo.createFromString(username); + await this.addUser(newUserObj.id); } /** diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html index c32c99510..b1298ef51 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.html @@ -66,7 +66,9 @@ picture_as_pdf {{ 'PDF' | translate }} - + + [showNotFoundButton]="true" + (clickNotFound)="createNewSubmitter($event)" + > + + add + {{ 'Create user' | translate }} + + @@ -843,7 +852,14 @@ [multiple]="true" placeholder="{{ 'Supporters' | translate }}" [inputListValues]="supporterObserver" - > + [showNotFoundButton]="true" + (clickNotFound)="createNewSupporter($event)" + > + + add + {{ 'Create user' | translate }} + + diff --git a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts index 83c80175d..0735c7f71 100644 --- a/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts +++ b/client/src/app/site/motions/modules/motion-detail/components/motion-detail/motion-detail.component.ts @@ -29,7 +29,7 @@ import { MotionRepositoryService, ParagraphToChoose } from 'app/core/repositorie import { StatuteParagraphRepositoryService } from 'app/core/repositories/motions/statute-paragraph-repository.service'; import { WorkflowRepositoryService } from 'app/core/repositories/motions/workflow-repository.service'; import { TagRepositoryService } from 'app/core/repositories/tags/tag-repository.service'; -import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service'; +import { NewUser, UserRepositoryService } from 'app/core/repositories/users/user-repository.service'; import { ConfigService } from 'app/core/ui-services/config.service'; import { DiffLinesInParagraph, LineRange } from 'app/core/ui-services/diff.service'; import { LinenumberingService } from 'app/core/ui-services/linenumbering.service'; @@ -1705,6 +1705,31 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit, } } + public async createNewSubmitter(username: string): Promise { + const newUserObj = await this.createNewUser(username); + this.addNewUserToFormCtrl(newUserObj, 'submitters_id'); + } + + public async createNewSupporter(username: string): Promise { + const newUserObj = await this.createNewUser(username); + this.addNewUserToFormCtrl(newUserObj, 'supporters_id'); + } + + private addNewUserToFormCtrl(newUserObj: NewUser, controlName: string): void { + const control = this.contentForm.get(controlName); + let currentSubmitters: number[] = control.value; + if (currentSubmitters?.length) { + currentSubmitters.push(newUserObj.id); + } else { + currentSubmitters = [newUserObj.id]; + } + control.setValue(currentSubmitters); + } + + private createNewUser(username: string): Promise { + return this.userRepo.createFromString(username); + } + public swipe(e: TouchEvent, when: string): void { const coord: [number, number] = [e.changedTouches[0].pageX, e.changedTouches[0].pageY]; const time = new Date().getTime();