Merge pull request #4169 from tsiegleauq/gender-client
Add gender field to users
This commit is contained in:
commit
c48148fc01
@ -2,6 +2,11 @@ import { Searchable } from '../base/searchable';
|
|||||||
import { SearchRepresentation } from '../../../core/services/search.service';
|
import { SearchRepresentation } from '../../../core/services/search.service';
|
||||||
import { BaseModel } from '../base/base-model';
|
import { BaseModel } from '../base/base-model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterable pre selection of genders (sexes)
|
||||||
|
*/
|
||||||
|
export const genders = ['Female', 'Male', 'Diverse'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of a user in contrast to the operator.
|
* Representation of a user in contrast to the operator.
|
||||||
* @ignore
|
* @ignore
|
||||||
@ -14,6 +19,7 @@ export class User extends BaseModel<User> implements Searchable {
|
|||||||
public title: string;
|
public title: string;
|
||||||
public first_name: string;
|
public first_name: string;
|
||||||
public last_name: string;
|
public last_name: string;
|
||||||
|
public gender: string;
|
||||||
public structure_level: string;
|
public structure_level: string;
|
||||||
public number: string;
|
public number: string;
|
||||||
public about_me: string;
|
public about_me: string;
|
||||||
|
@ -4,9 +4,7 @@
|
|||||||
<h2><span translate>List of speakers</span></h2>
|
<h2><span translate>List of speakers</span></h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="menu-slot" *osPerms="'agenda.can_manage_list_of_speakers'">
|
<div class="menu-slot" *osPerms="'agenda.can_manage_list_of_speakers'">
|
||||||
<button type="button" mat-icon-button [matMenuTriggerFor]="speakerMenu">
|
<button type="button" mat-icon-button [matMenuTriggerFor]="speakerMenu"><mat-icon>more_vert</mat-icon></button>
|
||||||
<mat-icon>more_vert</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</os-head-bar>
|
</os-head-bar>
|
||||||
|
|
||||||
@ -68,6 +66,7 @@
|
|||||||
<span *ngIf="hasSpokenCount(item)" class="red-warning-text speaker-warning">
|
<span *ngIf="hasSpokenCount(item)" class="red-warning-text speaker-warning">
|
||||||
{{ hasSpokenCount(item) + 1 }}. <span translate>contribution</span>
|
{{ hasSpokenCount(item) + 1 }}. <span translate>contribution</span>
|
||||||
</span>
|
</span>
|
||||||
|
<span *ngIf="item.gender">({{ item.gender | translate }})</span>
|
||||||
</span>
|
</span>
|
||||||
<mat-button-toggle-group *osPerms="'agenda.can_manage_list_of_speakers'">
|
<mat-button-toggle-group *osPerms="'agenda.can_manage_list_of_speakers'">
|
||||||
<mat-button-toggle matTooltip="{{ 'Begin speech' | translate }}" (click)="onStartButton(item)">
|
<mat-button-toggle matTooltip="{{ 'Begin speech' | translate }}" (click)="onStartButton(item)">
|
||||||
@ -117,7 +116,6 @@
|
|||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<mat-menu #speakerMenu="matMenu">
|
<mat-menu #speakerMenu="matMenu">
|
||||||
|
|
||||||
<button mat-menu-item *ngIf="closedList" (click)="openSpeakerList()">
|
<button mat-menu-item *ngIf="closedList" (click)="openSpeakerList()">
|
||||||
<mat-icon>mic</mat-icon>
|
<mat-icon>mic</mat-icon>
|
||||||
<span translate>Open list of speakers</span>
|
<span translate>Open list of speakers</span>
|
||||||
|
@ -46,6 +46,10 @@ export class ViewSpeaker extends BaseViewModel implements Selectable {
|
|||||||
return this.user.full_name || this.user.username;
|
return this.user.full_name || this.user.username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get gender(): string {
|
||||||
|
return this.user.gender || '';
|
||||||
|
}
|
||||||
|
|
||||||
public constructor(speaker?: Speaker, user?: User) {
|
public constructor(speaker?: Speaker, user?: User) {
|
||||||
super();
|
super();
|
||||||
this._speaker = speaker;
|
this._speaker = speaker;
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="title-slot">
|
<div class="title-slot">
|
||||||
<h2>
|
<h2>
|
||||||
<span *ngIf="newUser" translate>New participant</span>
|
<span *ngIf="newUser" translate>New participant</span> <span *ngIf="!newUser">{{ user.full_name }}</span>
|
||||||
<span *ngIf="!newUser">{{ user.full_name }}</span>
|
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -39,61 +38,74 @@
|
|||||||
[formGroup]="personalInfoForm"
|
[formGroup]="personalInfoForm"
|
||||||
(ngSubmit)="saveUser()"
|
(ngSubmit)="saveUser()"
|
||||||
*ngIf="user"
|
*ngIf="user"
|
||||||
(keydown)="onKeyDown($event)">
|
(keydown)="onKeyDown($event)"
|
||||||
|
>
|
||||||
<!-- <h3 translate>Personal Data</h3> -->
|
<!-- <h3 translate>Personal Data</h3> -->
|
||||||
<div *ngIf="isAllowed('seeName')">
|
<div *ngIf="isAllowed('seeName')">
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<mat-form-field
|
<mat-form-field
|
||||||
class="form16 distance force-min-with"
|
class="form16 distance force-min-with"
|
||||||
*ngIf="user.title || (editUser && isAllowed('manage'))">
|
*ngIf="user.title || (editUser && isAllowed('manage'))"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
matInput
|
matInput
|
||||||
osAutofocus
|
osAutofocus
|
||||||
placeholder="{{ 'Title' | translate }}"
|
placeholder="{{ 'Title' | translate }}"
|
||||||
formControlName="title"
|
formControlName="title"
|
||||||
[value]="user.title"/>
|
[value]="user.title"
|
||||||
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<!-- First name -->
|
<!-- First name -->
|
||||||
<mat-form-field
|
<mat-form-field
|
||||||
class="form37 distance force-min-with"
|
class="form37 distance force-min-with"
|
||||||
*ngIf="user.first_name || (editUser && isAllowed('manage'))">
|
*ngIf="user.first_name || (editUser && isAllowed('manage'))"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
matInput
|
matInput
|
||||||
placeholder="{{ 'Given name' | translate }}"
|
placeholder="{{ 'Given name' | translate }}"
|
||||||
formControlName="first_name"
|
formControlName="first_name"
|
||||||
[value]="user.first_name"/>
|
[value]="user.first_name"
|
||||||
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<!-- Last name -->
|
<!-- Last name -->
|
||||||
<mat-form-field
|
<mat-form-field class="form37 force-min-with" *ngIf="user.last_name || (editUser && isAllowed('manage'))">
|
||||||
class="form37 force-min-with"
|
|
||||||
*ngIf="user.last_name || (editUser && isAllowed('manage'))">
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
matInput
|
matInput
|
||||||
placeholder="{{ 'Surname' | translate }}"
|
placeholder="{{ 'Surname' | translate }}"
|
||||||
formControlName="last_name"
|
formControlName="last_name"
|
||||||
[value]="user.last_name"/>
|
[value]="user.last_name"
|
||||||
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="isAllowed('seePersonal')">
|
<div *ngIf="isAllowed('seePersonal')">
|
||||||
<!-- E-Mail -->
|
<!-- E-Mail -->
|
||||||
<mat-form-field *ngIf="user.email || editUser">
|
<mat-form-field class="form70 distance" *ngIf="user.email || editUser">
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
matInput
|
matInput
|
||||||
placeholder="{{ 'Email' | translate }}"
|
placeholder="{{ 'Email' | translate }}"
|
||||||
name="email"
|
name="email"
|
||||||
formControlName="email"
|
formControlName="email"
|
||||||
[value]="user.email"/>
|
[value]="user.email"
|
||||||
|
/>
|
||||||
<mat-error *ngIf="personalInfoForm.get('email').hasError('email')" translate>
|
<mat-error *ngIf="personalInfoForm.get('email').hasError('email')" translate>
|
||||||
Please enter a valid email address
|
Please enter a valid email address
|
||||||
</mat-error>
|
</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
<!-- Gender -->
|
||||||
|
<mat-form-field class="form25 force-min-with" *ngIf="user.gender || editUser">
|
||||||
|
<mat-select placeholder="{{ 'Gender' | translate }}" formControlName="gender">
|
||||||
|
<mat-option>-</mat-option>
|
||||||
|
<mat-option *ngFor="let gender of genderList" [value]="gender">{{ gender | translate }}</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -104,19 +116,22 @@
|
|||||||
matInput
|
matInput
|
||||||
placeholder="{{ 'Structure level' | translate }}"
|
placeholder="{{ 'Structure level' | translate }}"
|
||||||
formControlName="structure_level"
|
formControlName="structure_level"
|
||||||
[value]="user.structure_level"/>
|
[value]="user.structure_level"
|
||||||
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<!-- Participant Number -->
|
<!-- Participant Number -->
|
||||||
<mat-form-field
|
<mat-form-field
|
||||||
class="form25 force-min-with"
|
class="form25 force-min-with"
|
||||||
*ngIf="user.participant_number || (editUser && isAllowed('manage'))">
|
*ngIf="user.participant_number || (editUser && isAllowed('manage'))"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
matInput
|
matInput
|
||||||
placeholder="{{ 'Participant number' | translate }}"
|
placeholder="{{ 'Participant number' | translate }}"
|
||||||
formControlName="number"
|
formControlName="number"
|
||||||
[value]="user.participant_number"/>
|
[value]="user.participant_number"
|
||||||
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -136,7 +151,8 @@
|
|||||||
matInput
|
matInput
|
||||||
placeholder="{{ 'Initial password' | translate }}"
|
placeholder="{{ 'Initial password' | translate }}"
|
||||||
formControlName="default_password"
|
formControlName="default_password"
|
||||||
[value]="user.default_password"/>
|
[value]="user.default_password"
|
||||||
|
/>
|
||||||
<mat-hint align="end">Generate</mat-hint>
|
<mat-hint align="end">Generate</mat-hint>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -144,7 +160,8 @@
|
|||||||
matSuffix
|
matSuffix
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
[disabled]="!newUser"
|
[disabled]="!newUser"
|
||||||
(click)="generatePassword()">
|
(click)="generatePassword()"
|
||||||
|
>
|
||||||
<mat-icon>sync_problem</mat-icon>
|
<mat-icon>sync_problem</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
@ -166,7 +183,8 @@
|
|||||||
matInput
|
matInput
|
||||||
placeholder="{{ 'Username' | translate }}"
|
placeholder="{{ 'Username' | translate }}"
|
||||||
formControlName="username"
|
formControlName="username"
|
||||||
[value]="user.username"/>
|
[value]="user.username"
|
||||||
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -177,7 +195,8 @@
|
|||||||
matInput
|
matInput
|
||||||
placeholder="{{ 'Comment' | translate }}"
|
placeholder="{{ 'Comment' | translate }}"
|
||||||
formControlName="comment"
|
formControlName="comment"
|
||||||
[value]="user.comment"/>
|
[value]="user.comment"
|
||||||
|
/>
|
||||||
<mat-hint translate>Only for internal notes.</mat-hint>
|
<mat-hint translate>Only for internal notes.</mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
@ -187,7 +206,8 @@
|
|||||||
<mat-checkbox
|
<mat-checkbox
|
||||||
formControlName="is_present"
|
formControlName="is_present"
|
||||||
matTooltip="{{ 'Designates whether this user is in the room.' | translate }}"
|
matTooltip="{{ 'Designates whether this user is in the room.' | translate }}"
|
||||||
[value]="user.is_present">
|
[value]="user.is_present"
|
||||||
|
>
|
||||||
<span translate>Is present</span>
|
<span translate>Is present</span>
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
|
|
||||||
@ -199,7 +219,8 @@
|
|||||||
matTooltip="{{
|
matTooltip="{{
|
||||||
'Designates whether this user should be treated as active. Unselect this instead of deleting the account.'
|
'Designates whether this user should be treated as active. Unselect this instead of deleting the account.'
|
||||||
| translate
|
| translate
|
||||||
}}">
|
}}"
|
||||||
|
>
|
||||||
<span translate>Is active</span>
|
<span translate>Is active</span>
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
|
|
||||||
@ -207,7 +228,8 @@
|
|||||||
<mat-checkbox
|
<mat-checkbox
|
||||||
formControlName="is_committee"
|
formControlName="is_committee"
|
||||||
[value]="user.is_committee"
|
[value]="user.is_committee"
|
||||||
matTooltip="{{ 'Designates whether this user should be treated as a committee.' | translate }}">
|
matTooltip="{{ 'Designates whether this user should be treated as a committee.' | translate }}"
|
||||||
|
>
|
||||||
<span translate>Is a committee</span>
|
<span translate>Is a committee</span>
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||||
|
import { MatSnackBar } from '@angular/material';
|
||||||
|
import { Title } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { genders } from 'app/shared/models/users/user';
|
||||||
import { ViewUser } from '../../models/view-user';
|
import { ViewUser } from '../../models/view-user';
|
||||||
import { UserRepositoryService } from '../../services/user-repository.service';
|
import { UserRepositoryService } from '../../services/user-repository.service';
|
||||||
import { Group } from '../../../../shared/models/users/group';
|
import { Group } from '../../../../shared/models/users/group';
|
||||||
import { DataStoreService } from '../../../../core/services/data-store.service';
|
import { DataStoreService } from '../../../../core/services/data-store.service';
|
||||||
import { OperatorService } from '../../../../core/services/operator.service';
|
import { OperatorService } from '../../../../core/services/operator.service';
|
||||||
import { BaseViewComponent } from '../../../base/base-view';
|
import { BaseViewComponent } from '../../../base/base-view';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
import { MatSnackBar } from '@angular/material';
|
|
||||||
import { Title } from '@angular/platform-browser';
|
|
||||||
import { PromptService } from '../../../../core/services/prompt.service';
|
import { PromptService } from '../../../../core/services/prompt.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,6 +64,11 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
public groups: Group[];
|
public groups: Group[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hold the list of genders (sexes) publicly to dynamically iterate in the view
|
||||||
|
*/
|
||||||
|
public genderList = genders;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for user
|
* Constructor for user
|
||||||
*
|
*
|
||||||
@ -114,6 +121,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks, if the given user id matches with the operator ones.
|
* Checks, if the given user id matches with the operator ones.
|
||||||
|
*
|
||||||
* @param userId The id to check, if it's the operator
|
* @param userId The id to check, if it's the operator
|
||||||
* @returns If the user is the operator
|
* @returns If the user is the operator
|
||||||
*/
|
*/
|
||||||
@ -178,6 +186,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
title: [''],
|
title: [''],
|
||||||
first_name: [''],
|
first_name: [''],
|
||||||
last_name: [''],
|
last_name: [''],
|
||||||
|
gender: [''],
|
||||||
structure_level: [''],
|
structure_level: [''],
|
||||||
number: [''],
|
number: [''],
|
||||||
about_me: [''],
|
about_me: [''],
|
||||||
@ -226,6 +235,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
this.personalInfoForm.get('first_name'),
|
this.personalInfoForm.get('first_name'),
|
||||||
this.personalInfoForm.get('last_name'),
|
this.personalInfoForm.get('last_name'),
|
||||||
this.personalInfoForm.get('email'),
|
this.personalInfoForm.get('email'),
|
||||||
|
this.personalInfoForm.get('gender'),
|
||||||
this.personalInfoForm.get('structure_level'),
|
this.personalInfoForm.get('structure_level'),
|
||||||
this.personalInfoForm.get('number'),
|
this.personalInfoForm.get('number'),
|
||||||
this.personalInfoForm.get('groups_id'),
|
this.personalInfoForm.get('groups_id'),
|
||||||
@ -241,6 +251,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
allowedFormFields.push(
|
allowedFormFields.push(
|
||||||
this.personalInfoForm.get('username'),
|
this.personalInfoForm.get('username'),
|
||||||
this.personalInfoForm.get('email'),
|
this.personalInfoForm.get('email'),
|
||||||
|
this.personalInfoForm.get('gender'),
|
||||||
this.personalInfoForm.get('about_me')
|
this.personalInfoForm.get('about_me')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,10 @@ export class ViewUser extends BaseProjectableModel {
|
|||||||
return this.user ? this.user.email : null;
|
return this.user ? this.user.email : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get gender(): string {
|
||||||
|
return this.user ? this.user.gender : null;
|
||||||
|
}
|
||||||
|
|
||||||
public get structure_level(): string {
|
public get structure_level(): string {
|
||||||
return this.user ? this.user.structure_level : null;
|
return this.user ? this.user.structure_level : null;
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,12 @@ export class UserRepositoryService extends BaseRepository<ViewUser, User> {
|
|||||||
updateUser.username = viewUser.username;
|
updateUser.username = viewUser.username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the update user does not have a gender-field, send gender as empty string.
|
||||||
|
// This allow to delete a previously selected gender
|
||||||
|
if (!updateUser.gender) {
|
||||||
|
updateUser.gender = '';
|
||||||
|
}
|
||||||
|
|
||||||
return await this.dataSend.updateModel(updateUser);
|
return await this.dataSend.updateModel(updateUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user