⚠️ WIP migrating tmp to patch

This commit is contained in:
pakintada@gmail.com 2024-02-22 16:04:34 +07:00
parent 89ce1f361c
commit fed315367a
13 changed files with 317 additions and 270 deletions

View file

@ -34,7 +34,19 @@
alt="Tao Bin Logo"
/>
</a>
<!-- Redis Status -->
<div class="p-2 rounded-lg border border-double border-black" [ngStyle]="redisStatus == 'Online'?{'background-color':'greenyellow'}:{'background-color':'tomato'}">
<p class="text-center font-bold">{{redisStatus}}</p>
</div>
</div>
<!-- File Change Status -->
<button *ngIf="showDetectChanges">
<h1 class="text-center font-extrabold text-2xl text-red-500 animate-pulse">Detect Changes! Click</h1>
</button>
<div class="flex items-center">
<div class="flex items-center ml-3">
<div class="flex flex-row">
@ -155,3 +167,5 @@
</div>
</div>
</div>
<!--Modal-->

View file

@ -1,10 +1,15 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, RouterModule } from '@angular/router';
import { DatePipe, NgFor, NgIf, NgOptimizedImage } from '@angular/common';
import { CommonModule, DatePipe, NgFor, NgIf, NgOptimizedImage } from '@angular/common';
import { GoogleButtonComponent } from 'src/app/shared/googleButton/googleButton.component';
import { UserService } from '../services/user.service';
import { User } from '../models/user.model';
import { Subject, Subscription, map, share, takeUntil, timer } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { environment } from 'src/environments/environment';
import { RecipeService } from '../services/recipe.service';
import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage';
import { MergeComponent } from "../../features/merge/merge.component";
interface MenuItem {
name: string;
@ -13,17 +18,19 @@ interface MenuItem {
}
@Component({
selector: 'app-layout',
templateUrl: './layout.component.html',
standalone: true,
imports: [
RouterModule,
NgFor,
NgIf,
GoogleButtonComponent,
DatePipe,
NgOptimizedImage,
],
selector: 'app-layout',
templateUrl: './layout.component.html',
standalone: true,
imports: [
RouterModule,
NgFor,
NgIf,
GoogleButtonComponent,
DatePipe,
NgOptimizedImage,
CommonModule,
MergeComponent
]
})
export class LayoutComponent implements OnInit, OnDestroy {
current_department = this._router.snapshot.paramMap.get('department')!;
@ -51,12 +58,17 @@ export class LayoutComponent implements OnInit, OnDestroy {
user: User | null = null;
exit$ = new Subject<void>();
redisStatus:string = "Offline";
showDetectChanges: boolean = false;
constructor(
private _userService: UserService,
private _router: ActivatedRoute
private _router: ActivatedRoute,
private _httpClient: HttpClient,
private _recipeService: RecipeService
) {}
ngOnInit(): void {
async ngOnInit(): Promise<void> {
this._userService.currentUser
.pipe(takeUntil(this.exit$))
.subscribe((user) => (this.user = user));
@ -69,6 +81,32 @@ export class LayoutComponent implements OnInit, OnDestroy {
.subscribe((time) => {
this.date = time;
});
this._httpClient.get(environment.api + "/health/redis").subscribe((status) => {
this.redisStatus = (status as any)["status"];
});
// check if saves existed
this._recipeService.getSavedTmp(
await this._recipeService.getCurrentCountry(),
this._recipeService.getCurrentFile()
).subscribe({
next: async (data: any) => {
if(data != undefined && typeof data === 'object'){
// check if attr exists
if(data.files != null){
this.showDetectChanges = true;
await AsyncStorage.setItem("detectChanges", "true");
} else {
this.showDetectChanges = false;
await AsyncStorage.setItem("detectChanges", "false");
}
} else {
this.showDetectChanges = false;
await AsyncStorage.setItem("detectChanges", "false");
}
}
});
}
ngOnDestroy() {

View file

@ -47,7 +47,10 @@ export class RecipeService {
return this.tmp_files;
}
constructor(private _httpClient: HttpClient, private _route: ActivatedRoute) {}
constructor(
private _httpClient: HttpClient,
private _route: ActivatedRoute
) {}
getRecipesDashboard(
params: any = {
@ -95,8 +98,9 @@ export class RecipeService {
);
}
async getRecipeDetail(productCode: string): Promise<Observable<RecipeDetail>> {
async getRecipeDetail(
productCode: string
): Promise<Observable<RecipeDetail>> {
let asyncCountry = await this.getCurrentCountry(this.department!);
console.log('get detail by asyncCountry', asyncCountry);
@ -115,8 +119,7 @@ export class RecipeService {
async getRecipeDetailMat(
productCode: string
): Promise<Observable<{ result: RecipeDetailMat[]; }>> {
): Promise<Observable<{ result: RecipeDetailMat[] }>> {
let asyncCountry = await this.getCurrentCountry(this.department!);
return this._httpClient.get<{ result: RecipeDetailMat[] }>(
@ -133,10 +136,8 @@ export class RecipeService {
}
getCurrentFile(): string {
// TODO: get default from server
const currentRecipeFile = localStorage.getItem('currentRecipeFile');
if (currentRecipeFile) {
return currentRecipeFile;
@ -150,9 +151,7 @@ export class RecipeService {
}
async getCurrentCountry(department?: string): Promise<string> {
if(department){
if (department) {
// translate back to full name
let fullname = getCountryMapSwitcher(department);
@ -167,7 +166,9 @@ export class RecipeService {
// const currentRecipeCountry = localStorage.getItem('currentRecipeCountry');
const currentRecipeCountry = await AsyncStorage.getItem<string>('currentRecipeCountry');
const currentRecipeCountry = await AsyncStorage.getItem<string>(
'currentRecipeCountry'
);
if (currentRecipeCountry) {
return currentRecipeCountry;
}
@ -275,13 +276,37 @@ export class RecipeService {
);
}
async getRawRecipeOfProductCode(country: string, filename: string, productCode: string): Promise<Observable<{}>> {
async getRawRecipeOfProductCode(
country: string,
filename: string,
productCode: string
): Promise<Observable<{}>> {
return this._httpClient.get<{}>(
environment.api + '/recipes/' + country + '/' + filename + '/' + productCode + '/raw_full',
environment.api +
'/recipes/' +
country +
'/' +
filename +
'/' +
productCode +
'/raw_full',
{
withCredentials: true,
responseType: 'json',
}
);
}
async getPatchListOfCurrentFile(
country: string,
filename: string
): Promise<Observable<any>> {
console.log("try get patches", country, filename);
return this._httpClient.get<any>(
environment.api + '/recipes/patch/get/' + country + '/' + filename ,
{ withCredentials: true, responseType: 'json' }
);
}
}

View file

@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { MergeComponent } from '../merge/merge.component';
import { HttpClient } from '@angular/common/http';
import { environment } from 'src/environments/environment.development';
import { CommonModule } from '@angular/common';
@ -10,7 +10,7 @@ import { FetchLogService } from 'src/app/shared/services/fetch-log.service';
standalone: true,
templateUrl: './changelog.component.html',
styleUrls: ['./changelog.component.css'],
imports: [CommonModule, MergeComponent],
imports: [CommonModule],
})
export class ChangelogComponent {
public displayableLogs: string[] = [];

View file

@ -1,16 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { MergeServiceService } from './merge-service.service';
describe('MergeServiceService', () => {
let service: MergeServiceService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(MergeServiceService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View file

@ -1,14 +0,0 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MergeServiceService {
master_version: number = 0;
dev_version: number = 0;
output_path:string = "";
changelog_path:string = "";
constructor() { }
}

View file

@ -1,55 +1 @@
<div class="flex-3 bg-stone-400 h-screen justify-centers items-center">
<h3 class="text-2xl text-center py-4 font-semibold">Merge 2 json</h3>
<div class="bg-stone-600 p-1 m-2 rounded-md">
<div class="bg-stone-500 m-2 rounded-md">
<p class="px-1 py-5 font-semibold">
❓ What does this function do?
</p>
<div class="bg-stone-300 rounded">
<p class="px-2 ">
Apply changes from the `dev` version
<br>into the `master` version
</p>
</div>
</div>
<div class="bg-stone-200 p-1 m-2 rounded-md">
<p class="px-2 py-4 text-md text-center font-bold">
❗Beware❗
<br>`master` = base version
<br>`dev` = your version
</p>
</div>
<form class="space-y-6 p-3 bg-stone-500 rounded" [formGroup]="mergeForm" (ngSubmit)="fetchMerge()">
<div class="flex">
<label class="flex-1 text-red-700 font-bold bg-yellow-100 rounded text-center" for="master_version">Master</label>
<input class="flex-1 mx-1 bg-slate-300 hover:bg-blue-400 text-center border border-collapse rounded-md" id="master_version" formControlName="master_version" type="text" required>
</div>
<div class="flex">
<label class="flex-1 bg-yellow-100 font-bold rounded text-center" for="dev_version">Dev</label>
<input class="flex-1 mx-1 bg-slate-300 hover:bg-blue-400 text-center border border-collapse rounded-md" id="dev_version" formControlName="dev_version" type="text" required>
</div>
<!-- Output path -->
<div class="flex">
<label class="flex-1 bg-yellow-100 font-bold rounded text-center" for="output_path">Output Path (.json)</label>
<input class="flex-1 mx-1 bg-slate-300 hover:bg-blue-400 text-center border border-collapse rounded-md" id="output_path" formControlName="output_path" type="text" required>
</div>
<!-- Changelog path -->
<div class="flex">
<label class="flex-1 bg-yellow-100 font-bold rounded text-center" for="changelog_path">Changelog Path (.json)</label>
<input class="flex-1 mx-1 bg-slate-300 hover:bg-blue-400 text-center border border-collapse rounded-md" id="changelog_path" formControlName="changelog_path" type="text" required>
</div>
<button class="button font-semibold bg-red-300 p-4 border border-collapse rounded-md" type="submit">Begin Merge</button>
</form>
</div>
</div>
<p>merge works!</p>

View file

@ -1,21 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MergeComponent } from './merge.component';
describe('MergeComponent', () => {
let component: MergeComponent;
let fixture: ComponentFixture<MergeComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [MergeComponent]
});
fixture = TestBed.createComponent(MergeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -1,90 +1,31 @@
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import { MergeServiceService } from './merge-service.service';
import { HttpClient, HttpParams } from '@angular/common/http';
import { environment } from 'src/environments/environment.development';
import { Observable } from 'rxjs';
import { ChangelogComponent } from '../changelog/changelog.component';
import { FetchLogService } from 'src/app/shared/services/fetch-log.service';
import { RecipeService } from 'src/app/core/services/recipe.service';
@Component({
selector: 'app-merge',
standalone: true,
imports: [CommonModule, ReactiveFormsModule, ChangelogComponent],
imports: [CommonModule],
templateUrl: './merge.component.html',
styleUrls: ['./merge.component.css']
})
export class MergeComponent<T> {
export class MergeComponent implements OnInit {
exceptionValues = [0, null, undefined]
mergeForm = this.formBuilder.group({
master_version: 0,
dev_version: 0,
output_path: "",
changelog_path: ""
});
default_output_path = "cofffeemachineConfig/merge/"
default_changelog_path = "cofffeemachineConfig/changelog/"
mergeLogs: Map<string, string> | void | undefined
patchMap: any = {}
constructor(
private targets: MergeServiceService,
private formBuilder: FormBuilder,
private httpClient: HttpClient,
private chlog: ChangelogComponent
){
// Default fetching logs
private _recipeService: RecipeService
) { }
// fetch html
// this.fetchLogsToDisplay("", true, false);
// // fetch log file
// this.fetchLogsToDisplay("", false, false);
// // fetch json
// this.mergeLogs = this.fetchLogsToDisplay("", false, true);
async ngOnInit(): Promise<void> {
(await this._recipeService.getPatchListOfCurrentFile(
await this._recipeService.getCurrentCountry(),
this._recipeService.getCurrentFile()
)).subscribe({
next: (data: any) => {
this.patchMap = data;
console.log("patches",this.patchMap);
}
});
}
private isException(value: any){
return this.exceptionValues.includes(value)
}
fetchMerge(){
if(this.isException(this.mergeForm.value.master_version) || this.isException(this.mergeForm.value.dev_version)){
return
}
this.targets.master_version = this.mergeForm.value.master_version!;
this.targets.dev_version = this.mergeForm.value.dev_version!;
this.targets.output_path = this.default_output_path + this.mergeForm.value.output_path!;
this.targets.changelog_path = this.default_changelog_path + this.mergeForm.value.changelog_path!;
// TODO: Fetch merge. Modify this to websocket
this.httpClient.post<T>(environment.api+"/merge", {
master: this.targets.master_version,
dev: this.targets.dev_version,
output: this.targets.output_path,
changelog: this.targets.changelog_path
}, {
withCredentials: true
}).subscribe({
next: (value: T) => {
console.log(value)
if(typeof value === "object" && value !== null){
if("message" in value){
// fetch html
// this.fetchLogsToDisplay("", true, false);
// fetch log file
// this.fetchLogsToDisplay("", false, false);
// fetch json
this.mergeLogs = new FetchLogService(this.httpClient).fetchLogsToDisplay("", false, true,this.targets.changelog_path);
this.chlog.fetchLoglist();
this.chlog.translateLogDirToString();
}
}
},
})
}
}

View file

@ -89,7 +89,7 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
savedTmpfiles: any[] = [];
saveTab: boolean = false;
showSaveNoti: boolean = true;
showSaveNoti: boolean = false;
department: string = this.route.parent!.snapshot.params['department'];
copyList: any[] = [];
@ -197,7 +197,7 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
})
);
// FIXME: Lag assigned
// : Lag assigned
this.recipesDashboard$.subscribe(async (data) => {
this.currentVersion = data.configNumber;
@ -241,37 +241,37 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
// end of FIXME
this._recipeService
.getSavedTmp(
await this._recipeService.getCurrentCountry(this.department),
this._recipeService.getCurrentFile()
)
.subscribe({
next: (files: any) => {
console.log('Obtain saves: ', typeof files, files);
this.showSaveNoti = false;
if (files != undefined && typeof files === 'object') {
if (files.files != null) {
console.log(
'Obtain saves object: ',
files.files[0],
typeof files
);
this.savedTmpfiles = files.files;
} else {
this.showSaveNoti = false;
this.savedTmpfiles = [];
console.log(this.showSaveNoti, this.savedTmpfiles);
}
// let svf = (document.getElementById('select_savefile_modal') as HTMLInputElement)!.checked;
// console.log("isSavedModalOpened",svf)
} else {
this.showSaveNoti = false;
this.savedTmpfiles = [];
console.log(this.showSaveNoti, this.savedTmpfiles);
}
},
});
// this._recipeService
// .getSavedTmp(
// await this._recipeService.getCurrentCountry(this.department),
// this._recipeService.getCurrentFile()
// )
// .subscribe({
// next: (files: any) => {
// console.log('Obtain saves: ', typeof files, files);
// this.showSaveNoti = false;
// if (files != undefined && typeof files === 'object') {
// if (files.files != null) {
// console.log(
// 'Obtain saves object: ',
// files.files[0],
// typeof files
// );
// this.savedTmpfiles = files.files;
// } else {
// this.showSaveNoti = false;
// this.savedTmpfiles = [];
// console.log(this.showSaveNoti, this.savedTmpfiles);
// }
// // let svf = (document.getElementById('select_savefile_modal') as HTMLInputElement)!.checked;
// // console.log("isSavedModalOpened",svf)
// } else {
// this.showSaveNoti = false;
// this.savedTmpfiles = [];
// console.log(this.showSaveNoti, this.savedTmpfiles);
// }
// },
// });
(await this._materialService.getMaterialCodes())
.pipe(