From 48e900f3c53cd0d5a9abaebf45cdc871adc65821 Mon Sep 17 00:00:00 2001 From: FyloZ Date: Fri, 26 Mar 2021 15:48:18 -0400 Subject: [PATCH] Ajout du support des groupes dans la modification d'une recette. --- src/app/modules/colors/colors.module.ts | 4 +- .../step-table/step-table.component.html | 67 +++++++++++-- .../step-table/step-table.component.sass | 3 + .../step-table/step-table.component.ts | 97 ++++++++++++++++--- .../colors/pages/edit/edit.component.html | 11 ++- .../colors/pages/edit/edit.component.ts | 38 +++++++- .../pages/explore/explore.component.html | 6 +- .../colors/pages/explore/explore.component.ts | 2 +- .../modules/colors/services/recipe.service.ts | 13 ++- .../employees/pages/add/add.component.ts | 2 +- .../employees/pages/edit/edit.component.ts | 2 +- .../groups/pages/list/list.component.ts | 3 +- .../modules/groups/services/group.service.ts | 4 + .../permissions-list.component.ts | 1 + src/app/modules/shared/model/recipe.model.ts | 41 ++++++-- src/styles.sass | 9 ++ tsconfig.json | 2 +- 17 files changed, 256 insertions(+), 49 deletions(-) diff --git a/src/app/modules/colors/colors.module.ts b/src/app/modules/colors/colors.module.ts index 75a9ad1..6832ed8 100644 --- a/src/app/modules/colors/colors.module.ts +++ b/src/app/modules/colors/colors.module.ts @@ -18,6 +18,7 @@ import {MixAddComponent} from './pages/mix/mix-add/mix-add.component'; import {MixEditComponent} from './pages/mix/mix-edit/mix-edit.component'; import { ImagesEditorComponent } from './components/images-editor/images-editor.component'; import { MixesCardComponent } from './components/mixes-card/mixes-card.component'; +import {MatSortModule} from '@angular/material/sort' @NgModule({ @@ -29,7 +30,8 @@ import { MixesCardComponent } from './components/mixes-card/mixes-card.component ColorsRoutingModule, SharedModule, MatExpansionModule, - FormsModule + FormsModule, + MatSortModule ] }) export class ColorsModule { diff --git a/src/app/modules/colors/components/step-table/step-table.component.html b/src/app/modules/colors/components/step-table/step-table.component.html index 3922552..115f924 100644 --- a/src/app/modules/colors/components/step-table/step-table.component.html +++ b/src/app/modules/colors/components/step-table/step-table.component.html @@ -1,16 +1,63 @@ - - - Étapes - + + + Étapes + + + + Groupe + + + {{group.name}} + + + - +

Aucun groupe n'est sélectionné

+ + + + + + + +
- + + + + + + - + @@ -32,4 +79,4 @@
Position{{i + 1}}{{step.position}} + + + + + MessageContenu @@ -20,11 +67,11 @@ - + - +
-
+ diff --git a/src/app/modules/colors/components/step-table/step-table.component.sass b/src/app/modules/colors/components/step-table/step-table.component.sass index 44d6821..e34f3e9 100644 --- a/src/app/modules/colors/components/step-table/step-table.component.sass +++ b/src/app/modules/colors/components/step-table/step-table.component.sass @@ -1,5 +1,8 @@ mat-expansion-panel min-width: 560px + .empty-text + color: rgba(0, 0, 0, 0.54) + mat-form-field width: 20rem diff --git a/src/app/modules/colors/components/step-table/step-table.component.ts b/src/app/modules/colors/components/step-table/step-table.component.ts index f5e3a7e..3d92d34 100644 --- a/src/app/modules/colors/components/step-table/step-table.component.ts +++ b/src/app/modules/colors/components/step-table/step-table.component.ts @@ -1,6 +1,8 @@ -import {Component, Input, ViewChild} from '@angular/core'; -import {RecipeStep} from "../../../shared/model/recipe.model"; -import {MatTable} from "@angular/material/table"; +import {Component, Input} from '@angular/core' +import {Recipe, RecipeStep, recipeStepsForGroupId, sortRecipeSteps} from '../../../shared/model/recipe.model' +import {MatTable} from '@angular/material/table' +import {Observable} from 'rxjs' +import {EmployeeGroup} from '../../../shared/model/employee' @Component({ selector: 'cre-step-table', @@ -8,20 +10,89 @@ import {MatTable} from "@angular/material/table"; styleUrls: ['./step-table.component.sass'] }) export class StepTableComponent { - @ViewChild('stepTable', {static: true}) stepTable: MatTable - readonly columns = ['position', 'message', 'buttonRemove'] + readonly columns = ['position', 'buttonsPosition', 'message', 'buttonRemove'] - @Input() steps: RecipeStep[] + @Input() recipe: Recipe + @Input() groups$: Observable + @Input() selectedGroupId: number | null - hoveredStep : RecipeStep | null + hoveredStep: RecipeStep | null - addStep() { - this.steps.push({id: null, message: ""}) - this.stepTable.renderRows() + private groupSteps = new Map() + + addStep(table: MatTable) { + const addedStep = new RecipeStep(null, '', this.selectedGroupSteps.length + 1) + this.selectedGroupSteps.push(addedStep) + table.renderRows() } - removeStep(position: number) { - this.steps.splice(position, 1) - this.stepTable.renderRows() + removeStep(position: number, table: MatTable) { + this.selectedGroupSteps.splice(position, 1) + + // Decreases the position of each step above the removed one + for (let i = position; i < this.selectedGroupSteps.length; i++) { + this.selectedGroupSteps[i].position -= 1 + } + + table.renderRows() + } + + increasePosition(step: RecipeStep, table: MatTable) { + this.updateStepPosition(step, step.position + 1) + this.sort(table) + } + + decreasePosition(step: RecipeStep, table: MatTable) { + this.updateStepPosition(step, step.position - 1) + this.sort(table) + } + + sort(table: MatTable) { + this.groupSteps.set(this.selectedGroupId, sortRecipeSteps(this.selectedGroupSteps)) + table.renderRows() + } + + selectedGroupStepAtPosition(position: number): RecipeStep { + return this.selectedGroupSteps.find(s => s.position === position) + } + + selectedGroupHasStepAtPosition(position: number): boolean { + return this.selectedGroupStepAtPosition(position) != undefined + } + + get selectedGroupSteps(): RecipeStep[] { + if (!this.groupSteps.has(this.selectedGroupId)) { + this.groupSteps.set(this.selectedGroupId, recipeStepsForGroupId(this.recipe, this.selectedGroupId)) + } + return this.groupSteps.get(this.selectedGroupId) + } + + get selectedGroupStepsCount(): number { + return this.selectedGroupSteps.length + } + + get mappedUpdatedSteps(): Map { + const updatedStepsMap = new Map() + this.recipe.groupsInformation.forEach(i => { + updatedStepsMap.set(i.group.id, i.steps) + }) + + // Add steps for groups that were not already in the recipe + this.groupSteps.forEach((steps, groupId) => { + if (!updatedStepsMap.has(groupId)) { + updatedStepsMap.set(groupId, steps) + } + }) + return updatedStepsMap + } + + private updateStepPosition(step: RecipeStep, updatedPosition: number) { + if (!this.selectedGroupHasStepAtPosition(updatedPosition)) { + step.position = updatedPosition + } else { + const conflictingStep = this.selectedGroupStepAtPosition(updatedPosition) + conflictingStep.position = step.position + step.position = updatedPosition + } } } diff --git a/src/app/modules/colors/pages/edit/edit.component.html b/src/app/modules/colors/pages/edit/edit.component.html index 3d3705e..2ff1d65 100644 --- a/src/app/modules/colors/pages/edit/edit.component.html +++ b/src/app/modules/colors/pages/edit/edit.component.html @@ -3,7 +3,9 @@
- +
@@ -36,7 +38,12 @@
- + +
diff --git a/src/app/modules/colors/pages/edit/edit.component.ts b/src/app/modules/colors/pages/edit/edit.component.ts index c4f8a20..6b3acc6 100644 --- a/src/app/modules/colors/pages/edit/edit.component.ts +++ b/src/app/modules/colors/pages/edit/edit.component.ts @@ -1,6 +1,6 @@ import {Component, ViewChild} from '@angular/core' import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' -import {Recipe} from '../../../shared/model/recipe.model' +import {Recipe, RecipeStep} from '../../../shared/model/recipe.model' import {RecipeService} from '../../services/recipe.service' import {ActivatedRoute, Router} from '@angular/router' import {Validators} from '@angular/forms' @@ -12,6 +12,9 @@ import {EntityEditComponent} from '../../../shared/components/entity-edit/entity import {ImagesEditorComponent} from '../../components/images-editor/images-editor.component' import {ErrorModel, ErrorService} from '../../../shared/service/error.service' import {AlertService} from '../../../shared/service/alert.service' +import {GroupService} from '../../../groups/services/group.service' +import {AppState} from '../../../shared/app-state' +import {StepTableComponent} from '../../components/step-table/step-table.component' @Component({ selector: 'cre-edit', @@ -24,6 +27,7 @@ export class EditComponent extends ErrorHandlingComponent { @ViewChild('imagesEditor') imagesEditor: ImagesEditorComponent recipe: Recipe | null + groups$ = this.groupService.all formFields = [ { name: 'name', @@ -108,8 +112,10 @@ export class EditComponent extends ErrorHandlingComponent { constructor( private recipeService: RecipeService, + private groupService: GroupService, private accountService: AccountService, private alertService: AlertService, + private appState: AppState, errorService: ErrorService, router: Router, activatedRoute: ActivatedRoute @@ -125,10 +131,10 @@ export class EditComponent extends ErrorHandlingComponent { parseInt(this.activatedRoute.snapshot.paramMap.get('id')), recipe => { this.recipe = recipe - if (this.recipe.mixes.length == 0) { + if (this.recipe.mixCount == 0) { this.alertService.pushWarning('Il n\'y a aucun mélange dans cette recette') } - if (this.recipe.steps.length == 0) { + if (this.recipe.stepCount == 0) { this.alertService.pushWarning('Il n\'y a aucune étape dans cette recette') } }, @@ -140,11 +146,18 @@ export class EditComponent extends ErrorHandlingComponent { this.units$.next(unit) } - submit(editComponent: EntityEditComponent) { + submit(editComponent: EntityEditComponent, stepTable: StepTableComponent) { const values = editComponent.values this.submittedValues = values + + const steps = stepTable.mappedUpdatedSteps + if (!this.stepsPositionsAreValid(steps)) { + this.alertService.pushError('Les étapes ne peuvent pas avoir une position inférieure à 1') + return + } + this.subscribeAndNavigate( - this.recipeService.update(this.recipe.id, values.name, values.description, values.color, values.gloss, values.sample, values.approbationDate, values.remark, this.recipe.steps), + this.recipeService.update(this.recipe.id, values.name, values.description, values.color, values.gloss, values.sample, values.approbationDate, values.remark, steps), '/color/list' ) } @@ -159,4 +172,19 @@ export class EditComponent extends ErrorHandlingComponent { get hasDeletePermission(): boolean { return this.accountService.hasPermission(EmployeePermission.REMOVE_RECIPE) } + + get loggedInEmployeeGroupId(): number { + return this.appState.authenticatedEmployee.group?.id + } + + private stepsPositionsAreValid(steps: Map): boolean { + let valid = true + steps.forEach((steps, _) => { + if (steps.find(s => s.position === 0)) { + valid = false + return + } + }) + return valid + } } diff --git a/src/app/modules/colors/pages/explore/explore.component.html b/src/app/modules/colors/pages/explore/explore.component.html index 39adb75..c516c0d 100644 --- a/src/app/modules/colors/pages/explore/explore.component.html +++ b/src/app/modules/colors/pages/explore/explore.component.html @@ -35,9 +35,9 @@
-
- -
+ + +
diff --git a/src/app/modules/colors/pages/explore/explore.component.ts b/src/app/modules/colors/pages/explore/explore.component.ts index 46bf6b9..958c8fe 100644 --- a/src/app/modules/colors/pages/explore/explore.component.ts +++ b/src/app/modules/colors/pages/explore/explore.component.ts @@ -55,7 +55,7 @@ export class ExploreComponent extends ErrorHandlingComponent { this.recipe = r this.note = r.note - if (this.recipe.mixes.length <= 0 || this.recipe.steps.length <= 0) { + if (this.recipe.mixCount <= 0 || this.recipe.stepCount <= 0) { this.alertService.pushWarning('Cette recette n\'est pas complète') } }, diff --git a/src/app/modules/colors/services/recipe.service.ts b/src/app/modules/colors/services/recipe.service.ts index 3f847d1..9eb2298 100644 --- a/src/app/modules/colors/services/recipe.service.ts +++ b/src/app/modules/colors/services/recipe.service.ts @@ -3,7 +3,6 @@ import {ApiService} from '../../shared/service/api.service' import {Observable} from 'rxjs' import {Recipe, RecipeStep} from '../../shared/model/recipe.model' import {map} from 'rxjs/operators' -import {MaterialQuantity} from '../../material/service/inventory.service' @Injectable({ providedIn: 'root' @@ -44,12 +43,20 @@ export class RecipeService { return this.api.post('/recipe', body) } - update(id: number, name: string, description: string, color: string, gloss: number, sample: number, approbationDate: string, remark: string, steps: RecipeStep[] = null) { - const body = {id, name, description, color, gloss, sample, remark, steps} + update(id: number, name: string, description: string, color: string, gloss: number, sample: number, approbationDate: string, remark: string, steps: Map) { + const body = {id, name, description, color, gloss, sample, remark, steps: []} if (approbationDate) { // @ts-ignore body.approbationDate = approbationDate } + + steps.forEach((groupSteps, groupId) => { + const mappedGroupSteps = groupSteps.map(s => { + return {message: s.message, position: s.position} + }) + body.steps.push({groupId, steps: mappedGroupSteps}) + }) + return this.api.put('/recipe', body) } diff --git a/src/app/modules/employees/pages/add/add.component.ts b/src/app/modules/employees/pages/add/add.component.ts index dd6e404..21f2d51 100644 --- a/src/app/modules/employees/pages/add/add.component.ts +++ b/src/app/modules/employees/pages/add/add.component.ts @@ -66,7 +66,7 @@ export class AddComponent extends ErrorHandlingComponent { icon: 'account-multiple', type: 'select', defaultValue: -1, - options$: this.groupService.all.pipe(map(groups => groups.map(g => { + options$: this.groupService.allWithDefault.pipe(map(groups => groups.map(g => { return {value: g.id, label: g.name} }))) }, { diff --git a/src/app/modules/employees/pages/edit/edit.component.ts b/src/app/modules/employees/pages/edit/edit.component.ts index 15b49a1..afa4023 100644 --- a/src/app/modules/employees/pages/edit/edit.component.ts +++ b/src/app/modules/employees/pages/edit/edit.component.ts @@ -49,7 +49,7 @@ export class EditComponent extends ErrorHandlingComponent { icon: 'account-multiple', type: 'select', valueFn: employee => employee.group ? employee.group.id : -1, - options$: this.groupService.all.pipe(map(groups => groups.map(g => { + options$: this.groupService.allWithDefault.pipe(map(groups => groups.map(g => { return {value: g.id, label: g.name} }))) }, { diff --git a/src/app/modules/groups/pages/list/list.component.ts b/src/app/modules/groups/pages/list/list.component.ts index e1a917a..93c9ded 100644 --- a/src/app/modules/groups/pages/list/list.component.ts +++ b/src/app/modules/groups/pages/list/list.component.ts @@ -1,7 +1,6 @@ import {Component} from '@angular/core' import {GroupService} from '../../services/group.service' import {EmployeeGroup, EmployeePermission} from '../../../shared/model/employee' -import {map} from 'rxjs/operators' import {AccountService} from '../../../accounts/services/account.service' import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component' import {ActivatedRoute, Router} from '@angular/router' @@ -14,7 +13,7 @@ import {AlertService} from '../../../shared/service/alert.service' styleUrls: ['./list.component.sass'] }) export class ListComponent extends ErrorHandlingComponent { - groups$ = this.groupService.all.pipe(map(groups => groups.filter(g => g.id >= 0))) + groups$ = this.groupService.all defaultGroup: EmployeeGroup = null columns = [ {def: 'name', title: 'Nom', valueFn: g => g.name}, diff --git a/src/app/modules/groups/services/group.service.ts b/src/app/modules/groups/services/group.service.ts index fe56c48..565332c 100644 --- a/src/app/modules/groups/services/group.service.ts +++ b/src/app/modules/groups/services/group.service.ts @@ -15,6 +15,10 @@ export class GroupService { get all(): Observable { return this.api.get('/employee/group') + } + + get allWithDefault(): Observable { + return this.all .pipe(tap(groups => groups.unshift({ id: -1, name: 'Aucun', diff --git a/src/app/modules/shared/components/permissions-list/permissions-list.component.ts b/src/app/modules/shared/components/permissions-list/permissions-list.component.ts index 7595864..b63ac16 100644 --- a/src/app/modules/shared/components/permissions-list/permissions-list.component.ts +++ b/src/app/modules/shared/components/permissions-list/permissions-list.component.ts @@ -17,6 +17,7 @@ export class PermissionsListComponent { } get permissions(): EmployeePermission[] { + // @ts-ignore return this.filterPermissions(this.employee ? this.employee.permissions : this.group.permissions) } diff --git a/src/app/modules/shared/model/recipe.model.ts b/src/app/modules/shared/model/recipe.model.ts index 16dc864..679ba1a 100644 --- a/src/app/modules/shared/model/recipe.model.ts +++ b/src/app/modules/shared/model/recipe.model.ts @@ -1,6 +1,7 @@ -import {Material} from "./material.model"; -import {LocalDate} from "js-joda"; -import {Company} from "./company.model"; +import {Material} from './material.model' +import {LocalDate} from 'js-joda' +import {Company} from './company.model' +import {EmployeeGroup} from './employee' export class Recipe { constructor( @@ -12,9 +13,26 @@ export class Recipe { public sample: number, public approbationDate: LocalDate, public remark: string, - public note: string, public company: Company, public mixes: Mix[], + public groupsInformation: RecipeGroupInformation[] + ) { + } + + get mixCount(): number { + return this.mixes.length + } + + get stepCount(): number { + return this.groupsInformation.flatMap(i => i.steps).length + } +} + +export class RecipeGroupInformation { + constructor( + public id: number, + public group: EmployeeGroup, + public note: string, public steps: RecipeStep[] ) { } @@ -34,7 +52,8 @@ export class MixMaterial { constructor( public id: number, public material: Material, - public quantity: number + public quantity: number, + public position: number ) { } } @@ -51,7 +70,17 @@ class MixType { export class RecipeStep { constructor( public id: number, - public message: string + public message: string, + public position: number ) { } } + +export function recipeStepsForGroupId(recipe: Recipe, groupId: number): RecipeStep[] { + const groupInformation = recipe.groupsInformation.find(i => i.group.id === groupId) + return groupInformation ? sortRecipeSteps(groupInformation.steps) : [] +} + +export function sortRecipeSteps(steps: RecipeStep[]): RecipeStep[] { + return steps.sort((a, b) => a.position - b.position) +} diff --git a/src/styles.sass b/src/styles.sass index 2e6f3f5..d51f3b8 100644 --- a/src/styles.sass +++ b/src/styles.sass @@ -85,6 +85,15 @@ mat-expansion-panel.table-title &:hover, &:focus background-color: $color-primary !important + &.header-field .mat-form-field-flex + background-color: white + + .mat-form-field-outline + opacity: 1 + + &:first-child + opacity: 0 + mat-panel-title color: $light-primary-text !important font-weight: bold diff --git a/tsconfig.json b/tsconfig.json index 8c4ef3b..fcea47f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,7 @@ "importHelpers": true, "target": "es2015", "lib": [ - "es2018", + "es2019", "dom" ] },