Ajout du support pour le nouvel API de fichiers
This commit is contained in:
parent
753afcf07f
commit
b7f50fca38
|
@ -1,15 +1,15 @@
|
|||
<mat-card *ngIf="editionMode || hasImages">
|
||||
<mat-card *ngIf="editionMode || imagesUrls">
|
||||
<mat-card-header>
|
||||
<mat-card-title>Images</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content [class.no-action]="!editionMode">
|
||||
<div class="d-flex flex-row justify-content-around flex-wrap">
|
||||
<div *ngFor="let imageId of (imageIds$ | async)" class="d-flex flex-column align-self-center m-3">
|
||||
<div *ngFor="let imageUrl of imagesUrls" class="d-flex flex-column align-self-center m-3">
|
||||
<div class="image-wrapper">
|
||||
<img src="{{backendUrl}}/recipe/{{recipe.id}}/image/{{imageId}}" width="300px"/>
|
||||
<img [src]="imageUrl" width="300px"/>
|
||||
<div class="d-flex flex-row justify-content-end mt-2" [class.justify-content-between]="editionMode">
|
||||
<button mat-raised-button color="primary" (click)="openImage(imageId)">Afficher</button>
|
||||
<button *ngIf="editionMode" mat-raised-button color="warn" (click)="delete(imageId)">Retirer</button>
|
||||
<button mat-raised-button color="primary" (click)="openImage(imageUrl)">Afficher</button>
|
||||
<button *ngIf="editionMode" mat-raised-button color="warn" (click)="delete(imageUrl)">Retirer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,11 +2,9 @@ import {Component, Input} from '@angular/core'
|
|||
import {Recipe} from '../../../shared/model/recipe.model'
|
||||
import {SubscribingComponent} from '../../../shared/components/subscribing.component'
|
||||
import {ActivatedRoute, Router} from '@angular/router'
|
||||
import {Observable} from 'rxjs'
|
||||
import {RecipeImageService} from '../../services/recipe-image.service'
|
||||
import {environment} from '../../../../../environments/environment'
|
||||
import {ErrorService} from '../../../shared/service/error.service'
|
||||
import {globalLoadingWheel} from '../../../shared/components/loading-wheel/loading-wheel.component'
|
||||
import {openJpg} from '../../../shared/utils/utils'
|
||||
|
||||
@Component({
|
||||
selector: 'cre-images-editor',
|
||||
|
@ -17,9 +15,7 @@ export class ImagesEditorComponent extends SubscribingComponent {
|
|||
@Input() recipe: Recipe
|
||||
@Input() editionMode = false
|
||||
|
||||
imageIds$: Observable<number[]>
|
||||
backendUrl = environment.apiUrl
|
||||
hasImages = false
|
||||
imagesUrls: string[]
|
||||
|
||||
constructor(
|
||||
private recipeImageService: RecipeImageService,
|
||||
|
@ -33,35 +29,29 @@ export class ImagesEditorComponent extends SubscribingComponent {
|
|||
ngOnInit() {
|
||||
super.ngOnInit()
|
||||
|
||||
this.loadImagesIds()
|
||||
this.subscribe(
|
||||
this.imageIds$,
|
||||
ids => this.hasImages = ids.length > 0,
|
||||
false,
|
||||
1
|
||||
)
|
||||
this.imagesUrls = this.recipe.imagesUrls
|
||||
}
|
||||
|
||||
submit(event) {
|
||||
const image = event.target.files[0]
|
||||
this.subscribe(
|
||||
this.recipeImageService.save(image, this.recipe.id),
|
||||
() => this.loadImagesIds()
|
||||
r => this.imagesUrls = r.imagesUrls
|
||||
)
|
||||
}
|
||||
|
||||
openImage(imageId: number) {
|
||||
window.open(`${environment.apiUrl}/recipe/${this.recipe.id}/image/${imageId}`, '_blank')
|
||||
openImage(url: string) {
|
||||
openJpg(url)
|
||||
}
|
||||
|
||||
delete(imageId: number) {
|
||||
delete(url: string) {
|
||||
this.subscribe(
|
||||
this.recipeImageService.delete(imageId, this.recipe.id),
|
||||
() => this.loadImagesIds()
|
||||
this.recipeImageService.delete(url, this.recipe.id),
|
||||
() => this.removeUrl(url)
|
||||
)
|
||||
}
|
||||
|
||||
private loadImagesIds() {
|
||||
this.imageIds$ = this.recipeImageService.getAllIdsForRecipe(this.recipe.id)
|
||||
private removeUrl(url: string) {
|
||||
this.imagesUrls = this.imagesUrls.filter(u => u !== url)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,8 +126,8 @@
|
|||
<button
|
||||
mat-raised-button
|
||||
color="accent"
|
||||
[disabled]="!hasSimdutMap[getMixMaterialFromDto(mixMaterial).material.id]"
|
||||
(click)="openSimdutFile(mixMaterial)">
|
||||
[disabled]="!hasSimdut(getMixMaterialFromDto(mixMaterial).material)"
|
||||
(click)="openSimdut(mixMaterial)">
|
||||
Fiche signalitique
|
||||
</button>
|
||||
</ng-container>
|
||||
|
|
|
@ -12,6 +12,7 @@ import {environment} from '../../../../../environments/environment'
|
|||
import {MaterialService} from '../../../material/service/material.service'
|
||||
import {EmployeePermission} from '../../../shared/model/employee'
|
||||
import {AccountService} from '../../../accounts/services/account.service'
|
||||
import {Material, openSimdut} from '../../../shared/model/material.model'
|
||||
|
||||
@Component({
|
||||
selector: 'cre-mix-table',
|
||||
|
@ -38,7 +39,6 @@ export class MixTableComponent extends SubscribingComponent {
|
|||
units = UNIT_MILLILITER
|
||||
mixMaterials: MixMaterialDto[] = []
|
||||
hoveredMixMaterial: MixMaterial | null
|
||||
hasSimdutMap: any = {}
|
||||
|
||||
// BPac printer
|
||||
printer: PtouchPrinter | null
|
||||
|
@ -67,12 +67,14 @@ export class MixTableComponent extends SubscribingComponent {
|
|||
this.units$,
|
||||
u => this.convertQuantities(u)
|
||||
)
|
||||
}
|
||||
|
||||
this.mixMaterials.forEach(mixMaterial => this.subscribe(
|
||||
this.materialService.hasSimdut(mixMaterial.materialId),
|
||||
b => this.hasSimdutMap[mixMaterial.materialId] = b
|
||||
)
|
||||
)
|
||||
hasSimdut(material: Material): boolean {
|
||||
return material.simdutUrl != null
|
||||
}
|
||||
|
||||
openSimdut(mixMaterial: MixMaterial) {
|
||||
openSimdut(mixMaterial.material)
|
||||
}
|
||||
|
||||
changeLocation(event: any) {
|
||||
|
@ -135,10 +137,6 @@ export class MixTableComponent extends SubscribingComponent {
|
|||
return Math.round(quantity * 1000) / 1000
|
||||
}
|
||||
|
||||
openSimdutFile(mixMaterial: MixMaterialDto) {
|
||||
window.open(`${environment.apiUrl}/material/${mixMaterial.materialId}/simdut`, '_blank')
|
||||
}
|
||||
|
||||
async print() {
|
||||
const base = this.mix.mixMaterials
|
||||
.map(ma => ma.material)
|
||||
|
|
|
@ -73,8 +73,8 @@
|
|||
</div>
|
||||
|
||||
<!-- Images -->
|
||||
<div [hidden]="!images.hasImages">
|
||||
<cre-images-editor #images [recipe]="recipe" [editionMode]="false"></cre-images-editor>
|
||||
<div *ngIf="recipe.imagesUrls">
|
||||
<cre-images-editor [recipe]="recipe" [editionMode]="false"></cre-images-editor>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {ApiService} from "../../shared/service/api.service";
|
||||
import {Observable} from "rxjs";
|
||||
import {Injectable} from '@angular/core'
|
||||
import {ApiService} from '../../shared/service/api.service'
|
||||
import {Observable} from 'rxjs'
|
||||
import {Recipe} from '../../shared/model/recipe.model'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
@ -11,22 +12,17 @@ export class RecipeImageService {
|
|||
) {
|
||||
}
|
||||
|
||||
getAllIdsForRecipe(recipeId: number): Observable<number[]> {
|
||||
return this.api.get(`/recipe/${recipeId}/image`)
|
||||
}
|
||||
|
||||
save(image: File, recipeId: number): Observable<void> {
|
||||
save(image: File, recipeId: number): Observable<Recipe> {
|
||||
const body = new FormData()
|
||||
body.append('image', image)
|
||||
return this.api.post<void>(`/recipe/${recipeId}/image`, body, true)
|
||||
return this.api.put<Recipe>(`/recipe/${recipeId}/image`, body)
|
||||
}
|
||||
|
||||
deleteAll(imageIds: number[], recipeId: number) {
|
||||
imageIds.forEach(id => this.delete(id, recipeId))
|
||||
}
|
||||
delete(url: string, recipeId: number): Observable<void> {
|
||||
const urlFragments = url.split('%2F')
|
||||
const imageName = urlFragments[urlFragments.length - 1].replace('.jpg', '')
|
||||
|
||||
delete(imageId: number, recipeId: number): Observable<void> {
|
||||
return this.api.delete<void>(`/recipe/${recipeId}/image/${imageId}`)
|
||||
return this.api.delete<void>(`/recipe/${recipeId}/image/${imageName}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
color="primary"
|
||||
[disabled]="!hasSimdut"
|
||||
[attr.title]="!hasSimdut ? 'Ce produit n\'a pas de fiche signalitique' : null"
|
||||
(click)="openSimdutUrl()">
|
||||
(click)="openSimdut()">
|
||||
Voir la fiche signalitique
|
||||
</button>
|
||||
<cre-file-button
|
||||
|
|
|
@ -6,8 +6,7 @@ import {MaterialTypeService} from '../../../material-type/service/material-type.
|
|||
import {MaterialService} from '../../service/material.service'
|
||||
import {ActivatedRoute, Router} from '@angular/router'
|
||||
import {ErrorHandlingComponent} from '../../../shared/components/subscribing.component'
|
||||
import {Material} from '../../../shared/model/material.model'
|
||||
import {environment} from '../../../../../environments/environment'
|
||||
import {Material, openSimdut} from '../../../shared/model/material.model'
|
||||
import {ErrorHandler, ErrorService} from '../../../shared/service/error.service'
|
||||
|
||||
@Component({
|
||||
|
@ -65,7 +64,6 @@ export class EditComponent extends ErrorHandlingComponent {
|
|||
fileType: 'application/pdf'
|
||||
}
|
||||
]
|
||||
hasSimdut = false
|
||||
selectedSimdutFile: File | null
|
||||
|
||||
errorHandlers: ErrorHandler[] = [{
|
||||
|
@ -100,11 +98,6 @@ export class EditComponent extends ErrorHandlingComponent {
|
|||
id,
|
||||
material => this.material = material
|
||||
)
|
||||
|
||||
this.subscribe(
|
||||
this.materialService.hasSimdut(id),
|
||||
b => this.hasSimdut = b
|
||||
)
|
||||
}
|
||||
|
||||
submit(values) {
|
||||
|
@ -121,8 +114,11 @@ export class EditComponent extends ErrorHandlingComponent {
|
|||
)
|
||||
}
|
||||
|
||||
openSimdutUrl() {
|
||||
const simdutUrl = environment.apiUrl + `/material/${this.material.id}/simdut`
|
||||
window.open(simdutUrl, '_blank')
|
||||
get hasSimdut(): boolean {
|
||||
return this.material.simdutUrl != null
|
||||
}
|
||||
|
||||
openSimdut() {
|
||||
openSimdut(this.material)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,13 @@ import {MaterialService} from '../../service/material.service'
|
|||
import {EmployeePermission} from '../../../shared/model/employee'
|
||||
import {ActivatedRoute, Router} from '@angular/router'
|
||||
import {ErrorService} from '../../../shared/service/error.service'
|
||||
import {Material} from '../../../shared/model/material.model'
|
||||
import {Material, openSimdut} from '../../../shared/model/material.model'
|
||||
import {AccountService} from '../../../accounts/services/account.service'
|
||||
import {convertQuantity, UNIT_MILLILITER} from '../../../shared/units'
|
||||
import {MatSort} from '@angular/material/sort'
|
||||
import {MatTableDataSource} from '@angular/material/table'
|
||||
import {MaterialTypeService} from '../../../material-type/service/material-type.service'
|
||||
import {InventoryService} from '../../service/inventory.service'
|
||||
import {environment} from '../../../../../environments/environment'
|
||||
|
||||
@Component({
|
||||
selector: 'cre-list',
|
||||
|
@ -24,7 +23,6 @@ export class InventoryComponent extends ErrorHandlingComponent {
|
|||
materials: Material[] | null
|
||||
materialTypes$ = this.materialTypeService.all
|
||||
dataSource: MatTableDataSource<Material>
|
||||
hasSimdut: any
|
||||
|
||||
columns = ['name', 'materialType', 'quantity', 'addQuantity', 'lowQuantityIcon', 'simdutIcon', 'editButton', 'openSimdutButton']
|
||||
hoveredMaterial: Material | null
|
||||
|
@ -59,13 +57,6 @@ export class InventoryComponent extends ErrorHandlingComponent {
|
|||
true,
|
||||
1
|
||||
)
|
||||
|
||||
this.subscribe(
|
||||
this.materialService.getSimduts(),
|
||||
ids => this.hasSimdut = ids,
|
||||
false,
|
||||
1
|
||||
)
|
||||
}
|
||||
|
||||
setupDataSource(): MatTableDataSource<Material> {
|
||||
|
@ -102,11 +93,11 @@ export class InventoryComponent extends ErrorHandlingComponent {
|
|||
}
|
||||
|
||||
materialHasSimdut(material: Material): boolean {
|
||||
return this.hasSimdut && this.hasSimdut.filter(i => i === material.id).length > 0
|
||||
return material.simdutUrl != null
|
||||
}
|
||||
|
||||
openSimdut(material: Material) {
|
||||
window.open(`${environment.apiUrl}/material/${material.id}/simdut`, '_blank')
|
||||
openSimdut(material)
|
||||
}
|
||||
|
||||
addQuantity(material: Material, input: HTMLInputElement) {
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
import {MaterialType} from "./materialtype.model";
|
||||
import {openPdf} from '../utils/utils'
|
||||
|
||||
export class Material {
|
||||
constructor(
|
||||
public id: number,
|
||||
public name: string,
|
||||
public inventoryQuantity: number,
|
||||
public materialType: MaterialType
|
||||
public materialType: MaterialType,
|
||||
public simdutUrl: string
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
export function openSimdut(material: Material) {
|
||||
openPdf(material.simdutUrl)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ export class Recipe {
|
|||
public remark: string,
|
||||
public company: Company,
|
||||
public mixes: Mix[],
|
||||
public groupsInformation: RecipeGroupInformation[]
|
||||
public groupsInformation: RecipeGroupInformation[],
|
||||
public imagesUrls: string[]
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,9 @@ export class ErrorService {
|
|||
}
|
||||
|
||||
const error = response.error
|
||||
if (!error || !error.type) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.activeHandler) {
|
||||
matchingModels = this.activeHandler.errorHandlers.filter(m => m.filter(error)) // Find error models whose filter matches the current error
|
||||
|
|
|
@ -2,3 +2,19 @@
|
|||
export function valueOr<T>(value: T, or: T): T {
|
||||
return value ? value : or
|
||||
}
|
||||
|
||||
const MEDIA_TYPE_PDF = 'application/pdf'
|
||||
const MEDIA_TYPE_JPG = 'image/jpeg'
|
||||
|
||||
export function openPdf(url: string) {
|
||||
openUrl(url, MEDIA_TYPE_PDF)
|
||||
}
|
||||
|
||||
export function openJpg(url: string) {
|
||||
openUrl(url, MEDIA_TYPE_JPG)
|
||||
}
|
||||
|
||||
function openUrl(url: string, mediaType: string) {
|
||||
const encodedUrl = `${url}&mediaType=${encodeURIComponent(mediaType)}`
|
||||
window.open(encodedUrl, '_blank')
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue