Merge branch 'main' of github.com:Poomipat-Ch/taobin_recipe_manager
This commit is contained in:
commit
45851422f7
20 changed files with 1216 additions and 593 deletions
|
|
@ -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<MaterialCode[]> {
|
||||
): Promise<Observable<MaterialCode[]>> {
|
||||
|
||||
// async country
|
||||
let asyncCountry = await AsyncStorage.getItem<string>('currentRecipeCountry');
|
||||
|
||||
return this._httpClient.get<MaterialCode[]>(
|
||||
`${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<Observable<{
|
||||
"materialId": number,
|
||||
"name": string,
|
||||
"type": string
|
||||
}[] | null>{
|
||||
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<MaterialSetting> {
|
||||
): Promise<Observable<MaterialSetting>> {
|
||||
|
||||
let asyncCountry = await AsyncStorage.getItem<string>('currentRecipeCountry');
|
||||
|
||||
return this._httpClient.get<MaterialSetting>(
|
||||
`${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<string> {
|
||||
|
||||
// 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<string>('currentRecipeCountry');
|
||||
|
||||
if (currentRecipeCountry) {
|
||||
return currentRecipeCountry;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<RecipesDashboard> {
|
||||
|
|
@ -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<RecipeOverviewList> {
|
||||
): Promise<Observable<RecipeOverviewList>> {
|
||||
return this._httpClient.get<RecipeOverviewList>(
|
||||
environment.api + '/recipes/overview',
|
||||
{
|
||||
|
|
@ -90,13 +95,17 @@ export class RecipeService {
|
|||
);
|
||||
}
|
||||
|
||||
getRecipeDetail(productCode: string): Observable<RecipeDetail> {
|
||||
async getRecipeDetail(productCode: string): Promise<Observable<RecipeDetail>> {
|
||||
|
||||
let asyncCountry = await this.getCurrentCountry(this.department!);
|
||||
console.log('get detail by asyncCountry', asyncCountry);
|
||||
|
||||
return this._httpClient.get<RecipeDetail>(
|
||||
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<Observable<{ result: RecipeDetailMat[]; }>> {
|
||||
|
||||
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<string> {
|
||||
|
||||
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<string>('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<Recipe01[]>(
|
||||
environment.api +
|
||||
'/recipes/' +
|
||||
|
|
|
|||
|
|
@ -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<Topping> {
|
||||
async getToppings(country: string, filename: string): Promise<Observable<Topping>> {
|
||||
console.log("getToppings", country);
|
||||
let asyncCountry = await this._recipeService.getCurrentCountry();
|
||||
country = getCountryMapSwitcher(asyncCountry);
|
||||
console.log("getToppingsPreFetch", country, asyncCountry);
|
||||
return this._httpClient.get<Topping>(
|
||||
`${environment.api}/recipes/${country}/${filename}/toppings`,
|
||||
{
|
||||
|
|
@ -23,7 +29,11 @@ export class ToppingService {
|
|||
);
|
||||
}
|
||||
|
||||
getToppingsOfRecipe(country: string, filename: string, productCode: string): Observable<ToppingSet[]> {
|
||||
async getToppingsOfRecipe(country: string, filename: string, productCode: string): Promise<Observable<ToppingSet[]>> {
|
||||
console.log("getToppingsOfRecipe", country);
|
||||
let asyncCountry = await this._recipeService.getCurrentCountry();
|
||||
country = country || asyncCountry;
|
||||
console.log("getToppingsOfRecipePreFetch", country, asyncCountry);
|
||||
return this._httpClient.get<ToppingSet[]>(
|
||||
`${environment.api}/recipes/${country}/${filename}/${productCode}/toppings`,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,19 +7,17 @@
|
|||
class="block p-6 bg-white border border-gray-200 rounded-lg shadow w-full"
|
||||
>
|
||||
<div *ngIf="isLoaded; else indicator" [@inOutAnimation]>
|
||||
|
||||
|
||||
<!-- productCode -->
|
||||
<div>
|
||||
<input
|
||||
class="input input-bordered input-xs text-lg text-gray-900 my-2"
|
||||
type="text"
|
||||
name="productCode"
|
||||
[value]="productCode"
|
||||
(keyup)="onProductCodeChange($event)"
|
||||
[disabled]="!isEditable()"
|
||||
/>
|
||||
</div>
|
||||
<!-- productCode -->
|
||||
<div>
|
||||
<input
|
||||
class="input input-bordered input-xs text-lg text-gray-900 my-2"
|
||||
type="text"
|
||||
name="productCode"
|
||||
[value]="productCode"
|
||||
(keyup)="onProductCodeChange($event)"
|
||||
[disabled]="!isEditable()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<h5 class="mb-2 text-xl font-bold text-gray-900">
|
||||
|
|
@ -29,7 +27,6 @@
|
|||
<h5 class="mb-2 text-xl font-bold text-gray-900">
|
||||
{{ recipeDetailForm.getRawValue().otherName }}
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
<div class="flex items-center mb-2">
|
||||
<div class="flex items-center">
|
||||
|
|
@ -110,7 +107,12 @@
|
|||
|
||||
<div *ngIf="hasSubmenu()">
|
||||
<div *ngFor="let sub of listSubMenuProductcodes()">
|
||||
<button class="btn btn-sm btn-primary m-2" (click)="selectSubmenu(sub)">{{sub}}</button>
|
||||
<button
|
||||
class="btn btn-sm btn-primary m-2"
|
||||
(click)="selectSubmenu(sub)"
|
||||
>
|
||||
{{ sub }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -118,45 +120,52 @@
|
|||
</div>
|
||||
<div id="recipeList" class="carousel-item w-full">
|
||||
<div
|
||||
class="overflow-auto h-[75vh] mb-4 rounded bg-white border border-gray-200 shadow w-1/2"
|
||||
>
|
||||
<app-recipe-list
|
||||
[productCode]="productCode"
|
||||
[isSubMenu]="false"
|
||||
(recipeListFormChange)="onRecipeListFormChange($event)"
|
||||
></app-recipe-list>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="toppingSet" class="carousel-item w-full">
|
||||
|
||||
<div class="overflow-auto h-[75vh] mb-4 rounded bg-white border border-gray-200 shadow">
|
||||
|
||||
<app-recipe-toppingset
|
||||
[productCode]="productCode"
|
||||
(toppingSetChange)="onToppingListChange($event)"
|
||||
></app-recipe-toppingset>
|
||||
|
||||
class="overflow-auto h-[75vh] mb-4 rounded bg-white border border-gray-200 shadow"
|
||||
>
|
||||
<app-recipe-list
|
||||
[productCode]="productCode"
|
||||
[isSubMenu]="false"
|
||||
(recipeListFormChange)="onRecipeListFormChange($event)"
|
||||
></app-recipe-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div id="toppingSet" class="carousel-item w-full">
|
||||
<div
|
||||
class="overflow-auto h-[75vh] mb-4 rounded bg-white border border-gray-200 shadow max-w-screen-xl"
|
||||
>
|
||||
<app-recipe-toppingset
|
||||
[productCode]="productCode"
|
||||
(toppingSetChange)="onToppingListChange($event)"
|
||||
></app-recipe-toppingset>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- try pop up modal -->
|
||||
|
||||
|
||||
<!-- TODO: do topping -->
|
||||
|
||||
<div
|
||||
class="sticky bottom-0 col-span-3 max-w-screen-lg flex justify-end bg-white rounded-full drop-shadow-2xl p-3"
|
||||
>
|
||||
|
||||
<div class="flex justify-center w-full start-0 py-2">
|
||||
<a href="{{department}}/recipe/{{productCode}}#name" class="btn btn-xs">1</a>
|
||||
<a href="{{department}}/recipe/{{productCode}}#recipeList" class="btn btn-xs">2</a>
|
||||
<a href="{{department}}/recipe/{{productCode}}#toppingSet" class="btn btn-xs">3</a>
|
||||
</div>
|
||||
<div class="flex justify-center w-full start-0 py-2">
|
||||
<a
|
||||
href="{{ department }}/recipe/{{ productCode }}#name"
|
||||
class="btn btn-xs"
|
||||
>1</a
|
||||
>
|
||||
<a
|
||||
href="{{ department }}/recipe/{{ productCode }}#recipeList"
|
||||
class="btn btn-xs"
|
||||
>2</a
|
||||
>
|
||||
<a
|
||||
href="{{ department }}/recipe/{{ productCode }}#toppingSet"
|
||||
class="btn btn-xs"
|
||||
>3</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- <div> Commit Message </div> -->
|
||||
<!-- <p class="text-2xl mr-8 text-gray-400 dark:text-gray-500">Commit Message</p> -->
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
<th class="px-6 py-3">Is Use</th>
|
||||
<th class="px-6 py-3">Material ID</th>
|
||||
<th class="px-6 py-3">Material Name</th>
|
||||
<th class="px-6 py-3">Settings</th>
|
||||
<th class="px-6 py-3">Volume</th>
|
||||
<th class="">Settings</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
|
|
@ -12,129 +13,140 @@
|
|||
*ngFor="let mat of recipeListData.controls; let i = index"
|
||||
>
|
||||
<tr
|
||||
class="bg-white la border-b hover:bg-secondary"
|
||||
class="bg-white border-b hover:bg-secondary max-h-4"
|
||||
formGroupName="{{ i }}"
|
||||
(mousedown)="initHoldEvent()"
|
||||
(mouseup)="openRecipeListEditor(i)"
|
||||
>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<td class="font-medium text-gray-900 whitespace-nowrap sticky left-0">
|
||||
<input type="checkbox" class="toggle" formControlName="isUse" />
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<td class="font-medium text-gray-900 whitespace-nowrap sticky">
|
||||
<input
|
||||
type="text"
|
||||
class="input"
|
||||
class="input w-20"
|
||||
formControlName="materialPathId"
|
||||
(click)="openMaterialList(i)"
|
||||
/>
|
||||
</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap">
|
||||
<td class="font-medium text-gray-900 whitespace-nowrap sticky">
|
||||
<input type="text" class="input" formControlName="name" />
|
||||
</td>
|
||||
<!-- powder -->
|
||||
<!-- <div *ngIf="getTypeForRecipeListAtIndex(i)['category'] == 'powder'">
|
||||
|
||||
</div> -->
|
||||
|
||||
<td
|
||||
class="m-2 px-4 py-4 font-medium text-gray-900 whitespace-nowrap"
|
||||
class="font-medium text-gray-900 whitespace-nowrap"
|
||||
*ngIf="
|
||||
displayByCond(i, 'powderGram', 'not-zero', { compare: undefined })
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="flex justify-center items-center space-x-2 bg-purple-300 rounded-md"
|
||||
class="flex justify-center items-center space-x-2 bg-purple-300 rounded-md p-2"
|
||||
>
|
||||
<p>Volume</p>
|
||||
<input type="text" class="input w-16" formControlName="powderGram" />
|
||||
<input type="text" class="bg-transparent w-8" formControlName="powderGram" />
|
||||
<p>gram</p>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td
|
||||
class="m-2 px-4 py-4 font-medium text-gray-900 whitespace-nowrap"
|
||||
*ngIf="
|
||||
displayByCond(i, 'syrupGram', 'not-zero', { compare: undefined }) &&
|
||||
getTypeForRecipeListAtIndex(i)['category'] == 'syrup'
|
||||
"
|
||||
class="font-medium text-gray-900 whitespace-nowrap"
|
||||
*ngIf="displayByCond(i, 'powderGram', 'zero', { compare: undefined })"
|
||||
>
|
||||
<div class="flex items-center space-x-2 bg-purple-300 rounded-md">
|
||||
<div
|
||||
class="flex items-center space-x-2 bg-purple-300 rounded-md p-2"
|
||||
*ngIf="
|
||||
displayByCond(i, 'syrupGram', 'not-zero', { compare: undefined }) &&
|
||||
getTypeForRecipeListAtIndex(i)['category'] == 'syrup'
|
||||
"
|
||||
>
|
||||
<p>Volume</p>
|
||||
<input type="text" class="input w-16" formControlName="syrupGram" />
|
||||
<input type="text" class="bg-transparent w-8" formControlName="syrupGram" />
|
||||
<p>gram</p>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="m-2 px-4 py-4 space-y-2 font-medium text-gray-900 whitespace-nowrap"
|
||||
>
|
||||
<div class="flex items-center justify-center space-x-4 bg-gray-200">
|
||||
<div
|
||||
class="flex items-center rounded-md"
|
||||
*ngIf="isStringParamExist(i)"
|
||||
>
|
||||
<div
|
||||
class="flex items-center rounded-md "
|
||||
*ngFor="let param of getStringParamOfIndex(i)"
|
||||
>
|
||||
<!-- <p> </p> -->
|
||||
<p *ngIf="param.pkey == 'notail'">tail</p>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-bordered w-16"
|
||||
placeholder="{{ param.pvalue }}"
|
||||
(click)="openStringParamEditor(i)"
|
||||
/>
|
||||
<p class="m-4" *ngIf="param.pkey == 'esp-v2-press-value'">
|
||||
mA
|
||||
</p>
|
||||
<td class="font-medium text-gray-900 whitespace-nowrap">
|
||||
<div class="flex flex-row p-2 space-x-3">
|
||||
<div class="flex items-center justify-center bg-gray-200">
|
||||
<div class="items-center rounded-md" *ngIf="isStringParamExist(i)">
|
||||
<div
|
||||
class="flex items-center rounded-md tooltip"
|
||||
[attr.data-tip]="param.pkey"
|
||||
*ngFor="let param of getStringParamOfIndex(i)"
|
||||
>
|
||||
<!-- <p> </p> -->
|
||||
<p *ngIf="param.pkey == 'notail'">tail</p>
|
||||
<input
|
||||
type="text"
|
||||
class="w-8 bg-transparent"
|
||||
placeholder="{{ param.pvalue }}"
|
||||
(click)="openStringParamEditor(i)"
|
||||
/>
|
||||
<p *ngIf="param.pkey == 'esp-v2-press-value'">mA</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center space-x-2 rounded-md bg-red-200"
|
||||
*ngIf="
|
||||
displayByCond(i, 'waterYield', 'not-zero', { compare: undefined })
|
||||
"
|
||||
>
|
||||
<p>Hot</p>
|
||||
<input type="text" class="input w-16" formControlName="waterYield" />
|
||||
<p>ml</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center space-x-2 rounded-md bg-blue-200"
|
||||
*ngIf="
|
||||
displayByCond(i, 'waterCold', 'not-zero', { compare: undefined })
|
||||
"
|
||||
>
|
||||
<p>Cold</p>
|
||||
<input type="text" class="input w-16" formControlName="waterCold" />
|
||||
<p>ml</p>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center justify-center space-x-2 rounded-md bg-green-300"
|
||||
*ngIf="
|
||||
displayByCond(i, 'stirTime', 'not-zero', { compare: undefined }) &&
|
||||
getTypeForRecipeListAtIndex(i)['category'] != 'cup' &&
|
||||
!isTopping(getTypeForRecipeListAtIndex(i)['id'])
|
||||
"
|
||||
>
|
||||
<p *ngIf="getTypeForRecipeListAtIndex(i)['category'] == 'bean'">
|
||||
Grinder
|
||||
</p>
|
||||
<p *ngIf="getTypeForRecipeListAtIndex(i)['category'] == 'whipper'">
|
||||
Mix
|
||||
</p>
|
||||
<p
|
||||
<div
|
||||
class="tooltip flex items-center justify-evenly space-x-2 rounded-md bg-red-200 p-2"
|
||||
data-tip="Hot"
|
||||
*ngIf="
|
||||
getTypeForRecipeListAtIndex(i)['category'] == 'others' &&
|
||||
(getTypeForRecipeListAtIndex(i)['id'] == 8001 ||
|
||||
getTypeForRecipeListAtIndex(i)['id'] == 8002)
|
||||
displayByCond(i, 'waterYield', 'not-zero', { compare: undefined })
|
||||
"
|
||||
>
|
||||
Clean
|
||||
</p>
|
||||
<input type="text" class="input w-16" formControlName="stirTime" />
|
||||
<p>sec</p>
|
||||
<p>Hot</p>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
class="w-8 bg-transparent"
|
||||
formControlName="waterYield"
|
||||
/>
|
||||
<p>ml</p>
|
||||
</div>
|
||||
<div
|
||||
class="tooltip flex items-center justify-center space-x-2 rounded-md bg-blue-200 p-2"
|
||||
data-tip="Cold"
|
||||
*ngIf="
|
||||
displayByCond(i, 'waterCold', 'not-zero', { compare: undefined })
|
||||
"
|
||||
>
|
||||
<p>Cold</p>
|
||||
<input
|
||||
type="text"
|
||||
class="w-8 bg-transparent"
|
||||
formControlName="waterCold"
|
||||
/>
|
||||
<p>ml</p>
|
||||
</div>
|
||||
<div
|
||||
class="tooltip flex items-center justify-center space-x-2 rounded-md bg-green-300 p-2"
|
||||
[attr.data-tip]="
|
||||
getTooltipForStirTime(getTypeForRecipeListAtIndex(i))
|
||||
"
|
||||
*ngIf="
|
||||
displayByCond(i, 'stirTime', 'not-zero', {
|
||||
compare: undefined
|
||||
}) &&
|
||||
getTypeForRecipeListAtIndex(i)['category'] != 'cup' &&
|
||||
!isTopping(getTypeForRecipeListAtIndex(i)['id'])
|
||||
"
|
||||
>
|
||||
<p>{{getTooltipForStirTime(getTypeForRecipeListAtIndex(i))}}</p>
|
||||
<input
|
||||
type="text"
|
||||
class="bg-transparent w-8"
|
||||
formControlName="stirTime"
|
||||
/>
|
||||
<p>sec</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse collapse-open" *ngIf="isTopping(getTypeForRecipeListAtIndex(i)['id'])">
|
||||
<div class="collapse-title">Topping Settings</div>
|
||||
<div class="collapse-content">
|
||||
<app-recipe-topping
|
||||
[productCode]="productCode"
|
||||
[index]="getToppingSlotNumber(getTypeForRecipeListAtIndex(i)['id'])"
|
||||
(toppingSetChange)="onToppingSetChange($event, i)"
|
||||
></app-recipe-topping>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -291,7 +303,11 @@
|
|||
<summary class="cursor-pointer">Water</summary>
|
||||
<div class="flex items-center space-x-2">
|
||||
<p class="text-base m-4">Hot (waterYield)</p>
|
||||
<input type="text" class="input w-16" formControlName="waterYield" />
|
||||
<input
|
||||
type="text"
|
||||
class="input w-16"
|
||||
formControlName="waterYield"
|
||||
/>
|
||||
<p class="text-base m-4">ml</p>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -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<void> {
|
||||
(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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
<div [formGroup]="toppingForm">
|
||||
<div formArrayName="toppingList" *ngFor="let topping of toppingList.controls; let i = index">
|
||||
<div formGroupName="{{ i }}">
|
||||
|
||||
<input type="checkbox" />
|
||||
<!-- toppingGroup -->
|
||||
<ng-select
|
||||
appendTo="body"
|
||||
[clearable]="false"
|
||||
[compareWith]="this.compareFunc"
|
||||
formControlName="groupID"
|
||||
(close)="getDefaultOfGroup(getGroupIdByIndex(i))"
|
||||
>
|
||||
<ng-option
|
||||
*ngFor="let item of allToppingsDefinitions"
|
||||
[value]="item.groupId.toString()"
|
||||
>
|
||||
<div>{{ item.name }} ({{ item.groupId }})</div>
|
||||
</ng-option>
|
||||
</ng-select>
|
||||
<!-- defaultSelect -->
|
||||
<ng-select
|
||||
appendTo="body"
|
||||
[clearable]="false"
|
||||
[compareWith]="this.compareFunc"
|
||||
formControlName="defaultIDSelect"
|
||||
>
|
||||
<ng-option
|
||||
*ngFor="let item of getMembersByGroupId(getGroupIdByIndex(this.index!))"
|
||||
[value]="item.id.toString()"
|
||||
>
|
||||
<div>{{ item.name }} ({{ item.id }})</div>
|
||||
</ng-option>
|
||||
</ng-select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -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<unknown[]>();
|
||||
|
||||
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<void> {
|
||||
// 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);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<table class="table" [formGroup]="toppingForm">
|
||||
<!-- <table class="table" [formGroup]="toppingForm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Slot (Material Id)</th>
|
||||
|
|
@ -48,4 +48,4 @@
|
|||
<!-- ListGroupID -->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</table> -->
|
||||
|
|
|
|||
|
|
@ -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<unknown[]>();
|
||||
// @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<unknown[]>();
|
||||
|
||||
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<void> {
|
||||
// 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();
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -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<RecipesDashboard>;
|
||||
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<void> {
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
client/src/app/shared/helpers/asyncStorage.ts
Normal file
14
client/src/app/shared/helpers/asyncStorage.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
export class AsyncStorage {
|
||||
static async getItem<T>(key: string) {
|
||||
return new Promise<T>((resolve) => {
|
||||
resolve(localStorage.getItem(key) as T);
|
||||
});
|
||||
}
|
||||
|
||||
static async setItem(key: string, value: string) {
|
||||
return new Promise<void>((resolve) => {
|
||||
localStorage.setItem(key, value);
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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<string, string>[] = [
|
||||
new Tuple<string, string>('tha', 'Thailand'),
|
||||
new Tuple<string, string>('mys', 'Malaysia'),
|
||||
new Tuple<string, string>('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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
15
client/src/app/shared/helpers/tuple.ts
Normal file
15
client/src/app/shared/helpers/tuple.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
export class Tuple<T, U> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue