diff --git a/client/src/app/core/services/material.service.ts b/client/src/app/core/services/material.service.ts index a9f9b51..4f3019f 100644 --- a/client/src/app/core/services/material.service.ts +++ b/client/src/app/core/services/material.service.ts @@ -2,22 +2,32 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { MaterialCode, MaterialSetting } from '../models/recipe.model'; import { environment } from 'src/environments/environment'; -import { Observable } from 'rxjs'; +import { Observable, count } from 'rxjs'; +import { ActivatedRoute } from '@angular/router'; +import { getCountryMapSwitcher } from 'src/app/shared/helpers/recipe'; +import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage'; @Injectable({ providedIn: 'root' }) export class MaterialService { - constructor(private _httpClient: HttpClient) {} - getMaterialCodes( + private department = this._route.snapshot.paramMap.get('department') + + constructor(private _httpClient: HttpClient, private _route: ActivatedRoute) {} + + async getMaterialCodes( matIds?: number[], country?: string, filename?: string - ): Observable { + ): Promise> { + + // async country + let asyncCountry = await AsyncStorage.getItem('currentRecipeCountry'); + return this._httpClient.get( `${environment.api}/materials/code`, { params: { - country: country || this.getCurrentCountry(), + country: country || asyncCountry, filename: filename || this.getCurrentFile(), mat_ids: matIds?.join(',') || '', }, @@ -26,19 +36,26 @@ export class MaterialService { ); } - getFullMaterialDetail( + async getFullMaterialDetail( country?: string, filename?: string - ): Observable<{ + ): Promise{ - console.log("getFullMaterialDetail", country, filename); + }[] | null>>{ + console.log("getFullMaterialDetail", country, "where filename = ",filename, "department.short = ", this.department!); - country = country || this.getCurrentCountry(); + let currentCountryWithoutDepartment = await this.getCurrentCountry(); + let asyncCountry = await this.getCurrentCountry(this.department!); + + console.log("[FullMatFetchService] get current country = ", currentCountryWithoutDepartment, " do switch tuple = ", getCountryMapSwitcher(currentCountryWithoutDepartment)); + country = getCountryMapSwitcher(currentCountryWithoutDepartment); filename = filename || this.getCurrentFile(); + // finalize fetch from what? + console.log("country, filename", country, filename); + return this._httpClient.get<{ "materialId": number, "name": string, @@ -48,16 +65,19 @@ export class MaterialService { }); } - getMaterialSettingById( + async getMaterialSettingById( id: number, country?: string, filename?: string - ): Observable { + ): Promise> { + + let asyncCountry = await AsyncStorage.getItem('currentRecipeCountry'); + return this._httpClient.get( `${environment.api}/materials/setting/${id}`, { params: { - country: country || this.getCurrentCountry(), + country: country || asyncCountry, filename: filename || this.getCurrentFile(), }, withCredentials: true, @@ -71,11 +91,30 @@ export class MaterialService { return currentRecipeFile; } - return 'coffeethai02_580.json'; + return 'default'; } - getCurrentCountry(): string { - const currentRecipeCountry = localStorage.getItem('currentRecipeCountry'); + async getCurrentCountry(department? : string): Promise { + + // fetch by using department + if(department){ + + // translate back to full name + let fullname = getCountryMapSwitcher(department); + + console.log('Material.service::fullname: ', fullname); + + await AsyncStorage.setItem('currentRecipeCountry', fullname); + + // localStorage.setItem('currentRecipeCountry', fullname); + return fullname; + } + + + // const currentRecipeCountry = localStorage.getItem('currentRecipeCountry'); + + const currentRecipeCountry = await AsyncStorage.getItem('currentRecipeCountry'); + if (currentRecipeCountry) { return currentRecipeCountry; } diff --git a/client/src/app/core/services/recipe.service.ts b/client/src/app/core/services/recipe.service.ts index b183d01..730d7b5 100644 --- a/client/src/app/core/services/recipe.service.ts +++ b/client/src/app/core/services/recipe.service.ts @@ -12,6 +12,9 @@ import { } from '../models/recipe.model'; import { environment } from 'src/environments/environment'; import { RecipeMetaData } from 'src/app/shared/types/recipe'; +import { getCountryMapSwitcher } from 'src/app/shared/helpers/recipe'; +import { ActivatedRoute } from '@angular/router'; +import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage'; type RecipeOverviewParams = { filename: string; @@ -38,15 +41,17 @@ export class RecipeService { private tmp_files: string[] = []; + private department = this._route.snapshot.paramMap.get('department'); + private get tmpfiles(): string[] { return this.tmp_files; } - constructor(private _httpClient: HttpClient) {} + constructor(private _httpClient: HttpClient, private _route: ActivatedRoute) {} getRecipesDashboard( - params: RecipeDashboardParams = { - country: this.getCurrentCountry(), + params: any = { + country: this.getCurrentCountry(this.department!), filename: this.getCurrentFile(), } ): Observable { @@ -63,16 +68,16 @@ export class RecipeService { ); } - getRecipeOverview( - params: RecipeOverviewParams = { - country: this.getCurrentCountry(), + async getRecipeOverview( + params: any = { + country: this.getCurrentCountry(this.department!), filename: this.getCurrentFile(), materialIds: [], offset: 0, take: 20, search: '', } - ): Observable { + ): Promise> { return this._httpClient.get( environment.api + '/recipes/overview', { @@ -90,13 +95,17 @@ export class RecipeService { ); } - getRecipeDetail(productCode: string): Observable { + async getRecipeDetail(productCode: string): Promise> { + + let asyncCountry = await this.getCurrentCountry(this.department!); + console.log('get detail by asyncCountry', asyncCountry); + return this._httpClient.get( environment.api + '/recipes/' + productCode, { params: { filename: this.getCurrentFile(), - country: this.getCurrentCountry(), + country: asyncCountry, }, withCredentials: true, responseType: 'json', @@ -104,15 +113,18 @@ export class RecipeService { ); } - getRecipeDetailMat( + async getRecipeDetailMat( productCode: string - ): Observable<{ result: RecipeDetailMat[] }> { + ): Promise> { + + let asyncCountry = await this.getCurrentCountry(this.department!); + return this._httpClient.get<{ result: RecipeDetailMat[] }>( environment.api + '/recipes/' + productCode + '/mat', { params: { filename: this.getCurrentFile(), - country: this.getCurrentCountry(), + country: asyncCountry, }, withCredentials: true, responseType: 'json', @@ -121,20 +133,41 @@ export class RecipeService { } getCurrentFile(): string { + + // TODO: get default from server + + const currentRecipeFile = localStorage.getItem('currentRecipeFile'); if (currentRecipeFile) { return currentRecipeFile; } - return 'coffeethai02_580.json'; + return 'default'; } setCurrentFile(filename: string) { localStorage.setItem('currentRecipeFile', filename); } - getCurrentCountry(): string { - const currentRecipeCountry = localStorage.getItem('currentRecipeCountry'); + async getCurrentCountry(department?: string): Promise { + + if(department){ + + // translate back to full name + let fullname = getCountryMapSwitcher(department); + + console.log('fullname: ', fullname); + + // localStorage.setItem('currentRecipeCountry', fullname); + + await AsyncStorage.setItem('currentRecipeCountry', fullname); + + return fullname; + } + + // const currentRecipeCountry = localStorage.getItem('currentRecipeCountry'); + + const currentRecipeCountry = await AsyncStorage.getItem('currentRecipeCountry'); if (currentRecipeCountry) { return currentRecipeCountry; } @@ -225,6 +258,7 @@ export class RecipeService { } getSubMenus(country: string, filename: string, productCode: string) { + console.log('getSubMenus', country, filename, productCode); return this._httpClient.get( environment.api + '/recipes/' + diff --git a/client/src/app/core/services/topping.service.ts b/client/src/app/core/services/topping.service.ts index 0f282d3..22d1ca5 100644 --- a/client/src/app/core/services/topping.service.ts +++ b/client/src/app/core/services/topping.service.ts @@ -1,16 +1,22 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; +import { Observable, count } from 'rxjs'; import { environment } from 'src/environments/environment'; import { Topping, ToppingSet } from '../models/recipe.model'; +import { RecipeService } from './recipe.service'; +import { getCountryMapSwitcher } from 'src/app/shared/helpers/recipe'; @Injectable({ providedIn: 'root', }) export class ToppingService { - constructor(private _httpClient: HttpClient) {} + constructor(private _httpClient: HttpClient, private _recipeService: RecipeService) {} - getToppings(country: string, filename: string): Observable { + async getToppings(country: string, filename: string): Promise> { + console.log("getToppings", country); + let asyncCountry = await this._recipeService.getCurrentCountry(); + country = getCountryMapSwitcher(asyncCountry); + console.log("getToppingsPreFetch", country, asyncCountry); return this._httpClient.get( `${environment.api}/recipes/${country}/${filename}/toppings`, { @@ -23,7 +29,11 @@ export class ToppingService { ); } - getToppingsOfRecipe(country: string, filename: string, productCode: string): Observable { + async getToppingsOfRecipe(country: string, filename: string, productCode: string): Promise> { + console.log("getToppingsOfRecipe", country); + let asyncCountry = await this._recipeService.getCurrentCountry(); + country = country || asyncCountry; + console.log("getToppingsOfRecipePreFetch", country, asyncCountry); return this._httpClient.get( `${environment.api}/recipes/${country}/${filename}/${productCode}/toppings`, { diff --git a/client/src/app/features/recipes/recipe-details/recipe-details.component.html b/client/src/app/features/recipes/recipe-details/recipe-details.component.html index 1d31cf1..9969e91 100644 --- a/client/src/app/features/recipes/recipe-details/recipe-details.component.html +++ b/client/src/app/features/recipes/recipe-details/recipe-details.component.html @@ -7,19 +7,17 @@ class="block p-6 bg-white border border-gray-200 rounded-lg shadow w-full" >
- - - -
- -
+ +
+ +
@@ -29,7 +27,6 @@
{{ recipeDetailForm.getRawValue().otherName }}
-
@@ -110,7 +107,12 @@
- +
@@ -118,45 +120,52 @@
- - +
-
- -
- 1 - 2 - 3 -
+
+ 1 + 2 + 3 +
diff --git a/client/src/app/features/recipes/recipe-details/recipe-details.component.ts b/client/src/app/features/recipes/recipe-details/recipe-details.component.ts index 29f41ca..8f3e030 100644 --- a/client/src/app/features/recipes/recipe-details/recipe-details.component.ts +++ b/client/src/app/features/recipes/recipe-details/recipe-details.component.ts @@ -20,7 +20,6 @@ import { UserPermissions } from 'src/app/core/auth/userPermissions'; import { ToppingService } from 'src/app/core/services/topping.service'; import { copy, transformToTSV } from 'src/app/shared/helpers/copy'; -import { RecipeToppingsetComponent } from "./recipe-toppingset/recipe-toppingset.component"; @Component({ selector: 'app-recipe-details', @@ -41,7 +40,6 @@ import { RecipeToppingsetComponent } from "./recipe-toppingset/recipe-toppingset ConfirmModal, DatePipe, RecipeListComponent, - RecipeToppingsetComponent, FormsModule ] }) @@ -94,11 +92,11 @@ export class RecipeDetailsComponent implements OnInit { toppingSet: ToppingSet[] | null = null; submenus: Recipe01[] | null = null; - ngOnInit() { + async ngOnInit() { this.productCode = this._route.snapshot.params['productCode']; - this.recipeDetail$ = this._recipeService - .getRecipeDetail(this.productCode) + this.recipeDetail$ = (await this._recipeService + .getRecipeDetail(this.productCode)) .pipe(first()); this.recipeDetail$.subscribe((detail) => { @@ -109,7 +107,7 @@ export class RecipeDetailsComponent implements OnInit { this.recipeOriginalDetail = { ...this.recipeDetailForm.getRawValue() }; }); - this._recipeService.getSubMenus(this._recipeService.getCurrentCountry(), this._recipeService.getCurrentFile(), this.productCode).subscribe((data) => { + this._recipeService.getSubMenus(await this._recipeService.getCurrentCountry(), this._recipeService.getCurrentFile(), this.productCode).subscribe((data) => { console.log('Submenus', data); this.submenus = data; }); @@ -117,7 +115,7 @@ export class RecipeDetailsComponent implements OnInit { this.recipeDetailForm.valueChanges.subscribe(this.onRecipeDetailFormChange); - this._toppingService.getToppingsOfRecipe(this.department, this._recipeService.getCurrentFile(), this.productCode).subscribe((data) => { + (await this._toppingService.getToppingsOfRecipe(this.department, this._recipeService.getCurrentFile(), this.productCode)).subscribe((data) => { this.toppingSet = data; // console.log('Toppings', data); }) @@ -143,7 +141,7 @@ export class RecipeDetailsComponent implements OnInit { confirmSave = { title: 'The changes detected!', message: 'Do you want to save changes?', - confirmCallBack: () => { + confirmCallBack: async () => { console.log('confirm save'); // get username @@ -177,7 +175,7 @@ export class RecipeDetailsComponent implements OnInit { // TODO: update value in targeted recipe console.log('to_send', to_send); this._recipeService.editChanges( - this._recipeService.getCurrentCountry(), + await this._recipeService.getCurrentCountry(this.department), this._recipeService.getCurrentFile(), { ...to_send, @@ -227,8 +225,9 @@ export class RecipeDetailsComponent implements OnInit { } onRecipeListFormChange(repl: unknown[]) { - // console.log('Recipe List Form Changed', repl); - this.repl = repl as never[]; + console.log('Recipe List Form Changed', repl); + this.repl = repl[1] as never[]; + this.tpl = repl[0] as never[]; this.isValueChanged ||= repl != undefined; } diff --git a/client/src/app/features/recipes/recipe-details/recipe-list/recipe-list.component.html b/client/src/app/features/recipes/recipe-details/recipe-list/recipe-list.component.html index 2222c72..660051a 100644 --- a/client/src/app/features/recipes/recipe-details/recipe-list/recipe-list.component.html +++ b/client/src/app/features/recipes/recipe-details/recipe-list/recipe-list.component.html @@ -4,7 +4,8 @@ Is Use Material ID Material Name - Settings + Volume + Settings - + - + - + - -

Volume

- +

gram

-
+

Volume

- +

gram

- -
-
-
- -

tail

- -

- mA -

+ +
+
+
+
+ +

tail

+ +

mA

+
-
-
-

Hot

- -

ml

-
-
-

Cold

- -

ml

-
-
-

- Grinder -

-

- Mix -

-

- Clean -

- -

sec

+

Hot

+ + +

ml

+
+
+

Cold

+ +

ml

+
+
+

{{getTooltipForStirTime(getTypeForRecipeListAtIndex(i))}}

+ +

sec

+
+
+
+
Topping Settings
+
+ +
@@ -291,7 +303,11 @@ Water

Hot (waterYield)

- +

ml

diff --git a/client/src/app/features/recipes/recipe-details/recipe-list/recipe-list.component.ts b/client/src/app/features/recipes/recipe-details/recipe-list/recipe-list.component.ts index aefd18d..821fadf 100644 --- a/client/src/app/features/recipes/recipe-details/recipe-list/recipe-list.component.ts +++ b/client/src/app/features/recipes/recipe-details/recipe-list/recipe-list.component.ts @@ -1,5 +1,5 @@ import { NgFor, NgIf } from '@angular/common'; -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR } from '@angular/core'; import { FormArray, FormBuilder, @@ -29,14 +29,17 @@ import { StringParam, stringParamsDefinition, conditionTests, - inRange + inRange, + convertFromInterProductCode } from 'src/app/shared/helpers/recipe'; +import { RecipeToppingComponent } from '../recipe-topping/recipe-topping.component'; + @Component({ - selector: 'app-recipe-list', - templateUrl: './recipe-list.component.html', - standalone: true, - imports: [NgIf, NgFor, ReactiveFormsModule, FormsModule], + selector: 'app-recipe-list', + templateUrl: './recipe-list.component.html', + standalone: true, + imports: [NgIf, NgFor, ReactiveFormsModule, FormsModule, RecipeToppingComponent] }) export class RecipeListComponent implements OnInit { @Input({ required: true }) productCode!: string; @@ -78,6 +81,9 @@ export class RecipeListComponent implements OnInit { // detailed recipe list showDetailRecipeList: boolean = false; + // topping list + public toppingList: any[] = []; + constructor( private _recipeService: RecipeService, private _materialService: MaterialService, @@ -94,9 +100,9 @@ export class RecipeListComponent implements OnInit { private _recipeListOriginalArray!: RecipeDetailMat[]; - ngOnInit(): void { - this._recipeService - .getRecipeDetailMat(this.productCode) + async ngOnInit(): Promise { + (await this._recipeService + .getRecipeDetailMat(this.productCode)) .pipe(first()) .subscribe(({ result }) => { this._recipeListOriginalArray = result; @@ -278,18 +284,23 @@ export class RecipeListComponent implements OnInit { emitted_res.push(recipeDetailMat); }); - this.recipeListFormChange.emit(emitted_res as unknown[]); + // do another emit + + this.recipeListFormChange.emit([this.toppingList, emitted_res] as unknown[]); } else { this.recipeListFormChange.emit([]); } }); // TODO: embed this to recipelist - this._materialService.getMaterialCodes().subscribe((materials) => { + (await + // TODO: embed this to recipelist + this._materialService.getMaterialCodes()).subscribe((materials) => { this.materialList = materials; + console.log("[MatService] get materials", materials.length); }); - this._materialService.getFullMaterialDetail().subscribe((materials) => { + (await this._materialService.getFullMaterialDetail()).subscribe((materials) => { this.fullMaterialList = materials; this.categoriedMaterial = this.ListCategory(); console.log(this.categoriedMaterial); @@ -324,9 +335,17 @@ export class RecipeListComponent implements OnInit { // console.log("make material list by category", this.makeListCategory()); this.showMaterialSelector = false; - this.recipeListData.at(i).get('materialPathId')?.setValue(material); - console.log('set mat ', material, 'to slot', i); + // query material for its name + let materialName = this.fullMaterialList!.find( + (mat) => mat.materialId == material + )!.name; + + this.recipeListData.at(i).get('name')?.setValue( + materialName + ); + + console.log('set mat ', material, materialName,'to slot', i); } getTypeForRecipeListAtIndex(i: any) { @@ -372,6 +391,17 @@ export class RecipeListComponent implements OnInit { this.fullMaterialList!.forEach((mat) => { let category = getMaterialType(mat.materialId); + // try again + if(category == 'others'){ + // find min + // console.log(Math.floor(mat.materialId / 1000) ); + let interCode = Math.floor(mat.materialId / 10000) * 10000; + let originalCode = mat.materialId - (interCode); + + // console.log("from",mat.materialId,"interCode", interCode, "originalCode", originalCode); + category = getMaterialType(originalCode); + // console.log("get original category of inter", category); + } if (Array.isArray(catMap[category])) { catMap[category].push({ @@ -391,7 +421,11 @@ export class RecipeListComponent implements OnInit { isNotExistbyCatagories = (materialId: number) => getMaterialType(materialId) == 'others'; - isTopping = (materialId: number) => { return inRange(8111, 8130, materialId); }; + isTopping = (materialId: number) => { + return inRange(8111, 8130, convertFromInterProductCode(materialId)); + }; + + getToppingSlotNumber = (mat: number) => convertFromInterProductCode(mat) - 8110; isStringParamExist = (i: number) => { let rawStringParam = this.recipeListData.at(i).get('StringParam')?.value; @@ -481,7 +515,7 @@ export class RecipeListComponent implements OnInit { if(this.timeoutHandler){ console.log("timeout get", this.timeout); - if(this.timeout >= 5){ + if(this.timeout >= 20){ this.showDetailRecipeList = true; } @@ -501,4 +535,34 @@ export class RecipeListComponent implements OnInit { this.recipeListData.value[i][key] ); } + + getTooltipForStirTime = (cat: { + category: string; + name: any; + id: any; +}) => { + switch (cat.category) { + case 'whipper': + return 'Mix'; + case 'bean': + return 'Grinder'; + case 'others': + + if(inRange(8001, 8002, cat.id)){ + return 'Clean'; + } + + break; + default: + break; + } + + return ''; + }; + + onToppingSetChange = (event: any, index: number) => { + // console.log('onToppingSetChange at index', index, "get event", event); + this.toppingList[event[0]] = event[1]; + // console.log('onToppingSetChange', this.toppingList); + } } diff --git a/client/src/app/features/recipes/recipe-details/recipe-topping/recipe-topping.component.html b/client/src/app/features/recipes/recipe-details/recipe-topping/recipe-topping.component.html new file mode 100644 index 0000000..8da2488 --- /dev/null +++ b/client/src/app/features/recipes/recipe-details/recipe-topping/recipe-topping.component.html @@ -0,0 +1,38 @@ +
+
+
+ + + + + +
{{ item.name }} ({{ item.groupId }})
+
+
+ + + +
{{ item.name }} ({{ item.id }})
+
+
+
+
+ +
diff --git a/client/src/app/features/recipes/recipe-details/recipe-topping/recipe-topping.component.ts b/client/src/app/features/recipes/recipe-details/recipe-topping/recipe-topping.component.ts new file mode 100644 index 0000000..7fd4e4a --- /dev/null +++ b/client/src/app/features/recipes/recipe-details/recipe-topping/recipe-topping.component.ts @@ -0,0 +1,161 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { NgSelectModule } from '@ng-select/ng-select'; +import { + FormArray, + FormBuilder, + FormsModule, + ReactiveFormsModule, +} from '@angular/forms'; +import { RecipeService } from 'src/app/core/services/recipe.service'; +import { ToppingService } from 'src/app/core/services/topping.service'; +import { + Topping, + ToppingGroup, + ToppingSet, +} from 'src/app/core/models/recipe.model'; +import { ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'app-recipe-topping', + standalone: true, + imports: [CommonModule, NgSelectModule, FormsModule, ReactiveFormsModule], + templateUrl: './recipe-topping.component.html', +}) +export class RecipeToppingComponent implements OnInit { + @Input() productCode: string = ''; + @Input() index: number | undefined = undefined; + @Output() toppingSetChange = new EventEmitter(); + + allToppings: Topping | undefined = undefined; + + allToppingsDefinitions: + | { groupId: string; name: string; members: string; default: string }[] + | null = [{ groupId: '0', name: 'none', members: '0', default: '0' }]; + + allToppingMembersByGroup: { + id: string; + members: { id: string; name: string }[]; + }[] = []; + department = this._route.snapshot.paramMap.get('department'); + + private _toppingSetOriginalArray!: ToppingSet[]; + + // form + toppingForm = this._formBuilder.group( + { + toppingList: this._formBuilder.array([]), + }, + { + updateOn: 'blur', + } + ); + + get toppingList(): FormArray { + return this.toppingForm.get('toppingList') as FormArray; + } + + constructor( + private _formBuilder: FormBuilder, + private _recipeService: RecipeService, + private _toppingService: ToppingService, + private _route: ActivatedRoute + ) {} + async ngOnInit(): Promise { + // get topping of this recipe + + // initialize toppinglist form + + ( + await this._toppingService.getToppingsOfRecipe( + await this._recipeService.getCurrentCountry(), + this._recipeService.getCurrentFile(), + this.productCode + ) + ).subscribe((data) => { + this._toppingSetOriginalArray = data; + // console.log('ToppingSet', data); + + // check length of toppingList if in range with given index + if(this.index && data.length >= this.index!){ + this.toppingList.push( + this._formBuilder.group({ + isUse: data[this.index!].isUse, + groupID: data[this.index!].groupID, + defaultIDSelect: data[this.index!].defaultIDSelect, + ListGroupID: data[this.index!].ListGroupID, + }) + ); + } + }); + + // get all topping + ( + await this._toppingService.getToppings( + this.department!, + this._recipeService.getCurrentFile() + ) + ).subscribe((data) => { + this.allToppings = data; + // console.log('allToppings', data); + + data.ToppingGroup.forEach((group: ToppingGroup) => { + if (this.allToppingsDefinitions != null) { + // this.allToppingsDefinitions = {}; + this.allToppingsDefinitions.push({ + groupId: group.groupID, + name: group.name, + members: group.idInGroup, + default: group.idDefault, + }); + + this.allToppingMembersByGroup.push({ + id: group.groupID, + members: this.mapToppingListToMember(group.idInGroup.split(',')), + }); + } + }); + }); + + + // emit value changes + this.toppingForm.valueChanges.subscribe((value) => { + console.log('emit value', value); + this.toppingSetChange.emit([this.index, this.toppingList.value]); + }); + } + + compareFunc = (a: any, b: any) => a.toString() === b.toString(); + + mapToppingListToMember = (mm: string[]) => + mm.map((m) => { + // find actual topping from toppingList + let actualTopping = this.allToppings!.ToppingList.find((t) => t.id == m); + + return { + id: actualTopping!.id, + name: actualTopping?.name == null ? m : actualTopping!.name, + }; + }); + + getMembersByGroupId(groupID: string) { + return this.allToppingMembersByGroup.find((x) => x.id == groupID)?.members; + } + + getGroupIdByIndex(i: number) { + return (this.toppingList.value![0] as any).groupID as string; + } + + getDefaultOfGroup(groupID: any) { + this.toppingList.controls.forEach((control) => { + if ((control.value as any).groupID == groupID) { + + let newDefault = (this.allToppingsDefinitions as any).find( + (x: any) => x.groupId == groupID + )!.default; + + control.get('defaultIDSelect')?.setValue(newDefault); + } + }) + } +} diff --git a/client/src/app/features/recipes/recipe-details/recipe-toppingset/recipe-toppingset.component.html b/client/src/app/features/recipes/recipe-details/recipe-toppingset/recipe-toppingset.component.html index edd4336..215a0f7 100644 --- a/client/src/app/features/recipes/recipe-details/recipe-toppingset/recipe-toppingset.component.html +++ b/client/src/app/features/recipes/recipe-details/recipe-toppingset/recipe-toppingset.component.html @@ -1,4 +1,4 @@ - + -
+ --> diff --git a/client/src/app/features/recipes/recipe-details/recipe-toppingset/recipe-toppingset.component.ts b/client/src/app/features/recipes/recipe-details/recipe-toppingset/recipe-toppingset.component.ts index 2590fff..26a3757 100644 --- a/client/src/app/features/recipes/recipe-details/recipe-toppingset/recipe-toppingset.component.ts +++ b/client/src/app/features/recipes/recipe-details/recipe-toppingset/recipe-toppingset.component.ts @@ -1,220 +1,220 @@ -import { NgFor } from '@angular/common'; -import { Component, Input, Output, OnInit, EventEmitter } from '@angular/core'; -import { - FormArray, - FormBuilder, - FormsModule, - ReactiveFormsModule, -} from '@angular/forms'; -import { forEach, isEqual } from 'lodash'; -import { - Topping, - ToppingGroup, - ToppingList, - ToppingSet, -} from 'src/app/core/models/recipe.model'; -import { RecipeService } from 'src/app/core/services/recipe.service'; -import { ToppingService } from 'src/app/core/services/topping.service'; -import { NgSelectModule } from '@ng-select/ng-select'; -import { CommonModule } from '@angular/common'; +// import { NgFor } from '@angular/common'; +// import { Component, Input, Output, OnInit, EventEmitter } from '@angular/core'; +// import { +// FormArray, +// FormBuilder, +// FormsModule, +// ReactiveFormsModule, +// } from '@angular/forms'; +// import { forEach, isEqual } from 'lodash'; +// import { +// Topping, +// ToppingGroup, +// ToppingList, +// ToppingSet, +// } from 'src/app/core/models/recipe.model'; +// import { RecipeService } from 'src/app/core/services/recipe.service'; +// import { ToppingService } from 'src/app/core/services/topping.service'; +// import { NgSelectModule } from '@ng-select/ng-select'; +// import { CommonModule } from '@angular/common'; -@Component({ - selector: 'app-recipe-toppingset', - templateUrl: './recipe-toppingset.component.html', - standalone: true, - imports: [ - NgFor, - FormsModule, - ReactiveFormsModule, - CommonModule, - NgSelectModule, - ], -}) -export class RecipeToppingsetComponent implements OnInit { - @Input() productCode!: string; - @Output() toppingSetChange = new EventEmitter(); +// @Component({ +// selector: 'app-recipe-toppingset', +// templateUrl: './recipe-toppingset.component.html', +// standalone: true, +// imports: [ +// NgFor, +// FormsModule, +// ReactiveFormsModule, +// CommonModule, +// NgSelectModule, +// ], +// }) +// export class RecipeToppingsetComponent implements OnInit { +// @Input() productCode!: string; +// @Output() toppingSetChange = new EventEmitter(); - allToppings: Topping | undefined = undefined; +// allToppings: Topping | undefined = undefined; - allToppingsDefinitions: - | { groupId: string; name: string; members: string; default: string }[] - | null = [{ groupId: '0', name: 'none', members: '0', default: '0' }]; +// allToppingsDefinitions: +// | { groupId: string; name: string; members: string; default: string }[] +// | null = [{ groupId: '0', name: 'none', members: '0', default: '0' }]; - allToppingMembersByGroup: { - id: string; - members: { id: string; name: string }[]; - }[] = []; +// allToppingMembersByGroup: { +// id: string; +// members: { id: string; name: string }[]; +// }[] = []; - private _toppingSetOriginalArray!: ToppingSet[]; +// private _toppingSetOriginalArray!: ToppingSet[]; - constructor( - private _recipeService: RecipeService, - private _toppingService: ToppingService, - private _formBuilder: FormBuilder - ) {} +// constructor( +// private _recipeService: RecipeService, +// private _toppingService: ToppingService, +// private _formBuilder: FormBuilder +// ) {} - toppingForm = this._formBuilder.group( - { - toppingList: this._formBuilder.array([]), - }, - { updateOn: 'blur' } - ); +// toppingForm = this._formBuilder.group( +// { +// toppingList: this._formBuilder.array([]), +// }, +// { updateOn: 'blur' } +// ); - get toppingList(): FormArray { - return this.toppingForm.get('toppingList') as FormArray; - } +// get toppingList(): FormArray { +// return this.toppingForm.get('toppingList') as FormArray; +// } - ngOnInit(): void { - this._toppingService - .getToppingsOfRecipe( - this._recipeService.getCurrentCountry(), - this._recipeService.getCurrentFile(), - this.productCode - ) - .subscribe((data) => { - // this.toppingForm.patchValue({toppingList: data}); - this._toppingSetOriginalArray = data; +// async ngOnInit(): Promise { +// this._toppingService +// .getToppingsOfRecipe( +// await this._recipeService.getCurrentCountry(), +// this._recipeService.getCurrentFile(), +// this.productCode +// ) +// .subscribe((data) => { +// // this.toppingForm.patchValue({toppingList: data}); +// this._toppingSetOriginalArray = data; - data.forEach((toppingSet: ToppingSet) => { - this.toppingList.push( - this._formBuilder.group({ - isUse: toppingSet.isUse, - groupID: toppingSet.groupID, - defaultIDSelect: toppingSet.defaultIDSelect, - ListGroupID: toppingSet.ListGroupID, - }) - ); - }); +// data.forEach((toppingSet: ToppingSet) => { +// this.toppingList.push( +// this._formBuilder.group({ +// isUse: toppingSet.isUse, +// groupID: toppingSet.groupID, +// defaultIDSelect: toppingSet.defaultIDSelect, +// ListGroupID: toppingSet.ListGroupID, +// }) +// ); +// }); - // console.log('controls', this.toppingList.controls); +// // console.log('controls', this.toppingList.controls); - // this.toppingSetChange.emit(this.toppingSetList); - }); +// // this.toppingSetChange.emit(this.toppingSetList); +// }); - // fetch all toppings : group and list - this._toppingService - .getToppings( - this._recipeService.getCurrentCountry(), - this._recipeService.getCurrentFile() - ) - .subscribe((data) => { - this.allToppings = data; - // console.log('allToppings', data); +// // fetch all toppings : group and list +// this._toppingService +// .getToppings( +// await this._recipeService.getCurrentCountry(), +// this._recipeService.getCurrentFile() +// ) +// .subscribe((data) => { +// this.allToppings = data; +// // console.log('allToppings', data); - data.ToppingGroup.forEach((group: ToppingGroup) => { - if (this.allToppingsDefinitions != null) { - // this.allToppingsDefinitions = {}; - this.allToppingsDefinitions.push({ - groupId: group.groupID, - name: group.name, - members: group.idInGroup, - default: group.idDefault, - }); +// data.ToppingGroup.forEach((group: ToppingGroup) => { +// if (this.allToppingsDefinitions != null) { +// // this.allToppingsDefinitions = {}; +// this.allToppingsDefinitions.push({ +// groupId: group.groupID, +// name: group.name, +// members: group.idInGroup, +// default: group.idDefault, +// }); - this.allToppingMembersByGroup.push({ - id: group.groupID, - members: this.mapToppingListToMember(group.idInGroup.split(',')), - }); - } - }); +// this.allToppingMembersByGroup.push({ +// id: group.groupID, +// members: this.mapToppingListToMember(group.idInGroup.split(',')), +// }); +// } +// }); - // console.log(this.allToppingsDefinitions); - // console.log('allToppingMembersByGroup', this.allToppingMembersByGroup); - }); +// // console.log(this.allToppingsDefinitions); +// // console.log('allToppingMembersByGroup', this.allToppingMembersByGroup); +// }); - this.toppingForm.valueChanges.subscribe((value) => { - //validator - for (let i = 0; i < value.toppingList!.length; i++) { - let toppingSet = value.toppingList![i] as any; +// this.toppingForm.valueChanges.subscribe((value) => { +// //validator +// for (let i = 0; i < value.toppingList!.length; i++) { +// let toppingSet = value.toppingList![i] as any; - // handle null case - if (toppingSet.defaultIDSelect == null) { - toppingSet.defaultIDSelect = 0; - } +// // handle null case +// if (toppingSet.defaultIDSelect == null) { +// toppingSet.defaultIDSelect = 0; +// } - // handle null case - if (toppingSet.groupID == null) { - toppingSet.groupID = '0'; - } +// // handle null case +// if (toppingSet.groupID == null) { +// toppingSet.groupID = '0'; +// } - // handle null case - if (!Array.isArray(toppingSet.ListGroupID)) { - toppingSet.ListGroupID = [parseInt(toppingSet.groupID), 0, 0, 0]; - } - } - let isDiff = !isEqual(this._toppingSetOriginalArray, value.toppingList!); +// // handle null case +// if (!Array.isArray(toppingSet.ListGroupID)) { +// toppingSet.ListGroupID = [parseInt(toppingSet.groupID), 0, 0, 0]; +// } +// } +// let isDiff = !isEqual(this._toppingSetOriginalArray, value.toppingList!); - if (isDiff) { - let newToppingSetList: any[] = []; +// if (isDiff) { +// let newToppingSetList: any[] = []; - forEach(value.toppingList!, (toppingSet: any) => { - // transform value - toppingSet.defaultIDSelect = parseInt(toppingSet.defaultIDSelect); +// forEach(value.toppingList!, (toppingSet: any) => { +// // transform value +// toppingSet.defaultIDSelect = parseInt(toppingSet.defaultIDSelect); - newToppingSetList.push(toppingSet); - }); +// newToppingSetList.push(toppingSet); +// }); - // console.log('newToppingList', newToppingSetList); - this.toppingSetChange.emit(newToppingSetList as unknown[]); - } else { - // console.log('newToppingListNoChange', value.toppingList); - this.toppingSetChange.emit([]); - } - }); - } +// // console.log('newToppingList', newToppingSetList); +// this.toppingSetChange.emit(newToppingSetList as unknown[]); +// } else { +// // console.log('newToppingListNoChange', value.toppingList); +// this.toppingSetChange.emit([]); +// } +// }); +// } - // match group id to its name - getGroupName(groupID: string) { - // check if array - if (Array.isArray(this.allToppings!.ToppingGroup)) { - return (this.allToppings!.ToppingGroup as ToppingGroup[]).find( - (group) => group.groupID == groupID - )?.name; - } else { - return undefined; - } - } +// // match group id to its name +// getGroupName(groupID: string) { +// // check if array +// if (Array.isArray(this.allToppings!.ToppingGroup)) { +// return (this.allToppings!.ToppingGroup as ToppingGroup[]).find( +// (group) => group.groupID == groupID +// )?.name; +// } else { +// return undefined; +// } +// } - openToppingList(i: any) { - console.log('select', i); - } +// openToppingList(i: any) { +// console.log('select', i); +// } - currentGroupId(i: any) { - console.log('currentGroupId', i); - return (this.toppingForm.value.toppingList![i] as any).groupID as string; - } +// currentGroupId(i: any) { +// console.log('currentGroupId', i); +// return (this.toppingForm.value.toppingList![i] as any).groupID as string; +// } - getMembersByGroupId(groupID: string) { - return this.allToppingMembersByGroup.find((x) => x.id == groupID)?.members; - } +// getMembersByGroupId(groupID: string) { +// return this.allToppingMembersByGroup.find((x) => x.id == groupID)?.members; +// } - getGroupIdByIndex(i: number) { - // console.log("getGroupId",this.toppingList.value![i]) - return (this.toppingList.value![i] as any).groupID as string; - } +// getGroupIdByIndex(i: number) { +// // console.log("getGroupId",this.toppingList.value![i]) +// return (this.toppingList.value![i] as any).groupID as string; +// } - mapToppingListToMember = (mm: string[]) => - mm.map((m) => { - // find actual topping from toppingList - let actualTopping = this.allToppings!.ToppingList.find((t) => t.id == m); +// mapToppingListToMember = (mm: string[]) => +// mm.map((m) => { +// // find actual topping from toppingList +// let actualTopping = this.allToppings!.ToppingList.find((t) => t.id == m); - return { - id: actualTopping!.id, - name: actualTopping?.name == null ? m : actualTopping!.name, - }; - }); +// return { +// id: actualTopping!.id, +// name: actualTopping?.name == null ? m : actualTopping!.name, +// }; +// }); - getDefaultOfGroup(groupID: any) { - this.toppingList.controls.forEach((control) => { - if ((control.value as any).groupID == groupID) { - let newDefault = this.allToppingsDefinitions!.find( - (x) => x.groupId == groupID - )!.default; - // set new defaultid - control.get('defaultIDSelect')?.setValue(newDefault); - } - }); - } +// getDefaultOfGroup(groupID: any) { +// this.toppingList.controls.forEach((control) => { +// if ((control.value as any).groupID == groupID) { +// let newDefault = this.allToppingsDefinitions!.find( +// (x) => x.groupId == groupID +// )!.default; +// // set new defaultid +// control.get('defaultIDSelect')?.setValue(newDefault); +// } +// }); +// } - compareFunc = (a: any, b: any) => a.toString() === b.toString(); -} +// compareFunc = (a: any, b: any) => a.toString() === b.toString(); +// } diff --git a/client/src/app/features/recipes/recipes.component.ts b/client/src/app/features/recipes/recipes.component.ts index 7d19b07..d079bf9 100644 --- a/client/src/app/features/recipes/recipes.component.ts +++ b/client/src/app/features/recipes/recipes.component.ts @@ -1,4 +1,5 @@ import { + AfterViewInit, Component, ElementRef, OnDestroy, @@ -24,7 +25,7 @@ import { tap, } from 'rxjs'; import * as lodash from 'lodash'; -import { ActivatedRoute, RouterLink } from '@angular/router'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { NgSelectModule } from '@ng-select/ng-select'; import { FormsModule } from '@angular/forms'; import { MaterialService } from 'src/app/core/services/material.service'; @@ -32,6 +33,8 @@ import { UserService } from 'src/app/core/services/user.service'; import { UserPermissions } from 'src/app/core/auth/userPermissions'; import { ToppingService } from 'src/app/core/services/topping.service'; import { copy, transformToTSV } from 'src/app/shared/helpers/copy'; +import { getCountryMapSwitcher } from 'src/app/shared/helpers/recipe'; +import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage'; @Component({ selector: 'app-recipes', @@ -46,7 +49,7 @@ import { copy, transformToTSV } from 'src/app/shared/helpers/copy'; ], templateUrl: './recipes.component.html', }) -export class RecipesComponent implements OnInit, OnDestroy { +export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit { recipesDashboard$!: Observable; recipeOverviewList!: RecipeOverview[]; selectMaterialFilter: number[] | null = null; @@ -89,12 +92,12 @@ export class RecipesComponent implements OnInit, OnDestroy { department: string = this.route.parent!.snapshot.params['department']; copyList: any[] = []; - @ViewChild('table', { static: false }) set content(table: ElementRef) { - // expose element ref for other fn + currentVersion: number | undefined = undefined; + @ViewChild('table', { static: false }) set content(table: ElementRef) { table.nativeElement.addEventListener( 'scroll', - () => { + async () => { if (this.isHasMore === false) { return; } @@ -103,15 +106,15 @@ export class RecipesComponent implements OnInit, OnDestroy { const isBottom = scrollTop + clientHeight >= scrollHeight - 10; if (isBottom && !this.isLoadMore) { this.isLoadMore = true; - this._recipeService + (await this._recipeService .getRecipeOverview({ offset: this.offset, take: this.take, search: this.oldSearchStr, filename: this._recipeService.getCurrentFile(), - country: this._recipeService.getCurrentCountry(), + country: await this._recipeService.getCurrentCountry(this.department), materialIds: this.selectMaterialFilter || [], - }) + })) .subscribe(({ result, hasMore, totalCount }) => { if (this.recipeOverviewList) { this.recipeOverviewList = @@ -134,26 +137,28 @@ export class RecipesComponent implements OnInit, OnDestroy { private _materialService: MaterialService, private _toppingService: ToppingService, private route: ActivatedRoute, - private _userService: UserService + private _userService: UserService, + private _router: Router ) {} - ngOnInit(): void { + async ngOnInit(): Promise { + console.log('Trigger onInit where department = ', this.department); this.recipesDashboard$ = this._recipeService .getRecipesDashboard({ filename: this._recipeService.getCurrentFile(), - country: this._recipeService.getCurrentCountry(), + country: await this._recipeService.getCurrentCountry(this.department!), }) .pipe( - finalize(() => { - this._recipeService + finalize(async () => { + (await this._recipeService .getRecipeOverview({ offset: this.offset, take: this.take, search: this.oldSearchStr, filename: this._recipeService.getCurrentFile(), - country: this._recipeService.getCurrentCountry(), + country: await this._recipeService.getCurrentCountry(this.department!), materialIds: this.selectMaterialFilter || [], - }) + })) .subscribe(({ result, hasMore, totalCount }) => { this.recipeOverviewList = result; this.offset += 10; @@ -163,9 +168,34 @@ export class RecipesComponent implements OnInit, OnDestroy { }) ); + // FIXME: Lag assigned + + this.recipesDashboard$.subscribe((data) => { + this.currentVersion = data.configNumber; + console.log('current version', this.currentVersion); + }); + + console.log('ngAfterViewInit::department', this.department); + console.log('::CurrentFile', this._recipeService.getCurrentFile()); + + (await this._materialService + .getFullMaterialDetail( + this.department, + this._recipeService.getCurrentFile() + )) + .subscribe((mat) => { + this.materialDetail = mat; + console.log(this.materialDetail?.length, "[0]=", mat?.at(0), "current country", this._recipeService.getCurrentCountry(), "currentFile", this._recipeService.getCurrentFile()); + + // check material detail + console.log('first material', this.materialDetail![0]); + }); + + // end of FIXME + this._recipeService .getSavedTmp( - this._recipeService.getCurrentCountry(), + await this._recipeService.getCurrentCountry(this.department), this._recipeService.getCurrentFile() ) .subscribe({ @@ -195,8 +225,10 @@ export class RecipesComponent implements OnInit, OnDestroy { }); // TODO: get all materials; MaterialSetting + MaterialCode - this._materialService - .getMaterialCodes() + (await + // TODO: get all materials; MaterialSetting + MaterialCode + this._materialService + .getMaterialCodes()) .pipe( map((mat) => mat.map((m) => ({ @@ -209,18 +241,8 @@ export class RecipesComponent implements OnInit, OnDestroy { this.materialList = materials; }); - this._materialService - .getFullMaterialDetail( - this.department, - this._recipeService.getCurrentFile() - ) - .subscribe((mat) => { - this.materialDetail = mat; - console.log(this.materialDetail?.length); - }); - - this._toppingService - .getToppings(this.department, this._recipeService.getCurrentFile()) + (await this._toppingService + .getToppings(this.department, this._recipeService.getCurrentFile())) .subscribe((tp) => { this.toppings = { toppingGroup: tp.ToppingGroup, @@ -232,24 +254,35 @@ export class RecipesComponent implements OnInit, OnDestroy { this.initRecipeSelection(); } + ngAfterViewInit(): void { + console.log('After view on init trigger'); + } + setSearch(event: Event) { console.log((event.target as HTMLInputElement).value); this.searchStr = (event.target as HTMLInputElement).value; } - search(event: Event) { + async search(event: Event) { + + // country + let country = await this._recipeService.getCurrentCountry(this.department).then( + (country) => country + ); + + this.offset = 0; this.isLoadMore = true; this.oldSearchStr = this.searchStr; - this._recipeService + (await this._recipeService .getRecipeOverview({ offset: this.offset, take: this.take, search: this.oldSearchStr, filename: this._recipeService.getCurrentFile(), - country: this._recipeService.getCurrentCountry(), + country: country, materialIds: this.selectMaterialFilter || [], - }) + })) .subscribe(({ result, hasMore, totalCount }) => { this.recipeOverviewList = result; this.offset += 10; @@ -397,40 +430,63 @@ export class RecipesComponent implements OnInit, OnDestroy { ); } - countrySelected(country: string) { + async countrySelected(country: string) { this.selectedCountry = country; this.isCountrySelected = true; - localStorage.setItem('currentRecipeCountry', country); + // localStorage.setItem('currentRecipeCountry', country); + + await AsyncStorage.setItem('currentRecipeCountry', country); + + // force reload, will fix this later + void this._router + .navigate([`/${getCountryMapSwitcher(country)}/recipes`]); } - loadRecipe(recipeFileName: string) { + async loadRecipe(recipeFileName: string) { // clear all recipes this.offset = 0; this.isHasMore = true; this.isLoadMore = true; this.oldSearchStr = ''; - localStorage.setItem('currentRecipeFile', recipeFileName); + // localStorage.setItem('currentRecipeFile', recipeFileName); - this.recipesDashboard$ = this._recipeService.getRecipesDashboard({ - filename: recipeFileName, - country: this.selectedCountry!, - }); + await AsyncStorage.setItem('currentRecipeFile', recipeFileName); - this._recipeService - .getRecipeOverview({ - offset: this.offset, - take: this.take, - search: this.oldSearchStr, - filename: recipeFileName, - country: this.selectedCountry!, - materialIds: this.selectMaterialFilter || [], - }) - .subscribe(({ result, hasMore, totalCount }) => { - this.recipeOverviewList = result; - this.offset += 10; - this.isHasMore = hasMore; - this.isLoadMore = false; - }); + + + + console.log('loadRecipe', recipeFileName, "currentCountry", this.department, "selectedCountry", this.selectedCountry); + + // clear all menus + this.recipeOverviewList = []; + + // this.recipesDashboard$ = this._recipeService.getRecipesDashboard({ + // filename: recipeFileName, + // country: this.selectedCountry!, + // }); + + // this.recipesDashboard$.subscribe((data) => { + // this.currentVersion = data.configNumber; + // console.log('current version', this.currentVersion); + // }); + + // this._recipeService + // .getRecipeOverview({ + // offset: this.offset, + // take: this.take, + // search: this.oldSearchStr, + // filename: recipeFileName, + // country: this.selectedCountry!, + // materialIds: this.selectMaterialFilter || [], + // }) + // .subscribe(({ result, hasMore, totalCount }) => { + // this.recipeOverviewList = result; + // this.offset += 10; + // this.isHasMore = hasMore; + // this.isLoadMore = false; + // }); + + window.location.reload(); } // end of Recipe Version selection @@ -438,7 +494,9 @@ export class RecipesComponent implements OnInit, OnDestroy { openJsonTab() { window.open( environment.api + - `/recipes/${this._recipeService.getCurrentCountry()}/${this._recipeService.getCurrentFile()}/json`, + `/recipes/${this._recipeService.getCurrentCountry( + this.department + )}/${this._recipeService.getCurrentFile()}/json`, '_blank' ); } @@ -448,7 +506,7 @@ export class RecipesComponent implements OnInit, OnDestroy { this.saveTab = true; } - loadSavedFile(file_commit: any) { + async loadSavedFile(file_commit: any) { this.showSaveNoti = false; this.saveTab = false; console.log('loadSavedFile', file_commit, this.department); @@ -472,7 +530,7 @@ export class RecipesComponent implements OnInit, OnDestroy { console.log(file_commit.Change_file.split('/')[2]); - this._recipeService + (await this._recipeService .getRecipeOverview({ offset: this.offset, take: this.take, @@ -480,7 +538,7 @@ export class RecipesComponent implements OnInit, OnDestroy { filename: file_commit.Change_file.split('/')[2], country: country, materialIds: this.selectMaterialFilter || [], - }) + })) .subscribe(({ result, hasMore, totalCount }) => { console.log('loadSavedFile', result); this._recipeService.setCurrentFile( @@ -503,26 +561,22 @@ export class RecipesComponent implements OnInit, OnDestroy { item.name.toLowerCase().includes(term.toLowerCase()) || item.materialId.toString().includes(term); - - addToCopyList(data: any){ - - if(this.copyList.includes(data)){ - + addToCopyList(data: any) { + if (this.copyList.includes(data)) { let index = this.copyList.indexOf(data); this.copyList.splice(index, 1); } else { this.copyList = [...this.copyList, data]; } - } - - async copyToTsv(data: any){ - - await copy(transformToTSV(data)).then( (value) => { + async copyToTsv(data: any) { + await copy(transformToTSV(data)) + .then((value) => { console.log('copyToTsv', value); - }).catch( (err) => { + }) + .catch((err) => { console.log('copyToTsvErr', err); }); - } + } } diff --git a/client/src/app/shared/helpers/asyncStorage.ts b/client/src/app/shared/helpers/asyncStorage.ts new file mode 100644 index 0000000..6b3e304 --- /dev/null +++ b/client/src/app/shared/helpers/asyncStorage.ts @@ -0,0 +1,14 @@ +export class AsyncStorage { + static async getItem(key: string) { + return new Promise((resolve) => { + resolve(localStorage.getItem(key) as T); + }); + } + + static async setItem(key: string, value: string) { + return new Promise((resolve) => { + localStorage.setItem(key, value); + resolve(); + }); + } +} diff --git a/client/src/app/shared/helpers/recipe.ts b/client/src/app/shared/helpers/recipe.ts index c42d251..baa004b 100644 --- a/client/src/app/shared/helpers/recipe.ts +++ b/client/src/app/shared/helpers/recipe.ts @@ -1,3 +1,5 @@ +import { Tuple } from "./tuple"; + var rangeMaterialMapping: { [key: string]: (id: number) => boolean } = { soda: (id: number) => id == 1031, water: (id: number) => id == 1, @@ -46,6 +48,14 @@ export function isNonMaterial(materialId: number) { ); } +// Inter mode checker +export function convertFromInterProductCode(materialId: number) { + let interPrefix = Math.floor(materialId / 10000) * 10000; + let interId = materialId - interPrefix; + + return interId; +} + // StringParam export class StringParam { @@ -92,5 +102,24 @@ export var stringParamsDefinition: { [key: string]: string } = { export var conditionTests: { [key: string]: (arg: any) => boolean } = { 'not-zero': (arg: any) => arg != 0, + 'zero': (arg: any) => arg == 0, 'false-if-another-exist': (arg: any) => arg[1] != undefined } + + +export var countryMap: Tuple[] = [ + new Tuple('tha', 'Thailand'), + new Tuple('mys', 'Malaysia'), + new Tuple('aus', 'Australia'), +]; + +export function getCountryMapSwitcher(param: string) { + + console.log("param = ", param); + + for (const country of countryMap) { + if(country.first == param || country.second == param){ + return country.switchGet(param); + } + } +} diff --git a/client/src/app/shared/helpers/tuple.ts b/client/src/app/shared/helpers/tuple.ts new file mode 100644 index 0000000..541a250 --- /dev/null +++ b/client/src/app/shared/helpers/tuple.ts @@ -0,0 +1,15 @@ +export class Tuple { + constructor(public first: T, public second: U) {} + + public get(): [T, U] { + return [this.first, this.second]; + } + + public switchGet(elem: any): any{ + if(elem == this.first){ + return this.second; + } else { + return this.first; + } + } +} diff --git a/server/data/data.go b/server/data/data.go index d37d53b..a74285e 100644 --- a/server/data/data.go +++ b/server/data/data.go @@ -18,18 +18,25 @@ import ( ) type RecipeWithTimeStamps struct { - Recipe models.Recipe + Recipe map[string]*models.Recipe TimeStamps int64 } type Data struct { - CurrentFile string - CurrentCountryID string - AllRecipeFiles map[string][]helpers.RecipePath - currentRecipe *models.Recipe - recipeMap map[string]RecipeWithTimeStamps - Countries []helpers.CountryName - taoLogger *logger.TaoLogger + CurrentFile map[string]string + CurrentCountryID map[string]string + DefaultCountryMap []DefaultByCountry + AllRecipeFiles map[string][]helpers.RecipePath + currentRecipe map[string]*models.Recipe + recipeMap map[string]RecipeWithTimeStamps + Countries []helpers.CountryName + taoLogger *logger.TaoLogger +} + +type DefaultByCountry struct { + CountryShortName string + CountryLongName string + DefaultFileVersion int } var ( @@ -51,99 +58,165 @@ func NewData(taoLogger *logger.TaoLogger) *Data { allRecipeFiles := helpers.ScanRecipeFiles(countries) defaultFile := "coffeethai02_600.json" - defaultCountry := "tha" - // TODO: read 'version' file - versionPath := path.Join("cofffeemachineConfig", defaultCountry, "version") - taoLogger.Log.Debug("version", zap.Any("version path", versionPath)) + // TODO: read 'version' file by country - // versionFile, err := os.Open(versionPath) - content, err := os.ReadFile(versionPath) + // versionPath := path.Join("cofffeemachineConfig", defaultCountry, "version") + // taoLogger.Log.Debug("version", zap.Any("version path", versionPath)) - if err != nil { - taoLogger.Log.Debug("Error when open version file", zap.Error(err)) - } + // // versionFile, err := os.Open(versionPath) + // content, err := os.ReadFile(versionPath) - initVersion := string(content) + // if err != nil { + // taoLogger.Log.Debug("Error when open version file", zap.Error(err)) + // } - // read latest version - // set latest to default version - latest_version, err := strconv.Atoi(initVersion) + // initVersion := string(content) - if err != nil { - latest_version = 600 - } + // // read latest version + // // set latest to default version + // latest_version, err := strconv.Atoi(initVersion) - for _, v := range allRecipeFiles[defaultCountry] { + // if err != nil { + // latest_version = 600 + // } - // extract filename as version - current_version_iter, err := strconv.Atoi(strings.Split(strings.Split(v.Name, "_")[1], ".")[0]) + defaultForEachCountry := []DefaultByCountry{} + for _, elem := range countries { + // generate default of all countries + currentVersionPath := path.Join("cofffeemachineConfig", elem.CountryID, "version") + // this is default version for each country + content, err := os.ReadFile(currentVersionPath) if err != nil { - continue + taoLogger.Log.Debug("Error when open version file", zap.Error(err)) } - if current_version_iter == latest_version { - // taoLogger.Log.Debug("current_version_iter", zap.Any("current_version_iter", current_version_iter)) - // set latest - latest_version = current_version_iter - defaultFile = v.Name - break + initVersion := string(content) + + // read latest version + latest_version, _ := strconv.Atoi(initVersion) + defaultForEachCountry = append(defaultForEachCountry, DefaultByCountry{CountryShortName: elem.CountryID, CountryLongName: elem.CountryName, DefaultFileVersion: latest_version}) + } + + currentFileMap := make(map[string]string) + CurrentCountryIDMap := make(map[string]string) + currentDefaultFileForEachCountry := make(map[string]*models.Recipe) + + // all default versions as string + versionsString := "" + + // loop default for each country + + for _, v := range defaultForEachCountry { + + for _, v2 := range allRecipeFiles[v.CountryShortName] { + + // extract filename as version + current_version_iter, err := strconv.Atoi(strings.Split(strings.Split(v2.Name, "_")[1], ".")[0]) + + if err != nil { + continue + } + + if current_version_iter == v.DefaultFileVersion { + currentFileMap[v.CountryShortName] = v2.Name + CurrentCountryIDMap[v.CountryShortName] = v.CountryLongName + + versionsString = versionsString + v.CountryShortName + ":" + strconv.Itoa(current_version_iter) + "," + + // do read default + defaultRecipe, err := helpers.ReadRecipeFile(v.CountryShortName, v2.Name) + if err != nil { + log.Panic("Error when read default recipe file for each country:", v.CountryShortName, err) + } + + currentDefaultFileForEachCountry[v.CountryShortName] = defaultRecipe + break + } } } - taoLogger.Log.Debug("defaultFile", zap.Any("defaultFile", defaultFile), zap.Any("latest_version", latest_version)) + // for _, v := range allRecipeFiles[defaultCountry] { - defaultRecipe, err := helpers.ReadRecipeFile(defaultCountry, defaultFile) + // // extract filename as version + // current_version_iter, err := strconv.Atoi(strings.Split(strings.Split(v.Name, "_")[1], ".")[0]) - if err != nil { - log.Panic("Error when read default recipe file:", err) - } + // if err != nil { + // continue + // } + + // if current_version_iter == latest_version { + // // taoLogger.Log.Debug("current_version_iter", zap.Any("current_version_iter", current_version_iter)) + // // set latest + // latest_version = current_version_iter + // defaultFile = v.Name + // break + // } + // } + + // FIXME: default file bug. do assign each default recipe model to each country + + // taoLogger.Log.Debug("defaultFile", zap.Any("defaultFile", defaultFile), zap.Any("latest_version", versionsString)) + + // defaultRecipe, err := helpers.ReadRecipeFile(defaultCountry, defaultFile) + + // if err != nil { + // log.Panic("Error when read default recipe file:", err) + // } return &Data{ - CurrentFile: defaultFile, - CurrentCountryID: defaultCountry, + CurrentFile: currentFileMap, + CurrentCountryID: CurrentCountryIDMap, AllRecipeFiles: allRecipeFiles, - currentRecipe: defaultRecipe, + currentRecipe: currentDefaultFileForEachCountry, recipeMap: map[string]RecipeWithTimeStamps{ defaultFile: { - Recipe: *defaultRecipe, + Recipe: currentDefaultFileForEachCountry, TimeStamps: time.Now().Unix(), }, }, - Countries: countries, - taoLogger: taoLogger, + Countries: countries, + taoLogger: taoLogger, + DefaultCountryMap: defaultForEachCountry, } } func (d *Data) GetRecipe(countryID, filename string) *models.Recipe { + d.taoLogger.Log.Debug("invoke GetRecipe", zap.String("countryID", countryID), zap.String("filename", filename)) + if countryID == "" { - return d.currentRecipe + return d.currentRecipe["tha"] } - if filename == "" || filename == d.CurrentFile { - return d.currentRecipe + if filename == "" || filename == d.CurrentFile[countryID] { + return d.currentRecipe[countryID] } if recipe, ok := d.recipeMap[filename]; ok { - d.CurrentFile = filename - d.CurrentCountryID = countryID - return &recipe.Recipe + d.CurrentFile[countryID] = filename + // d.CurrentCountryID[countryID] = countryID + return recipe.Recipe[countryID] } // change current version and read new recipe - d.CurrentFile = filename + + if filename == "default" { + filename = d.CurrentFile[countryID] + } + + // d.CurrentFile[countryID] = filename d.taoLogger.Log.Debug("GetRecipe", zap.String("filename", filename), zap.String("countryID", countryID)) - d.CurrentCountryID = countryID + // d.CurrentCountryID[countryID] = countryID recipe, err := helpers.ReadRecipeFile(countryID, filename) if err != nil { - d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) - return d.currentRecipe + d.taoLogger.Log.Error("GetRecipe: Error when read recipe file, Return default recipe", zap.Error(err)) + return d.currentRecipe[countryID] } - d.currentRecipe = recipe + d.currentRecipe[countryID] = recipe // save to map if len(d.recipeMap) > 5 { // limit keep in memory 5 version @@ -160,47 +233,73 @@ func (d *Data) GetRecipe(countryID, filename string) *models.Recipe { } d.recipeMap[filename] = RecipeWithTimeStamps{ - Recipe: *d.currentRecipe, + Recipe: d.currentRecipe, TimeStamps: time.Now().Unix(), } - return d.currentRecipe + return d.currentRecipe[countryID] } -func (d *Data) GetRecipe01() []models.Recipe01 { - return d.currentRecipe.Recipe01 -} +// func (d *Data) GetRecipe01() []models.Recipe01 { +// return d.currentRecipe.Recipe01 +// } -func (d *Data) GetCurrentRecipe() *models.Recipe { - return d.currentRecipe -} +// func (d *Data) GetCurrentRecipe() *models.Recipe { +// return d.currentRecipe +// } func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string) (models.Recipe01, error) { - if !strings.Contains(filename, "tmp") { - if filename == "" || filename == d.CurrentFile { - fmt.Println("GetRecipe01ByProductCode.ReadCurrent", filename, d.CurrentFile) - for _, v := range d.currentRecipe.Recipe01 { - if v.ProductCode == productCode { - return v, nil - } - } - } else if recipe, ok := d.recipeMap[filename]; ok { - fmt.Println("GetRecipe01ByProductCode.ReadMap", filename, d.CurrentFile) - for _, v := range recipe.Recipe.Recipe01 { - if v.ProductCode == productCode { - return v, nil - } + // try convert + if len(countryID) != 3 { + for k, v := range d.CurrentCountryID { + fmt.Println("GetRecipe01ByProductCode.Iterate", k, v, v == countryID) + if v == countryID { + countryID = k + break } } } + fmt.Println("GetRecipe01ByProductCode", filename, countryID, productCode) - d.CurrentFile = filename - d.CurrentCountryID = countryID + if !strings.Contains(filename, "tmp") { + if filename == "" || filename == d.CurrentFile[countryID] { + // , d.CurrentFile, countryID, "result by country id", len(d.currentRecipe[countryID].Recipe01) + fmt.Println("GetRecipe01ByProductCode.ReadCurrent::filename", filename) + fmt.Println("GetRecipe01ByProductCode.ReadCurrent::countryID", countryID) + fmt.Println("GetRecipe01ByProductCode.ReadCurrent::CurrentFile", d.CurrentFile) + fmt.Println("GetRecipe01ByProductCode.ReadCurrent::CurrentCountryID", d.CurrentCountryID) + + for _, v := range d.currentRecipe[countryID].Recipe01 { + if v.ProductCode == productCode { + return v, nil + } + } + fmt.Println("No result in current recipe", countryID) + } else if recipe, ok := d.recipeMap[filename]; ok { + fmt.Println("GetRecipe01ByProductCode.ReadMap", filename, d.CurrentFile, recipe.Recipe[countryID], "countryID=", countryID) + for _, v := range recipe.Recipe[countryID].Recipe01 { + if v.ProductCode == productCode { + d.taoLogger.Log.Debug("GetRecipe01ByProductCode.getSuccess", zap.Any("fromFile", filename), zap.Any("whereSource", d.recipeMap)) + return v, nil + } + } + d.taoLogger.Log.Debug("GetRecipe01ByProductCode.getFail", zap.Any("fromFile", filename), zap.Any("whereSource", d.recipeMap)) + } + } + + d.taoLogger.Log.Debug("GetRecipe01ByProductCode", zap.Any("filename", filename), zap.Any("countryID", countryID), zap.Any("productCode", productCode)) + + if filename == "default" { + filename = d.CurrentFile[countryID] + } + + // d.CurrentFile[countryID] = filename + // d.CurrentCountryID[countryID] = countryID for _, v := range countries { if v.CountryName == countryID { - d.CurrentCountryID = v.CountryID + // d.CurrentCountryID[countryID] = v.CountryID countryID = v.CountryID break } @@ -209,8 +308,8 @@ func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string) recipe, err := helpers.ReadRecipeFile(countryID, filename) if err != nil { - d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) - for _, v := range d.currentRecipe.Recipe01 { + d.taoLogger.Log.Error("GetRecipe01ByProductCode: Error when read recipe file, Return default recipe", zap.Error(err)) + for _, v := range d.currentRecipe[countryID].Recipe01 { if v.ProductCode == productCode { return v, nil } @@ -219,7 +318,7 @@ func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string) d.taoLogger.Log.Debug("GetRecipe01ByProductCode", zap.Any("productCode", productCode), zap.Any("version", recipe.MachineSetting.ConfigNumber)) - d.currentRecipe = recipe + d.currentRecipe[countryID] = recipe // save to map if len(d.recipeMap) > 5 { // limit keep in memory 5 version @@ -236,11 +335,11 @@ func (d *Data) GetRecipe01ByProductCode(filename, countryID, productCode string) } d.recipeMap[filename] = RecipeWithTimeStamps{ - Recipe: *d.currentRecipe, + Recipe: d.currentRecipe, TimeStamps: time.Now().Unix(), } - for _, v := range d.currentRecipe.Recipe01 { + for _, v := range d.currentRecipe[countryID].Recipe01 { if v.ProductCode == productCode { // d.taoLogger.Log.Debug("GetRecipe01ByProductCode", zap.Any("productCode", productCode), zap.Any("result", v)) return v, nil @@ -290,38 +389,44 @@ func (d *Data) GetMaterialSetting(countryID, filename string) []models.MaterialS result := make([]models.MaterialSetting, 0) if countryID == "" { - copy(result, d.currentRecipe.MaterialSetting) + copy(result, d.currentRecipe[countryID].MaterialSetting) return result } if !strings.Contains(filename, "tmp") { - if filename == "" || filename == d.CurrentFile { - copy(result, d.currentRecipe.MaterialSetting) - d.taoLogger.Log.Debug("GetMaterialSetting", zap.Any("result", result)) - return d.currentRecipe.MaterialSetting + if filename == "" || filename == d.CurrentFile[countryID] { + // copy(result, d.currentRecipe[countryID].MaterialSetting) + // d.taoLogger.Log.Debug("GetMaterialSetting", zap.Any("result", result)) + return d.currentRecipe[countryID].MaterialSetting } if recipe, ok := d.recipeMap[filename]; ok { - copy(result, recipe.Recipe.MaterialSetting) - d.CurrentFile = filename - d.CurrentCountryID = countryID - return d.currentRecipe.MaterialSetting + copy(result, recipe.Recipe[countryID].MaterialSetting) + d.CurrentFile[countryID] = filename + // d.CurrentCountryID[countryID] = countryID + return d.currentRecipe[countryID].MaterialSetting } } - d.CurrentFile = filename - d.CurrentCountryID = countryID + if filename == "default" { + filename = d.CurrentFile[countryID] + } + + // d.taoLogger.Log.Debug("GetMaterialSetting", zap.Any("filename", filename), zap.Any("countryID", countryID)) + + // d.CurrentFile[countryID] = filename + // d.CurrentCountryID[countryID] = countryID recipe, err := helpers.ReadRecipeFile(countryID, filename) if err != nil { - d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) - copy(result, d.currentRecipe.MaterialSetting) - return d.currentRecipe.MaterialSetting + d.taoLogger.Log.Error("GetMaterialSetting: Error when read recipe file, Return default recipe", zap.Error(err)) + copy(result, d.currentRecipe[countryID].MaterialSetting) + return d.currentRecipe[countryID].MaterialSetting } - d.taoLogger.Log.Debug("GetMaterialSetting", zap.Any("recipe", recipe.MaterialSetting)) + // d.taoLogger.Log.Debug("GetMaterialSetting", zap.Any("recipe", recipe.MaterialSetting)) - d.currentRecipe = recipe + d.currentRecipe[countryID] = recipe // save to map if len(d.recipeMap) > 5 { // limit keep in memory 5 version @@ -338,7 +443,7 @@ func (d *Data) GetMaterialSetting(countryID, filename string) []models.MaterialS } d.recipeMap[filename] = RecipeWithTimeStamps{ - Recipe: *d.currentRecipe, + Recipe: d.currentRecipe, TimeStamps: time.Now().Unix(), } @@ -349,22 +454,27 @@ func (d *Data) GetMaterialSetting(countryID, filename string) []models.MaterialS func (d *Data) GetMaterialCode(ids []uint64, countryID, filename string) []models.MaterialCode { var result []models.MaterialCode - if filename == "" || filename == d.CurrentFile { - result = d.currentRecipe.MaterialCode + if filename == "" || filename == d.CurrentFile[countryID] { + result = d.currentRecipe[countryID].MaterialCode } else if recipe, ok := d.recipeMap[filename]; ok { - d.CurrentFile = filename - return recipe.Recipe.MaterialCode + d.CurrentFile[countryID] = filename + return recipe.Recipe[countryID].MaterialCode } else { - d.CurrentFile = filename - d.CurrentCountryID = countryID + + if filename == "default" { + filename = d.CurrentFile[countryID] + } + + // d.CurrentFile[countryID] = filename + // d.CurrentCountryID[countryID] = countryID recipe, err := helpers.ReadRecipeFile(countryID, filename) if err != nil { - d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) - return d.currentRecipe.MaterialCode + d.taoLogger.Log.Error("GetMaterialCode: Error when read recipe file, Return default recipe", zap.Error(err)) + return d.currentRecipe[countryID].MaterialCode } - d.currentRecipe = recipe + d.currentRecipe[countryID] = recipe // save to map if len(d.recipeMap) > 5 { // limit keep in memory 5 version @@ -381,11 +491,11 @@ func (d *Data) GetMaterialCode(ids []uint64, countryID, filename string) []model } d.recipeMap[filename] = RecipeWithTimeStamps{ - Recipe: *d.currentRecipe, + Recipe: d.currentRecipe, TimeStamps: time.Now().Unix(), } - result = d.currentRecipe.MaterialCode + result = d.currentRecipe[countryID].MaterialCode } if len(ids) == 0 { @@ -411,31 +521,41 @@ func (d *Data) GetMaterialCode(ids []uint64, countryID, filename string) []model func (d *Data) GetToppings(countryID, filename string) models.Topping { - if filename == "" || filename == d.CurrentFile { - return d.currentRecipe.Topping + if filename == "" || filename == d.CurrentFile[countryID] { + return d.currentRecipe[countryID].Topping } else if recipe, ok := d.recipeMap[filename]; ok { - d.CurrentFile = filename - return recipe.Recipe.Topping + d.CurrentFile[countryID] = filename + return recipe.Recipe[countryID].Topping } - d.CurrentFile = filename - d.CurrentCountryID = countryID + + if filename == "default" { + filename = d.CurrentFile[countryID] + } + + // d.CurrentFile[countryID] = filename + // d.CurrentCountryID[countryID] = countryID recipe, err := helpers.ReadRecipeFile(countryID, filename) if err != nil { - d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) - return d.currentRecipe.Topping + d.taoLogger.Log.Error("GetToppings: Error when read recipe file, Return default recipe", zap.Error(err)) + return d.currentRecipe[countryID].Topping } - d.currentRecipe = recipe + d.currentRecipe[countryID] = recipe return recipe.Topping } func (d *Data) GetToppingsOfRecipe(countryID, filename string, productCode string) ([]models.ToppingSet, error) { + + if filename == "default" { + filename = d.CurrentFile[countryID] + } + recipe, err := d.GetRecipe01ByProductCode(filename, countryID, productCode) if err != nil { - d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) + d.taoLogger.Log.Error("GetToppingOfRecipe: Error when read recipe file, Return default recipe", zap.Error(err)) return []models.ToppingSet{}, err } @@ -443,10 +563,15 @@ func (d *Data) GetToppingsOfRecipe(countryID, filename string, productCode strin } func (d *Data) GetSubmenusOfRecipe(countryID, filename, productCode string) ([]models.Recipe01, error) { + + if filename == "default" { + filename = d.CurrentFile[countryID] + } + recipe, err := d.GetRecipe01ByProductCode(filename, countryID, productCode) if err != nil { - d.taoLogger.Log.Error("Error when read recipe file, Return default recipe", zap.Error(err)) + d.taoLogger.Log.Error("GetSubmenusOfRecipe: Error when read recipe file, Return default recipe", zap.Error(err)) return []models.Recipe01{}, err } diff --git a/server/data/sqlite.go b/server/data/sqlite.go index 2124f42..2007dee 100644 --- a/server/data/sqlite.go +++ b/server/data/sqlite.go @@ -1,11 +1,23 @@ package data import ( + "fmt" + "os" + "github.com/jmoiron/sqlx" _ "github.com/mattn/go-sqlite3" ) func NewSqliteDatabase() *sqlx.DB { + + // ensure that database exists + info, err := os.Stat("./data/database.db") + if os.IsNotExist(err) { + fmt.Println("No database found. Check path: ", err) + } else { + fmt.Println("Database existed. ", info) + } + db := sqlx.MustConnect("sqlite3", "./data/database.db") return db } diff --git a/server/routers/material.go b/server/routers/material.go index bd4ba48..c5ce714 100644 --- a/server/routers/material.go +++ b/server/routers/material.go @@ -75,17 +75,7 @@ func (mr *MaterialRouter) GetFullMaterialDetail(w http.ResponseWriter, r *http.R }) } - // for _, matCode := range matCodes { - // for index, matDetail := range materialDetails { - // if matCode.MaterialID == matDetail["materialId"] { - // materialDetails[index]["name"] = matCode.PackageDescription - // } else if matDetail["materialId"].(uint64) > 8110 && matDetail["materialId"].(uint64) <= 8130 { - // slotNum := matDetail["materialId"].(uint64) - 8110 - // // mr.taoLogger.Log.Debug("GetFullMaterialDetail", zap.Any("slotNum", matDetail["materialId"]), zap.Any("slotNum", slotNum)) - // materialDetails[index]["name"] = "Topping" + strconv.Itoa(int(slotNum)) - // } - // } - // } + mr.taoLogger.Log.Debug("GetFullMaterialDetail", zap.Any("materialDetails", materialDetails[0])) // send result if err := json.NewEncoder(w).Encode(materialDetails); err != nil { @@ -141,7 +131,7 @@ func (mr *MaterialRouter) getMaterialSettingByMatID(w http.ResponseWriter, r *ht countryID, err := mr.data.GetCountryIDByName(country) if err != nil { - mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err)) + // mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err)) http.Error(w, "Country not found", http.StatusNotFound) return } @@ -152,7 +142,7 @@ func (mr *MaterialRouter) getMaterialSettingByMatID(w http.ResponseWriter, r *ht matIDuint, err := strconv.ParseUint(matID, 10, 64) if err != nil { - mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err)) + // mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err)) http.Error(w, "Invalid material id", http.StatusBadRequest) return } @@ -167,7 +157,7 @@ func (mr *MaterialRouter) getMaterialSettingByMatID(w http.ResponseWriter, r *ht } if err := json.NewEncoder(w).Encode(matSetting); err != nil { - mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err)) + // mr.taoLogger.Log.Error("MaterialRouter.GetMaterialSettingByMatID", zap.Error(err)) http.Error(w, "Internal Error", http.StatusInternalServerError) return } diff --git a/server/routers/recipe.go b/server/routers/recipe.go index f1a6aae..f0a5886 100644 --- a/server/routers/recipe.go +++ b/server/routers/recipe.go @@ -173,6 +173,8 @@ func (rr *RecipeRouter) dashBoard(w http.ResponseWriter, r *http.Request) { country := r.URL.Query().Get("country") filename := r.URL.Query().Get("filename") + rr.taoLogger.Log.Debug("RecipeRouter.Dashboard", zap.Any("country", country), zap.Any("filename", filename)) + result, err := rr.recipeService.GetRecipeDashboard(&contracts.RecipeDashboardRequest{ Country: country, Filename: filename, @@ -205,6 +207,8 @@ func (rr *RecipeRouter) overview(w http.ResponseWriter, r *http.Request) { filename := r.URL.Query().Get("filename") materialIds := r.URL.Query().Get("materialIds") + rr.taoLogger.Log.Debug("RecipeRouter.Overview", zap.Any("take", take), zap.Any("offset", offset), zap.Any("country", country), zap.Any("filename", filename), zap.Any("materialIds", materialIds)) + var materialIdsUint []int for _, v := range strings.Split(materialIds, ",") { materialIdUint, err := strconv.ParseUint(v, 10, 64) diff --git a/server/services/recipe/recipe.go b/server/services/recipe/recipe.go index ef70f73..675d6ca 100644 --- a/server/services/recipe/recipe.go +++ b/server/services/recipe/recipe.go @@ -67,7 +67,7 @@ func (rs *recipeService) GetRecipeDetailMat(request *contracts.RecipeDetailReque return contracts.RecipeDetailMatListResponse{}, fmt.Errorf("country name: %s not found", request.Country) } - // rs.taoLogger.Log.Debug("GetRecipeDetailMat", zap.Any("request", request)) + rs.taoLogger.Log.Debug("GetRecipeDetailMat", zap.Any("request", request)) recipe, err := rs.db.GetRecipe01ByProductCode(request.Filename, request.Country, request.ProductCode) @@ -186,6 +186,16 @@ func (rs *recipeService) GetRecipeDashboard(request *contracts.RecipeDashboardRe recipe := rs.db.GetRecipe(countryID, request.Filename) + // recheck if filename is `default` + + if request.Filename == "default" { + for _, v := range rs.db.DefaultCountryMap { + if v.CountryShortName == request.Country || v.CountryLongName == request.Country { + request.Filename = rs.db.CurrentFile[v.CountryShortName] + } + } + } + result := contracts.RecipeDashboardResponse{ ConfigNumber: recipe.MachineSetting.ConfigNumber, LastUpdated: recipe.Timestamp,