Ajout du support pour les images des recettes dans le frontend Angular
This commit is contained in:
parent
93bae1504b
commit
17e056544d
|
@ -1,5 +1,6 @@
|
|||
<cre-header></cre-header>
|
||||
<div>
|
||||
<div class="dark-background"></div>
|
||||
<router-outlet></router-outlet>
|
||||
|
||||
<div class="offline-server-card-wrapper" [hidden]="isServerOnline">
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
<div class="dark-background"></div>
|
||||
<form [formGroup]="form">
|
||||
<mat-card class="x-centered y-centered">
|
||||
<mat-card-header>
|
||||
|
|
|
@ -16,10 +16,12 @@ import {MixEditorComponent} from './components/mix-editor/mix-editor.component';
|
|||
import {UnitSelectorComponent} from './components/unit-selector/unit-selector.component';
|
||||
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';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [ListComponent, AddComponent, EditComponent, ExploreComponent, RecipeInfoComponent, MixTableComponent, StepListComponent, StepTableComponent, MixEditorComponent, UnitSelectorComponent, MixAddComponent, MixEditComponent],
|
||||
declarations: [ListComponent, AddComponent, EditComponent, ExploreComponent, RecipeInfoComponent, MixTableComponent, StepListComponent, StepTableComponent, MixEditorComponent, UnitSelectorComponent, MixAddComponent, MixEditComponent, ImagesEditorComponent, MixesCardComponent],
|
||||
imports: [
|
||||
ColorsRoutingModule,
|
||||
SharedModule,
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<mat-card>
|
||||
<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 class="image-wrapper">
|
||||
<img src="{{backendUrl}}/recipe/{{recipe.id}}/image/{{imageId}}" 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<mat-card-actions *ngIf="editionMode">
|
||||
<cre-file-button
|
||||
color="accent"
|
||||
label="Ajouter"
|
||||
accept="image/jpeg,image/png"
|
||||
(change)="submit($event)">
|
||||
</cre-file-button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
|
@ -0,0 +1,9 @@
|
|||
mat-card
|
||||
background-color: rgba(255, 255, 255, 0.5)
|
||||
max-width: 90vw !important
|
||||
|
||||
.image-wrapper
|
||||
padding: 16px
|
||||
border-radius: 4px
|
||||
box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12)
|
||||
background-color: white
|
|
@ -0,0 +1,57 @@
|
|||
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";
|
||||
|
||||
@Component({
|
||||
selector: 'cre-images-editor',
|
||||
templateUrl: './images-editor.component.html',
|
||||
styleUrls: ['./images-editor.component.sass']
|
||||
})
|
||||
export class ImagesEditorComponent extends SubscribingComponent {
|
||||
@Input() recipe: Recipe
|
||||
@Input() editionMode = false
|
||||
|
||||
imageIds$: Observable<number[]>
|
||||
backendUrl = environment.apiUrl
|
||||
|
||||
constructor(
|
||||
private recipeImageService: RecipeImageService,
|
||||
router: Router,
|
||||
activatedRoute: ActivatedRoute
|
||||
) {
|
||||
super(activatedRoute, router)
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit()
|
||||
|
||||
this.loadImagesIds()
|
||||
}
|
||||
|
||||
submit(event) {
|
||||
const image = event.target.files[0]
|
||||
this.subscribe(
|
||||
this.recipeImageService.save(image, this.recipe.id),
|
||||
{next: () => this.loadImagesIds()}
|
||||
)
|
||||
}
|
||||
|
||||
openImage(imageId: number) {
|
||||
window.open(`${environment.apiUrl}/recipe/${this.recipe.id}/image/${imageId}`, '_blank')
|
||||
}
|
||||
|
||||
delete(imageId: number) {
|
||||
this.subscribe(
|
||||
this.recipeImageService.delete(imageId, this.recipe.id),
|
||||
{next: () => this.loadImagesIds()}
|
||||
)
|
||||
}
|
||||
|
||||
private loadImagesIds() {
|
||||
this.imageIds$ = this.recipeImageService.getAllIdsForRecipe(this.recipe.id)
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
</mat-expansion-panel-header>
|
||||
|
||||
<div class="mix-actions d-flex flex-row justify-content-between">
|
||||
<ng-container *ngIf="!editing">
|
||||
<ng-container *ngIf="!editionMode">
|
||||
<div class="flex-grow-1">
|
||||
<mat-form-field class="dark">
|
||||
<mat-label>Casier</mat-label>
|
||||
|
@ -18,7 +18,7 @@
|
|||
<button mat-raised-button color="accent" (click)="deduct.emit()">Déduire</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="editing">
|
||||
<ng-container *ngIf="editionMode">
|
||||
<div class="flex-grow-1"></div>
|
||||
<button mat-raised-button color="accent" routerLink="/color/edit/mix/{{recipe.id}}/{{mix.id}}">Modifier</button>
|
||||
</ng-container>
|
||||
|
@ -92,8 +92,8 @@
|
|||
|
||||
<tr mat-header-row *matHeaderRowDef="mixColumns"></tr>
|
||||
<tr mat-row *matRowDef="let mixMaterial; columns: mixColumns"
|
||||
[class.low-quantity]="!editing && isInLowQuantity(mixMaterial.id)"></tr>
|
||||
<ng-container *ngIf="!editing">
|
||||
[class.low-quantity]="!editionMode && isInLowQuantity(mixMaterial.id)"></tr>
|
||||
<ng-container *ngIf="!editionMode">
|
||||
<tr mat-footer-row *matFooterRowDef="mixColumns"></tr>
|
||||
</ng-container>
|
||||
</table>
|
||||
|
|
|
@ -22,7 +22,7 @@ export class MixTableComponent extends SubscribingComponent {
|
|||
@Input() recipe: Recipe
|
||||
@Input() units$: Subject<string>
|
||||
@Input() deductErrorBody
|
||||
@Input() editing: boolean
|
||||
@Input() editionMode: boolean
|
||||
@Input() printingError = 2
|
||||
@Output() locationChange = new EventEmitter<{ id: number, location: string }>()
|
||||
@Output() quantityChange = new EventEmitter<{ id: number, materialId: number, quantity: number }>()
|
||||
|
@ -46,7 +46,7 @@ export class MixTableComponent extends SubscribingComponent {
|
|||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
|
||||
if (this.editing) {
|
||||
if (this.editionMode) {
|
||||
this.mixColumns = this.COLUMNS_STATIC
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ export class MixTableComponent extends SubscribingComponent {
|
|||
}
|
||||
|
||||
private convertQuantities(newUnit: string) {
|
||||
this.computedQuantities.forEach(q => convertMixMaterialQuantity(q, this.units, newUnit))
|
||||
this.computedQuantities.forEach(q => q.quantity = convertMixMaterialQuantity(q, this.units, newUnit))
|
||||
this.units = newUnit
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<mat-card class="mt-5">
|
||||
<mat-card>
|
||||
<mat-card-header>
|
||||
<mat-card-title>Étapes</mat-card-title>
|
||||
</mat-card-header>
|
||||
|
|
|
@ -35,34 +35,21 @@
|
|||
[formFields]="formFields"
|
||||
[unknownError]="unknownError"
|
||||
[customError]="errorMessage"
|
||||
[disableButtons]="true">
|
||||
[disableButtons]="true"
|
||||
[noTopMargin]="true">
|
||||
</cre-entity-edit>
|
||||
</div>
|
||||
|
||||
<div class="recipe-mixes-wrapper">
|
||||
<mat-card>
|
||||
<mat-card-header>
|
||||
<mat-card-title>Mélanges</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content class="no-action pl-5">
|
||||
<ng-container *ngFor="let mix of recipe.mixes; let i = index">
|
||||
<cre-mix-table
|
||||
[class.no-top-margin]="i == 0"
|
||||
[recipe]="recipe"
|
||||
[mix]="mix"
|
||||
[units$]="units$"
|
||||
[editing]="true">
|
||||
</cre-mix-table>
|
||||
</ng-container>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-raised-button color="accent" routerLink="/color/add/mix/{{recipe.id}}">Ajouter</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
<cre-mixes-card [recipe]="recipe" [units$]="units$" [editionMode]="true"></cre-mixes-card>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<div>
|
||||
<cre-step-table [steps]="recipe.steps"></cre-step-table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<cre-images-editor #imagesEditor [recipe]="recipe" [editionMode]="true"></cre-images-editor>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,17 +1,2 @@
|
|||
.recipe-wrapper > div
|
||||
margin: 0 3rem 3rem
|
||||
|
||||
mat-card
|
||||
margin-top: 3rem
|
||||
|
||||
.recipe-mixes-wrapper mat-card
|
||||
min-width: 20rem
|
||||
|
||||
mat-card
|
||||
mat-card-content
|
||||
margin-bottom: 0
|
||||
padding-top: 16px !important
|
||||
padding-bottom: 0 !important
|
||||
|
||||
mat-card-actions
|
||||
margin-top: 0
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import {Component} from '@angular/core';
|
||||
import {Component, ViewChild} from '@angular/core';
|
||||
import {SubscribingComponent} from "../../../shared/components/subscribing.component";
|
||||
import {Recipe} from "../../../shared/model/recipe.model";
|
||||
import {RecipeService} from "../../services/recipe.service";
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {FormBuilder, Validators} from "@angular/forms";
|
||||
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 {EmployeePermission} from "../../../shared/model/employee";
|
||||
import {EntityEditComponent} from "../../../shared/components/entity-edit/entity-edit.component";
|
||||
import {ImagesEditorComponent} from "../../components/images-editor/images-editor.component";
|
||||
|
||||
@Component({
|
||||
selector: 'cre-edit',
|
||||
|
@ -18,6 +19,8 @@ import {EntityEditComponent} from "../../../shared/components/entity-edit/entity
|
|||
export class EditComponent extends SubscribingComponent {
|
||||
readonly unitConstants = {UNIT_MILLILITER, UNIT_LITER, UNIT_GALLON}
|
||||
|
||||
@ViewChild('imagesEditor') imagesEditor: ImagesEditorComponent
|
||||
|
||||
recipe: Recipe | null
|
||||
formFields = [
|
||||
{
|
||||
|
|
|
@ -42,31 +42,28 @@
|
|||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="recipe-content">
|
||||
<div class="recipe-content d-flex flex-row justify-content-around align-items-start flex-wrap mt-5">
|
||||
<!-- Mixes -->
|
||||
<div>
|
||||
<ng-container *ngFor="let mix of recipe.mixes">
|
||||
<cre-mix-table
|
||||
[mix]="mix"
|
||||
[recipe]="recipe"
|
||||
[deductErrorBody]="deductErrorBody"
|
||||
[units$]="units$"
|
||||
(quantityChange)="changeQuantity($event)"
|
||||
(locationChange)="changeMixLocation($event)"
|
||||
(deduct)="deductMixQuantities(mix.id)"
|
||||
[(printingError)]="printingError">
|
||||
</cre-mix-table>
|
||||
</ng-container>
|
||||
<cre-mixes-card
|
||||
[recipe]="recipe"
|
||||
[deductErrorBody]="deductErrorBody"
|
||||
[units$]="units$"
|
||||
(quantityChange)="changeQuantity($event)"
|
||||
(locationChange)="changeMixLocation($event)"
|
||||
(deduct)="deductMixQuantities($event)"
|
||||
[(printingError)]="printingError">
|
||||
</cre-mixes-card>
|
||||
</div>
|
||||
|
||||
<!-- Steps -->
|
||||
<div>
|
||||
<cre-step-list [steps]="recipe.steps"></cre-step-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Images -->
|
||||
<div class="recipe-images">
|
||||
Images
|
||||
<!-- Images -->
|
||||
<div>
|
||||
<cre-images-editor [recipe]="recipe" [editionMode]="false"></cre-images-editor>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,21 +1,2 @@
|
|||
.recipe-content
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: center
|
||||
|
||||
div
|
||||
margin-bottom: 1rem
|
||||
|
||||
.recipe-images
|
||||
margin-top: 5rem
|
||||
padding: 2rem
|
||||
background-color: grey
|
||||
|
||||
@media screen and (min-width: 1920px)
|
||||
.action-bar
|
||||
padding-bottom: 5rem
|
||||
|
||||
.recipe-content
|
||||
flex-direction: row
|
||||
justify-content: space-around
|
||||
align-items: start
|
||||
.recipe-content > div
|
||||
margin: 0 3rem 3rem
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {ApiService} from "../../shared/service/api.service";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class RecipeImageService {
|
||||
constructor(
|
||||
private api: ApiService
|
||||
) {
|
||||
}
|
||||
|
||||
getAllIdsForRecipe(recipeId: number): Observable<number[]> {
|
||||
return this.api.get(`/recipe/${recipeId}/image`)
|
||||
}
|
||||
|
||||
save(image: File, recipeId: number): Observable<void> {
|
||||
const body = new FormData()
|
||||
body.append('image', image)
|
||||
return this.api.post<void>(`/recipe/${recipeId}/image`, body, true)
|
||||
}
|
||||
|
||||
deleteAll(imageIds: number[], recipeId: number) {
|
||||
imageIds.forEach(id => this.delete(id, recipeId))
|
||||
}
|
||||
|
||||
delete(imageId: number, recipeId: number): Observable<void> {
|
||||
return this.api.delete<void>(`/recipe/${recipeId}/image/${imageId}`)
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ export class EmployeeService {
|
|||
}
|
||||
|
||||
updatePassword(id: number, password: string): Observable<void> {
|
||||
return this.api.put<void>(`/employee/${id}/password`, password, true, {headers: {contentType: 'text/plain'}})
|
||||
return this.api.put<void>(`/employee/${id}/password`, password, true, {contentType: 'text/plain'})
|
||||
}
|
||||
|
||||
delete(id: number): Observable<void> {
|
||||
|
|
|
@ -26,12 +26,11 @@
|
|||
(click)="openSimdutUrl()">
|
||||
Voir la fiche signalitique
|
||||
</button>
|
||||
<div class="edit-simdut-file-input">
|
||||
<button mat-raised-button color="accent" type="button">Modifier la fiche signalitique</button>
|
||||
<mat-form-field>
|
||||
<mat-label>{{field.label}}</mat-label>
|
||||
<ngx-mat-file-input #simdutFileInput [accept]="field.fileType" [formControl]="control"></ngx-mat-file-input>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<cre-file-button
|
||||
color="accent"
|
||||
label="Modifier la fiche signalitique"
|
||||
[accept]="field.accept"
|
||||
[control]="control">
|
||||
</cre-file-button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
.simdut-file
|
||||
button
|
||||
height: 43px
|
||||
|
||||
.edit-simdut-file-input
|
||||
width: 250px
|
||||
|
||||
mat-form-field
|
||||
z-index: 10
|
||||
margin-top: 10px
|
||||
opacity: 0
|
||||
|
||||
button
|
||||
position: absolute
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {Component, ViewChild} from '@angular/core';
|
||||
import {FormField} from "../../../shared/components/entity-add/entity-add.component";
|
||||
import {FormBuilder, Validators} from "@angular/forms";
|
||||
import {Validators} from "@angular/forms";
|
||||
import {map} from "rxjs/operators";
|
||||
import {MaterialTypeService} from "../../../material-type/service/material-type.service";
|
||||
import {MaterialService} from "../../service/material.service";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<mat-card *ngIf="entity" class="mt-5 x-centered">
|
||||
<mat-card *ngIf="entity" class="x-centered" [class.mt-5]="!noTopMargin">
|
||||
<mat-card-header>
|
||||
<mat-card-title>{{title}}</mat-card-title>
|
||||
</mat-card-header>
|
||||
|
|
|
@ -21,6 +21,7 @@ export class EntityEditComponent extends SubscribingComponent {
|
|||
@Input() unknownError = false
|
||||
@Input() customError: string | null
|
||||
@Input() disableButtons: boolean
|
||||
@Input() noTopMargin = false
|
||||
@Output() submit = new EventEmitter<any>()
|
||||
@Output() delete = new EventEmitter<void>()
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<div class="file-button-wrapper">
|
||||
<button mat-raised-button [color]="color" type="button">{{label}}</button>
|
||||
<mat-form-field>
|
||||
<mat-label>{{label}}</mat-label>
|
||||
<ngx-mat-file-input
|
||||
#fileInput
|
||||
[accept]="accept"
|
||||
[attr.formControl]="control">
|
||||
</ngx-mat-file-input>
|
||||
</mat-form-field>
|
||||
</div>
|
|
@ -0,0 +1,13 @@
|
|||
.file-button-wrapper
|
||||
width: 16rem
|
||||
|
||||
button
|
||||
width: 16rem
|
||||
|
||||
mat-form-field
|
||||
width: 16rem
|
||||
z-index: 10
|
||||
opacity: 0
|
||||
|
||||
button
|
||||
position: absolute
|
|
@ -0,0 +1,18 @@
|
|||
import {Component, Input, ViewChild} from '@angular/core';
|
||||
import {FormControl} from "@angular/forms";
|
||||
import {ThemePalette} from "@angular/material/core";
|
||||
import {MaterialFileInputModule} from "ngx-material-file-input";
|
||||
|
||||
@Component({
|
||||
selector: 'cre-file-button',
|
||||
templateUrl: './file-button.component.html',
|
||||
styleUrls: ['./file-button.component.sass']
|
||||
})
|
||||
export class FileButtonComponent {
|
||||
@ViewChild('fileInput') fileInput: MaterialFileInputModule
|
||||
|
||||
@Input() label: string
|
||||
@Input() color: ThemePalette
|
||||
@Input() accept: string
|
||||
@Input() control: FormControl | null
|
||||
}
|
|
@ -5,6 +5,7 @@ import {environment} from "../../../../environments/environment";
|
|||
import {AppState} from "../app-state";
|
||||
import {Router} from "@angular/router";
|
||||
import {map, share, takeUntil} from "rxjs/operators";
|
||||
import {valueOr} from "../utils/optional.utils";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
@ -61,7 +62,11 @@ export class ApiService implements OnDestroy {
|
|||
}
|
||||
|
||||
private executeHttpRequest<T>(requestFn: (httpOptions) => Observable<any>, needAuthentication = true, requestOptions: ApiRequestOptions = new ApiRequestOptions()): Observable<T> {
|
||||
const httpOptions = {withCredentials: false, observe: 'response'}
|
||||
const httpOptions = {
|
||||
withCredentials: false,
|
||||
headers: {contentType: valueOr(requestOptions.contentType, 'application/json')},
|
||||
observe: 'response'
|
||||
}
|
||||
if (needAuthentication) {
|
||||
if (this.checkAuthenticated()) {
|
||||
if (httpOptions) {
|
||||
|
@ -83,6 +88,7 @@ export class ApiService implements OnDestroy {
|
|||
const errorCheckSubscription = result$.subscribe({
|
||||
next: () => this.appState.isServerOnline = true,
|
||||
error: err => {
|
||||
console.error(err)
|
||||
errorCheckSubscription.unsubscribe()
|
||||
this.appState.isServerOnline = !(err.status === 0 && err.statusText === "Unknown Error");
|
||||
}
|
||||
|
@ -102,7 +108,8 @@ export class ApiService implements OnDestroy {
|
|||
|
||||
export class ApiRequestOptions {
|
||||
constructor(
|
||||
public takeFullResponse = false
|
||||
public takeFullResponse?,
|
||||
public contentType?
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,35 +26,37 @@ import {EntityEditComponent} from './components/entity-edit/entity-edit.componen
|
|||
import {MatSelectModule} from "@angular/material/select";
|
||||
import {MatOptionModule} from "@angular/material/core";
|
||||
import {MaterialFileInputModule} from "ngx-material-file-input";
|
||||
import { FileButtonComponent } from './file-button/file-button.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [HeaderComponent, EmployeeInfoComponent, LabeledIconComponent, ConfirmBoxComponent, PermissionsListComponent, PermissionsFieldComponent, NavComponent, EntityListComponent, EntityAddComponent, EntityEditComponent],
|
||||
exports: [
|
||||
CommonModule,
|
||||
HttpClientModule,
|
||||
HeaderComponent,
|
||||
MatCardModule,
|
||||
MatButtonModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatIconModule,
|
||||
MatTableModule,
|
||||
MatCheckboxModule,
|
||||
MatListModule,
|
||||
MatSelectModule,
|
||||
MatOptionModule,
|
||||
MaterialFileInputModule,
|
||||
ReactiveFormsModule,
|
||||
LabeledIconComponent,
|
||||
ConfirmBoxComponent,
|
||||
PermissionsListComponent,
|
||||
PermissionsFieldComponent,
|
||||
NavComponent,
|
||||
EntityListComponent,
|
||||
EntityAddComponent,
|
||||
EntityEditComponent
|
||||
],
|
||||
declarations: [HeaderComponent, EmployeeInfoComponent, LabeledIconComponent, ConfirmBoxComponent, PermissionsListComponent, PermissionsFieldComponent, NavComponent, EntityListComponent, EntityAddComponent, EntityEditComponent, FileButtonComponent],
|
||||
exports: [
|
||||
CommonModule,
|
||||
HttpClientModule,
|
||||
HeaderComponent,
|
||||
MatCardModule,
|
||||
MatButtonModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatIconModule,
|
||||
MatTableModule,
|
||||
MatCheckboxModule,
|
||||
MatListModule,
|
||||
MatSelectModule,
|
||||
MatOptionModule,
|
||||
MaterialFileInputModule,
|
||||
ReactiveFormsModule,
|
||||
LabeledIconComponent,
|
||||
ConfirmBoxComponent,
|
||||
PermissionsListComponent,
|
||||
PermissionsFieldComponent,
|
||||
NavComponent,
|
||||
EntityListComponent,
|
||||
EntityAddComponent,
|
||||
EntityEditComponent,
|
||||
FileButtonComponent
|
||||
],
|
||||
imports: [
|
||||
MatTabsModule,
|
||||
MatIconModule,
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
/** Returns [value] if it is not null or [or]. */
|
||||
export function valueOr<T>(value: T, or: T): T {
|
||||
return value ? value : or
|
||||
}
|
Loading…
Reference in New Issue