Normalisation de la liste des employés et des groupes.
This commit is contained in:
parent
4cafcf2142
commit
99cf9f7c0a
|
@ -64,7 +64,10 @@ export class AccountService implements OnDestroy {
|
|||
this.setLoggedInEmployeeFromApi()
|
||||
success()
|
||||
},
|
||||
error: err => this.errorService.handleError(err)
|
||||
error: err => {
|
||||
this.errorService.handleError(err)
|
||||
globalLoadingWheel.hide()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,66 +1,13 @@
|
|||
<div class="action-bar">
|
||||
<button *ngIf="canEditEmployee" mat-raised-button color="accent" routerLink="/employee/add">Ajouter</button>
|
||||
</div>
|
||||
<cre-entity-list
|
||||
addLink="/employee/add"
|
||||
addPermission="EDIT_EMPLOYEE"
|
||||
[entities$]="employees$"
|
||||
[columns]="columns"
|
||||
[buttons]="buttons"
|
||||
[expandable]="true"
|
||||
[rowDetailsTemplate]="employeeDetailsTemplate">
|
||||
</cre-entity-list>
|
||||
|
||||
<table class="mx-auto" *ngIf="employees$ | async as employees" mat-table multiTemplateDataRows [dataSource]="employees">
|
||||
<ng-container matColumnDef="id">
|
||||
<th mat-header-cell *matHeaderCellDef>Numéro d'employé</th>
|
||||
<td mat-cell *matCellDef="let employee">{{employee.id}}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>Nom</th>
|
||||
<td mat-cell *matCellDef="let employee">{{employee.firstName}} {{employee.lastName}}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="group">
|
||||
<th mat-header-cell *matHeaderCellDef>Groupe</th>
|
||||
<td mat-cell *matCellDef="let employee">
|
||||
<ng-container *ngIf="employee.group">{{employee.group.name}}</ng-container>
|
||||
<ng-container *ngIf="!employee.group">Aucun</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="lastLogin">
|
||||
<th mat-header-cell *matHeaderCellDef>Dernière connexion</th>
|
||||
<td mat-cell *matCellDef="let employee">
|
||||
<ng-container *ngIf="employee.lastLoginTime">{{getDate(employee.lastLoginTime).toLocaleString()}}</ng-container>
|
||||
<ng-container *ngIf="!employee.lastLoginTime">Jamais</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="permissionCount">
|
||||
<th mat-header-cell *matHeaderCellDef>Permissions</th>
|
||||
<td mat-cell *matCellDef="let employee">
|
||||
<ng-container *ngIf="employee.permissions">{{employee.permissions.length}}</ng-container>
|
||||
<ng-container *ngIf="!employee.permissions">0</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="editButton">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell [class.disabled]="!canEditEmployee" *matCellDef="let employee">
|
||||
<button mat-raised-button color="accent" routerLink="/employee/edit/{{employee.id}}">Modifier</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="editPasswordButton">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell [class.disabled]="!canEditEmployeePassword" *matCellDef="let employee">
|
||||
<button mat-raised-button color="accent" routerLink="/employee/password/edit/{{employee.id}}">Modifier mot de passe</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="expandedDetail">
|
||||
<td mat-cell *matCellDef="let employee" [attr.colspan]="columns.length">
|
||||
<div class="entity-detail"
|
||||
[@detailExpand]="employee === expandedElement ? 'expanded' : 'collapsed'">
|
||||
<cre-permissions-list [employee]="employee" class="w-100"></cre-permissions-list>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="columns"></tr>
|
||||
<tr
|
||||
mat-row
|
||||
*matRowDef="let employee; columns: columns"
|
||||
class="entity-row can-expand"
|
||||
[class.expanded-row]="expandedElement === employee"
|
||||
(click)="expandedElement = expandedElement === employee ? null : employee">
|
||||
</tr>
|
||||
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="detail-row"></tr>
|
||||
</table>
|
||||
<ng-template #employeeDetailsTemplate let-employee="entity">
|
||||
<cre-permissions-list [employee]="employee" class="w-100"></cre-permissions-list>
|
||||
</ng-template>
|
||||
|
|
|
@ -23,9 +23,22 @@ import {ErrorService} from '../../../shared/service/error.service'
|
|||
})
|
||||
export class ListComponent extends ErrorHandlingComponent {
|
||||
employees$: Observable<Employee[]>
|
||||
columns = ['id', 'name', 'group', 'permissionCount', 'lastLogin', 'editButton', 'editPasswordButton']
|
||||
|
||||
expandedElement: Employee | null
|
||||
columns = [
|
||||
{def: 'id', title: 'Numéro d\'employé', valueFn: e => e.id},
|
||||
{def: 'name', title: 'Nom', valueFn: e => `${e.firstName} ${e.lastName}`},
|
||||
{def: 'group', title: 'Groupe', valueFn: e => e.group ? e.group.name : 'Aucun'},
|
||||
{def: 'permissionCount', title: 'Nombre de permissions', valueFn: e => e.permissions.length},
|
||||
{def: 'lastLogin', title: 'Dernière connexion', valueFn: e => e.lastLoginTime ? this.getDate(e.lastLoginTime).toLocaleString() : 'Jamais'}
|
||||
]
|
||||
buttons = [{
|
||||
text: 'Modifier',
|
||||
linkFn: employee => `/employee/edit/${employee.id}`,
|
||||
permission: EmployeePermission.EDIT_EMPLOYEE
|
||||
}, {
|
||||
text: 'Modifier mot de passe',
|
||||
linkFn: employee => `/employee/password/edit/${employee.id}`,
|
||||
permission: EmployeePermission.EDIT_EMPLOYEE_PASSWORD
|
||||
}]
|
||||
|
||||
constructor(
|
||||
private employeeService: EmployeeService,
|
||||
|
@ -44,12 +57,4 @@ export class ListComponent extends ErrorHandlingComponent {
|
|||
getDate(dateString: string) {
|
||||
return new Date(dateString)
|
||||
}
|
||||
|
||||
get canEditEmployee(): boolean {
|
||||
return this.accountService.hasPermission(EmployeePermission.EDIT_EMPLOYEE)
|
||||
}
|
||||
|
||||
get canEditEmployeePassword(): boolean {
|
||||
return this.accountService.hasPermission(EmployeePermission.EDIT_EMPLOYEE_PASSWORD)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,66 +1,13 @@
|
|||
<div class="action-bar">
|
||||
<button *ngIf="canEditGroup" mat-raised-button color="accent" routerLink="/group/add">Ajouter</button>
|
||||
</div>
|
||||
<cre-entity-list
|
||||
addLink="/group/add"
|
||||
addPermission="EDIT_EMPLOYEE_GROUP"
|
||||
[entities$]="groups$"
|
||||
[columns]="columns"
|
||||
[buttons]="buttons"
|
||||
[expandable]="true"
|
||||
[rowDetailsTemplate]="groupDetailsTemplate">
|
||||
</cre-entity-list>
|
||||
|
||||
<table *ngIf="groups$ | async as groups" mat-table class="mx-auto" multiTemplateDataRows [dataSource]="groups">
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef>Nom</th>
|
||||
<td mat-cell *matCellDef="let group">{{group.name}}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="permissionCount">
|
||||
<th mat-header-cell *matHeaderCellDef>Nombre de permissions</th>
|
||||
<td mat-cell *matCellDef="let group">{{group.permissions.length}}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="employeeCount">
|
||||
<th mat-header-cell *matHeaderCellDef>Nombre d'utilisateurs</th>
|
||||
<td mat-cell *matCellDef="let group">{{group.employeeCount}}</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="defaultGroup">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell [class.disabled]="!canSetBrowserDefaultGroup" *matCellDef="let group">
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
[disabled]="isDefaultGroup(group) ? true : null"
|
||||
(click)="setDefaultGroup(group)">
|
||||
<ng-container *ngIf="!isDefaultGroup(group)">
|
||||
Définir par défaut
|
||||
</ng-container>
|
||||
<ng-container *ngIf="isDefaultGroup(group)">
|
||||
Par défaut
|
||||
</ng-container>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="editGroup">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell [class.disabled]="!canEditGroup" *matCellDef="let group">
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
routerLink="/group/edit/{{group.id}}">
|
||||
Modifier
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="expandedDetail">
|
||||
<td mat-cell *matCellDef="let group" [attr.colspan]="columns.length">
|
||||
<div class="entity-detail"
|
||||
[@detailExpand]="group == expandedElement && canViewEmployee ? 'expanded' : 'collapsed'">
|
||||
<cre-permissions-list [group]="group"></cre-permissions-list>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="columns"></tr>
|
||||
<tr
|
||||
mat-row
|
||||
*matRowDef="let group; columns: columns"
|
||||
class="entity-row"
|
||||
[class.expanded-row]="expandedElement === group"
|
||||
[class.can-expand]="canViewEmployee"
|
||||
(click)="expandedElement = expandedElement === group ? null : group">
|
||||
</tr>
|
||||
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="detail-row"></tr>
|
||||
</table>
|
||||
<ng-template #groupDetailsTemplate let-group="entity">
|
||||
<cre-permissions-list [group]="group"></cre-permissions-list>
|
||||
</ng-template>
|
||||
|
|
|
@ -2,31 +2,35 @@ import {Component} from '@angular/core'
|
|||
import {GroupService} from '../../services/group.service'
|
||||
import {EmployeeGroup, EmployeePermission} from '../../../shared/model/employee'
|
||||
import {map} from 'rxjs/operators'
|
||||
import {animate, state, style, transition, trigger} from '@angular/animations'
|
||||
import {AccountService} from '../../../accounts/services/account.service'
|
||||
import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component'
|
||||
import {ActivatedRoute, Router} from '@angular/router'
|
||||
import {ErrorModel, ErrorService} from '../../../shared/service/error.service'
|
||||
import {AlertService} from '../../../shared/service/alert.service'
|
||||
import {globalLoadingWheel} from '../../../shared/components/loading-wheel/loading-wheel.component'
|
||||
|
||||
@Component({
|
||||
selector: 'cre-groups',
|
||||
templateUrl: './list.component.html',
|
||||
styleUrls: ['./list.component.sass'],
|
||||
animations: [
|
||||
trigger('detailExpand', [
|
||||
state('collapsed', style({height: '0px', minHeight: '0'})),
|
||||
state('expanded', style({height: '*'})),
|
||||
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
|
||||
])
|
||||
]
|
||||
styleUrls: ['./list.component.sass']
|
||||
})
|
||||
export class ListComponent extends ErrorHandlingComponent {
|
||||
groups$ = this.groupService.all.pipe(map(groups => groups.filter(g => g.id >= 0)))
|
||||
defaultGroup: EmployeeGroup = null
|
||||
columns = ['name', 'permissionCount', 'employeeCount', 'defaultGroup', 'editGroup']
|
||||
expandedElement: EmployeeGroup | null
|
||||
columns = [
|
||||
{def: 'name', title: 'Nom', valueFn: g => g.name},
|
||||
{def: 'permissionCount', title: 'Nombre de permissions', valueFn: g => g.permissions.length},
|
||||
{def: 'employeeCount', title: 'Nombre d\'utilisateurs', valueFn: g => g.employeeCount}
|
||||
]
|
||||
buttons = [{
|
||||
text: 'Définir par défaut',
|
||||
clickFn: group => this.setDefaultGroup(group),
|
||||
permission: EmployeePermission.SET_BROWSER_DEFAULT_GROUP,
|
||||
disabledFn: group => this.isDefaultGroup(group)
|
||||
}, {
|
||||
text: 'Modifier',
|
||||
linkFn: group => `/group/edit/${group.id}`,
|
||||
permission: EmployeePermission.EDIT_EMPLOYEE_GROUP
|
||||
}]
|
||||
|
||||
handledErrorModels: ErrorModel[] = [{
|
||||
filter: error => error.status === 404,
|
||||
|
@ -48,6 +52,7 @@ export class ListComponent extends ErrorHandlingComponent {
|
|||
this.subscribe(
|
||||
this.groupService.defaultGroup,
|
||||
group => this.defaultGroup = group,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -62,16 +67,4 @@ export class ListComponent extends ErrorHandlingComponent {
|
|||
isDefaultGroup(group: EmployeeGroup): boolean {
|
||||
return this.defaultGroup && this.defaultGroup.id == group.id
|
||||
}
|
||||
|
||||
get canViewEmployee(): boolean {
|
||||
return this.accountService.hasPermission(EmployeePermission.VIEW_EMPLOYEE)
|
||||
}
|
||||
|
||||
get canEditGroup(): boolean {
|
||||
return this.accountService.hasPermission(EmployeePermission.EDIT_EMPLOYEE_GROUP)
|
||||
}
|
||||
|
||||
get canSetBrowserDefaultGroup(): boolean {
|
||||
return this.accountService.hasPermission(EmployeePermission.SET_BROWSER_DEFAULT_GROUP)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<button *ngIf="hasPermission(addPermission)" mat-raised-button color="accent" [routerLink]="addLink">Ajouter</button>
|
||||
</div>
|
||||
|
||||
<table class="mx-auto" *ngIf="entities$ | async as entities" mat-table [dataSource]="entities">
|
||||
<table class="mx-auto" *ngIf="entities$ | async as entities" mat-table multiTemplateDataRows [dataSource]="entities">
|
||||
<!-- Columns -->
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.def">
|
||||
<th mat-header-cell *matHeaderCellDef>{{column.title}}</th>
|
||||
|
@ -20,20 +20,40 @@
|
|||
<!-- Buttons -->
|
||||
<ng-container *ngFor="let button of buttons; let buttonIndex = index" matColumnDef="button{{buttonIndex}}">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell [class.disabled]="!hasPermissionToUseButton(button)" *matCellDef="let entity; let i = index">
|
||||
<td mat-cell [class.disabled]="!hasPermissionToUseButton(button)" *matCellDef="let entity; let i = dataIndex">
|
||||
<ng-container *ngIf="(!hoveredEntity && i === 0) || hoveredEntity === entity">
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
[routerLink]="button.link ? button.link.externalLink ? undefined : button.link : button.linkFn(entity).externalLink ? undefined : button.linkFn(entity)"
|
||||
[routerLink]="getRouterLink(button, entity)"
|
||||
[disabled]="button.disabledFn && button.disabledFn(entity)"
|
||||
(click)="openExternalLink(button, entity)">
|
||||
(click)="clickButton(button, entity)">
|
||||
{{button.text}}
|
||||
</button>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="expandable" matColumnDef="expandedDetail">
|
||||
<td mat-cell *matCellDef="let entity" [attr.colspan]="tableCols.length">
|
||||
<div class="entity-detail" [@detailExpand]="entity === expandedEntity ? 'expanded' : 'collapsed'">
|
||||
<ng-container [ngTemplateOutlet]="rowDetailsTemplate"
|
||||
[ngTemplateOutletContext]="{entity: entity, expandedEntity: expandedEntity}"></ng-container>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="tableCols"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: tableCols" (mouseover)="hoveredEntity = row"></tr>
|
||||
<tr
|
||||
mat-row
|
||||
class="entity-row"
|
||||
*matRowDef="let row; columns: tableCols"
|
||||
[class.expanded-row]="expandedEntity === row"
|
||||
[class.can-expand]="expandable"
|
||||
(mouseover)="hoveredEntity = row"
|
||||
(click)="expandedEntity = expandedEntity === row ? null : row">
|
||||
</tr>
|
||||
<ng-container *ngIf="expandable">
|
||||
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="detail-row"></tr>
|
||||
</ng-container>
|
||||
</table>
|
||||
|
|
|
@ -2,11 +2,19 @@ import {Component, Input} from '@angular/core'
|
|||
import {Observable} from 'rxjs'
|
||||
import {AccountService} from '../../../accounts/services/account.service'
|
||||
import {EmployeePermission} from '../../model/employee'
|
||||
import {animate, state, style, transition, trigger} from '@angular/animations'
|
||||
|
||||
@Component({
|
||||
selector: 'cre-entity-list',
|
||||
templateUrl: './entity-list.component.html',
|
||||
styleUrls: ['./entity-list.component.sass']
|
||||
styleUrls: ['./entity-list.component.sass'],
|
||||
animations: [
|
||||
trigger('detailExpand', [
|
||||
state('collapsed', style({height: '0px', minHeight: '0'})),
|
||||
state('expanded', style({height: '*'})),
|
||||
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
|
||||
])
|
||||
]
|
||||
})
|
||||
export class EntityListComponent<T> {
|
||||
@Input() entities$: Observable<T>
|
||||
|
@ -15,8 +23,11 @@ export class EntityListComponent<T> {
|
|||
@Input() buttons?: TableButton[]
|
||||
@Input() addLink: string
|
||||
@Input() addPermission: EmployeePermission
|
||||
@Input() expandable = false
|
||||
@Input() rowDetailsTemplate
|
||||
|
||||
hoveredEntity: T | null
|
||||
expandedEntity: T | null
|
||||
|
||||
constructor(
|
||||
private accountService: AccountService
|
||||
|
@ -31,23 +42,43 @@ export class EntityListComponent<T> {
|
|||
return this.accountService.hasPermission(permission)
|
||||
}
|
||||
|
||||
openExternalLink(button: TableButton, entity: T) {
|
||||
let externalLink = null
|
||||
getRouterLink(button: TableButton, entity: T): string {
|
||||
// @ts-ignore
|
||||
if (button.link && button.link.externalLink) {
|
||||
if (button.link && !button.link.externalLink) {
|
||||
// @ts-ignore
|
||||
externalLink = button.link.externalLink
|
||||
} else {
|
||||
const linkFnResult = button.linkFn(entity)
|
||||
return button.link
|
||||
} else if (button.linkFn) {
|
||||
const fnResult = button.linkFn(entity)
|
||||
// @ts-ignore
|
||||
if (linkFnResult && linkFnResult.externalLink) {
|
||||
if (!fnResult.externalLink) {
|
||||
// @ts-ignore
|
||||
externalLink = linkFnResult.externalLink
|
||||
return fnResult
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
if (externalLink) {
|
||||
window.open(externalLink, '_blank')
|
||||
clickButton(button: TableButton, entity: T) {
|
||||
if (button.link || button.linkFn) {
|
||||
let externalLink = null
|
||||
// @ts-ignore
|
||||
if (button.link && button.link.externalLink) {
|
||||
// @ts-ignore
|
||||
externalLink = button.link.externalLink
|
||||
} else {
|
||||
const linkFnResult = button.linkFn(entity)
|
||||
// @ts-ignore
|
||||
if (linkFnResult && linkFnResult.externalLink) {
|
||||
// @ts-ignore
|
||||
externalLink = linkFnResult.externalLink
|
||||
}
|
||||
}
|
||||
|
||||
if (externalLink) {
|
||||
window.open(externalLink, '_blank')
|
||||
}
|
||||
} else if (button.clickFn) {
|
||||
button.clickFn(entity)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,6 +118,7 @@ export class TableButton {
|
|||
public text: string,
|
||||
public link: string | { externalLink: string } | null,
|
||||
public linkFn: (T) => string | { externalLink: string } | null,
|
||||
public clickFn: (T) => void,
|
||||
public permission: EmployeePermission | null,
|
||||
public disabledFn: (T) => boolean | null
|
||||
) {
|
||||
|
|
Loading…
Reference in New Issue