Merge branch 'bug-solving' into 'master'

Corrections de plusieurs bugs

Closes #7, #8, #12, #14, #15, and #16

See merge request color-recipes-explorer/frontend!7
This commit is contained in:
William Nolin 2021-03-14 01:44:17 +00:00
commit 1eb97333fd
22 changed files with 64 additions and 43 deletions

View File

@ -1,6 +1,6 @@
<cre-header></cre-header>
<cre-global-alert-handler></cre-global-alert-handler>
<div>
<div class="pb-5">
<div class="dark-background"></div>
<router-outlet></router-outlet>

View File

@ -73,9 +73,7 @@ export class AccountService implements OnDestroy {
)
.subscribe({
next: () => {
this.appState.isAuthenticated = false
this.appState.authenticationExpiration = -1
this.appState.authenticatedEmployee = null
this.appState.resetAuthenticatedEmployee()
this.checkAuthenticationStatus()
success()
},

View File

@ -1,4 +1,4 @@
<mat-card>
<mat-card *ngIf="editionMode || hasImages">
<mat-card-header>
<mat-card-title>Images</mat-card-title>
</mat-card-header>

View File

@ -18,6 +18,7 @@ export class ImagesEditorComponent extends SubscribingComponent {
imageIds$: Observable<number[]>
backendUrl = environment.apiUrl
hasImages = false
constructor(
private recipeImageService: RecipeImageService,
@ -32,6 +33,11 @@ export class ImagesEditorComponent extends SubscribingComponent {
super.ngOnInit()
this.loadImagesIds()
this.subscribe(
this.imageIds$,
ids => this.hasImages = ids.length > 0,
1
)
}
submit(event) {

View File

@ -1,4 +1,4 @@
<mat-card *ngIf="recipe && (!editionMode || mix)" class="x-centered y-centered">
<mat-card *ngIf="recipe && (!editionMode || mix)" class="x-centered mt-5">
<mat-card-header>
<mat-card-title *ngIf="!editionMode">Création d'un mélange pour la recette {{recipe.company.name}}
- {{recipe.name}}</mat-card-title>

View File

@ -24,7 +24,7 @@
<div class="recipe-content d-flex flex-row justify-content-around align-items-start flex-wrap mt-5">
<!-- Mixes -->
<div>
<div *ngIf="recipe.mixes.length > 0">
<cre-mixes-card
[recipe]="recipe"
[deductErrorBody]="deductErrorBody"
@ -36,7 +36,7 @@
</div>
<!-- Steps -->
<div>
<div *ngIf="recipe.steps.length > 0">
<cre-step-list [steps]="recipe.steps"></cre-step-list>
</div>

View File

@ -50,6 +50,10 @@ export class ExploreComponent extends ErrorHandlingComponent {
r => {
this.recipe = r
this.note = r.note
if (this.recipe.mixes.length <= 0 || this.recipe.steps.length <= 0) {
this.alertService.pushWarning("Cette recette n'est pas complète")
}
},
'/colors/list'
)

View File

@ -1,6 +1,6 @@
<mat-card class="x-centered mt-5">
<mat-card-header>
<mat-card-title>Création d'un employé</mat-card-title>
<mat-card-title>Création d'un utilisateur</mat-card-title>
</mat-card-header>
<mat-card-content>
<form [formGroup]="form">

View File

@ -1,6 +1,6 @@
<mat-card *ngIf="employee" class="x-centered mt-5">
<mat-card-header>
<mat-card-title>Modification de l'employé #{{employee.id}}</mat-card-title>
<mat-card-title>Modification de l'utilisateur #{{employee.id}}</mat-card-title>
</mat-card-header>
<mat-card-content>
<form [formGroup]="form">

View File

@ -48,7 +48,7 @@
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let employee" [attr.colspan]="columns.length">
<div class="entity-detail"
[@detailExpand]="employee == expandedElement ? 'expanded' : 'collapsed'">
[@detailExpand]="employee === expandedElement ? 'expanded' : 'collapsed'">
<cre-permissions-list [employee]="employee" class="w-100"></cre-permissions-list>
</div>
</td>

View File

@ -1,7 +1,7 @@
<mat-card *ngIf="employee" class="x-centered mt-5">
<form [formGroup]="form">
<mat-card-header>
<mat-card-title>Modification du mot de passe de l'employé #{{employee.id}}</mat-card-title>
<mat-card-title>Modification du mot de passe de l'utilisateur #{{employee.id}}</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-form-field>

View File

@ -21,7 +21,7 @@ export class EmployeeService {
}
save(id: number, firstName: string, lastName: string, password: string, group: number, permissions: EmployeePermission[]): Observable<Employee> {
const employee = {id, firstName, lastName, password, group, permissions}
const employee = {id, firstName, lastName, password, groupId: group, permissions}
return this.api.post<Employee>('/employee', employee)
}

View File

@ -12,7 +12,7 @@
<td mat-cell *matCellDef="let group">{{group.permissions.length}}</td>
</ng-container>
<ng-container matColumnDef="employeeCount">
<th mat-header-cell *matHeaderCellDef>Nombre d'employés</th>
<th mat-header-cell *matHeaderCellDef>Nombre d'utilisateurs</th>
<td mat-cell *matCellDef="let group">{{group.employeeCount}}</td>
</ng-container>
<ng-container matColumnDef="defaultGroup">
@ -48,7 +48,7 @@
<td mat-cell *matCellDef="let group" [attr.colspan]="columns.length">
<div class="entity-detail"
[@detailExpand]="group == expandedElement && canViewEmployee ? 'expanded' : 'collapsed'">
<cre-employees-list [group]="group" class="w-100"></cre-employees-list>
<cre-permissions-list [group]="group"></cre-permissions-list>
</div>
</td>
</ng-container>

View File

@ -13,6 +13,13 @@ export class AppState {
authenticatedUser$ = new Subject<{ authenticated: boolean, authenticatedUser: Employee }>()
serverOnline$ = new Subject<boolean>()
resetAuthenticatedEmployee() {
this.isAuthenticated = false
this.authenticationExpiration = -1
this.authenticatedEmployee = null
}
set isServerOnline(isOnline: boolean) {
if (!isOnline) this.authenticatedEmployee = null
this.serverOnline$.next(isOnline);

View File

@ -3,13 +3,15 @@
<div class="spacer"></div>
<div mat-tab-nav-bar backgroundColor="primary">
<ng-container *ngFor="let link of links">
<a
*ngIf="link.enabled"
mat-tab-link
[active]="activeLink.startsWith(link.route)"
(click)="activeLink = link.route">
{{ link.title }}
</a>
<ng-container *ngIf="link.route !== '/catalog' || catalogEnabled">
<a
*ngIf="link.enabled"
mat-tab-link
[active]="activeLink.startsWith(link.route)"
(click)="activeLink = link.route">
{{ link.title }}
</a>
</ng-container>
</ng-container>
</div>
</nav>

View File

@ -12,10 +12,12 @@ import {ErrorService} from '../../service/error.service'
styleUrls: ['./header.component.sass']
})
export class HeaderComponent extends SubscribingComponent {
catalogEnabled = false
links: HeaderLink[] = [
{route: '/color', title: 'Couleurs', requiredPermission: EmployeePermission.VIEW_RECIPE},
{route: '/catalog', title: 'Catalogue', enabled: true},
{route: '/employee', title: 'Employés', requiredPermission: EmployeePermission.VIEW_EMPLOYEE},
{route: '/employee', title: 'Utilisateurs', requiredPermission: EmployeePermission.VIEW_EMPLOYEE},
{route: '/group', title: 'Groupes', requiredPermission: EmployeePermission.VIEW_EMPLOYEE_GROUP},
{route: '/account/login', title: 'Connexion', enabled: true},
{route: '/account/logout', title: 'Déconnexion', enabled: false},
@ -81,6 +83,10 @@ export class HeaderComponent extends SubscribingComponent {
l.enabled = employee && employee.permissions.indexOf(l.requiredPermission) >= 0
}
})
this.catalogEnabled = this.accountService.hasPermission(EmployeePermission.VIEW_MATERIAL_TYPE) ||
this.accountService.hasPermission(EmployeePermission.VIEW_MATERIAL) ||
this.accountService.hasPermission(EmployeePermission.VIEW_COMPANY)
}
private link(route: string) {

View File

@ -6,7 +6,7 @@
<ng-container *ngTemplateOutlet="permissionTemplate;context:{type: 'remove'}"></ng-container>
<ng-container *ngTemplateOutlet="permissionTemplate;context:{type: 'other'}"></ng-container>
</div>
<mat-error *ngIf="!permissionsValid">Un group doit avoir au moins une permission</mat-error>
<mat-error *ngIf="!permissionsValid">Vous devez sélectionner au moins une permission</mat-error>
</div>
<ng-template

View File

@ -1,5 +1,5 @@
<div class="d-flex flex-column">
<div class="permissions-list" *ngIf="employee.permissions">
<div class="permissions-list" *ngIf="permissions">
<p>Permissions</p>
<ng-container *ngTemplateOutlet="permissionsList; context:{permissions: permissions}"></ng-container>
</div>

View File

@ -1,13 +1,14 @@
import {Component, Input, OnInit} from '@angular/core';
import {Employee, EmployeePermission, mapped_permissions} from "../../model/employee";
import {Component, Input, OnInit} from '@angular/core'
import {Employee, EmployeeGroup, EmployeePermission, mapped_permissions} from '../../model/employee'
@Component({
selector: 'cre-permissions-list',
templateUrl: './permissions-list.component.html',
styleUrls: ['./permissions-list.component.sass']
})
export class PermissionsListComponent implements OnInit {
export class PermissionsListComponent {
@Input() employee: Employee
@Input() group: EmployeeGroup
// @ts-ignore
private _permissions = Object.values(mapped_permissions).flatMap(p => p)
@ -15,10 +16,11 @@ export class PermissionsListComponent implements OnInit {
constructor() {
}
ngOnInit(): void {
get permissions(): EmployeePermission[] {
return this.filterPermissions(this.employee ? this.employee.permissions : this.group.permissions)
}
get permissions(): EmployeePermission[] {
return this._permissions.filter(p => this.employee.permissions.indexOf(p.permission) >= 0).map(p => p.description)
private filterPermissions(permissions: EmployeePermission[]) {
return this._permissions.filter(p => permissions.indexOf(p.permission) >= 0).map(p => p.description)
}
}

View File

@ -65,7 +65,7 @@ export const mapped_permissions = {
description: 'Voir',
impliedPermissions: [EmployeePermission.VIEW_MATERIAL, EmployeePermission.VIEW_MATERIAL_TYPE, EmployeePermission.VIEW_COMPANY, EmployeePermission.VIEW_RECIPE]
},
{permission: EmployeePermission.VIEW_EMPLOYEE, description: 'Voir les employés', impliedPermissions: []},
{permission: EmployeePermission.VIEW_EMPLOYEE, description: 'Voir les utilisateurs', impliedPermissions: []},
{permission: EmployeePermission.VIEW_EMPLOYEE_GROUP, description: 'Voir les groupes', impliedPermissions: []},
],
edit: [
@ -96,7 +96,7 @@ export const mapped_permissions = {
},
{
permission: EmployeePermission.EDIT_EMPLOYEE,
description: 'Modifier les employés',
description: 'Modifier les utilisateurs',
impliedPermissions: [EmployeePermission.VIEW_EMPLOYEE]
},
{
@ -138,7 +138,7 @@ export const mapped_permissions = {
},
{
permission: EmployeePermission.REMOVE_EMPLOYEE,
description: 'Supprimer des employés',
description: 'Supprimer des utilisateurs',
impliedPermissions: [EmployeePermission.EDIT_EMPLOYEE]
},
{

View File

@ -7,6 +7,7 @@ import {Router} from '@angular/router'
import {map, share, takeUntil} from 'rxjs/operators'
import {valueOr} from '../utils/utils'
import {ErrorService} from './error.service'
import {AccountService} from '../../accounts/services/account.service'
@Injectable({
providedIn: 'root'
@ -77,17 +78,16 @@ export class ApiService implements OnDestroy {
console.error('httpOptions need to be specified to use credentials in HTTP methods.')
}
} else {
this.appState.resetAuthenticatedEmployee()
this.navigateToLogin()
}
}
const result$ = requestOptions.takeFullResponse
return requestOptions.takeFullResponse
? requestFn(httpOptions)
.pipe(takeUntil(this._destroy$), share())
: requestFn(httpOptions)
.pipe(takeUntil(this._destroy$), map(r => r.body), share())
return result$
}
private checkAuthenticated(): boolean {

View File

@ -172,12 +172,6 @@ div.empty
height: 2.3rem
border: solid 1px white
//&.light-mode
// color: black
// width: 2.3rem
// height: 2.3rem
// border: solid 1px black
div
position: absolute
width: 2rem
@ -196,6 +190,7 @@ div.empty
left: 0
background-color: black
opacity: 0.05
z-index: -1
.darker-background
position: fixed
@ -205,6 +200,7 @@ div.empty
left: 0
background-color: black
opacity: 0.4
z-index: -1
.color-warning
color: #fdd835