Update recipe list
This commit is contained in:
parent
4ccdd090c1
commit
f564c37b15
|
@ -9,7 +9,7 @@
|
||||||
<p *ngIf="hasEditPermission">Vous pouvez en créer une <b><a routerLink="/catalog/company/add">ici</a></b>.</p>
|
<p *ngIf="hasEditPermission">Vous pouvez en créer une <b><a routerLink="/catalog/company/add">ici</a></b>.</p>
|
||||||
</cre-warning-alert>
|
</cre-warning-alert>
|
||||||
|
|
||||||
<cre-table *ngIf="!companiesEmpty" class="mx-auto" [dataSource]="companies$ | async" [columns]="columns">
|
<cre-table *ngIf="!companiesEmpty" class="mx-auto" [data]="companies$ | async" [columns]="columns">
|
||||||
<ng-container matColumnDef="name">
|
<ng-container matColumnDef="name">
|
||||||
<th mat-header-cell *matHeaderCellDef>Nom</th>
|
<th mat-header-cell *matHeaderCellDef>Nom</th>
|
||||||
<td mat-cell *matCellDef="let company">{{company.name}}</td>
|
<td mat-cell *matCellDef="let company">{{company.name}}</td>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<cre-table
|
<cre-table
|
||||||
*ngIf="!materialTypesEmpty"
|
*ngIf="!materialTypesEmpty"
|
||||||
class="mx-auto"
|
class="mx-auto"
|
||||||
[dataSource]="materialTypes$ | async"
|
[data]="materialTypes$ | async"
|
||||||
[columns]="columns">
|
[columns]="columns">
|
||||||
<ng-container matColumnDef="name">
|
<ng-container matColumnDef="name">
|
||||||
<th mat-header-cell *matHeaderCellDef>Nom</th>
|
<th mat-header-cell *matHeaderCellDef>Nom</th>
|
||||||
|
|
|
@ -36,7 +36,12 @@
|
||||||
<ng-template
|
<ng-template
|
||||||
#recipeTableTemplate
|
#recipeTableTemplate
|
||||||
let-recipes="recipes">
|
let-recipes="recipes">
|
||||||
<table class="mx-auto" mat-table [dataSource]="recipes">
|
<cre-table
|
||||||
|
class="w-100"
|
||||||
|
[columns]="columns"
|
||||||
|
[data]="recipes"
|
||||||
|
[filter]="searchQuery"
|
||||||
|
[filterFn]="recipeFilterPredicate">
|
||||||
<!-- Recipe's info -->
|
<!-- Recipe's info -->
|
||||||
<ng-container matColumnDef="name">
|
<ng-container matColumnDef="name">
|
||||||
<th mat-header-cell *matHeaderCellDef>Nom</th>
|
<th mat-header-cell *matHeaderCellDef>Nom</th>
|
||||||
|
@ -84,19 +89,16 @@
|
||||||
<!-- Buttons -->
|
<!-- Buttons -->
|
||||||
<ng-container matColumnDef="buttonView">
|
<ng-container matColumnDef="buttonView">
|
||||||
<th mat-header-cell *matHeaderCellDef></th>
|
<th mat-header-cell *matHeaderCellDef></th>
|
||||||
<td mat-cell *matCellDef="let recipe">
|
<td mat-cell *matCellDef="let recipe; let i = index">
|
||||||
<button mat-flat-button color="accent" routerLink="/color/explore/{{recipe.id}}">Voir</button>
|
<cre-accent-button [creInteractiveCell]="i" routerLink="/color/explore/{{recipe.id}}">Voir</cre-accent-button>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="buttonEdit">
|
<ng-container matColumnDef="buttonEdit">
|
||||||
<th mat-header-cell *matHeaderCellDef></th>
|
<th mat-header-cell *matHeaderCellDef></th>
|
||||||
<td mat-cell *matCellDef="let recipe" [class.disabled]="!hasEditPermission">
|
<td mat-cell *matCellDef="let recipe; let i = index" [class.disabled]="!hasEditPermission">
|
||||||
<button mat-flat-button color="accent" routerLink="/color/edit/{{recipe.id}}">Modifier</button>
|
<cre-accent-button [creInteractiveCell]="i" routerLink="/color/edit/{{recipe.id}}">Modifier</cre-accent-button>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
</cre-table>
|
||||||
<tr mat-header-row *matHeaderRowDef="tableCols"></tr>
|
|
||||||
<tr mat-row *matRowDef="let recipe; columns: tableCols" [hidden]="hiddenRecipes[recipe.id]"></tr>
|
|
||||||
</table>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import {ChangeDetectorRef, Component} from '@angular/core';
|
import {ChangeDetectorRef, Component} from '@angular/core'
|
||||||
import {ErrorHandlingComponent} from '../shared/components/subscribing.component';
|
import {ErrorHandlingComponent} from '../shared/components/subscribing.component'
|
||||||
import {Company} from '../shared/model/company.model';
|
import {Company} from '../shared/model/company.model'
|
||||||
import {getRecipeLuma, Recipe} from '../shared/model/recipe.model';
|
import {getRecipeLuma, Recipe, recipeMatchesFilter} from '../shared/model/recipe.model'
|
||||||
import {CompanyService} from '../company/service/company.service';
|
import {CompanyService} from '../company/service/company.service'
|
||||||
import {RecipeService} from './services/recipe.service';
|
import {RecipeService} from './services/recipe.service'
|
||||||
import {AccountService} from '../accounts/services/account.service';
|
import {AccountService} from '../accounts/services/account.service'
|
||||||
import {ConfigService} from '../shared/service/config.service';
|
import {ConfigService} from '../shared/service/config.service'
|
||||||
import {AppState} from '../shared/app-state';
|
import {AppState} from '../shared/app-state'
|
||||||
import {ErrorService} from '../shared/service/error.service';
|
import {ErrorService} from '../shared/service/error.service'
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import {ActivatedRoute, Router} from '@angular/router'
|
||||||
import {Config} from '../shared/model/config.model';
|
import {Config} from '../shared/model/config.model'
|
||||||
import {Permission} from '../shared/model/user';
|
import {Permission} from '../shared/model/user'
|
||||||
import {FormControl} from '@angular/forms';
|
import {FormControl} from '@angular/forms'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'cre-recipe-list',
|
selector: 'cre-recipe-list',
|
||||||
|
@ -21,12 +21,13 @@ import {FormControl} from '@angular/forms';
|
||||||
export class RecipeList extends ErrorHandlingComponent {
|
export class RecipeList extends ErrorHandlingComponent {
|
||||||
companies: Company[] = []
|
companies: Company[] = []
|
||||||
recipes: Map<number, Recipe[]> = new Map<number, Recipe[]>()
|
recipes: Map<number, Recipe[]> = new Map<number, Recipe[]>()
|
||||||
tableCols = ['name', 'description', 'color', 'sample', 'iconNotApproved', 'buttonView', 'buttonEdit']
|
columns = ['name', 'description', 'color', 'sample', 'iconNotApproved', 'buttonView', 'buttonEdit']
|
||||||
searchQuery = ''
|
|
||||||
panelForcedExpanded = false
|
panelForcedExpanded = false
|
||||||
hiddenRecipes = []
|
|
||||||
|
|
||||||
searchControl: FormControl
|
searchControl: FormControl
|
||||||
|
searchQuery = ''
|
||||||
|
|
||||||
|
recipeFilterPredicate = recipeMatchesFilter
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private companyService: CompanyService,
|
private companyService: CompanyService,
|
||||||
|
@ -62,7 +63,13 @@ export class RecipeList extends ErrorHandlingComponent {
|
||||||
this.searchControl = new FormControl('')
|
this.searchControl = new FormControl('')
|
||||||
this.subscribe(
|
this.subscribe(
|
||||||
this.searchControl.valueChanges,
|
this.searchControl.valueChanges,
|
||||||
value => this.searchRecipes(value)
|
value => {
|
||||||
|
this.searchQuery = value
|
||||||
|
if (value.length > 0 && !this.panelForcedExpanded) {
|
||||||
|
this.panelForcedExpanded = true
|
||||||
|
this.cdRef.detectChanges()
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,25 +88,14 @@ export class RecipeList extends ErrorHandlingComponent {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchRecipes(searchQuery) {
|
|
||||||
this.searchQuery = searchQuery
|
|
||||||
if (this.searchQuery.length > 0 && !this.panelForcedExpanded) {
|
|
||||||
this.panelForcedExpanded = true
|
|
||||||
this.cdRef.detectChanges()
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let recipeArray of this.recipes.values()) {
|
|
||||||
recipeArray.forEach(recipe => this.recipeMatchesSearchQuery(recipe))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isCompanyHidden(company: Company): boolean {
|
isCompanyHidden(company: Company): boolean {
|
||||||
const companyRecipes = this.recipes.get(company.id);
|
const companyRecipes = this.recipes.get(company.id)
|
||||||
return !(companyRecipes && companyRecipes.length >= 0) ||
|
return !(companyRecipes && companyRecipes.length >= 0) ||
|
||||||
this.searchQuery && this.searchQuery.length > 0 &&
|
this.searchQuery && this.searchQuery.length > 0 &&
|
||||||
companyRecipes.map(r => this.hiddenRecipes[r.id]).filter(r => !r).length <= 0
|
!companyRecipes.some(recipe => this.recipeFilterPredicate(recipe, this.searchQuery))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
isLight(recipe: Recipe): boolean {
|
isLight(recipe: Recipe): boolean {
|
||||||
return getRecipeLuma(recipe) > 200
|
return getRecipeLuma(recipe) > 200
|
||||||
}
|
}
|
||||||
|
@ -111,16 +107,4 @@ export class RecipeList extends ErrorHandlingComponent {
|
||||||
get hasCompanyEditPermission(): boolean {
|
get hasCompanyEditPermission(): boolean {
|
||||||
return this.accountService.hasPermission(Permission.EDIT_COMPANIES)
|
return this.accountService.hasPermission(Permission.EDIT_COMPANIES)
|
||||||
}
|
}
|
||||||
|
|
||||||
private recipeMatchesSearchQuery(recipe: Recipe) {
|
|
||||||
const matches = this.searchString(recipe.company.name) ||
|
|
||||||
this.searchString(recipe.name) ||
|
|
||||||
this.searchString(recipe.description) ||
|
|
||||||
(recipe.sample && this.searchString(recipe.sample.toString()))
|
|
||||||
this.hiddenRecipes[recipe.id] = !matches
|
|
||||||
}
|
|
||||||
|
|
||||||
private searchString(value: string): boolean {
|
|
||||||
return value.toLowerCase().indexOf(this.searchQuery.toLowerCase()) >= 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</p>
|
</p>
|
||||||
</cre-warning-alert>
|
</cre-warning-alert>
|
||||||
|
|
||||||
<cre-table [hidden]="materialCount <= 0" class="mx-auto" [dataSource]="mixMaterials" [columns]="columns">
|
<cre-table [hidden]="materialCount <= 0" class="mx-auto" [data]="mixMaterials" [columns]="columns">
|
||||||
<ng-container matColumnDef="position">
|
<ng-container matColumnDef="position">
|
||||||
<th mat-header-cell *matHeaderCellDef>Position</th>
|
<th mat-header-cell *matHeaderCellDef>Position</th>
|
||||||
<td mat-cell *matCellDef="let mixMaterial">{{mixMaterial.position}}</td>
|
<td mat-cell *matCellDef="let mixMaterial">{{mixMaterial.position}}</td>
|
||||||
|
|
|
@ -16,3 +16,15 @@ mat-expansion-panel
|
||||||
|
|
||||||
.recipe-content > div
|
.recipe-content > div
|
||||||
margin: 0 3rem 3rem
|
margin: 0 3rem 3rem
|
||||||
|
|
||||||
|
cre-table
|
||||||
|
.mat-column-name,
|
||||||
|
.mat-column-color,
|
||||||
|
.mat-column-iconNotApproved
|
||||||
|
width: 5em
|
||||||
|
|
||||||
|
.mat-column-description
|
||||||
|
width: 50em
|
||||||
|
|
||||||
|
.mat-column-sample
|
||||||
|
width: 10em
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
<table mat-table [dataSource]="dataSource">
|
<table
|
||||||
|
mat-table
|
||||||
|
[dataSource]="dataSource">
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="columns"></tr>
|
<tr mat-header-row *matHeaderRowDef="columns"></tr>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {CommonModule} from '@angular/common'
|
||||||
import {CreInteractiveCell, CrePositionButtons, CreTable} from './tables'
|
import {CreInteractiveCell, CrePositionButtons, CreTable} from './tables'
|
||||||
import {MatButtonModule} from "@angular/material/button";
|
import {MatButtonModule} from "@angular/material/button";
|
||||||
import {MatIconModule} from "@angular/material/icon";
|
import {MatIconModule} from "@angular/material/icon";
|
||||||
|
import {MatSortModule} from '@angular/material/sort'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -11,12 +12,13 @@ import {MatIconModule} from "@angular/material/icon";
|
||||||
CreInteractiveCell,
|
CreInteractiveCell,
|
||||||
CrePositionButtons
|
CrePositionButtons
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
CommonModule,
|
CommonModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
MatIconModule
|
MatIconModule,
|
||||||
],
|
MatSortModule
|
||||||
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CreTable,
|
CreTable,
|
||||||
CreInteractiveCell,
|
CreInteractiveCell,
|
||||||
|
|
|
@ -2,14 +2,16 @@ import {
|
||||||
AfterContentInit,
|
AfterContentInit,
|
||||||
Component,
|
Component,
|
||||||
ContentChildren,
|
ContentChildren,
|
||||||
Directive, EventEmitter,
|
Directive,
|
||||||
|
EventEmitter,
|
||||||
HostBinding,
|
HostBinding,
|
||||||
Input, Output,
|
Input,
|
||||||
|
Output,
|
||||||
QueryList,
|
QueryList,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
ViewEncapsulation
|
ViewEncapsulation
|
||||||
} from '@angular/core'
|
} from '@angular/core'
|
||||||
import {MatColumnDef, MatHeaderRowDef, MatRowDef, MatTable} from '@angular/material/table'
|
import {MatColumnDef, MatHeaderRowDef, MatRowDef, MatTable, MatTableDataSource} from '@angular/material/table'
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[creInteractiveCell]'
|
selector: '[creInteractiveCell]'
|
||||||
|
@ -57,17 +59,32 @@ export class CreTable<T> implements AfterContentInit {
|
||||||
@ViewChild(MatTable, {static: true}) table: MatTable<T>
|
@ViewChild(MatTable, {static: true}) table: MatTable<T>
|
||||||
|
|
||||||
@Input() columns: string[]
|
@Input() columns: string[]
|
||||||
@Input() dataSource: T[]
|
|
||||||
@Input() interactive = true
|
@Input() interactive = true
|
||||||
|
@Input() filterFn: (t: T, string: string) => boolean = () => true
|
||||||
|
|
||||||
|
@Input() set filter(filter: string) {
|
||||||
|
this.dataSource.filter = filter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input() set data(data: T[]) {
|
||||||
|
this.setupDataSource(data)
|
||||||
|
}
|
||||||
|
|
||||||
selectedIndex = 0
|
selectedIndex = 0
|
||||||
|
|
||||||
|
dataSource: MatTableDataSource<T>
|
||||||
|
|
||||||
ngAfterContentInit(): void {
|
ngAfterContentInit(): void {
|
||||||
this.columnDefs.forEach(columnDef => this.table.addColumnDef(columnDef))
|
this.columnDefs.forEach(columnDef => this.table.addColumnDef(columnDef))
|
||||||
this.rowDefs.forEach(rowDef => this.table.addRowDef(rowDef))
|
this.rowDefs.forEach(rowDef => this.table.addRowDef(rowDef))
|
||||||
this.headerRowDefs.forEach(headerRowDef => this.table.addHeaderRowDef(headerRowDef))
|
this.headerRowDefs.forEach(headerRowDef => this.table.addHeaderRowDef(headerRowDef))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setupDataSource(data: T[]) {
|
||||||
|
this.dataSource = new MatTableDataSource<T>(data)
|
||||||
|
this.dataSource.filterPredicate = (t, filter) => this.filterFn(t, filter)
|
||||||
|
}
|
||||||
|
|
||||||
onRowHover(index: number) {
|
onRowHover(index: number) {
|
||||||
if (this.interactive) {
|
if (this.interactive) {
|
||||||
this.interactiveCells.forEach(cell => cell.hoverIndex = index)
|
this.interactiveCells.forEach(cell => cell.hoverIndex = index)
|
||||||
|
@ -98,15 +115,15 @@ export class CrePositionButtons {
|
||||||
@Input() disableDecreaseButton = false
|
@Input() disableDecreaseButton = false
|
||||||
@Input() disableIncreaseButton = false
|
@Input() disableIncreaseButton = false
|
||||||
|
|
||||||
@Output() positionChange = new EventEmitter<number>();
|
@Output() positionChange = new EventEmitter<number>()
|
||||||
|
|
||||||
increasePosition() {
|
increasePosition() {
|
||||||
this.position += 1;
|
this.position += 1
|
||||||
this.positionChange.emit(this.position)
|
this.positionChange.emit(this.position)
|
||||||
}
|
}
|
||||||
|
|
||||||
decreasePosition() {
|
decreasePosition() {
|
||||||
this.position -= 1;
|
this.position -= 1
|
||||||
this.positionChange.emit(this.position)
|
this.positionChange.emit(this.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,3 +124,8 @@ export function getRecipeLuma(recipe: Recipe): number {
|
||||||
|
|
||||||
return 0.2126 * r + 0.7152 * g + 0.0722 * b // per ITU-R BT.709
|
return 0.2126 * r + 0.7152 * g + 0.0722 * b // per ITU-R BT.709
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function recipeMatchesFilter(recipe: Recipe, filter: string): boolean {
|
||||||
|
const recipeStr = recipe.company.name + recipe.name + recipe.description + recipe.sample
|
||||||
|
return recipeStr.toLowerCase().indexOf(filter.toLowerCase()) >= 0
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
</cre-action-group>
|
</cre-action-group>
|
||||||
</cre-action-bar>
|
</cre-action-bar>
|
||||||
|
|
||||||
<cre-table class="mx-auto" [dataSource]="touchUpKit.content" [columns]="contentTableCols" [interactive]="false">
|
<cre-table class="mx-auto" [data]="touchUpKit.content" [columns]="contentTableCols" [interactive]="false">
|
||||||
<ng-container matColumnDef="name">
|
<ng-container matColumnDef="name">
|
||||||
<th mat-header-cell *matHeaderCellDef>Nom</th>
|
<th mat-header-cell *matHeaderCellDef>Nom</th>
|
||||||
<td mat-cell *matCellDef="let product">{{product.name}}</td>
|
<td mat-cell *matCellDef="let product">{{product.name}}</td>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</cre-action-group>
|
</cre-action-group>
|
||||||
</cre-action-bar>
|
</cre-action-bar>
|
||||||
|
|
||||||
<cre-table class="mx-auto" [dataSource]="uncompletedTouchUpKits$ | async" [columns]="columns">
|
<cre-table class="mx-auto" [data]="uncompletedTouchUpKits$ | async" [columns]="columns">
|
||||||
<ng-container matColumnDef="project">
|
<ng-container matColumnDef="project">
|
||||||
<th mat-header-cell *matHeaderCellDef>Project</th>
|
<th mat-header-cell *matHeaderCellDef>Project</th>
|
||||||
<td mat-cell *matCellDef="let touchUpKit">{{touchUpKit.project}}</td>
|
<td mat-cell *matCellDef="let touchUpKit">{{touchUpKit.project}}</td>
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
<mat-card-title>Kits de retouche complétés</mat-card-title>
|
<mat-card-title>Kits de retouche complétés</mat-card-title>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<cre-table [dataSource]="completedTouchUpKits$ | async" [columns]="completedColumns">
|
<cre-table [data]="completedTouchUpKits$ | async" [columns]="completedColumns">
|
||||||
<ng-container matColumnDef="project">
|
<ng-container matColumnDef="project">
|
||||||
<th mat-header-cell *matHeaderCellDef>Project</th>
|
<th mat-header-cell *matHeaderCellDef>Project</th>
|
||||||
<td mat-cell *matCellDef="let touchUpKit">{{touchUpKit.project}}</td>
|
<td mat-cell *matCellDef="let touchUpKit">{{touchUpKit.project}}</td>
|
||||||
|
|
Loading…
Reference in New Issue