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:
commit
1eb97333fd
|
@ -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>
|
||||
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<mat-card>
|
||||
<mat-card *ngIf="editionMode || hasImages">
|
||||
<mat-card-header>
|
||||
<mat-card-title>Images</mat-card-title>
|
||||
</mat-card-header>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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'
|
||||
)
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue