update recipe list and disable git pulling

This commit is contained in:
Kenta420 2023-10-31 10:30:06 +07:00
parent 15e74d47e3
commit fea5f8452a
7 changed files with 171 additions and 133 deletions

View file

@ -6,18 +6,20 @@
<div *ngIf="isLoaded; else indicator" [@inOutAnimation]> <div *ngIf="isLoaded; else indicator" [@inOutAnimation]>
<div class="flex flex-wrap"> <div class="flex flex-wrap">
<h5 class="mb-2 text-xl font-bold text-gray-900"> <h5 class="mb-2 text-xl font-bold text-gray-900">
{{ recipeMetaData!.name }} {{ recipeDetail.value.name }}
</h5> </h5>
<h5 class="mb-2 px-3 text-xl font-bold text-gray-900">|</h5> <h5 class="mb-2 px-3 text-xl font-bold text-gray-900">|</h5>
<h5 class="mb-2 text-xl font-bold text-gray-900"> <h5 class="mb-2 text-xl font-bold text-gray-900">
{{ recipeMetaData!.productCode }} {{ recipeDetail.value.otherName }}
</h5> </h5>
</div> </div>
<div class="flex items-center mb-2"> <div class="flex items-center mb-2">
<div class="flex items-center"> <div class="flex items-center">
<p class="text-sm text-gray-500">Last Modify</p> <p class="text-sm text-gray-500">Last Modify</p>
<p class="ml-2 text-sm text-gray-900"> <p class="ml-2 text-sm text-gray-900">
{{ recipeMetaData!.lastModified | date : "dd/MM/yyyy HH:mm:ss" }} {{
recipeDetail.value.lastModified | date : "dd/MM/yyyy HH:mm:ss"
}}
</p> </p>
</div> </div>
</div> </div>
@ -109,7 +111,10 @@
<div <div
class="col-span-3 min-h-[500px] max-h-[500px] overflow-auto mb-4 rounded bg-white border border-gray-200 shadow" class="col-span-3 min-h-[500px] max-h-[500px] overflow-auto mb-4 rounded bg-white border border-gray-200 shadow"
> >
<app-recipe-list [recipeListData]="matForRecipeList"></app-recipe-list> <app-recipe-list
[matRecipeList]="materialListIds$"
[parentForm]="recipeDetail"
></app-recipe-list>
</div> </div>
<div class="grid grid-cols-2 gap-4 mb-4"> <div class="grid grid-cols-2 gap-4 mb-4">
<div <div

View file

@ -1,15 +1,24 @@
import { DatePipe, NgFor, NgIf } from '@angular/common'; import { DatePipe, NgFor, NgIf } from '@angular/common';
import { Component, EventEmitter, OnInit } from '@angular/core'; import { Component, EventEmitter, OnInit } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; import {
FormArray,
FormControl,
FormGroup,
ReactiveFormsModule,
} from '@angular/forms';
import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { BehaviorSubject, finalize, map } from 'rxjs'; import { BehaviorSubject, Subject, finalize, map } from 'rxjs';
import { RecipeService } from 'src/app/core/services/recipe.service'; import { RecipeService } from 'src/app/core/services/recipe.service';
import { ConfirmModal } from 'src/app/shared/modal/confirm/confirm-modal.component'; import { ConfirmModal } from 'src/app/shared/modal/confirm/confirm-modal.component';
import { animate, style, transition, trigger } from '@angular/animations'; import { animate, style, transition, trigger } from '@angular/animations';
import { MaterialService } from 'src/app/core/services/material.service'; import { MaterialService } from 'src/app/core/services/material.service';
import { RecipeMetaData, RecipeDetail } from 'src/app/shared/types/recipe'; import { RecipeMetaData, RecipeDetail } from 'src/app/shared/types/recipe';
import { RecipeListComponent } from './recipe-list/recipe-list.component'; import {
RecipeListComponent,
RecipeListDataFormGroup,
} from './recipe-list/recipe-list.component';
import { MatRecipe } from 'src/app/core/models/recipe.model';
@Component({ @Component({
selector: 'app-recipe-details', selector: 'app-recipe-details',
@ -50,8 +59,7 @@ export class RecipeDetailsComponent implements OnInit {
constructor( constructor(
private _route: ActivatedRoute, private _route: ActivatedRoute,
private _router: Router, private _router: Router,
private _recipeService: RecipeService, private _recipeService: RecipeService
private _materialService: MaterialService
) {} ) {}
recipeDetail = new FormGroup({ recipeDetail = new FormGroup({
@ -60,12 +68,21 @@ export class RecipeDetailsComponent implements OnInit {
otherName: new FormControl<string>(''), otherName: new FormControl<string>(''),
description: new FormControl<string>(''), description: new FormControl<string>(''),
otherDescription: new FormControl<string>(''), otherDescription: new FormControl<string>(''),
lastModified: new FormControl<Date>(new Date()),
price: new FormControl<number>(0), price: new FormControl<number>(0),
isUse: new FormControl<boolean>(false), isUse: new FormControl<boolean>(false),
isShow: new FormControl<boolean>(false), isShow: new FormControl<boolean>(false),
disable: new FormControl<boolean>(false), disable: new FormControl<boolean>(false),
}); });
materialListIds$: Subject<{
ids: number[];
matRecipeList: MatRecipe[];
}> = new Subject<{
ids: number[];
matRecipeList: MatRecipe[];
}>();
ngOnInit() { ngOnInit() {
this._recipeService this._recipeService
.getRecipesById(this._route.snapshot.params['productCode']) .getRecipesById(this._route.snapshot.params['productCode'])
@ -78,6 +95,7 @@ export class RecipeDetailsComponent implements OnInit {
otherName: recipe.otherName, otherName: recipe.otherName,
description: recipe.Description, description: recipe.Description,
otherDescription: recipe.otherDescription, otherDescription: recipe.otherDescription,
lastModified: recipe.LastChange,
price: recipe.cashPrice, price: recipe.cashPrice,
isUse: recipe.isUse, isUse: recipe.isUse,
isShow: recipe.isShow, isShow: recipe.isShow,
@ -98,84 +116,16 @@ export class RecipeDetailsComponent implements OnInit {
}, },
recipes: recipe.recipes, recipes: recipe.recipes,
}); });
const ids = recipe.recipes?.map((recipe) => recipe.materialPathId);
this.materialListIds$.next({
ids: ids || [],
matRecipeList: recipe.recipes || [],
});
this.recipeMetaData = recipeMetaData; this.recipeMetaData = recipeMetaData;
this.isLoaded = true; this.isLoaded = true;
}); });
this.originalRecipeDetail.subscribe((originalRecipeDetail) => {
if (originalRecipeDetail == null) return;
const ids = originalRecipeDetail.recipes?.map(
(recipe) => recipe.materialPathId
);
if (originalRecipeDetail.recipe.recipes != null) {
return;
}
this._materialService.getMaterialCodes(ids).subscribe((data) => {
this.originalRecipeDetail.next({
...originalRecipeDetail,
recipe: {
...originalRecipeDetail.recipe,
recipes: originalRecipeDetail
.recipes!.map((item) => {
for (let i = 0; i < data.length; i++) {
if (item.materialPathId === 0) {
return {
id: 0,
name: '',
enable: item.isUse,
mixOrder: item.MixOrder,
stirTime: item.stirTime,
powderGram: item.powderGram,
powderTime: item.powderTime,
syrupGram: item.syrupGram,
syrupTime: item.syrupTime,
waterCold: item.waterCold,
waterHot: item.waterYield,
};
}
if (item.materialPathId === data[i].materialID) {
return {
id: data[i].materialID,
name: data[i].PackageDescription,
enable: item.isUse,
mixOrder: item.MixOrder,
stirTime: item.stirTime,
powderGram: item.powderGram,
powderTime: item.powderTime,
syrupGram: item.syrupGram,
syrupTime: item.syrupTime,
waterCold: item.waterCold,
waterHot: item.waterYield,
};
}
}
return {
id: item.materialPathId,
name: '',
enable: item.isUse,
mixOrder: item.MixOrder,
stirTime: item.stirTime,
powderGram: item.powderGram,
powderTime: item.powderTime,
syrupGram: item.syrupGram,
syrupTime: item.syrupTime,
waterCold: item.waterCold,
waterHot: item.waterYield,
};
})
.sort((a, b) => {
return a.id === 0 ? 1 : a.id > b.id ? 1 : -1;
}),
},
});
this.isMatLoaded = true;
});
});
} }
showConfirmSaveModal: EventEmitter<boolean> = new EventEmitter<boolean>(); showConfirmSaveModal: EventEmitter<boolean> = new EventEmitter<boolean>();

View file

@ -1,4 +1,4 @@
<table class="table" *ngIf="$isLoaded; else indicator"> <table class="table" [formGroup]="parentForm">
<thead> <thead>
<tr class="bg-gray-200"> <tr class="bg-gray-200">
<th class="px-6 py-3">Enable</th> <th class="px-6 py-3">Enable</th>
@ -14,12 +14,12 @@
<th class="px-6 py-3">Water Hot</th> <th class="px-6 py-3">Water Hot</th>
</tr> </tr>
</thead> </thead>
<tbody formArrayName="recipes"> <tbody formArrayName="recipes" *ngIf="isMatLoaded">
<tr <tr
*ngFor="let mat of recipeListDataForm.controls; let i = index" *ngFor="let mat of recipeListData.controls; let i = index"
class="bg-white la border-b hover:bg-secondary" class="bg-white la border-b hover:bg-secondary"
> >
<div formGroupName="i"> <div formGroupName="{{ i }}">
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap"> <td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
<label> <label>
<input <input
@ -63,8 +63,3 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<ng-template #indicator>
<div class="flex w-full h-full justify-center items-center">
<span class="loading loading-spinner w-20"></span>
</div>
</ng-template>

View file

@ -6,10 +6,11 @@ import {
FormGroup, FormGroup,
ReactiveFormsModule, ReactiveFormsModule,
} from '@angular/forms'; } from '@angular/forms';
import { BehaviorSubject, Observable, map } from 'rxjs'; import { Observable } from 'rxjs';
import { MaterialData } from 'src/app/shared/types/recipe'; import { MatRecipe } from 'src/app/core/models/recipe.model';
import { MaterialService } from 'src/app/core/services/material.service';
interface RecipeListDataFormGroup { export interface RecipeListDataFormGroup {
id: FormControl<number | null>; id: FormControl<number | null>;
name: FormControl<string | null>; name: FormControl<string | null>;
enable: FormControl<boolean | null>; enable: FormControl<boolean | null>;
@ -30,36 +31,97 @@ interface RecipeListDataFormGroup {
imports: [NgIf, NgFor, ReactiveFormsModule], imports: [NgIf, NgFor, ReactiveFormsModule],
}) })
export class RecipeListComponent implements OnInit { export class RecipeListComponent implements OnInit {
@Input({ required: true }) recipeListData: Observable< @Input({ required: true }) matRecipeList!: Observable<{
MaterialData[] | undefined ids: number[];
> = new Observable<MaterialData[] | undefined>(undefined); matRecipeList: MatRecipe[];
}>;
$isLoaded: Observable<boolean> = this.recipeListData.pipe(map((x) => !!x)); @Input({ required: true }) parentForm!: FormGroup;
recipeListDataForm = new FormArray<FormGroup<RecipeListDataFormGroup>>([]); recipeListData!: FormArray<FormGroup<RecipeListDataFormGroup>>;
isMatLoaded: boolean = false;
constructor(private _materialService: MaterialService) {}
ngOnInit(): void { ngOnInit(): void {
this.recipeListData.subscribe((x) => { this.matRecipeList.subscribe((x) => {
if (x) { this._materialService.getMaterialCodes(x.ids).subscribe((data) => {
for (let recipe of x) { const matList = x.matRecipeList
const x = new FormControl<number>(0); .map((item) => {
this.recipeListDataForm.push( for (let i = 0; i < data.length; i++) {
new FormGroup<RecipeListDataFormGroup>({ if (item.materialPathId === 0) {
id: new FormControl<number>(recipe.id), return {
name: new FormControl<string>(recipe.name), id: 0,
enable: new FormControl<boolean>(recipe.enable), name: '',
mixOrder: new FormControl<number>(recipe.mixOrder), enable: item.isUse,
stirTime: new FormControl<number>(recipe.stirTime), mixOrder: item.MixOrder,
powderGram: new FormControl<number>(recipe.powderGram), stirTime: item.stirTime,
powderTime: new FormControl<number>(recipe.powderTime), powderGram: item.powderGram,
syrupGram: new FormControl<number>(recipe.syrupGram), powderTime: item.powderTime,
syrupTime: new FormControl<number>(recipe.syrupTime), syrupGram: item.syrupGram,
waterCold: new FormControl<number>(recipe.waterCold), syrupTime: item.syrupTime,
waterHot: new FormControl<number>(recipe.waterHot), waterCold: item.waterCold,
waterHot: item.waterYield,
};
}
if (item.materialPathId === data[i].materialID) {
return {
id: data[i].materialID,
name: data[i].PackageDescription,
enable: item.isUse,
mixOrder: item.MixOrder,
stirTime: item.stirTime,
powderGram: item.powderGram,
powderTime: item.powderTime,
syrupGram: item.syrupGram,
syrupTime: item.syrupTime,
waterCold: item.waterCold,
waterHot: item.waterYield,
};
}
}
return {
id: item.materialPathId,
name: '',
enable: item.isUse,
mixOrder: item.MixOrder,
stirTime: item.stirTime,
powderGram: item.powderGram,
powderTime: item.powderTime,
syrupGram: item.syrupGram,
syrupTime: item.syrupTime,
waterCold: item.waterCold,
waterHot: item.waterYield,
};
})
.sort((a, b) => {
return a.id === 0 ? 1 : a.id > b.id ? 1 : -1;
});
this.recipeListData = new FormArray<FormGroup<RecipeListDataFormGroup>>(
matList.map((item) => {
return new FormGroup<RecipeListDataFormGroup>({
id: new FormControl<number>(item.id),
name: new FormControl<string>(item.name),
enable: new FormControl<boolean>(item.enable),
mixOrder: new FormControl<number>(item.mixOrder),
stirTime: new FormControl<number>(item.stirTime),
powderGram: new FormControl<number>(item.powderGram),
powderTime: new FormControl<number>(item.powderTime),
syrupGram: new FormControl<number>(item.syrupGram),
syrupTime: new FormControl<number>(item.syrupTime),
waterCold: new FormControl<number>(item.waterCold),
waterHot: new FormControl<number>(item.waterHot),
});
}) })
); );
} this.parentForm.addControl('recipes', this.recipeListData);
} console.log(this.parentForm);
this.isMatLoaded = true;
});
}); });
} }
} }

View file

@ -3,6 +3,7 @@ package data
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"log"
"recipe-manager/helpers" "recipe-manager/helpers"
"recipe-manager/models" "recipe-manager/models"
"recipe-manager/services/logger" "recipe-manager/services/logger"
@ -47,7 +48,11 @@ func NewData() *Data {
defaultFile := "coffeethai02_580.json" defaultFile := "coffeethai02_580.json"
defaultCountry := "thai" defaultCountry := "thai"
defaultRecipe := helpers.ReadRecipeFile(defaultCountry, defaultFile) defaultRecipe, err := helpers.ReadRecipeFile(defaultCountry, defaultFile)
if err != nil {
log.Panic("Error when read default recipe file:", err)
}
return &Data{ return &Data{
CurrentFile: defaultFile, CurrentFile: defaultFile,
@ -83,7 +88,14 @@ func (d *Data) GetRecipe(countryID, filename string) models.Recipe {
// change current version and read new recipe // change current version and read new recipe
d.CurrentFile = filename d.CurrentFile = filename
d.CurrentCountryID = countryID d.CurrentCountryID = countryID
d.currentRecipe = helpers.ReadRecipeFile(countryID, filename) recipe, err := helpers.ReadRecipeFile(countryID, filename)
if err != nil {
logger.GetInstance().Error("Error when read recipe file", zap.Error(err))
return *d.currentRecipe
}
d.currentRecipe = recipe
// save to map // save to map
if len(d.recipeMap) > 5 { // limit keep in memory 5 version if len(d.recipeMap) > 5 { // limit keep in memory 5 version
@ -154,7 +166,15 @@ func (d *Data) GetMaterialSetting(countryID, filename string) []models.MaterialS
d.CurrentFile = filename d.CurrentFile = filename
d.CurrentCountryID = countryID d.CurrentCountryID = countryID
d.currentRecipe = helpers.ReadRecipeFile(countryID, filename) recipe, err := helpers.ReadRecipeFile(countryID, filename)
if err != nil {
logger.GetInstance().Error("Error when read recipe file", zap.Error(err))
copy(result, d.currentRecipe.MaterialSetting)
return result
}
d.currentRecipe = recipe
// save to map // save to map
if len(d.recipeMap) > 5 { // limit keep in memory 5 version if len(d.recipeMap) > 5 { // limit keep in memory 5 version
@ -190,7 +210,14 @@ func (d *Data) GetMaterialCode(ids []uint64, countryID, filename string) []model
} else { } else {
d.CurrentFile = filename d.CurrentFile = filename
d.CurrentCountryID = countryID d.CurrentCountryID = countryID
d.currentRecipe = helpers.ReadRecipeFile(countryID, filename) recipe, err := helpers.ReadRecipeFile(countryID, filename)
if err != nil {
logger.GetInstance().Error("Error when read recipe file", zap.Error(err))
return d.currentRecipe.MaterialCode
}
d.currentRecipe = recipe
// save to map // save to map
if len(d.recipeMap) > 5 { // limit keep in memory 5 version if len(d.recipeMap) > 5 { // limit keep in memory 5 version

View file

@ -2,6 +2,7 @@ package helpers
import ( import (
"encoding/json" "encoding/json"
"fmt"
"log" "log"
"os" "os"
"path" "path"
@ -29,7 +30,7 @@ func ReadFile(filePath string) (string, error) {
return string(file), nil return string(file), nil
} }
func ReadRecipeFile(countryID, filePath string) *models.Recipe { func ReadRecipeFile(countryID, filePath string) (*models.Recipe, error) {
if countryID == "thai" { if countryID == "thai" {
countryID = "" countryID = ""
@ -38,8 +39,7 @@ func ReadRecipeFile(countryID, filePath string) *models.Recipe {
file, err := os.Open(path.Join("cofffeemachineConfig", countryID, filePath)) file, err := os.Open(path.Join("cofffeemachineConfig", countryID, filePath))
if err != nil { if err != nil {
log.Fatalf("Error when open file: %s", err) return nil, fmt.Errorf("error when open file: %s", err)
return nil
} }
defer file.Close() defer file.Close()
@ -49,11 +49,10 @@ func ReadRecipeFile(countryID, filePath string) *models.Recipe {
err = json.NewDecoder(file).Decode(&data) err = json.NewDecoder(file).Decode(&data)
if err != nil { if err != nil {
log.Fatalf("Error when decode file: %s", err) return nil, fmt.Errorf("error when decode file: %s", err)
return nil
} }
return data return data, nil
} }
type RecipePath struct { type RecipePath struct {

View file

@ -36,7 +36,7 @@ func main() {
}() }()
// Spawn a goroutine to run git pull every 10 minutes // Spawn a goroutine to run git pull every 10 minutes
go RunGitRecipeWorker() //go RunGitRecipeWorker()
err := s.Run() err := s.Run()
if err != nil { if err != nil {