still have some bug about select file
This commit is contained in:
commit
ad32fe38ea
11 changed files with 325 additions and 130 deletions
|
|
@ -93,13 +93,13 @@ const routes: Routes = [
|
||||||
).then((m) => m.RecipeDetailsComponent),
|
).then((m) => m.RecipeDetailsComponent),
|
||||||
canActivate: [authGuard],
|
canActivate: [authGuard],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
path: 'log',
|
// path: 'log',
|
||||||
loadComponent: () =>
|
// loadComponent: () =>
|
||||||
import('./features/changelog/changelog.component').then(
|
// import('./features/changelog/changelog.component').then(
|
||||||
(m) => m.ChangelogComponent
|
// (m) => m.ChangelogComponent
|
||||||
),
|
// ),
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
redirectTo: 'recipes',
|
redirectTo: 'recipes',
|
||||||
|
|
|
||||||
|
|
@ -106,4 +106,20 @@ export class RecipeService {
|
||||||
getRecipeFileNames(country: string): string[] {
|
getRecipeFileNames(country: string): string[] {
|
||||||
return this.recipeFiles[country];
|
return this.recipeFiles[country];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editChanges(version: string, change: any){
|
||||||
|
console.log("target version = ", version);
|
||||||
|
console.log("change in edit: ",change.value)
|
||||||
|
return this._httpClient.post<{
|
||||||
|
status: string
|
||||||
|
}>(
|
||||||
|
environment.api + ('/recipes/edit/'+version),
|
||||||
|
change.value,
|
||||||
|
{ withCredentials: true, responseType: 'json', }
|
||||||
|
).subscribe({
|
||||||
|
next(value) {
|
||||||
|
console.log(value, change.value)
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,4 +94,16 @@
|
||||||
<!-- Temporary remove merge tool -->
|
<!-- Temporary remove merge tool -->
|
||||||
|
|
||||||
|
|
||||||
|
<div class="card h-full max-h-full">
|
||||||
|
<h2 class="card-title p-2">Diff</h2>
|
||||||
|
<!-- selectable version -->
|
||||||
|
<div class="card-body bg-stone-200">
|
||||||
|
<h3 class="card-title">Select Version</h3>
|
||||||
|
<div class="rela flex-row m-2" id="diff_version_select">
|
||||||
|
<input class="input input-md input-bordered m-2 bg-red-100" type="number" name="master_target" placeholder="Master Version" id="master_target">
|
||||||
|
<input class="input input-md input-bordered m-2 bg-green-100" type="number" name="target" placeholder="Target Version" id="target">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="button bg-stone-400 p-2 rounded m-2 text-black font-bold" id="diff_load" (click)="addVersion()">+ Add Version</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -150,5 +150,12 @@ export class ChangelogComponent {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add version button
|
||||||
|
addVersion(){
|
||||||
|
let dvs = document.getElementById("diff_version_select");
|
||||||
|
dvs!.innerHTML += `<input class="input input-md input-bordered m-2 bg-green-100" type="number" name="target" placeholder="Target Version" id="target">`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,14 @@ export class RecipeDetailsComponent implements OnInit {
|
||||||
message: 'Do you want to save changes?',
|
message: 'Do you want to save changes?',
|
||||||
confirmCallBack: () => {
|
confirmCallBack: () => {
|
||||||
console.log('confirm save');
|
console.log('confirm save');
|
||||||
|
// TODO: update value in targeted recipe
|
||||||
|
this._recipeService.editChanges(
|
||||||
|
this._recipeService.getCurrentVersion(),
|
||||||
|
{
|
||||||
|
...this.recipeDetail
|
||||||
|
}
|
||||||
|
);
|
||||||
|
console.log("Sending changes")
|
||||||
this._router.navigate(['/recipes']);
|
this._router.navigate(['/recipes']);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span
|
<span
|
||||||
>Recipe Version {{ recipes?.MachineSetting?.configNumber }} |
|
>Recipe Version {{ recipes?.MachineSetting?.configNumber }} |
|
||||||
{{ fileName }}</span
|
{{ currentFile }}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col ml-5">
|
<div class="flex flex-col ml-5">
|
||||||
|
|
@ -23,16 +23,17 @@
|
||||||
<div
|
<div
|
||||||
class="modal-box max-w-[600px] overflow-visible flex flex-col justify-center items-center gap-5"
|
class="modal-box max-w-[600px] overflow-visible flex flex-col justify-center items-center gap-5"
|
||||||
>
|
>
|
||||||
<h3 class="font-bold text-lg">เลือก Recipe ไฟล์</h3>
|
<h3 class="font-bold text-lg">Select Recipe File</h3>
|
||||||
<div class="flex flex-row gap-5">
|
<div class="flex flex-row gap-5">
|
||||||
<div class="dropdown dropdown-end">
|
<div class="dropdown dropdown-end">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
placeholder="เลือก Recipe File"
|
placeholder="Select Country"
|
||||||
class="input input-bordered input-sm w-full max-w-xs"
|
class="input input-bordered input-sm w-full max-w-xs"
|
||||||
(input)="setRecipeVersion($event)"
|
[value]="currentCountryFilter.getValue()"
|
||||||
(focus)="getRecipeVersions()"
|
(input)="setCountryFilter($event)"
|
||||||
|
(focus)="getRecipeCountries()"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="dropdown-content z-[1000] min-w-[200px] max-h-[500px] overflow-y-auto"
|
class="dropdown-content z-[1000] min-w-[200px] max-h-[500px] overflow-y-auto"
|
||||||
|
|
@ -41,34 +42,32 @@
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="menu p-2 shadow bg-base-100 rounded-box w-auto"
|
class="menu p-2 shadow bg-base-100 rounded-box w-auto"
|
||||||
>
|
>
|
||||||
<li *ngFor="let recipeVersion of recipeVersions">
|
<li *ngFor="let country of recipeCountryFiltered">
|
||||||
<a (click)="loadRecipe(recipeVersion)">{{
|
<a (click)="countrySelected(country)">{{
|
||||||
recipeVersion
|
country
|
||||||
}}</a>
|
}}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown dropdown-end">
|
<div *ngIf="isCountrySelected" class="dropdown dropdown-end">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
tabindex="0"
|
tabindex="1"
|
||||||
placeholder="เลือก Recipe File"
|
placeholder="เลือก Recipe File"
|
||||||
class="input input-bordered input-sm w-full max-w-xs"
|
class="input input-bordered input-sm w-full max-w-xs"
|
||||||
(input)="setRecipeVersion($event)"
|
(input)="setFileFilter($event)"
|
||||||
(focus)="getRecipeVersions()"
|
(focus)="getRecipeFileCountries()"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="dropdown-content z-[1000] min-w-[200px] max-h-[500px] overflow-y-auto"
|
class="dropdown-content z-[1000] min-w-[200px] max-h-[500px] overflow-y-auto"
|
||||||
>
|
>
|
||||||
<ul
|
<ul
|
||||||
tabindex="0"
|
tabindex="1"
|
||||||
class="menu p-2 shadow bg-base-100 rounded-box w-auto"
|
class="menu p-2 shadow bg-base-100 rounded-box w-auto"
|
||||||
>
|
>
|
||||||
<li *ngFor="let recipeVersion of recipeVersions">
|
<li *ngFor="let file of recipeFileCountries">
|
||||||
<a (click)="loadRecipe(recipeVersion)">{{
|
<a (click)="loadRecipe(file)">{{ file }}</a>
|
||||||
recipeVersion
|
|
||||||
}}</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -257,4 +256,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn-circle fixed z-100 bottom-5 right-1"
|
||||||
|
(click)="scrollToTop()"
|
||||||
|
>
|
||||||
|
^
|
||||||
|
</button>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
ElementRef,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit,
|
||||||
|
ViewChild,
|
||||||
|
} from '@angular/core';
|
||||||
import { UserService } from 'src/app/core/services/user.service';
|
import { UserService } from 'src/app/core/services/user.service';
|
||||||
import { User } from 'src/app/core/models/user.model';
|
import { User } from 'src/app/core/models/user.model';
|
||||||
import { DatePipe, NgFor, NgIf } from '@angular/common';
|
import { DatePipe, NgFor, NgIf } from '@angular/common';
|
||||||
|
|
@ -6,27 +12,20 @@ import { Recipe, Recipe01 } from 'src/app/core/models/recipe.model';
|
||||||
import { RecipeService } from 'src/app/core/services/recipe.service';
|
import { RecipeService } from 'src/app/core/services/recipe.service';
|
||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment';
|
||||||
import { RecipeModalComponent } from 'src/app/shared/modal/recipe-details/recipe-modal.component';
|
import { RecipeModalComponent } from 'src/app/shared/modal/recipe-details/recipe-modal.component';
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject, Subject, Subscriber, Subscription } from 'rxjs';
|
||||||
import * as lodash from 'lodash';
|
import * as lodash from 'lodash';
|
||||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||||
|
|
||||||
interface RecipeFileFilter {
|
|
||||||
country: string | null;
|
|
||||||
fileName: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-recipes',
|
selector: 'app-recipes',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [RouterLink, NgIf, NgFor, DatePipe, RecipeModalComponent],
|
imports: [RouterLink, NgIf, NgFor, DatePipe, RecipeModalComponent],
|
||||||
templateUrl: './recipes.component.html',
|
templateUrl: './recipes.component.html',
|
||||||
})
|
})
|
||||||
export class DashboardComponent implements OnInit {
|
export class DashboardComponent implements OnInit, OnDestroy {
|
||||||
recipes: Recipe | null = null;
|
recipes: Recipe | null = null;
|
||||||
recipes01: Recipe01[] | null = null;
|
recipes01: Recipe01[] | null = null;
|
||||||
recipeFileCountries: string[] = [];
|
currentFile: string = '';
|
||||||
recipeFileNames: string[] = [];
|
|
||||||
fileName: string = '';
|
|
||||||
|
|
||||||
tableHeads: string[] = [
|
tableHeads: string[] = [
|
||||||
'Product Code',
|
'Product Code',
|
||||||
|
|
@ -38,13 +37,6 @@ export class DashboardComponent implements OnInit {
|
||||||
private offset = 0;
|
private offset = 0;
|
||||||
private take = 20;
|
private take = 20;
|
||||||
|
|
||||||
recipeFileFilter: BehaviorSubject<RecipeFileFilter> =
|
|
||||||
new BehaviorSubject<RecipeFileFilter>({
|
|
||||||
country: null,
|
|
||||||
fileName: null,
|
|
||||||
});
|
|
||||||
recipeFileFilter$ = this.recipeFileFilter.asObservable();
|
|
||||||
|
|
||||||
isLoaded: boolean = false;
|
isLoaded: boolean = false;
|
||||||
isLoadMore: boolean = false;
|
isLoadMore: boolean = false;
|
||||||
isHasMore: boolean = true;
|
isHasMore: boolean = true;
|
||||||
|
|
@ -52,7 +44,12 @@ export class DashboardComponent implements OnInit {
|
||||||
private searchStr = '';
|
private searchStr = '';
|
||||||
private oldSearchStr = '';
|
private oldSearchStr = '';
|
||||||
|
|
||||||
|
tableCtx?: ElementRef;
|
||||||
|
|
||||||
@ViewChild('table', { static: false }) set content(table: ElementRef) {
|
@ViewChild('table', { static: false }) set content(table: ElementRef) {
|
||||||
|
// expose element ref for other fn
|
||||||
|
this.tableCtx = table;
|
||||||
|
|
||||||
table.nativeElement.addEventListener(
|
table.nativeElement.addEventListener(
|
||||||
'scroll',
|
'scroll',
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -82,7 +79,7 @@ export class DashboardComponent implements OnInit {
|
||||||
...recipesWithoutRecipe01,
|
...recipesWithoutRecipe01,
|
||||||
Recipe01: [],
|
Recipe01: [],
|
||||||
};
|
};
|
||||||
this.fileName = fileName;
|
this.currentFile = fileName;
|
||||||
this.offset += 10;
|
this.offset += 10;
|
||||||
this.isLoadMore = false;
|
this.isLoadMore = false;
|
||||||
this.isHasMore = hasMore;
|
this.isHasMore = hasMore;
|
||||||
|
|
@ -114,23 +111,13 @@ export class DashboardComponent implements OnInit {
|
||||||
...recipesWithoutRecipe01,
|
...recipesWithoutRecipe01,
|
||||||
Recipe01: [],
|
Recipe01: [],
|
||||||
};
|
};
|
||||||
this.fileName = fileName;
|
this.currentFile = fileName;
|
||||||
this.offset += 10;
|
this.offset += 10;
|
||||||
this.isLoaded = true;
|
this.isLoaded = true;
|
||||||
this.isHasMore = hasMore;
|
this.isHasMore = hasMore;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.recipeFileFilter$.subscribe((version) => {
|
this.initRecipeSelection();
|
||||||
this.recipeFileCountries = lodash.filter(
|
|
||||||
this._recipeService.getRecipeFileCountries(),
|
|
||||||
(v) => {
|
|
||||||
if (version.country) {
|
|
||||||
return v.includes(version.country);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setSearch(event: Event) {
|
setSearch(event: Event) {
|
||||||
|
|
@ -155,14 +142,75 @@ export class DashboardComponent implements OnInit {
|
||||||
...recipesWithoutRecipe01,
|
...recipesWithoutRecipe01,
|
||||||
Recipe01: [],
|
Recipe01: [],
|
||||||
};
|
};
|
||||||
this.fileName = fileName;
|
this.currentFile = fileName;
|
||||||
this.offset += 10;
|
this.offset += 10;
|
||||||
this.isLoaded = true;
|
this.isLoaded = true;
|
||||||
this.isHasMore = hasMore;
|
this.isHasMore = hasMore;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
loadRecipe(recipeVersion: string) {
|
// Recipe Version selection
|
||||||
|
currentCountryFilter: BehaviorSubject<string> = new BehaviorSubject<string>(
|
||||||
|
''
|
||||||
|
);
|
||||||
|
currentFileFilter: BehaviorSubject<string> = new BehaviorSubject<string>('');
|
||||||
|
recipeCountryFiltered: string[] = [];
|
||||||
|
recipeFileCountries: string[] = [];
|
||||||
|
|
||||||
|
currentCountryFilterSubScription: Subscription | null = null;
|
||||||
|
currentFileFilterSubScription: Subscription | null = null;
|
||||||
|
|
||||||
|
selectedCountry: string | null = null;
|
||||||
|
isCountrySelected: boolean = false;
|
||||||
|
|
||||||
|
initRecipeSelection() {
|
||||||
|
if (this._recipeService.getRecipeFileCountries().length == 0) {
|
||||||
|
this._recipeService.getRecipeCountries().subscribe((countries) => {
|
||||||
|
this.recipeCountryFiltered = countries;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setCountryFilter(event: Event) {
|
||||||
|
this.currentCountryFilter.next((event.target as HTMLInputElement).value);
|
||||||
|
}
|
||||||
|
|
||||||
|
setFileFilter(event: Event) {
|
||||||
|
this.currentFileFilter.next((event.target as HTMLInputElement).value);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRecipeCountries() {
|
||||||
|
this.currentCountryFilterSubScription = this.currentCountryFilter.subscribe(
|
||||||
|
(c) => {
|
||||||
|
const countries = this._recipeService.getRecipeFileCountries();
|
||||||
|
if (countries.length > 0) {
|
||||||
|
this.recipeFileCountries = lodash.filter(countries, (country) =>
|
||||||
|
country.includes(c)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRecipeFileCountries() {
|
||||||
|
this.currentFileFilterSubScription = this.currentFileFilter.subscribe(
|
||||||
|
(c) => {
|
||||||
|
const countries = this._recipeService.getRecipeFileCountries();
|
||||||
|
if (countries.length > 0) {
|
||||||
|
this.recipeCountryFiltered = lodash.filter(countries, (country) =>
|
||||||
|
country.includes(c)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
countrySelected(country: string) {
|
||||||
|
this.selectedCountry = country;
|
||||||
|
this.isCountrySelected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadRecipe(recipeFileName: string) {
|
||||||
// clear all recipes
|
// clear all recipes
|
||||||
this.recipes = null;
|
this.recipes = null;
|
||||||
this.recipes01 = null;
|
this.recipes01 = null;
|
||||||
|
|
@ -177,7 +225,7 @@ export class DashboardComponent implements OnInit {
|
||||||
offset: this.offset,
|
offset: this.offset,
|
||||||
take: this.take,
|
take: this.take,
|
||||||
search: this.oldSearchStr,
|
search: this.oldSearchStr,
|
||||||
version: recipeVersion,
|
version: recipeFileName,
|
||||||
})
|
})
|
||||||
.subscribe(({ recipes, hasMore, fileName }) => {
|
.subscribe(({ recipes, hasMore, fileName }) => {
|
||||||
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
|
const { Recipe01, ...recipesWithoutRecipe01 } = recipes;
|
||||||
|
|
@ -190,24 +238,14 @@ export class DashboardComponent implements OnInit {
|
||||||
...recipesWithoutRecipe01,
|
...recipesWithoutRecipe01,
|
||||||
Recipe01: [],
|
Recipe01: [],
|
||||||
};
|
};
|
||||||
this.fileName = fileName;
|
this.currentFile = fileName;
|
||||||
this.offset += 10;
|
this.offset += 10;
|
||||||
this.isLoaded = true;
|
this.isLoaded = true;
|
||||||
this.isHasMore = hasMore;
|
this.isHasMore = hasMore;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setRecipeVersion(event: Event) {
|
// end of Recipe Version selection
|
||||||
this.recipeVersion.next((event.target as HTMLInputElement).value);
|
|
||||||
}
|
|
||||||
|
|
||||||
getRecipeVersions() {
|
|
||||||
if (this.recipeVersionData.length > 0) return;
|
|
||||||
this._recipeService.getRecipeCountries().subscribe((versions) => {
|
|
||||||
this.recipeVersionData = versions;
|
|
||||||
this.recipeFileCountries = versions;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
openJsonTab() {
|
openJsonTab() {
|
||||||
window.open(
|
window.open(
|
||||||
|
|
@ -216,4 +254,17 @@ export class DashboardComponent implements OnInit {
|
||||||
'_blank'
|
'_blank'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scrollToTop() {
|
||||||
|
this.tableCtx!.nativeElement.scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this.currentCountryFilterSubScription) {
|
||||||
|
this.currentCountryFilterSubScription.unsubscribe();
|
||||||
|
}
|
||||||
|
if (this.currentFileFilterSubScription) {
|
||||||
|
this.currentFileFilterSubScription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,14 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"recipe-manager/helpers"
|
"recipe-manager/helpers"
|
||||||
"recipe-manager/models"
|
"recipe-manager/models"
|
||||||
|
"recipe-manager/services/logger"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Log = logger.GetInstance()
|
||||||
)
|
)
|
||||||
|
|
||||||
func readFile(version string) *models.Recipe {
|
func readFile(version string) *models.Recipe {
|
||||||
|
|
@ -123,6 +130,27 @@ func (d *Data) GetRecipe01() []models.Recipe01 {
|
||||||
return d.currentRecipe.Recipe01
|
return d.currentRecipe.Recipe01
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Data) GetRecipe01ByProductCode(code string) models.Recipe01 {
|
||||||
|
result := make([]models.Recipe01, 0)
|
||||||
|
|
||||||
|
for _, v := range d.currentRecipe.Recipe01 {
|
||||||
|
if v.ProductCode == code {
|
||||||
|
result = append(result, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Data) SetValuesToRecipe(recipe models.Recipe01) {
|
||||||
|
for _, v := range d.currentRecipe.Recipe01 {
|
||||||
|
if v.ProductCode == recipe.ProductCode {
|
||||||
|
v = recipe
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Data) GetMaterialSetting(version string) []models.MaterialSetting {
|
func (d *Data) GetMaterialSetting(version string) []models.MaterialSetting {
|
||||||
result := make([]models.MaterialSetting, 0)
|
result := make([]models.MaterialSetting, 0)
|
||||||
|
|
||||||
|
|
@ -235,3 +263,13 @@ func (d *Data) GetCountryIDByName(countryName string) (string, error) {
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("country name: %s not found", countryName)
|
return "", fmt.Errorf("country name: %s not found", countryName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Data) ExportToJSON() []byte {
|
||||||
|
b_recipe, err := json.Marshal(d.currentRecipe)
|
||||||
|
if err != nil {
|
||||||
|
Log.Error("Error when marshal recipe", zap.Error(err))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return b_recipe
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
type Recipe struct {
|
type Recipe struct {
|
||||||
Timestamp string `json:"Timestamp"`
|
Timestamp string `json:"Timestamp"`
|
||||||
MachineSetting MachineSetting `json:"MachineSetting"`
|
MachineSetting MachineSetting `json:"MachineSetting"`
|
||||||
|
|
@ -82,6 +84,19 @@ type Recipe01 struct {
|
||||||
Weight_float int `json:"weight_float"`
|
Weight_float int `json:"weight_float"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Recipe01) ToMap() map[string]interface{} {
|
||||||
|
var m map[string]interface{}
|
||||||
|
recipeRecord, _ := json.Marshal(r)
|
||||||
|
json.Unmarshal(recipeRecord, &m)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Recipe01) FromMap(m map[string]interface{}) Recipe01 {
|
||||||
|
recipeRecord, _ := json.Marshal(m)
|
||||||
|
json.Unmarshal(recipeRecord, &r)
|
||||||
|
return *r
|
||||||
|
}
|
||||||
|
|
||||||
type MatRecipe struct {
|
type MatRecipe struct {
|
||||||
MixOrder int `json:"MixOrder"`
|
MixOrder int `json:"MixOrder"`
|
||||||
FeedParameter int `json:"FeedParameter"`
|
FeedParameter int `json:"FeedParameter"`
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,19 @@ package routers
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"recipe-manager/data"
|
"recipe-manager/data"
|
||||||
"recipe-manager/models"
|
"recipe-manager/models"
|
||||||
|
"recipe-manager/services/logger"
|
||||||
"recipe-manager/services/sheet"
|
"recipe-manager/services/sheet"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RecipeRouter struct {
|
type RecipeRouter struct {
|
||||||
|
|
@ -19,6 +23,10 @@ type RecipeRouter struct {
|
||||||
sheetService sheet.SheetService
|
sheetService sheet.SheetService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
Log = logger.GetInstance()
|
||||||
|
)
|
||||||
|
|
||||||
func NewRecipeRouter(data *data.Data, sheetService sheet.SheetService) *RecipeRouter {
|
func NewRecipeRouter(data *data.Data, sheetService sheet.SheetService) *RecipeRouter {
|
||||||
return &RecipeRouter{
|
return &RecipeRouter{
|
||||||
data: data,
|
data: data,
|
||||||
|
|
@ -170,5 +178,53 @@ func (rr *RecipeRouter) Route(r chi.Router) {
|
||||||
}
|
}
|
||||||
json.NewEncoder(w).Encode(mapResult)
|
json.NewEncoder(w).Encode(mapResult)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
r.Post("/edit/{version}", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
Log.Debug("Edit: ", zap.String("path", r.RequestURI))
|
||||||
|
version := chi.URLParam(r, "version")
|
||||||
|
target_recipe := rr.data.GetRecipe(version)
|
||||||
|
|
||||||
|
Log.Debug("Target => ", zap.Any("target", target_recipe.MachineSetting.ConfigNumber))
|
||||||
|
|
||||||
|
// Body
|
||||||
|
var changes models.Recipe01
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&changes)
|
||||||
|
if err != nil {
|
||||||
|
Log.Error("Decode in request failed: ", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Debug("Changes: ", zap.Any("changes", changes))
|
||||||
|
// TODO: find the matched pd
|
||||||
|
target_menu := rr.data.GetRecipe01ByProductCode(changes.ProductCode)
|
||||||
|
|
||||||
|
menu_map := target_menu.ToMap()
|
||||||
|
change_map := changes.ToMap()
|
||||||
|
|
||||||
|
// Find changes
|
||||||
|
for key, val := range menu_map {
|
||||||
|
if val != change_map[key] {
|
||||||
|
menu_map[key] = change_map[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply changes
|
||||||
|
tempRecipe := models.Recipe01{}
|
||||||
|
tempRecipe = tempRecipe.FromMap(menu_map)
|
||||||
|
rr.data.SetValuesToRecipe(tempRecipe)
|
||||||
|
|
||||||
|
finalData := rr.data.ExportToJSON()
|
||||||
|
temp_finalData, err := json.MarshalIndent(finalData, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
Log.Error("Error when indent marshal recipe", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
os.WriteFile("./cofffeemachineConfig/coffeethai02_"+version+".json", temp_finalData, fs.FileMode(0666))
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
|
"status": "OK",
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
104
server/server.go
104
server/server.go
|
|
@ -324,67 +324,8 @@ func (s *Server) createHandler() {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// r.Get("/mergelogList", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// ch_dir, err := os.ReadDir("cofffeemachineConfig/changelog")
|
|
||||||
// if err != nil {
|
|
||||||
// Log.Error("Error while trying to read dir: ", zap.String("dir", "cofffeemachineConfig/changelog"), zap.Error(err))
|
|
||||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
// }
|
|
||||||
// displayable := make([]string, 0)
|
|
||||||
|
|
||||||
// for _, file := range ch_dir {
|
|
||||||
// if strings.Contains(file.Name(), ".html") {
|
|
||||||
|
|
||||||
// displayable = append(displayable, file.Name()[:len(file.Name())-len(filepath.Ext(file.Name()))])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// w.Header().Set("Content-Type", "application/json")
|
|
||||||
// w.WriteHeader(http.StatusOK)
|
|
||||||
// json.NewEncoder(w).Encode(map[string][]string{"dirs": displayable})
|
|
||||||
// })
|
|
||||||
|
|
||||||
r.Get("/listFileInDir/*", func(w http.ResponseWriter, r *http.Request) {
|
r.Get("/listFileInDir/*", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// // socket
|
|
||||||
// socket, err := upgrader.Upgrade(w, r, nil)
|
|
||||||
|
|
||||||
// if err != nil {
|
|
||||||
// Log.Error("Error while trying to upgrade socket: ", zap.Error(err))
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // TODO: Change to websocket for better performance
|
|
||||||
// for {
|
|
||||||
// msg_type, msg, err := socket.ReadMessage()
|
|
||||||
|
|
||||||
// if err != nil {
|
|
||||||
// Log.Warn("Idle ", zap.Any("status", err))
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var msgPayload map[string]interface{}
|
|
||||||
|
|
||||||
// err = json.Unmarshal(msg, &msgPayload)
|
|
||||||
// if err != nil {
|
|
||||||
// Log.Error("Error while trying to unmarshal message: ", zap.Error(err))
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // topic := msgPayload["topic"].(string)
|
|
||||||
|
|
||||||
// Log.Info("Receive message: ", zap.Any("msg_type", msg_type), zap.Any("msg", msgPayload))
|
|
||||||
|
|
||||||
// response, err := json.Marshal(map[string]interface{}{
|
|
||||||
// "message": "ok",
|
|
||||||
// })
|
|
||||||
// if err != nil {
|
|
||||||
// Log.Error("Error at marshalling response: ", zap.Error(err))
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// // respons to client
|
|
||||||
// socket.WriteMessage(msg_type, response)
|
|
||||||
// }
|
|
||||||
|
|
||||||
//spl
|
//spl
|
||||||
spl_path := strings.Split(r.RequestURI, "/")
|
spl_path := strings.Split(r.RequestURI, "/")
|
||||||
if len(spl_path) > 3 {
|
if len(spl_path) > 3 {
|
||||||
|
|
@ -437,6 +378,51 @@ func (s *Server) createHandler() {
|
||||||
Log.Debug("Scan dir completed < ", zap.String("path", r.RequestURI))
|
Log.Debug("Scan dir completed < ", zap.String("path", r.RequestURI))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
r.Get("/get_log_relation", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
// Python looker
|
||||||
|
py_exec, err := exec.LookPath("python")
|
||||||
|
if err != nil {
|
||||||
|
Log.Error("Error while trying to find python: ", zap.Error(err))
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
merge_timeline, api_err := os.Open("./python_api/merge_timeline.py")
|
||||||
|
if api_err != nil {
|
||||||
|
Log.Error("Error while trying to open merge_timeline.json: ", zap.Error(api_err))
|
||||||
|
http.Error(w, api_err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
defer merge_timeline.Close()
|
||||||
|
|
||||||
|
cmd := exec.Command(py_exec, merge_timeline.Name(), "get_relate")
|
||||||
|
|
||||||
|
Log.Debug("Command: ", zap.String("command", cmd.String()))
|
||||||
|
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
|
||||||
|
Log.Debug("Output: ", zap.String("output", string(out)))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
Log.Error("Error while trying to run python: ", zap.Error(err))
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up output
|
||||||
|
clean1 := strings.ReplaceAll(string(out), "\n", "")
|
||||||
|
clean2 := strings.ReplaceAll(clean1, "\r", "")
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||||
|
"message": clean2,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
r.Post("/diffpy/*", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
Log.Debug("Diffpy: ", zap.String("path", r.RequestURI))
|
||||||
|
// TODO: add command exec `python_Exec` `merge_recipe.py` `diff` `master_version` `version-version-version` `debug?` `flatten={true|false}` `out={true|false}`
|
||||||
|
})
|
||||||
|
|
||||||
sheetService, err := sheet.NewSheetService(context.Background(), s.cfg)
|
sheetService, err := sheet.NewSheetService(context.Background(), s.cfg)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue