add changes diffing modal & silence some logs

This commit is contained in:
pakintada@gmail.com 2024-03-01 00:22:28 +07:00
parent 148488e2c4
commit da353cec84
22 changed files with 1770 additions and 120 deletions

View file

@ -309,4 +309,19 @@ export class RecipeService {
{ withCredentials: true, responseType: 'json' }
);
}
async sortRecipe(
country: string,
filename: string,
sortKey: string,
): Promise<Observable<any>> {
return this._httpClient.post<any>(
environment.api + '/recipes/sort/' + country + '/' + filename ,
JSON.stringify({
"sortKey": sortKey
}),
{ withCredentials: true, responseType: 'json' }
);
}
}

View file

@ -0,0 +1,116 @@
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatCardModule } from '@angular/material/card';
import { compare } from 'src/app/shared/helpers/compare';
import { RecipeListComponent } from '../../recipes/recipe-details/recipe-list/recipe-list.component';
@Component({
selector: 'app-changes',
standalone: true,
templateUrl: './changes.component.html',
imports: [CommonModule, MatCardModule, RecipeListComponent],
})
export class ChangesComponent implements OnInit {
@Input() changePackage:
| {
// if is unchanged, do not show
minimizeUnchanged: boolean;
// do highlight when matched this data
highlightChangeWhenMatched: {};
// base product code
targetProductCode: string;
// full recipelist
targetRecipe: any;
// path
path: string;
// changes
changes: any;
}
| undefined = undefined;
diffList: any[] = [];
matchedIdx: number[] = [];
ngOnInit(): void {
// this.createDiffList(this.changePackage?.targetRecipe, this.changePackage?.targetRecipe);
// iterate
this.traverseByPath(
this.changePackage?.path!,
this.changePackage?.targetRecipe
);
}
createDiffList = (base: any, change: any) => {
// console.log("base", base, "change", change);
let compRes = compare(base, change);
// if (!this.diffList.includes(compRes)) {
// }
// for(let c of compRes){
// console.log("c", c, "diffList", this.diffList.indexOf(c));
// if(this.diffList.indexOf(c) == -1){
// this.diffList.push(c);
// }
// }
if(this.diffList.length == 0){
this.diffList = compRes;
}
// else if(this.diffList.length > 0){
// let concatable = true;
// // check if exist
// for(let i = 0; i < this.diffList.length; i++){
// for(let j = 0; j < compRes.length; j++){
// if(this.diffList[i] == compRes[j]){
// concatable = false;
// }
// }
// }
// if(concatable){
// this.diffList = this.diffList.concat(compRes);
// }
// }
console.log("diff list", this.diffList);
};
traverseByPath = (path: string, obj: any) => {
let pathList = path.split('.');
let data = obj;
for (let pathKey of pathList) {
if (pathKey != '') {
if (!isNaN(parseInt(pathKey))) {
let asIntKey = parseInt(pathKey);
data = data[asIntKey];
if (!this.matchedIdx.includes(asIntKey)) {
this.matchedIdx.push(parseInt(pathKey));
}
} else {
data = data[pathKey];
}
}
}
return data;
};
popLast = (keyString: string) => {
let keyList = keyString.split('.');
keyList.pop();
return keyList.join('.');
};
getChanges = () =>
this.traverseByPath(
this.popLast(this.changePackage!.path),
this.changePackage!.changes
);
removeDot = (s: string) => s.replace(".", "");
}

View file

@ -1,40 +1,68 @@
<p>merge works!</p>
<!-- 3 columns with master at center -->
<div class="grid grid-cols-3">
<!-- from patch -->
<div>
<div class="m-2" *ngFor="let patchKey of getPatchMapKeys()">
<div class="h-[80vh]">
<!-- select a commit -->
<div *ngIf="isPatchMapKeysLoaded()">
<label for="patchKeys">Select a commit : </label>
<select
class="select select-sm select-primary"
name="patchKeys"
(change)="selectCommit($event)"
>
<option>---</option>
<option *ngFor="let commit of getPatchMapKeys()" [value]="commit" id="commit_{{commit}}">
[{{ getCommitAttr(commit, "Created_at") }}] [{{
getCommitAttr(commit, "Editor")
}}] | {{ getCommitAttr(commit, "Msg") }}
</option>
</select>
<!-- enable from console -->
<button class="hidden" (click)="testLoadCheck()">Test load</button>
</div>
<!-- 3 columns with master at center -->
<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 != '---'"
>
<details class="collapse collapse-arrow">
<summary class="collapse-title">{{ selectedCommit }}</summary>
<div class="collapse-content">
<app-recipe-list
[productCode]="
getCommitAttr(selectedCommit, 'contents').productCode
"
[noFetch]="true"
[recipeList]="getCommitAttr(selectedCommit, 'contents').recipes"
[displayOnly]="true"
[diffChangeContext]="buildContext()"
(recipeListFormChange)="onRecipeListFormChange($event)"
></app-recipe-list>
</div>
</details>
</div>
<!-- from master -->
<div *ngIf="hasProductCodeOfCommits()">
<!-- display zone -->
<mat-card class="!bg-amber-300 !rounded-xl p-2">
<mat-card-title>
{{getCommitAttr(patchKey, 'Msg')}}
</mat-card-title>
<mat-card-content>
<div>
<p>date: {{getCommitAttr(patchKey, 'Created_at') }}</p>
<p>editor: {{getCommitAttr(patchKey, 'Editor') }}</p>
<p>ref: {{patchKey}}</p>
<p class="hidden">full ref: {{getCommitAttr(patchKey, 'Change_file')}}</p>
<button mat-raised-button class="!bg-white" (click)="copyRef(getCommitAttr(patchKey, 'Change_file'))">Copy full ref</button>
</div>
</mat-card-content>
</mat-card>
<div *ngFor="let pd of getProductCodesOfCommits()">
<div class="container">
<details class="collapse collapse-arrow">
<summary class="collapse-title">{{ pd }}</summary>
<div>
<app-recipe-list
[productCode]="pd!"
[noFetch]="false"
[displayOnly]="true"
[diffChangeContext]="buildContext()"
(recipeListFormChange)="onRecipeListFormChange($event)"
></app-recipe-list>
</div>
<!-- collapse -->
</details>
</div>
</div>
</div>
</div>
<!-- from master -->
<div>
<p>master</p>
</div>
<!-- from machine -->
<div>
<p>machine</p>
</div>
</div>

View file

@ -1,4 +1,16 @@
import { Component, Input, OnInit } from '@angular/core';
import {
AfterViewInit,
ApplicationRef,
Component,
ComponentFactoryResolver,
Injector,
Input,
OnDestroy,
OnInit,
TemplateRef,
ViewChild,
ViewContainerRef,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { RecipeService } from 'src/app/core/services/recipe.service';
import { MatCardModule } from '@angular/material/card';
@ -6,14 +18,38 @@ import { MatButtonModule } from '@angular/material/button';
import { copy } from 'src/app/shared/helpers/copy';
import { compare } from 'src/app/shared/helpers/compare';
import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage';
import { ChangesComponent } from './changes/changes.component';
import {
CdkPortal,
DomPortalOutlet,
Portal,
PortalModule,
TemplatePortal,
} from '@angular/cdk/portal';
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';
@Component({
selector: 'app-merge',
standalone: true,
imports: [CommonModule, MatCardModule, MatButtonModule],
templateUrl: './merge.component.html',
imports: [
CommonModule,
MatCardModule,
MatButtonModule,
ChangesComponent,
RecipeListComponent,
PortalModule,
MatFormFieldModule,
MatSelectModule,
FormsModule
],
})
export class MergeComponent implements OnInit {
export class MergeComponent implements OnInit, AfterViewInit, OnDestroy {
onRecipeListFormChange($event: any) {}
@Input() commit: Array<any> | undefined = undefined;
patchMap: any = {};
@ -23,11 +59,47 @@ export class MergeComponent implements OnInit {
//map productCode:commits
mapProductCodeWithCommits: any = {};
// master recipes for product code given by commits
targetRecipe: any = {}
targetRecipe: any = {};
// change map
changeMap: any = {};
constructor(private _recipeService: RecipeService) {}
// -------------------- current selection
currentTargetOfMaster: any = undefined;
highlightChanges: any = {};
selectedProductCode = '';
changePackage:
| {
minimizeUnchanged: boolean;
highlightChangeWhenMatched: {};
targetProductCode: string;
targetRecipe: any;
path: string;
changes: any;
}
| undefined = undefined;
selectedCommit: string = '';
// --------------------- Portal
// deprecated~!
// @ViewChild(CdkPortal)
// private portal: CdkPortal | undefined;
// private host: DomPortalOutlet | undefined;
selectedPortal!: Portal<any>;
templatePortal!: TemplatePortal<any>;
// template
@ViewChild('templateRecipeChangeContent')
templateRecipeChangeContent!: TemplateRef<any>;
constructor(
private _recipeService: RecipeService,
private _containerRef: ViewContainerRef // private cfr: ComponentFactoryResolver,
) // private appRef: ApplicationRef,
// private injector: Injector
{}
async ngOnInit(): Promise<void> {
(
@ -51,7 +123,7 @@ export class MergeComponent implements OnInit {
if (productCode) {
// check if exist in map
if (!this.mapProductCodeWithCommits[productCode]) {
this.mapProductCodeWithCommits[productCode] = [ key ];
this.mapProductCodeWithCommits[productCode] = [key];
} else {
this.mapProductCodeWithCommits[productCode].push(key);
}
@ -69,7 +141,29 @@ export class MergeComponent implements OnInit {
});
// fetch related product codes
}
ngAfterViewInit(): void {
//Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
//Add 'implements AfterViewInit' to the class.
// this.host = new DomPortalOutlet(
// document.querySelector('#view_change')!,
// this.cfr,
// this.appRef,
// this.injec2tor
// );
// this.host.attach(this.portal);
// console.log("Portal attached!");
this.templatePortal = new TemplatePortal(
this.templateRecipeChangeContent,
this._containerRef
);
}
ngOnDestroy(): void {
// this.host?.detach();
}
// funcitons
@ -77,20 +171,73 @@ export class MergeComponent implements OnInit {
// get patch map keys
getPatchMapKeys = () => Object.keys(this.patchMap);
// check if load patch keys
isPatchMapKeysLoaded = () => this.getPatchMapKeys().length > 0;
testLoadCheck = () => console.log('test load check', this.isPatchMapKeysLoaded());
// get product code targets
getProductCodesOfCommits = () => Object.keys(this.mapProductCodeWithCommits);
// mapProductCodeWithCommits have data in it yet?
hasProductCodeOfCommits = () =>
Object.keys(this.mapProductCodeWithCommits).length > 0;
// get commit message by commit id
getCommitAttr = (id: string, attr: string) => this.fullPatches[id][attr];
// copy to clipboard
copyRef = async (ref: string) => await copy(ref);
// do show warning conflict if contains same path key in change map
isThisCommitConflict = (patchId: string) => {
// loop key of change map
// find other patch if .changes array contains same path key
// if yes, return true
if (
this.changeMap[patchId] == undefined ||
this.changeMap[patchId] == null ||
!Object.keys(this.changeMap[patchId]).includes('changes')
) {
return false;
}
let commit = this.changeMap[patchId]['changes'] as Array<any>;
for (let key in this.changeMap) {
if (key !== patchId) {
let testCondition = this.changeMap[key].changes.some(
(change: any) =>
commit.find((commit: any) => commit.path === change.path) !=
undefined
);
return testCondition;
}
}
return false;
};
selectCommit = (commit: any) => {
console.log('select commit', commit.target.value);
this.selectedCommit = commit.target.value;
}
buildContext = () => {
return {
changeContext: undefined,
skipZeroes: true,
};
};
// ----------------------------- Master Functions ---------------------------
getMasterRecipeOfProductCode = async (productCode: string) => {
(await this._recipeService.getRawRecipeOfProductCode(
await this._recipeService.getCurrentCountry(),
this._recipeService.getCurrentFile(),
productCode
)).subscribe({
(
await this._recipeService.getRawRecipeOfProductCode(
await this._recipeService.getCurrentCountry(),
this._recipeService.getCurrentFile(),
productCode
)
).subscribe({
next: (data: any) => {
this.targetRecipe[productCode] = data;
// console.log("get master recipe", this.targetRecipe);
@ -106,12 +253,88 @@ export class MergeComponent implements OnInit {
);
// save only what changes
this.changeMap[patchId] = {
changes: cmp
changes: cmp,
};
});
console.log("change map", this.changeMap);
}
console.log('change map', this.changeMap);
},
});
};
};
generateMasterRecipeList(productCode: string): any {
// this do fetch recipelist
if (
this.targetRecipe[productCode] != undefined ||
this.targetRecipe[productCode] != null
) {
this.getMasterRecipeOfProductCode(productCode);
}
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('.');
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];
}
}
}
// 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;
// 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;
};
// revert search by using commit ref id to find productCode
getProductCodeByCommitRef = (commitRef: string) => {
return this.patchMap[commitRef].productCode;
};
}

View file

@ -1,4 +1,4 @@
<div class="justify-center w-full flex flex-row sticky top-0 z-10">
<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>
@ -25,6 +25,7 @@
(click)="addToSelection(i)"
(mousedown)="initHoldEvent()"
(mouseup)="openRecipeListEditor(i)"
*ngIf="invokeZeroMaterialChecker(i)"
>
<td class="font-medium text-gray-900 whitespace-nowrap sticky left-0">
<input type="checkbox" class="toggle" formControlName="isUse" />

View file

@ -1,5 +1,5 @@
import { CommonModule, NgFor, NgIf } from '@angular/common';
import { Component, EventEmitter, Input, OnInit, Output, ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR } from '@angular/core';
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR } from '@angular/core';
import {
FormArray,
FormBuilder,
@ -42,10 +42,15 @@ import Lang from 'src/app/shared/helpers/lang';
standalone: true,
imports: [CommonModule,NgIf, NgFor, ReactiveFormsModule, FormsModule, RecipeToppingComponent]
})
export class RecipeListComponent implements OnInit {
export class RecipeListComponent implements OnInit, OnChanges {
@Input({ required: true }) productCode!: string;
@Input() noFetch: boolean = false;
@Input() recipeList: any | undefined = undefined;
@Input() displayOnly: boolean = false;
@Input() diffChangeContext: {
changeContext: any;
skipZeroes: boolean;
} | undefined = undefined;
@Output() recipeListFormChange = new EventEmitter<unknown[]>();
materialList: MaterialCode[] = [];
@ -267,6 +272,7 @@ export class RecipeListComponent implements OnInit {
this.isMatLoaded = true;
});
} else if(this.recipeList != undefined){
console.log("test recipelist", this.recipeList);
this.recipeList.forEach( (recipeDetailMat: RecipeDetailMat, index: number) => {
// StringParam
@ -297,7 +303,7 @@ export class RecipeListComponent implements OnInit {
// --------------- mapping missing data ---------------
// map name
console.log("use recipeList input; ", recipeDetailMat);
// console.log("use recipeList input; ", recipeDetailMat);
this.recipeListData.push(
this._formBuilder.group({
@ -460,6 +466,216 @@ export class RecipeListComponent implements OnInit {
});
}
async ngOnChanges(changes: SimpleChanges): Promise<void> {
if(changes['recipeList']){
let previousRecipeList = changes['recipeList'].previousValue;
let newUpdatedRecipeList = changes['recipeList'].currentValue;
let firstTime = changes['recipeList'].isFirstChange();
console.log("test on changes", changes);
if(newUpdatedRecipeList != undefined && !firstTime){
console.log("test updated input recipelist", newUpdatedRecipeList);
// reset
this.stringParamData.clear();
this.recipeListData.clear();
newUpdatedRecipeList.forEach( (recipeDetailMat: RecipeDetailMat, index: number) => {
// StringParam
if (
recipeDetailMat.StringParam != '' ||
recipeDetailMat.StringParam != null
) {
let currStringParam = new StringParam(recipeDetailMat.StringParam);
let stringParamList = currStringParam.extract().as_list();
let stringParamListTransform: any[] = [];
for (let param of stringParamList) {
// boolean transform
if (param.pvalue == 'true') {
param.pvalue = true;
} else if (param.pvalue == 'false') {
param.pvalue = false;
}
}
this.stringParamData.push(
this._formBuilder.array(stringParamListTransform)
)
this.stringParams[index] = stringParamList;
}
// --------------- mapping missing data ---------------
// map name
// console.log("use recipeList input; ", recipeDetailMat);
this.recipeListData.push(
this._formBuilder.group({
StringParam: [
{
value: recipeDetailMat.StringParam,
disabled: !this.isEditable(),
},
],
isUse: [
{ value: recipeDetailMat.isUse, disabled: !this.isEditable() },
],
materialPathId: [
{
value: recipeDetailMat.materialPathId,
disabled: !this.isEditable(),
},
],
name: [{ value: recipeDetailMat.name, disabled: true }],
MixOrder: [
{
value: recipeDetailMat.MixOrder,
disabled: !this.isEditable(),
},
],
stirTime: [
{
value: recipeDetailMat.stirTime,
disabled: !this.isEditable(),
},
],
powderGram: [
{
value: recipeDetailMat.powderGram,
disabled: !this.isEditable(),
},
],
powderTime: [
{
value: recipeDetailMat.powderTime,
disabled: !this.isEditable(),
},
],
syrupGram: [
{
value: recipeDetailMat.syrupGram,
disabled: !this.isEditable(),
},
],
syrupTime: [
{
value: recipeDetailMat.syrupTime,
disabled: !this.isEditable(),
},
],
waterCold: [
{
value: recipeDetailMat.waterCold,
disabled: !this.isEditable(),
},
],
waterYield: [
{
value: recipeDetailMat.waterYield,
disabled: !this.isEditable(),
},
],
feedPattern: [
{
value: recipeDetailMat.feedPattern,
disabled: !this.isEditable(),
}
],
feedParameter: [
{
value: recipeDetailMat.feedParameter,
disabled: !this.isEditable(),
}
]
})
);
});
// 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[] = [];
// force type change. temporary solution
forEach(value.recipeListData!, (recipeDetailMat: any) => {
recipeDetailMat.materialPathId = parseInt(
recipeDetailMat.materialPathId!
);
// revert stirTime
recipeDetailMat.stirTime = recipeDetailMat.stirTime!;
emitted_res.push(recipeDetailMat);
});
this.recipeListFormChange.emit([this.toppingList, emitted_res] as unknown[]);
} else {
this.recipeListFormChange.emit([]);
}
});
this.stringParamForm.valueChanges.subscribe((value) => {
// value.stringParamData: Array
// where this.stringParams: {[key: number] : {pkey: string, pvalue: any}}
// transform value to map
let mapValue: { [key: number]: { pkey: string; pvalue: any }[] } = {};
forEach(value.stringParamData, (param: any, index: number) => {
mapValue[index] = param;
});
let checkLen =
Object.keys(mapValue).length ==
Object.keys(this.stringParams as any).length;
let baseLen =
Object.keys(this.stringParams as any).length >=
Object.keys(mapValue).length
? Object.keys(this.stringParams as any).length
: Object.keys(mapValue).length;
if (checkLen) {
for (let i = 0; i < baseLen; i++) {
if (!isEqual(this.stringParams[i], mapValue[i])) {
// console.log('check', (this.stringParams as any)[i], mapValue[i]);
// transform back to string
let initString = ',';
for (let key of Object.keys(mapValue[i])) {
initString += `${mapValue[i][parseInt(key)].pkey}=${
mapValue[i][parseInt(key)].pvalue
},`;
}
if (initString.length > 1) {
(this.recipeListData.at(i) as any).controls.StringParam.setValue(
initString
);
// console.log('set', initString);
}
// do last
this.stringParams[i] = mapValue[i];
}
}
}
});
}
}
}
// add new row
addRow() {
@ -521,6 +737,11 @@ export class RecipeListComponent implements OnInit {
}
isEditable() {
if(this.displayOnly){
return !this.displayOnly;
}
return this._userService
.getCurrentUser()!
.permissions.includes(UserPermissions.EDITOR);
@ -737,7 +958,7 @@ export class RecipeListComponent implements OnInit {
await Promise.resolve();
if (this.timeoutHandler) {
if (this.timeout >= 20) {
if (this.timeout >= 20 && !this.displayOnly) {
// alert("Opening Recipe List Editor in detail")
if (confirm("Are you sure you want to open Recipe List Editor in detail?")) {
this.showDetailRecipeList = true;
@ -810,4 +1031,17 @@ export class RecipeListComponent implements OnInit {
}
// ----------------------------- Change/Diff -------------------------------
invokeZeroMaterialChecker = (index: number) => {
if(this.diffChangeContext?.skipZeroes == true){
// check if current index's material is 0
let isZeroMaterial = this.recipeListData.at(index).get('materialPathId')?.value == "0";
if(isZeroMaterial){
return false;
}
}
return true;
}
}

View file

@ -82,21 +82,26 @@ export class RecipeToppingComponent implements OnInit {
this._toppingSetOriginalArray = data;
console.log('ToppingSet', data, this.index, data.length >= this.index!, data[0]);
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,
})
);
if(data[this.index!] != undefined && data[this.index!] != null){
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,
})
);
}
console.log('SubscribeToppingSet', this.toppingList, "list group id=", this.listGroupId);
}
console.log('SubscribeToppingSet', this.toppingList, "list group id=", this.listGroupId);
});
// get all topping

View file

@ -305,7 +305,8 @@
<th scope="col" class="px-6 py-3" *ngFor="let header of tableHeads">
<div class="flex items-center uppercase">
{{ header }}
<a href="#"
<!-- sorting -->
<button (click)="sortByHeader(header)"
><svg
class="w-3 h-3 ml-1.5"
aria-hidden="true"
@ -317,7 +318,7 @@
d="M8.574 11.024h6.852a2.075 2.075 0 0 0 1.847-1.086 1.9 1.9 0 0 0-.11-1.986L13.736 2.9a2.122 2.122 0 0 0-3.472 0L6.837 7.952a1.9 1.9 0 0 0-.11 1.986 2.074 2.074 0 0 0 1.847 1.086Zm6.852 1.952H8.574a2.072 2.072 0 0 0-1.847 1.087 1.9 1.9 0 0 0 .11 1.985l3.426 5.05a2.123 2.123 0 0 0 3.472 0l3.427-5.05a1.9 1.9 0 0 0 .11-1.985 2.074 2.074 0 0 0-1.846-1.087Z"
/>
</svg>
</a>
</button>
</div>
</th>
<th scope="col" class="px-6 py-3"></th>

View file

@ -166,7 +166,6 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
// );
// // get default file that should be opened
}
);
@ -626,4 +625,35 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
console.log('copyToTsvErr', err);
});
}
// ------------------------------------ sorting ------------------------------------
async sortByHeader(header: string) {
// productCode
// name
// otherName
// description
// otherDescription
// LastUpdate
// activate sorting
console.log('sortByHeader', header);
//
// send to server [/recipe/sort]
(
await this._recipeService.sortRecipe(
await this._recipeService.getCurrentCountry(),
this._recipeService.getCurrentFile(),
header
)
).subscribe({
next: (data: any) => {
if(data.status == 'OK'){
window.location.reload();
}
}
});
}
}