develop #5
|
@ -4,6 +4,8 @@
|
|||
</mat-card-header>
|
||||
<mat-card-content [class.no-action]="!editionMode">
|
||||
<div class="d-flex flex-row justify-content-around flex-wrap">
|
||||
<p *ngIf="imagesUrls.length <= 0" class="light-text text-center">Aucune image n'est associée à cette couleur</p>
|
||||
|
||||
<div *ngFor="let imageUrl of imagesUrls" class="d-flex flex-column align-self-center m-3">
|
||||
<div class="image-wrapper">
|
||||
<img [src]="imageUrl" width="300px"/>
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
<mat-card-title>Mélanges</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content [class.no-action]="!editionMode">
|
||||
<p *ngIf="recipe.mixes.length <= 0" class="light-text text-center">Il n'y a aucun mélange dans cette couleur</p>
|
||||
|
||||
<ng-container *ngFor="let mix of recipe.mixes; let i = index">
|
||||
<cre-mix-table
|
||||
[class.no-top-margin]="i == 0"
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<div *ngIf="recipe">
|
||||
<cre-action-bar>
|
||||
<cre-action-group>
|
||||
<cre-primary-button routerLink="/color/list">Retour</cre-primary-button>
|
||||
<cre-unit-selector (unitChange)="changeUnits($event)"></cre-unit-selector>
|
||||
</cre-action-group>
|
||||
<cre-action-group>
|
||||
<cre-warn-button (click)="deleteConfirmBox.show()">Supprimer</cre-warn-button>
|
||||
<cre-accent-button (click)="submit()">Enregistrer</cre-accent-button>
|
||||
</cre-action-group>
|
||||
</cre-action-bar>
|
||||
|
||||
<div class="recipe-wrapper d-flex flex-row justify-content-around align-items-start flex-wrap">
|
||||
<section>
|
||||
<recipe-form [recipe]="recipe"></recipe-form>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<cre-mixes-card [recipe]="recipe" [units$]="units$" [editionMode]="true"></cre-mixes-card>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<cre-step-table [recipe]="recipe" [groups$]="groups$" [selectedGroupId]="loggedInUserGroupId"></cre-step-table>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<cre-images-editor [recipe]="recipe" [editionMode]="true"></cre-images-editor>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<cre-confirm-box
|
||||
#deleteConfirmBox
|
||||
message="Voulez-vous vraiment supprimer la couleur {{recipe?.name}}?"
|
||||
(confirm)="delete()">
|
||||
</cre-confirm-box>
|
|
@ -1,12 +1,13 @@
|
|||
<div class="mt-5">
|
||||
<cre-warning-alert *ngIf="!loading && !hasCompanies">
|
||||
<div *ngIf="!loading && !hasCompanies" class="mt-5">
|
||||
<cre-warning-alert>
|
||||
<p>Il n'y a actuellement aucune bannière enregistrée dans le système.</p>
|
||||
<p *ngIf="hasCompanyEditPermission">Vous pouvez en créer une <b><a routerLink="/catalog/company/add">ici</a></b>.</p>
|
||||
</cre-warning-alert>
|
||||
</div>
|
||||
|
||||
<cre-form *ngIf="hasCompanies" #form [formControls]="controls" class="mx-auto">
|
||||
<cre-form-title>Ajouter une recette</cre-form-title>
|
||||
<cre-form-title *ngIf="!recipe">Ajouter une couleur</cre-form-title>
|
||||
<cre-form-title *ngIf="recipe">Modifier la couleur {{recipe.name}}</cre-form-title>
|
||||
<cre-form-content>
|
||||
<cre-input [control]="controls.name" label="Name" icon="form-textbox"></cre-input>
|
||||
<cre-input [control]="controls.description" label="Description" icon="text"></cre-input>
|
||||
|
@ -17,7 +18,7 @@
|
|||
<cre-input [control]="controls.remark" label="Remarque" icon="text"></cre-input>
|
||||
<cre-combo-box [control]="controls.company" label="Bannière" [entries]="companyEntries$"></cre-combo-box>
|
||||
</cre-form-content>
|
||||
<cre-form-actions>
|
||||
<cre-form-actions *ngIf="!recipe">
|
||||
<cre-primary-button routerLink="/color/list">Retour</cre-primary-button>
|
||||
<cre-accent-button [disabled]="form.invalid" (click)="submit()">Enregistrer</cre-accent-button>
|
||||
</cre-form-actions>
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
<div *ngIf="recipe">
|
||||
<div class="action-bar backward">
|
||||
<div class="d-flex flex-column">
|
||||
<div class="mt-1 pb-2">
|
||||
<button mat-raised-button color="primary" routerLink="/color/list">Retour</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
[disabled]="editComponent.form && editComponent.form.invalid"
|
||||
(click)="submit(editComponent, stepTable)">
|
||||
Enregistrer
|
||||
</button>
|
||||
<button
|
||||
mat-raised-button
|
||||
color="warn"
|
||||
(click)="confirmBoxComponent.show()">
|
||||
Supprimer
|
||||
</button>
|
||||
</div>
|
||||
<mat-form-field>
|
||||
<mat-label>Unités</mat-label>
|
||||
<mat-select [value]="unitConstants.UNIT_MILLILITER" (selectionChange)="changeUnits($event.value)">
|
||||
<mat-option [value]="unitConstants.UNIT_MILLILITER">Millilitres</mat-option>
|
||||
<mat-option [value]="unitConstants.UNIT_LITER">Litres</mat-option>
|
||||
<mat-option [value]="unitConstants.UNIT_GALLON">Gallons</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="flex-grow-1"></div>
|
||||
</div>
|
||||
|
||||
<div class="recipe-wrapper d-flex flex-row justify-content-around align-items-start flex-wrap">
|
||||
<div>
|
||||
<cre-entity-edit
|
||||
#editComponent
|
||||
title="Modifier la couleur {{recipe.name}}"
|
||||
deleteConfirmMessage="Voulez-vous vraiment supprimer la couleur {{recipe.name}}?"
|
||||
[entity]="recipe"
|
||||
[formFields]="formFields"
|
||||
[disableButtons]="true"
|
||||
[noTopMargin]="true">
|
||||
</cre-entity-edit>
|
||||
</div>
|
||||
|
||||
<div class="recipe-mixes-wrapper">
|
||||
<cre-mixes-card [recipe]="recipe" [units$]="units$" [editionMode]="true"></cre-mixes-card>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<cre-step-table
|
||||
#stepTable
|
||||
[recipe]="recipe"
|
||||
[groups$]="groups$"
|
||||
[selectedGroupId]="loggedInUserGroupId">
|
||||
</cre-step-table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<cre-images-editor #imagesEditor [recipe]="recipe" [editionMode]="true"></cre-images-editor>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<cre-confirm-box
|
||||
#confirmBoxComponent
|
||||
message="Voulez-vous vraiment supprimer la couleur {{recipe?.name}}?"
|
||||
(confirm)="delete()">
|
||||
</cre-confirm-box>
|
|
@ -1,2 +0,0 @@
|
|||
.recipe-wrapper > div
|
||||
margin: 0 3rem 3rem
|
|
@ -1,186 +0,0 @@
|
|||
import {Component, ViewChild} from '@angular/core'
|
||||
import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component'
|
||||
import {Recipe, recipeMixCount, RecipeStep, recipeStepCount} from '../../../shared/model/recipe.model'
|
||||
import {RecipeService} from '../../services/recipe.service'
|
||||
import {ActivatedRoute, Router} from '@angular/router'
|
||||
import {Validators} from '@angular/forms'
|
||||
import {Subject} from 'rxjs'
|
||||
import {UNIT_GALLON, UNIT_LITER, UNIT_MILLILITER} from '../../../shared/units'
|
||||
import {AccountService} from '../../../accounts/services/account.service'
|
||||
import {EntityEditComponent} from '../../../shared/components/entity-edit/entity-edit.component'
|
||||
import {ImagesEditorComponent} from '../../components/images-editor/images-editor.component'
|
||||
import {ErrorHandler, 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',
|
||||
templateUrl: './edit.component.html',
|
||||
styleUrls: ['./edit.component.sass']
|
||||
})
|
||||
export class EditComponent extends ErrorHandlingComponent {
|
||||
readonly unitConstants = {UNIT_MILLILITER, UNIT_LITER, UNIT_GALLON}
|
||||
|
||||
@ViewChild('imagesEditor') imagesEditor: ImagesEditorComponent
|
||||
|
||||
recipe: Recipe | null
|
||||
groups$ = this.groupService.all
|
||||
formFields = [
|
||||
{
|
||||
name: 'name',
|
||||
label: 'Nom',
|
||||
icon: 'form-textbox',
|
||||
type: 'text',
|
||||
required: true,
|
||||
errorMessages: [
|
||||
{conditionFn: errors => errors.required, message: 'Un nom est requis'}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
label: 'Description',
|
||||
icon: 'text',
|
||||
type: 'text',
|
||||
required: true,
|
||||
errorMessages: [
|
||||
{conditionFn: errors => errors.required, message: 'Une description est requise'}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'color',
|
||||
label: 'Couleur',
|
||||
icon: 'palette',
|
||||
type: 'color',
|
||||
required: true,
|
||||
errorMessages: [
|
||||
{conditionFn: errors => errors.required, message: 'Une couleur est requise'}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'gloss',
|
||||
label: 'Lustre',
|
||||
type: 'slider',
|
||||
min: 0,
|
||||
max: 100,
|
||||
validator: Validators.compose([Validators.required, Validators.min(0), Validators.max(100)]),
|
||||
errorMessages: [
|
||||
{conditionFn: errors => errors.required, message: 'Le lustre de la couleur est requis'}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'sample',
|
||||
label: 'Échantillon',
|
||||
icon: 'pound',
|
||||
type: 'number',
|
||||
validator: Validators.min(0),
|
||||
errorMessages: [
|
||||
{conditionFn: errors => errors.required, message: 'Un numéro d\'échantillon est requis'},
|
||||
{conditionFn: errors => errors.min, message: 'Le numéro d\'échantillon doit être supérieur ou égal à 0'}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'approbationDate',
|
||||
label: 'Date d\'approbation',
|
||||
icon: 'calendar',
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
name: 'remark',
|
||||
label: 'Remarque',
|
||||
icon: 'text',
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
name: 'company',
|
||||
label: 'Bannière',
|
||||
icon: 'domain',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
valueFn: recipe => recipe.company.name,
|
||||
}
|
||||
]
|
||||
units$ = new Subject<string>()
|
||||
submittedValues: any | null
|
||||
|
||||
errorHandlers: ErrorHandler[] = [{
|
||||
filter: error => error.type === 'notfound-recipe-id',
|
||||
consumer: error => this.urlUtils.navigateTo('/color/list')
|
||||
}]
|
||||
|
||||
constructor(
|
||||
private recipeService: RecipeService,
|
||||
private groupService: GroupService,
|
||||
private accountService: AccountService,
|
||||
private alertService: AlertService,
|
||||
private appState: AppState,
|
||||
errorService: ErrorService,
|
||||
router: Router,
|
||||
activatedRoute: ActivatedRoute
|
||||
) {
|
||||
super(errorService, activatedRoute, router)
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit()
|
||||
|
||||
this.subscribeEntityById(
|
||||
this.recipeService,
|
||||
parseInt(this.activatedRoute.snapshot.paramMap.get('id')),
|
||||
recipe => {
|
||||
this.recipe = recipe
|
||||
this.appState.title = `${recipe.name} (Modifications)`
|
||||
|
||||
if (recipeMixCount(this.recipe) == 0) {
|
||||
this.alertService.pushWarning('Il n\'y a aucun mélange dans cette recette')
|
||||
}
|
||||
if (recipeStepCount(this.recipe) == 0) {
|
||||
this.alertService.pushWarning('Il n\'y a aucune étape dans cette recette')
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
changeUnits(unit: string) {
|
||||
this.units$.next(unit)
|
||||
}
|
||||
|
||||
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, steps),
|
||||
'/color/list'
|
||||
)
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.subscribeAndNavigate(
|
||||
this.recipeService.delete(this.recipe.id),
|
||||
'/color/list'
|
||||
)
|
||||
}
|
||||
|
||||
get loggedInUserGroupId(): number {
|
||||
return this.appState.authenticatedUser.group?.id
|
||||
}
|
||||
|
||||
private stepsPositionsAreValid(steps: Map<number, RecipeStep[]>): boolean {
|
||||
let valid = true
|
||||
steps.forEach((steps, _) => {
|
||||
if (steps.find(s => s.position === 0)) {
|
||||
valid = false
|
||||
return
|
||||
}
|
||||
})
|
||||
return valid
|
||||
}
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {ListComponent} from "./pages/list/list.component";
|
||||
import {EditComponent} from "./pages/edit/edit.component";
|
||||
import {ExploreComponent} from "./pages/explore/explore.component";
|
||||
import {MixEditComponent} from "./pages/mix/mix-edit/mix-edit.component";
|
||||
import {MixAddComponent} from "./pages/mix/mix-add/mix-add.component";
|
||||
import {RecipeAdd} from './recipes';
|
||||
import {ListComponent} from './pages/list/list.component';
|
||||
import {ExploreComponent} from './pages/explore/explore.component';
|
||||
import {MixEditComponent} from './pages/mix/mix-edit/mix-edit.component';
|
||||
import {MixAddComponent} from './pages/mix/mix-add/mix-add.component';
|
||||
import {RecipeAdd, RecipeEdit} from './recipes';
|
||||
|
||||
const routes: Routes = [{
|
||||
path: 'list',
|
||||
|
@ -15,7 +14,7 @@ const routes: Routes = [{
|
|||
component: RecipeAdd
|
||||
}, {
|
||||
path: 'edit/:id',
|
||||
component: EditComponent
|
||||
component: RecipeEdit
|
||||
}, {
|
||||
path: 'add/mix/:recipeId',
|
||||
component: MixAddComponent
|
||||
|
|
|
@ -3,7 +3,6 @@ import {NgModule} from '@angular/core'
|
|||
import {RecipesRoutingModule} from './recipes-routing.module'
|
||||
import {SharedModule} from '../shared/shared.module'
|
||||
import {ListComponent} from './pages/list/list.component'
|
||||
import {EditComponent} from './pages/edit/edit.component'
|
||||
import {MatExpansionModule} from '@angular/material/expansion'
|
||||
import {FormsModule} from '@angular/forms'
|
||||
import {ExploreComponent} from './pages/explore/explore.component'
|
||||
|
@ -20,13 +19,13 @@ import {MixesCardComponent} from './components/mixes-card/mixes-card.component'
|
|||
import {MatSortModule} from '@angular/material/sort'
|
||||
import {CreInputsModule} from '../shared/components/inputs/inputs.module';
|
||||
import {CreButtonsModule} from '../shared/components/buttons/buttons.module';
|
||||
import {RecipeAdd, RecipeForm} from './recipes';
|
||||
import {RecipeAdd, RecipeEdit, RecipeForm} from './recipes';
|
||||
import {CreActionBarModule} from '../shared/components/action-bar/action-bar.module';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
ListComponent,
|
||||
EditComponent,
|
||||
ExploreComponent,
|
||||
RecipeInfoComponent,
|
||||
MixTableComponent,
|
||||
|
@ -39,7 +38,8 @@ import {RecipeAdd, RecipeForm} from './recipes';
|
|||
ImagesEditorComponent,
|
||||
MixesCardComponent,
|
||||
RecipeForm,
|
||||
RecipeAdd
|
||||
RecipeAdd,
|
||||
RecipeEdit
|
||||
],
|
||||
exports: [
|
||||
UnitSelectorComponent
|
||||
|
@ -51,7 +51,8 @@ import {RecipeAdd, RecipeForm} from './recipes';
|
|||
FormsModule,
|
||||
MatSortModule,
|
||||
CreInputsModule,
|
||||
CreButtonsModule
|
||||
CreButtonsModule,
|
||||
CreActionBarModule
|
||||
]
|
||||
})
|
||||
export class RecipesModule {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
.recipe-wrapper > section
|
||||
margin: 0 3rem 3rem
|
||||
|
||||
cre-form
|
||||
margin-top: 0 !important
|
||||
|
|
@ -1,56 +1,27 @@
|
|||
import {ErrorHandlingComponent, SubscribingComponent} from '../shared/components/subscribing.component';
|
||||
import {Observable} from 'rxjs';
|
||||
import {Observable, Subject} from 'rxjs';
|
||||
import {ComboBoxEntry} from '../shared/components/inputs/inputs';
|
||||
import {map, tap} from 'rxjs/operators';
|
||||
import {RecipeService} from './services/recipe.service';
|
||||
import {CompanyService} from '../company/service/company.service';
|
||||
import {AppState} from '../shared/app-state';
|
||||
import {ErrorService} from '../shared/service/error.service';
|
||||
import {ErrorHandler, ErrorService} from '../shared/service/error.service';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {FormControl, Validators} from '@angular/forms';
|
||||
import {Component, EventEmitter, Input, Output} from '@angular/core';
|
||||
import {Recipe} from '../shared/model/recipe.model';
|
||||
import {Component, EventEmitter, Input, Output, ViewChild, ViewEncapsulation} from '@angular/core';
|
||||
import {Recipe, recipeMixCount, RecipeStep, recipeStepCount} from '../shared/model/recipe.model';
|
||||
import {AccountService} from '../accounts/services/account.service';
|
||||
import {Permission} from '../shared/model/user';
|
||||
|
||||
@Component({
|
||||
selector: 'cre-recipe-add',
|
||||
templateUrl: 'add.html'
|
||||
})
|
||||
export class RecipeAdd extends ErrorHandlingComponent {
|
||||
controls: any
|
||||
companyEntries$: Observable<ComboBoxEntry[]> = this.companyService.all.pipe(
|
||||
map(companies => companies.map(c => new ComboBoxEntry(c.id, c.name))),
|
||||
)
|
||||
|
||||
errorHandlers = [{
|
||||
filter: error => error.type === `exists-recipe-company-name`,
|
||||
messageProducer: error => `Une couleur avec le nom ${error.name} existe déjà pour la bannière ${error.company}`
|
||||
}]
|
||||
|
||||
constructor(
|
||||
private recipeService: RecipeService,
|
||||
private companyService: CompanyService,
|
||||
private appState: AppState,
|
||||
errorService: ErrorService,
|
||||
router: Router,
|
||||
activatedRoute: ActivatedRoute
|
||||
) {
|
||||
super(errorService, activatedRoute, router)
|
||||
this.appState.title = 'Nouvelle couleur'
|
||||
}
|
||||
|
||||
submit(recipe: Recipe) {
|
||||
this.subscribe(
|
||||
this.recipeService.save(recipe),
|
||||
recipe => this.urlUtils.navigateTo(`/color/edit/${recipe.id}`)
|
||||
)
|
||||
}
|
||||
}
|
||||
import {AlertService} from '../shared/service/alert.service';
|
||||
import {GroupService} from '../groups/services/group.service';
|
||||
import {StepTableComponent} from './components/step-table/step-table.component';
|
||||
import {anyMap} from '../shared/utils/map.utils';
|
||||
|
||||
@Component({
|
||||
selector: 'recipe-form',
|
||||
templateUrl: 'form.html'
|
||||
templateUrl: 'form.html',
|
||||
styleUrls: ['recipes.sass'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class RecipeForm extends SubscribingComponent {
|
||||
@Input() recipe: Recipe | null
|
||||
|
@ -77,14 +48,14 @@ export class RecipeForm extends SubscribingComponent {
|
|||
this.fetchCompanies()
|
||||
|
||||
this.controls = {
|
||||
name: new FormControl(null, Validators.required),
|
||||
description: new FormControl(null, Validators.required),
|
||||
color: new FormControl('#ffffff', Validators.required),
|
||||
gloss: new FormControl(0, Validators.compose([Validators.required, Validators.min(0), Validators.max(100)])),
|
||||
sample: new FormControl(null, Validators.compose([Validators.required, Validators.min(0)])),
|
||||
approbationDate: new FormControl(null),
|
||||
remark: new FormControl(null),
|
||||
company: new FormControl(null, Validators.required)
|
||||
name: new FormControl(this.recipe?.name, Validators.required),
|
||||
description: new FormControl(this.recipe?.description, Validators.required),
|
||||
color: new FormControl(this.recipe?.color ?? '#ffffff', Validators.required),
|
||||
gloss: new FormControl(this.recipe?.gloss ?? 0, Validators.compose([Validators.required, Validators.min(0), Validators.max(100)])),
|
||||
sample: new FormControl(this.recipe?.sample, Validators.compose([Validators.required, Validators.min(0)])),
|
||||
approbationDate: new FormControl(this.recipe?.approbationDate),
|
||||
remark: new FormControl(this.recipe?.remark),
|
||||
company: new FormControl({value: this.recipe?.company.id, disabled: !!this.recipe}, Validators.required)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,8 +67,12 @@ export class RecipeForm extends SubscribingComponent {
|
|||
}
|
||||
|
||||
submit() {
|
||||
this.submitForm.emit({
|
||||
id: this.recipe?.id,
|
||||
this.submitForm.emit(this.updatedRecipe)
|
||||
}
|
||||
|
||||
get updatedRecipe(): Recipe {
|
||||
return {
|
||||
...this.recipe,
|
||||
name: this.controls.name.value,
|
||||
description: this.controls.description.value,
|
||||
color: this.controls.color.value,
|
||||
|
@ -106,14 +81,128 @@ export class RecipeForm extends SubscribingComponent {
|
|||
approbationDate: this.controls.approbationDate.value,
|
||||
remark: this.controls.remark.value,
|
||||
company: this.controls.company.value,
|
||||
mixes: this.recipe?.mixes,
|
||||
approbationExpired: this.recipe?.approbationExpired,
|
||||
groupsInformation: this.recipe?.groupsInformation,
|
||||
imagesUrls: this.recipe?.imagesUrls
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
get hasCompanyEditPermission(): boolean {
|
||||
return this.accountService.hasPermission(Permission.EDIT_COMPANIES)
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'cre-recipe-add',
|
||||
templateUrl: 'add.html'
|
||||
})
|
||||
export class RecipeAdd extends ErrorHandlingComponent {
|
||||
errorHandlers = [{
|
||||
filter: error => error.type === `exists-recipe-company-name`,
|
||||
messageProducer: error => `Une couleur avec le nom ${error.name} existe déjà pour la bannière ${error.company}`
|
||||
}]
|
||||
|
||||
constructor(
|
||||
private recipeService: RecipeService,
|
||||
private companyService: CompanyService,
|
||||
private appState: AppState,
|
||||
errorService: ErrorService,
|
||||
router: Router,
|
||||
activatedRoute: ActivatedRoute
|
||||
) {
|
||||
super(errorService, activatedRoute, router)
|
||||
this.appState.title = 'Nouvelle couleur'
|
||||
}
|
||||
|
||||
submit(recipe: Recipe) {
|
||||
this.subscribe(
|
||||
this.recipeService.save(recipe),
|
||||
recipe => this.urlUtils.navigateTo(`/color/edit/${recipe.id}`)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'cre-recipe-edit',
|
||||
templateUrl: 'edit.html',
|
||||
styleUrls: ['recipes.sass']
|
||||
})
|
||||
export class RecipeEdit extends ErrorHandlingComponent {
|
||||
@ViewChild(StepTableComponent) stepTable: StepTableComponent
|
||||
@ViewChild(RecipeForm) form: RecipeForm
|
||||
|
||||
recipe: Recipe
|
||||
groups$ = this.groupService.all
|
||||
units$ = new Subject<string>()
|
||||
|
||||
errorHandlers: ErrorHandler[] = [{
|
||||
filter: error => error.type === 'notfound-recipe-id',
|
||||
consumer: _ => this.urlUtils.navigateTo('/color/list')
|
||||
}]
|
||||
|
||||
constructor(
|
||||
private recipeService: RecipeService,
|
||||
private companyService: CompanyService,
|
||||
private groupService: GroupService,
|
||||
private appState: AppState,
|
||||
private alertService: AlertService,
|
||||
errorService: ErrorService,
|
||||
router: Router,
|
||||
activatedRoute: ActivatedRoute
|
||||
) {
|
||||
super(errorService, activatedRoute, router)
|
||||
|
||||
this.fetchRecipe()
|
||||
}
|
||||
|
||||
private fetchRecipe() {
|
||||
const recipeId = this.urlUtils.parseIntUrlParam('id')
|
||||
this.subscribe(
|
||||
this.recipeService.getById(recipeId),
|
||||
recipe => {
|
||||
this.recipe = recipe
|
||||
this.appState.title = `${recipe.name} (Modifications)`
|
||||
|
||||
if (recipeMixCount(this.recipe) == 0) {
|
||||
this.alertService.pushWarning('Il n\'y a aucun mélange dans cette recette')
|
||||
}
|
||||
if (recipeStepCount(this.recipe) == 0) {
|
||||
this.alertService.pushWarning('Il n\'y a aucune étape dans cette recette')
|
||||
}
|
||||
},
|
||||
true,
|
||||
1
|
||||
)
|
||||
}
|
||||
|
||||
changeUnits(unit: string) {
|
||||
this.units$.next(unit)
|
||||
}
|
||||
|
||||
submit() {
|
||||
const recipe = this.form.updatedRecipe
|
||||
const steps = this.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(recipe, steps),
|
||||
'/color/list'
|
||||
)
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.subscribeAndNavigate(
|
||||
this.recipeService.delete(this.recipe.id),
|
||||
'/color/list'
|
||||
)
|
||||
}
|
||||
|
||||
get loggedInUserGroupId(): number {
|
||||
return this.appState.authenticatedUser.group?.id
|
||||
}
|
||||
|
||||
private stepsPositionsAreValid(steps: Map<number, RecipeStep[]>): boolean {
|
||||
return !anyMap(steps, (groupId, steps) => !!steps.find(s => s.position === 0))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,11 +48,10 @@ export class RecipeService {
|
|||
return this.api.post<Recipe>('/recipe', body)
|
||||
}
|
||||
|
||||
update(id: number, name: string, description: string, color: string, gloss: number, sample: number, approbationDate: string, remark: string, steps: Map<number, RecipeStep[]>) {
|
||||
const body = {id, name, description, color, gloss, sample, remark, steps: []}
|
||||
if (approbationDate) {
|
||||
// @ts-ignore
|
||||
body.approbationDate = approbationDate
|
||||
update(recipe: Recipe, steps: Map<number, RecipeStep[]>) {
|
||||
const body = {
|
||||
...recipe,
|
||||
steps: []
|
||||
}
|
||||
|
||||
steps.forEach((groupSteps, groupId) => {
|
||||
|
|
|
@ -156,11 +156,20 @@ export class CreComboBoxComponent implements OnInit {
|
|||
next: entries => {
|
||||
this._entries = entries
|
||||
|
||||
this.internalControl.setValue(this.findEntryByKey(this.control.value)?.value)
|
||||
if (this.control.value) {
|
||||
this.internalControl.setValue(this.findEntryByKey(this.control.value)?.value)
|
||||
}
|
||||
|
||||
if (this.internalControl.disabled) {
|
||||
this.internalControl.disable()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.internalControl = new FormControl(null, Validators.compose([this.control.validator, this.valueValidator()]))
|
||||
this.internalControl = new FormControl({
|
||||
value: null,
|
||||
disabled: true
|
||||
}, Validators.compose([this.control.validator, this.valueValidator()]))
|
||||
this.internalControl.valueChanges.pipe(takeUntil(this._destroy$))
|
||||
.subscribe({
|
||||
next: value => {
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
export function anyMap<K, V>(map: Map<K, V>, predicate: (key: K, value: V) => boolean): boolean {
|
||||
return filterMap(map, predicate).size > 0
|
||||
}
|
||||
|
||||
export function filterMap<K, V>(map: Map<K, V>, predicate: (key: K, value: V) => boolean): Map<K, V> {
|
||||
const filteredMap = new Map<K, V>()
|
||||
map.forEach((value, key) => {
|
||||
|
|
Loading…
Reference in New Issue