Merge pull request #5500 from tsiegleauq/crate-users-svc

Add "create user" to more search value selectors
This commit is contained in:
Emanuel Schütze 2020-08-12 15:00:55 +02:00 committed by GitHub
commit b726801747
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 79 additions and 19 deletions

View File

@ -130,9 +130,9 @@ export class AssignmentRepositoryService extends BaseIsAgendaItemAndListOfSpeake
* of the candidate. Else, the candidate will be added if not on the list, * of the candidate. Else, the candidate will be added if not on the list,
* and removed if on the list * and removed if on the list
*/ */
public async changeCandidate(user: ViewUser, assignment: ViewAssignment, adding?: boolean): Promise<void> { public async changeCandidate(userId: number, assignment: ViewAssignment, adding?: boolean): Promise<void> {
const data = { user: user.id }; const data = { user: userId };
if (assignment.candidates.some(candidate => candidate.id === user.id) && adding !== true) { if (assignment.candidates.some(candidate => candidate.id === userId) && adding !== true) {
await this.httpService.delete(this.restPath + assignment.id + this.candidatureOtherPath, data); await this.httpService.delete(this.restPath + assignment.id + this.candidatureOtherPath, data);
} else if (adding !== false) { } else if (adding !== false) {
await this.httpService.post(this.restPath + assignment.id + this.candidatureOtherPath, data); await this.httpService.post(this.restPath + assignment.id + this.candidatureOtherPath, data);

View File

@ -22,6 +22,11 @@ export interface MassImportResult {
errors: { [id: number]: string }; errors: { [id: number]: string };
} }
export interface NewUser {
id: number;
name: string;
}
/** /**
* type for determining the user name from a string during import. * type for determining the user name from a string during import.
* See {@link parseUserString} for implementations * See {@link parseUserString} for implementations
@ -370,10 +375,10 @@ export class UserRepositoryService extends BaseRepository<ViewUser, User, UserTi
* @param user: String to create the user from * @param user: String to create the user from
* @returns Promise with a created user id and the raw name used as input * @returns Promise with a created user id and the raw name used as input
*/ */
public async createFromString(user: string): Promise<{ id: number; name: string }> { public async createFromString(user: string): Promise<NewUser> {
const newUser = this.parseUserString(user); const newUser = this.parseUserString(user);
const createdUser = await this.create(newUser); const createdUser = await this.create(newUser);
return { id: createdUser.id, name: user }; return { id: createdUser.id, name: user } as NewUser;
} }
/** /**

View File

@ -15,7 +15,7 @@
<div class="section-two"> <div class="section-two">
<!-- {number}. {item.getTitle()} --> <!-- {number}. {item.getTitle()} -->
<span *ngIf="count">{{ i + 1 }}.&nbsp;</span> <span *ngIf="count">{{ i + 1 }}.&nbsp;</span>
<span>{{ item.getTitle() }}</span> <span>{{ item?.getTitle() }}</span>
</div> </div>
<div class="section-three"> <div class="section-three">
<!-- Extra controls slot using implicit template references --> <!-- Extra controls slot using implicit template references -->

View File

@ -512,11 +512,11 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
* *
* @param username The name of the new user. * @param username The name of the new user.
*/ */
public onCreateUser(username: string): void { public async onCreateUser(username: string): Promise<void> {
this.userRepository.createFromString(username).then(result => { const newUser = await this.userRepository.createFromString(username);
this.addNewSpeaker(result.id); this.addNewSpeaker(newUser.id);
});
} }
/** /**
* Triggers an update of the filter for the list of available potential speakers * Triggers an update of the filter for the list of available potential speakers
* (triggered on an update of users or config) * (triggered on an update of users or config)

View File

@ -186,7 +186,14 @@
[multiple]="false" [multiple]="false"
placeholder="{{ 'Select a new candidate' | translate }}" placeholder="{{ 'Select a new candidate' | translate }}"
[inputListValues]="filteredCandidates" [inputListValues]="filteredCandidates"
></os-search-value-selector> [showNotFoundButton]="true"
(clickNotFound)="createNewCandidate($event)"
>
<ng-container notFoundDescription>
<mat-icon>add</mat-icon>
{{ 'Create user' | translate }}
</ng-container>
</os-search-value-selector>
</mat-form-field> </mat-form-field>
</form> </form>
</div> </div>

View File

@ -338,9 +338,8 @@ export class AssignmentDetailComponent extends BaseViewComponent implements OnIn
* @param userId the id of a ViewUser * @param userId the id of a ViewUser
*/ */
public async addUser(userId: number): Promise<void> { public async addUser(userId: number): Promise<void> {
const user = this.userRepo.getViewModel(userId); if (userId) {
if (user) { await this.repo.changeCandidate(userId, this.assignment, true).catch(this.raiseError);
await this.repo.changeCandidate(user, 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 * @param candidate A ViewAssignmentUser currently in the list of related users
*/ */
public async removeUser(candidate: ViewAssignmentRelatedUser): Promise<void> { public async removeUser(candidate: ViewAssignmentRelatedUser): Promise<void> {
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<void> {
const newUserObj = await this.userRepo.createFromString(username);
await this.addUser(newUserObj.id);
} }
/** /**

View File

@ -66,7 +66,9 @@
<mat-icon>picture_as_pdf</mat-icon> <mat-icon>picture_as_pdf</mat-icon>
<span>{{ 'PDF' | translate }}</span> <span>{{ 'PDF' | translate }}</span>
</button> </button>
<mat-divider *osPerms="['core.can_manage_projector', 'agenda.can_manage', 'core.can_see_history']"></mat-divider> <mat-divider
*osPerms="['core.can_manage_projector', 'agenda.can_manage', 'core.can_see_history']"
></mat-divider>
<!-- Project --> <!-- Project -->
<os-projector-button <os-projector-button
[object]="motion" [object]="motion"
@ -627,7 +629,14 @@
[multiple]="true" [multiple]="true"
placeholder="{{ 'Submitters' | translate }}" placeholder="{{ 'Submitters' | translate }}"
[inputListValues]="submitterObserver" [inputListValues]="submitterObserver"
></os-search-value-selector> [showNotFoundButton]="true"
(clickNotFound)="createNewSubmitter($event)"
>
<ng-container notFoundDescription>
<mat-icon>add</mat-icon>
{{ 'Create user' | translate }}
</ng-container>
</os-search-value-selector>
</mat-form-field> </mat-form-field>
</ng-container> </ng-container>
</div> </div>
@ -843,7 +852,14 @@
[multiple]="true" [multiple]="true"
placeholder="{{ 'Supporters' | translate }}" placeholder="{{ 'Supporters' | translate }}"
[inputListValues]="supporterObserver" [inputListValues]="supporterObserver"
></os-search-value-selector> [showNotFoundButton]="true"
(clickNotFound)="createNewSupporter($event)"
>
<ng-container notFoundDescription>
<mat-icon>add</mat-icon>
{{ 'Create user' | translate }}
</ng-container>
</os-search-value-selector>
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>

View File

@ -29,7 +29,7 @@ import { MotionRepositoryService, ParagraphToChoose } from 'app/core/repositorie
import { StatuteParagraphRepositoryService } from 'app/core/repositories/motions/statute-paragraph-repository.service'; import { StatuteParagraphRepositoryService } from 'app/core/repositories/motions/statute-paragraph-repository.service';
import { WorkflowRepositoryService } from 'app/core/repositories/motions/workflow-repository.service'; import { WorkflowRepositoryService } from 'app/core/repositories/motions/workflow-repository.service';
import { TagRepositoryService } from 'app/core/repositories/tags/tag-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 { ConfigService } from 'app/core/ui-services/config.service';
import { DiffLinesInParagraph, LineRange } from 'app/core/ui-services/diff.service'; import { DiffLinesInParagraph, LineRange } from 'app/core/ui-services/diff.service';
import { LinenumberingService } from 'app/core/ui-services/linenumbering.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<void> {
const newUserObj = await this.createNewUser(username);
this.addNewUserToFormCtrl(newUserObj, 'submitters_id');
}
public async createNewSupporter(username: string): Promise<void> {
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<NewUser> {
return this.userRepo.createFromString(username);
}
public swipe(e: TouchEvent, when: string): void { public swipe(e: TouchEvent, when: string): void {
const coord: [number, number] = [e.changedTouches[0].pageX, e.changedTouches[0].pageY]; const coord: [number, number] = [e.changedTouches[0].pageX, e.changedTouches[0].pageY];
const time = new Date().getTime(); const time = new Date().getTime();