Merge pull request #4169 from tsiegleauq/gender-client

Add gender field to users
This commit is contained in:
Emanuel Schütze 2019-01-22 13:35:25 +01:00 committed by GitHub
commit c48148fc01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 81 additions and 30 deletions

View File

@ -2,6 +2,11 @@ import { Searchable } from '../base/searchable';
import { SearchRepresentation } from '../../../core/services/search.service';
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.
* @ignore
@ -14,6 +19,7 @@ export class User extends BaseModel<User> implements Searchable {
public title: string;
public first_name: string;
public last_name: string;
public gender: string;
public structure_level: string;
public number: string;
public about_me: string;

View File

@ -4,9 +4,7 @@
<h2><span translate>List of speakers</span></h2>
</div>
<div class="menu-slot" *osPerms="'agenda.can_manage_list_of_speakers'">
<button type="button" mat-icon-button [matMenuTriggerFor]="speakerMenu">
<mat-icon>more_vert</mat-icon>
</button>
<button type="button" mat-icon-button [matMenuTriggerFor]="speakerMenu"><mat-icon>more_vert</mat-icon></button>
</div>
</os-head-bar>
@ -68,6 +66,7 @@
<span *ngIf="hasSpokenCount(item)" class="red-warning-text speaker-warning">
{{ hasSpokenCount(item) + 1 }}. <span translate>contribution</span>
</span>
<span *ngIf="item.gender">({{ item.gender | translate }})</span>
</span>
<mat-button-toggle-group *osPerms="'agenda.can_manage_list_of_speakers'">
<mat-button-toggle matTooltip="{{ 'Begin speech' | translate }}" (click)="onStartButton(item)">
@ -117,7 +116,6 @@
</mat-card>
<mat-menu #speakerMenu="matMenu">
<button mat-menu-item *ngIf="closedList" (click)="openSpeakerList()">
<mat-icon>mic</mat-icon>
<span translate>Open list of speakers</span>

View File

@ -46,6 +46,10 @@ export class ViewSpeaker extends BaseViewModel implements Selectable {
return this.user.full_name || this.user.username;
}
public get gender(): string {
return this.user.gender || '';
}
public constructor(speaker?: Speaker, user?: User) {
super();
this._speaker = speaker;

View File

@ -9,8 +9,7 @@
<!-- Title -->
<div class="title-slot">
<h2>
<span *ngIf="newUser" translate>New participant</span>
<span *ngIf="!newUser">{{ user.full_name }}</span>
<span *ngIf="newUser" translate>New participant</span> <span *ngIf="!newUser">{{ user.full_name }}</span>
</h2>
</div>
@ -39,61 +38,74 @@
[formGroup]="personalInfoForm"
(ngSubmit)="saveUser()"
*ngIf="user"
(keydown)="onKeyDown($event)">
(keydown)="onKeyDown($event)"
>
<!-- <h3 translate>Personal Data</h3> -->
<div *ngIf="isAllowed('seeName')">
<!-- Title -->
<mat-form-field
class="form16 distance force-min-with"
*ngIf="user.title || (editUser && isAllowed('manage'))">
*ngIf="user.title || (editUser && isAllowed('manage'))"
>
<input
type="text"
matInput
osAutofocus
placeholder="{{ 'Title' | translate }}"
formControlName="title"
[value]="user.title"/>
[value]="user.title"
/>
</mat-form-field>
<!-- First name -->
<mat-form-field
class="form37 distance force-min-with"
*ngIf="user.first_name || (editUser && isAllowed('manage'))">
*ngIf="user.first_name || (editUser && isAllowed('manage'))"
>
<input
type="text"
matInput
placeholder="{{ 'Given name' | translate }}"
formControlName="first_name"
[value]="user.first_name"/>
[value]="user.first_name"
/>
</mat-form-field>
<!-- Last name -->
<mat-form-field
class="form37 force-min-with"
*ngIf="user.last_name || (editUser && isAllowed('manage'))">
<mat-form-field class="form37 force-min-with" *ngIf="user.last_name || (editUser && isAllowed('manage'))">
<input
type="text"
matInput
placeholder="{{ 'Surname' | translate }}"
formControlName="last_name"
[value]="user.last_name"/>
[value]="user.last_name"
/>
</mat-form-field>
</div>
<div *ngIf="isAllowed('seePersonal')">
<!-- E-Mail -->
<mat-form-field *ngIf="user.email || editUser">
<mat-form-field class="form70 distance" *ngIf="user.email || editUser">
<input
type="email"
matInput
placeholder="{{ 'Email' | translate }}"
name="email"
formControlName="email"
[value]="user.email"/>
[value]="user.email"
/>
<mat-error *ngIf="personalInfoForm.get('email').hasError('email')" translate>
Please enter a valid email address
</mat-error>
</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>
@ -104,19 +116,22 @@
matInput
placeholder="{{ 'Structure level' | translate }}"
formControlName="structure_level"
[value]="user.structure_level"/>
[value]="user.structure_level"
/>
</mat-form-field>
<!-- Participant Number -->
<mat-form-field
class="form25 force-min-with"
*ngIf="user.participant_number || (editUser && isAllowed('manage'))">
*ngIf="user.participant_number || (editUser && isAllowed('manage'))"
>
<input
type="text"
matInput
placeholder="{{ 'Participant number' | translate }}"
formControlName="number"
[value]="user.participant_number"/>
[value]="user.participant_number"
/>
</mat-form-field>
</div>
@ -136,7 +151,8 @@
matInput
placeholder="{{ 'Initial password' | translate }}"
formControlName="default_password"
[value]="user.default_password"/>
[value]="user.default_password"
/>
<mat-hint align="end">Generate</mat-hint>
<button
type="button"
@ -144,7 +160,8 @@
matSuffix
mat-icon-button
[disabled]="!newUser"
(click)="generatePassword()">
(click)="generatePassword()"
>
<mat-icon>sync_problem</mat-icon>
</button>
</mat-form-field>
@ -166,7 +183,8 @@
matInput
placeholder="{{ 'Username' | translate }}"
formControlName="username"
[value]="user.username"/>
[value]="user.username"
/>
</mat-form-field>
</div>
@ -177,7 +195,8 @@
matInput
placeholder="{{ 'Comment' | translate }}"
formControlName="comment"
[value]="user.comment"/>
[value]="user.comment"
/>
<mat-hint translate>Only for internal notes.</mat-hint>
</mat-form-field>
</div>
@ -187,7 +206,8 @@
<mat-checkbox
formControlName="is_present"
matTooltip="{{ 'Designates whether this user is in the room.' | translate }}"
[value]="user.is_present">
[value]="user.is_present"
>
<span translate>Is present</span>
</mat-checkbox>
@ -199,7 +219,8 @@
matTooltip="{{
'Designates whether this user should be treated as active. Unselect this instead of deleting the account.'
| translate
}}">
}}"
>
<span translate>Is active</span>
</mat-checkbox>
@ -207,7 +228,8 @@
<mat-checkbox
formControlName="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>
</mat-checkbox>
</div>

View File

@ -1,16 +1,18 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
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 { UserRepositoryService } from '../../services/user-repository.service';
import { Group } from '../../../../shared/models/users/group';
import { DataStoreService } from '../../../../core/services/data-store.service';
import { OperatorService } from '../../../../core/services/operator.service';
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';
/**
@ -62,6 +64,11 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
*/
public groups: Group[];
/**
* Hold the list of genders (sexes) publicly to dynamically iterate in the view
*/
public genderList = genders;
/**
* 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.
*
* @param userId The id to check, if it's the operator
* @returns If the user is the operator
*/
@ -178,6 +186,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
title: [''],
first_name: [''],
last_name: [''],
gender: [''],
structure_level: [''],
number: [''],
about_me: [''],
@ -226,6 +235,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
this.personalInfoForm.get('first_name'),
this.personalInfoForm.get('last_name'),
this.personalInfoForm.get('email'),
this.personalInfoForm.get('gender'),
this.personalInfoForm.get('structure_level'),
this.personalInfoForm.get('number'),
this.personalInfoForm.get('groups_id'),
@ -241,6 +251,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
allowedFormFields.push(
this.personalInfoForm.get('username'),
this.personalInfoForm.get('email'),
this.personalInfoForm.get('gender'),
this.personalInfoForm.get('about_me')
);
}

View File

@ -47,6 +47,10 @@ export class ViewUser extends BaseProjectableModel {
return this.user ? this.user.email : null;
}
public get gender(): string {
return this.user ? this.user.gender : null;
}
public get structure_level(): string {
return this.user ? this.user.structure_level : null;
}

View File

@ -64,6 +64,12 @@ export class UserRepositoryService extends BaseRepository<ViewUser, User> {
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);
}