fix(diff_commit_merge): delayed commit data load condition

This commit is contained in:
pakintada@gmail.com 2024-03-01 14:33:48 +07:00
parent da353cec84
commit ce7d595427
8 changed files with 278 additions and 131 deletions

View file

@ -41,7 +41,7 @@
</div>
<!-- File Change Status -->
<button onclick="patch_merge_modal.showModal()" *ngIf="showDetectChanges">
<button onclick="patch_merge_modal.showModal()" *ngIf="isCommitLoaded">
<h1 class="text-center font-extrabold text-2xl text-red-500 animate-pulse">Detect Changes! Click</h1>

View file

@ -60,7 +60,8 @@ export class LayoutComponent implements OnInit, OnDestroy {
redisStatus:string = "Offline";
showDetectChanges: boolean = false;
changesCommit: any = undefined;
changesCommit!: any;
isCommitLoaded!: Promise<boolean>;
constructor(
private _userService: UserService,
@ -93,6 +94,12 @@ export class LayoutComponent implements OnInit, OnDestroy {
this._recipeService.getCurrentFile()
).subscribe({
next: async (data: any) => {
console.log("get saved tmp", data);
if(data != null && data != undefined){
this.isCommitLoaded = Promise.resolve(true);
}
if(data != undefined && typeof data === 'object'){
// check if attr exists
if(data.files != null && data.files != undefined){

View file

@ -297,10 +297,10 @@ export class RecipeService {
);
}
async getPatchListOfCurrentFile(
getPatchListOfCurrentFile(
country: string,
filename: string
): Promise<Observable<any>> {
): Observable<any> {
console.log("try get patches", country, filename);

View file

@ -8,7 +8,11 @@
(change)="selectCommit($event)"
>
<option>---</option>
<option *ngFor="let commit of getPatchMapKeys()" [value]="commit" id="commit_{{commit}}">
<option
*ngFor="let commit of getPatchMapKeys()"
[value]="commit"
id="commit_{{ commit }}"
>
[{{ getCommitAttr(commit, "Created_at") }}] [{{
getCommitAttr(commit, "Editor")
}}] | {{ getCommitAttr(commit, "Msg") }}
@ -23,12 +27,17 @@
<div class="flex flex-grow gap-4 p-4">
<!-- from patch -->
<div
class="w-100 overflow-x-visible overflow-y-visible"
*ngIf="hasProductCodeOfCommits() && selectedCommit != '' && selectedCommit != '---'"
*ngIf="
hasProductCodeOfCommits() &&
selectedCommit != '' &&
selectedCommit != '---'
"
>
<details class="collapse collapse-arrow">
<summary class="collapse-title">{{ selectedCommit }}</summary>
<div class="collapse-content">
<summary class="collapse-title bg-red-200">{{ selectedCommit }}</summary>
<div
class="collapse-content"
>
<app-recipe-list
[productCode]="
getCommitAttr(selectedCommit, 'contents').productCode

View file

@ -30,6 +30,7 @@ import { MatSelectModule } from '@angular/material/select';
import { MatFormFieldModule } from '@angular/material/form-field';
import { FormsModule } from '@angular/forms';
import { RecipeListComponent } from '../recipes/recipe-details/recipe-list/recipe-list.component';
import { ResizeEvent, ResizableModule } from 'angular-resizable-element';
@Component({
selector: 'app-merge',
@ -44,13 +45,15 @@ import { RecipeListComponent } from '../recipes/recipe-details/recipe-list/recip
PortalModule,
MatFormFieldModule,
MatSelectModule,
FormsModule
FormsModule,
ResizableModule
],
})
export class MergeComponent implements OnInit, AfterViewInit, OnDestroy {
onRecipeListFormChange($event: any) {}
@Input() commit: Array<any> | undefined = undefined;
// input from layout::getSavedTmp
@Input() commit: Array<any> | null | undefined = undefined;
patchMap: any = {};
fullPatches: any = {};
@ -70,13 +73,11 @@ export class MergeComponent implements OnInit, AfterViewInit, OnDestroy {
selectedProductCode = '';
changePackage:
| {
minimizeUnchanged: boolean;
{
highlightChangeWhenMatched: {};
targetProductCode: string;
targetRecipe: any;
path: string;
changes: any;
recipeListIndex: number[];
}
| undefined = undefined;
@ -102,12 +103,11 @@ export class MergeComponent implements OnInit, AfterViewInit, OnDestroy {
{}
async ngOnInit(): Promise<void> {
(
await this._recipeService.getPatchListOfCurrentFile(
this._recipeService.getPatchListOfCurrentFile(
await this._recipeService.getCurrentCountry(),
this._recipeService.getCurrentFile()
)
).subscribe({
.subscribe({
next: (data: any) => {
this.patchMap = data;
// console.log("patches",this.patchMap);
@ -156,10 +156,10 @@ export class MergeComponent implements OnInit, AfterViewInit, OnDestroy {
// this.host.attach(this.portal);
// console.log("Portal attached!");
this.templatePortal = new TemplatePortal(
this.templateRecipeChangeContent,
this._containerRef
);
// this.templatePortal = new TemplatePortal(
// this.templateRecipeChangeContent,
// this._containerRef
// );
}
ngOnDestroy(): void {
@ -183,7 +183,18 @@ export class MergeComponent implements OnInit, AfterViewInit, OnDestroy {
Object.keys(this.mapProductCodeWithCommits).length > 0;
// get commit message by commit id
getCommitAttr = (id: string, attr: string) => this.fullPatches[id][attr];
getCommitAttr = (id: string, attr: string) => {
// console.log("test full patches ", this.fullPatches);
// console.log("test full patches ", this.fullPatches[id]);
// console.log("test full patches ", this.fullPatches[id][attr]);
if (this.fullPatches[id] == undefined) {
return "";
}
return this.fullPatches[id][attr];
};
// copy to clipboard
copyRef = async (ref: string) => await copy(ref);
@ -222,9 +233,28 @@ export class MergeComponent implements OnInit, AfterViewInit, OnDestroy {
}
buildContext = () => {
if(this.selectedCommit == "" || this.selectedCommit == undefined || this.selectedCommit == '---'){
return {
changeContext: undefined,
skipZeroes: true,
toppingData: undefined,
}
}
// console.log("read commit contents",this.getCommitAttr(this.selectedCommit, 'contents').ToppingSet);
let patchData = this.fullPatches[this.selectedCommit];
console.log("patch data", patchData);
// this.changePackage = {
// };
return {
changeContext: undefined,
skipZeroes: true,
toppingData: this.getCommitAttr(this.selectedCommit, 'contents').ToppingSet,
};
};
@ -274,67 +304,67 @@ export class MergeComponent implements OnInit, AfterViewInit, OnDestroy {
return this.targetRecipe[productCode].recipes;
}
getRecipeFromSingleLayerPath = (
productCode: string,
path: string,
ref_id: string,
popLast?: boolean
) => {
console.log(
'mapProductCodeWithCommits map = ',
this.mapProductCodeWithCommits
);
// split path
let pathList = path.split('.');
// getRecipeFromSingleLayerPath = (
// productCode: string,
// path: string,
// ref_id: string,
// popLast?: boolean
// ) => {
// console.log(
// 'mapProductCodeWithCommits map = ',
// this.mapProductCodeWithCommits
// );
// // split path
// let pathList = path.split('.');
if (popLast) {
// pop last pathlist
pathList.pop();
}
// if (popLast) {
// // pop last pathlist
// pathList.pop();
// }
// get product code data
let productCodeData = this.targetRecipe[productCode];
let data = undefined;
for (let pathKey of pathList) {
if (data == undefined) {
if (!isNaN(parseInt(pathKey))) {
data = productCodeData[parseInt(pathKey)];
} else {
data = productCodeData[pathKey];
}
} else {
if (!isNaN(parseInt(pathKey))) {
data = data[parseInt(pathKey)];
} else {
data = data[pathKey];
}
}
}
// // get product code data
// let productCodeData = this.targetRecipe[productCode];
// let data = undefined;
// for (let pathKey of pathList) {
// if (data == undefined) {
// if (!isNaN(parseInt(pathKey))) {
// data = productCodeData[parseInt(pathKey)];
// } else {
// data = productCodeData[pathKey];
// }
// } else {
// if (!isNaN(parseInt(pathKey))) {
// data = data[parseInt(pathKey)];
// } else {
// data = data[pathKey];
// }
// }
// }
// console.log('data from path', path,"=", data);
// // console.log('data from path', path,"=", data);
// setter
this.selectedProductCode = productCode;
this.currentTargetOfMaster = productCodeData.recipes;
// configure for changes display
// this.highlightChanges = data;
// this.minimizeUnchanged = true;
// // setter
// this.selectedProductCode = productCode;
// this.currentTargetOfMaster = productCodeData.recipes;
// // configure for changes display
// // this.highlightChanges = data;
// // this.minimizeUnchanged = true;
// packing into one map; do update if selected
let changeConfigure = {
minimizeUnchanged: true,
highlightChangeWhenMatched: data,
targetProductCode: productCode,
targetRecipe: productCodeData,
path: path,
changes: this.fullPatches[ref_id].contents,
};
// // packing into one map; do update if selected
// let changeConfigure = {
// minimizeUnchanged: true,
// highlightChangeWhenMatched: data,
// targetProductCode: productCode,
// targetRecipe: productCodeData,
// path: path,
// changes: this.fullPatches[ref_id].contents,
// };
this.changePackage = changeConfigure;
};
// this.changePackage = changeConfigure;
// };
// revert search by using commit ref id to find productCode
getProductCodeByCommitRef = (commitRef: string) => {
return this.patchMap[commitRef].productCode;
};
// getProductCodeByCommitRef = (commitRef: string) => {
// return this.patchMap[commitRef].productCode;
// };
}

View file

@ -1,4 +1,7 @@
<div class="justify-center w-full flex flex-row sticky top-0 z-10" *ngIf="displayOnly == false">
<div
class="justify-center w-full flex flex-row sticky top-0 z-10"
*ngIf="displayOnly == false"
>
<button class="btn w-1/2" (click)="addRow()">Add</button>
<button class="btn w-1/2" (click)="removeRow()">Remove</button>
</div>
@ -202,6 +205,11 @@
[index]="
getToppingSlotNumber(getTypeForRecipeListAtIndex(i)['id'])
"
[diffContext]="
buildToppingContext(
getToppingSlotNumber(getTypeForRecipeListAtIndex(i)['id'])
)
"
(toppingSetChange)="onToppingSetChange($event, i)"
></app-recipe-topping>
</div>

View file

@ -50,6 +50,7 @@ export class RecipeListComponent implements OnInit, OnChanges {
@Input() diffChangeContext: {
changeContext: any;
skipZeroes: boolean;
toppingData: any;
} | undefined = undefined;
@Output() recipeListFormChange = new EventEmitter<unknown[]>();
@ -299,6 +300,7 @@ export class RecipeListComponent implements OnInit, OnChanges {
this.stringParams[index] = stringParamList;
}
// console.log("string param debug", this.stringParamData);
// --------------- mapping missing data ---------------
@ -491,6 +493,8 @@ export class RecipeListComponent implements OnInit, OnChanges {
let currStringParam = new StringParam(recipeDetailMat.StringParam);
let stringParamList = currStringParam.extract().as_list();
console.log('string param list',stringParamList);
let stringParamListTransform: any[] = [];
for (let param of stringParamList) {
// boolean transform
@ -508,6 +512,8 @@ export class RecipeListComponent implements OnInit, OnChanges {
this.stringParams[index] = stringParamList;
}
console.log("string param debug change", this.stringParamData);
// --------------- mapping missing data ---------------
// map name
@ -593,38 +599,42 @@ export class RecipeListComponent implements OnInit, OnChanges {
]
})
);
// map material
// fullMaterialList
this.setNameToRecipeList();
});
// resub listener
this.recipeListForm.valueChanges.subscribe((value) => {
// console.log(value.recipeListData);
// console.log("original recipe detail",this._recipeListOriginalArray);
if (
!isEqual(
sortBy(value, 'materialID'),
sortBy(this._recipeListOriginalArray, 'materialID')
)
) {
let emitted_res: any[] = [];
// this.recipeListForm.valueChanges.subscribe((value) => {
// // console.log(value.recipeListData);
// // console.log("original recipe detail",this._recipeListOriginalArray);
// if (
// !isEqual(
// sortBy(value, 'materialID'),
// sortBy(this._recipeListOriginalArray, 'materialID')
// )
// ) {
// let emitted_res: any[] = [];
// force type change. temporary solution
forEach(value.recipeListData!, (recipeDetailMat: any) => {
recipeDetailMat.materialPathId = parseInt(
recipeDetailMat.materialPathId!
);
// // force type change. temporary solution
// forEach(value.recipeListData!, (recipeDetailMat: any) => {
// recipeDetailMat.materialPathId = parseInt(
// recipeDetailMat.materialPathId!
// );
// revert stirTime
recipeDetailMat.stirTime = recipeDetailMat.stirTime!;
// // revert stirTime
// recipeDetailMat.stirTime = recipeDetailMat.stirTime!;
emitted_res.push(recipeDetailMat);
});
// emitted_res.push(recipeDetailMat);
// });
this.recipeListFormChange.emit([this.toppingList, emitted_res] as unknown[]);
} else {
this.recipeListFormChange.emit([]);
}
});
// this.recipeListFormChange.emit([this.toppingList, emitted_res] as unknown[]);
// } else {
// this.recipeListFormChange.emit([]);
// }
// });
this.stringParamForm.valueChanges.subscribe((value) => {
// value.stringParamData: Array
@ -672,6 +682,7 @@ export class RecipeListComponent implements OnInit, OnChanges {
}
});
}
}
}
@ -1044,4 +1055,29 @@ export class RecipeListComponent implements OnInit, OnChanges {
return true;
}
// reinit
buildToppingContext(index: number){
if(this.diffChangeContext != undefined && this.diffChangeContext.toppingData != undefined){
// console.log('building context of topping',index, this.diffChangeContext.toppingData[index])
return {
enableEditInDiffMode: false,
preFetchedData: [this.diffChangeContext.toppingData[index]]
};
}
return undefined;
}
// name mapping
setNameToRecipeList(){
this.recipeListData.value.forEach((recipe: any, index: number) => {
// get name from full material list
let mat_name = this.fullMaterialList!.find(
(mat) => mat.materialId.toString() == recipe.materialPathId.toString()
)!.name;
this.recipeListData.at(index).get('name')?.setValue(mat_name);
});
}
}

View file

@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NgSelectModule } from '@ng-select/ng-select';
import {
@ -22,9 +22,13 @@ import { ActivatedRoute } from '@angular/router';
imports: [CommonModule, NgSelectModule, FormsModule, ReactiveFormsModule],
templateUrl: './recipe-topping.component.html',
})
export class RecipeToppingComponent implements OnInit {
export class RecipeToppingComponent implements OnInit, OnChanges {
@Input() productCode: string = '';
@Input() index: number | undefined = undefined;
@Input() diffContext: {
enableEditInDiffMode: boolean;
preFetchedData: any;
} | undefined = undefined;
@Output() toppingSetChange = new EventEmitter<unknown[]>();
allToppings: Topping | undefined = undefined;
@ -70,39 +74,62 @@ export class RecipeToppingComponent implements OnInit {
async ngOnInit(): Promise<void> {
// get topping of this recipe
// initialize toppinglist form
// is read mode?
if(this.diffContext != undefined){
let toppingData = this.diffContext.preFetchedData! as Array<any>;
let readonly = this.diffContext.enableEditInDiffMode;
// suppose the topping data is array
(
await this._toppingService.getToppingsOfRecipe(
await this._recipeService.getCurrentCountry(),
this._recipeService.getCurrentFile(),
this.productCode
)
).subscribe((data) => {
this._toppingSetOriginalArray = data;
console.log('ToppingSet', data, this.index, data.length >= this.index!, data[0]);
// reset form
this.toppingList.clear();
// initialize toppinglist form
toppingData.forEach((topping, index) => {
this.listGroupId.push(topping.ListGroupID);
this.toppingList.push(
this._formBuilder.group({
isUse: {value: topping.isUse, disabled: readonly},
groupID: {value: topping.groupID, disabled: readonly},
defaultIDSelect: {value: topping.defaultIDSelect, disabled: readonly},
ListGroupID: {value: topping.ListGroupID, disabled: readonly},
})
);
});
} else {
// 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, this.index, data.length >= this.index!, data[0]);
if(data[this.index!] != undefined && data[this.index!] != null){
if(data[this.index!] != undefined && data[this.index!] != null){
this.listGroupId.push(data[this.index!].ListGroupID);
this.listGroupId.push(data[this.index!].ListGroupID);
// check length of toppingList if in range with given index
if (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,
})
);
// check length of toppingList if in range with given index
if (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,
})
);
}
console.log('SubscribeToppingSet', this.toppingList, "list group id=", this.listGroupId);
}
console.log('SubscribeToppingSet', this.toppingList, "list group id=", this.listGroupId);
}
});
});
}
// get all topping
(
@ -136,6 +163,32 @@ export class RecipeToppingComponent implements OnInit {
this.toppingForm.valueChanges.subscribe((value) => {this.triggerValueChange();});
}
// apply on read mode
ngOnChanges(changes: SimpleChanges): void {
console.log('changes on topping', changes);
if(changes['preFetchedData']){
let toppingSet = changes['preFetchedData'].currentValue as Array<any>;
this.toppingList.clear();
// initialize toppinglist form
toppingSet.forEach((topping, index) => {
this.listGroupId.push(topping.ListGroupID);
this.toppingList.push(
this._formBuilder.group({
isUse: {value: topping.isUse, disabled: true},
groupID: {value: topping.groupID, disabled: true},
defaultIDSelect: {value: topping.defaultIDSelect, disabled: true},
ListGroupID: {value: topping.ListGroupID, disabled: true},
})
);
});
}
}
compareFunc = (a: any, b: any) => a.toString() === b.toString();
mapToppingListToMember = (mm: string[]) =>
@ -307,4 +360,8 @@ export class RecipeToppingComponent implements OnInit {
ListGroupID: value.ListGroupID,
};
};
// read only mode
isReadonly = () => this.diffContext != undefined && this.diffContext.enableEditInDiffMode;
}