fix(CurrentRecipePointer): 🐛 Fix cache recipe

Remove continue last opened version
This commit is contained in:
pakintada@gmail.com 2024-04-11 16:59:37 +07:00
parent 4219c1cb43
commit 2b8745679f
16 changed files with 481 additions and 174 deletions

View file

@ -22,6 +22,7 @@
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21",
"rxjs": "~7.8.0",
"socket.io-client": "^4.7.5",
"tslib": "^2.3.0",
"zone.js": "~0.13.0"
},
@ -4069,8 +4070,7 @@
"node_modules/@socket.io/component-emitter": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==",
"dev": true
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
},
"node_modules/@tootallnate/once": {
"version": "1.1.2",
@ -6174,7 +6174,6 @@
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"dependencies": {
"ms": "2.1.2"
},
@ -6488,11 +6487,42 @@
"node": ">=10.2.0"
}
},
"node_modules/engine.io-client": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"node_modules/engine.io-client/node_modules/ws": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/engine.io-parser": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
"integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==",
"dev": true,
"engines": {
"node": ">=10.0.0"
}
@ -9508,8 +9538,7 @@
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/multicast-dns": {
"version": "7.2.5",
@ -11818,11 +11847,24 @@
}
}
},
"node_modules/socket.io-client": {
"version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz",
"integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"dev": true,
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
@ -13465,6 +13507,14 @@
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"dev": true
},
"node_modules/xmlhttprequest-ssl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",

View file

@ -24,6 +24,7 @@
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21",
"rxjs": "~7.8.0",
"socket.io-client": "^4.7.5",
"tslib": "^2.3.0",
"zone.js": "~0.13.0"
},

View file

@ -11,6 +11,7 @@ import { RecipeService } from '../services/recipe.service';
import { AsyncStorage } from 'src/app/shared/helpers/asyncStorage';
import { MergeComponent } from "../../features/merge/merge.component";
import { Debugger } from 'src/app/shared/helpers/debugger';
// import { SocketIOService } from 'src/app/shared/services/websocket.service';
interface MenuItem {
name: string;
@ -70,7 +71,8 @@ export class LayoutComponent implements OnInit, AfterViewInit, OnDestroy {
private _userService: UserService,
private _router: ActivatedRoute,
private _httpClient: HttpClient,
private _recipeService: RecipeService
private _recipeService: RecipeService,
// private _socket: SocketIOService
) {
this.debugger = new Debugger(this._recipeService.shareHttpClient());
}
@ -168,6 +170,7 @@ export class LayoutComponent implements OnInit, AfterViewInit, OnDestroy {
logout() {
this.exit$.next();
this.exit$.complete();
// this._socket.leaveRoom(this._userService.getCurrentUser()!.name, "recipe:response");
this._userService.logout();
}

View file

@ -15,6 +15,8 @@ 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';
import { SocketIOService } from 'src/app/shared/services/websocket.service';
import { UserService } from './user.service';
type RecipeOverviewParams = {
filename: string;
@ -49,10 +51,14 @@ export class RecipeService {
constructor(
private _httpClient: HttpClient,
private _route: ActivatedRoute
) {}
private _route: ActivatedRoute,
private _user: UserService,
// private _socket: SocketIOService
) {
// this._socket.checkIn(this._user.getCurrentUser()!.name, 'recipe:response');
}
shareHttpClient(){
shareHttpClient() {
return this._httpClient;
}
@ -62,6 +68,26 @@ export class RecipeService {
filename: this.getCurrentFile(),
}
): Observable<RecipesDashboard> {
// test socket service
// this._socket.getPayload(`${this._user.getCurrentUser()!.name}:recipe:response:cache`)?.subscribe({
// next: (c: any)=> {
// console.log("cache from server", c);
// }
// });
// this._socket.sendTopic('recipe:dashboard', {
// room: 'recipe:response',
// topic: 'recipe:dashboard',
// user: this._user.getCurrentUser()!.name,
// country: params.country,
// filename: params.filename,
// });
// return this._socket.getPayload(
// `recipe:dashboard:${this._user.getCurrentUser()!.name}:payload`
// )!;
return this._httpClient.get<RecipesDashboard>(
environment.api + '/recipes/dashboard',
{
@ -85,6 +111,20 @@ export class RecipeService {
search: '',
}
): Promise<Observable<RecipeOverviewList>> {
console.log("overview: ", params);
// this._socket.sendTopic('recipe:overview', {
// room: 'recipe:response',
// topic: 'recipe:overview',
// user: this._user.getCurrentUser()!.name,
// ...params
// });
// return this._socket.getPayload(
// `recipe:overview:${this._user.getCurrentUser()!.name}:payload`
// )!;
return this._httpClient.get<RecipeOverviewList>(
environment.api + '/recipes/overview',
{
@ -240,7 +280,7 @@ export class RecipeService {
});
}
upgradeRecipe(country: string, filename: string, ctx: any){
upgradeRecipe(country: string, filename: string, ctx: any) {
return this._httpClient.post<any>(
environment.api + ('/recipes/upgrade/' + country + '/' + filename),
ctx,
@ -316,29 +356,27 @@ export class RecipeService {
country: string,
filename: string
): Observable<any> {
console.log("try get patches", country, filename);
console.log('try get patches', country, filename);
return this._httpClient.get<any>(
environment.api + '/recipes/patch/get/' + country + '/' + filename ,
environment.api + '/recipes/patch/get/' + country + '/' + filename,
{ withCredentials: true, responseType: 'json' }
);
}
async sortRecipe(
country: string,
filename: string,
sortKey: string,
ascending: boolean
): Promise<Observable<any>> {
return this._httpClient.post<any>(
environment.api + '/recipes/sort/' + country + '/' + filename ,
JSON.stringify({
"sortKey": sortKey,
"ascending": ascending
}),
{ withCredentials: true, responseType: 'json' }
);
}
): Promise<Observable<any>> {
return this._httpClient.post<any>(
environment.api + '/recipes/sort/' + country + '/' + filename,
JSON.stringify({
sortKey: sortKey,
ascending: ascending,
}),
{ withCredentials: true, responseType: 'json' }
);
}
}

View file

@ -36,6 +36,7 @@ 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';
import { NotFoundHandler } from 'src/app/shared/helpers/notFoundHandler';
import { SocketIOService } from 'src/app/shared/services/websocket.service';
@Component({
selector: 'app-recipes',
@ -121,15 +122,15 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
),
materialIds: this.selectMaterialFilter || [],
})
).subscribe(({ result, hasMore, totalCount }) => {
).subscribe((p: any) => {
// console.log("result in scroll", result);
if (this.recipeOverviewList) {
this.recipeOverviewList = this.recipeOverviewList.concat(result);
this.recipeOverviewList = this.recipeOverviewList.concat(p.result);
} else {
this.recipeOverviewList = result;
this.recipeOverviewList = p.result;
}
this.offset += 10;
this.isHasMore = hasMore;
this.offset += 10;
this.isHasMore = p.hasMore;
this.isLoadMore = false;
});
}
@ -144,7 +145,8 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
private _toppingService: ToppingService,
private route: ActivatedRoute,
private _userService: UserService,
private _router: Router
private _router: Router,
// private _socket: SocketIOService
) {}
async ngOnInit(): Promise<void> {
@ -175,7 +177,7 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
country: await this._recipeService.getCurrentCountry(this.department!),
})
.pipe(
finalize(async () => {
finalize(async () => {
(
await this._recipeService.getRecipeOverview({
offset: this.offset,
@ -196,7 +198,7 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
})
);
// : Lag assigned
// : Lag assigned
this.recipesDashboard$.subscribe(async (data) => {
this.currentVersion = data.configNumber;
@ -212,7 +214,7 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
);
await AsyncStorage.setItem('currentRecipeFile', data.filename);
}
});
});
console.log('ngAfterViewInit::department', this.department);
console.log('::CurrentFile', this._recipeService.getCurrentFile());
@ -235,43 +237,11 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
);
// check material detail
console.log('first material', this.materialDetail![0]);
// console.log('first material', this.materialDetail![0]);
});
// 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);
// }
// },
// });
(await this._materialService.getMaterialCodes())
.pipe(
map((mat) =>
@ -540,10 +510,7 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
// end of Recipe Version selection
async openJsonTab() {
let country = await this._recipeService.getCurrentCountry(
this.department
);
let country = await this._recipeService.getCurrentCountry(this.department);
window.open(
environment.api +
@ -644,20 +611,20 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
// save toggle for each header
// get header if saved
let headerToggle = await AsyncStorage.getItem("sort_"+header);
let headerToggle = await AsyncStorage.getItem('sort_' + header);
let toggleAscend = true;
if(headerToggle == null || headerToggle == undefined){
await AsyncStorage.setItem("sort_"+header, "true");
} else if(headerToggle == "true") {
if (headerToggle == null || headerToggle == undefined) {
await AsyncStorage.setItem('sort_' + header, 'true');
} else if (headerToggle == 'true') {
toggleAscend = false;
await AsyncStorage.setItem("sort_"+header, "false");
} else if(headerToggle == "false"){
await AsyncStorage.setItem('sort_' + header, 'false');
} else if (headerToggle == 'false') {
toggleAscend = true;
await AsyncStorage.setItem("sort_"+header, "true");
await AsyncStorage.setItem('sort_' + header, 'true');
}
//
console.log("sort ", headerToggle, " to ", header);
console.log('sort ', headerToggle, ' to ', header);
// send to server [/recipe/sort]
(
@ -668,14 +635,26 @@ export class RecipesComponent implements OnInit, OnDestroy, AfterViewInit {
toggleAscend
)
).subscribe({
next: (data: any) => {
if(data.status == 'OK'){
if (data.status == 'OK') {
console.log(data.result);
// alert("refresh ... ");
window.location.reload();
}
}
},
});
}
// for debug
asJsonString = (data: any) => {
return JSON.stringify(data);
};
// make unique set array
filterMakeUnique(arr: any[], filterBy: string){
return arr.filter((recipe: any, index) => {
return index === arr.findIndex(a => a[filterBy] === recipe[filterBy]);
});
}
}

View file

@ -1,47 +1,62 @@
import { Injectable } from '@angular/core';
import { Observable, filter, share } from 'rxjs';
import { WebSocketSubject, webSocket } from 'rxjs/webSocket';
import { Observable } from 'rxjs';
import {io} from 'socket.io-client';
@Injectable({
providedIn: 'root'
})
export class WebsocketService {
export class SocketIOService {
private subject!: WebSocketSubject<unknown>;
private res: any;
private socket = io("http://localhost:3000");
private isConnected = false;
constructor() {}
public connect(url: string){
this.subject = webSocket(url);
checkIn(user: string, room: string){
this.subject.subscribe({
next: (msg: any) => {
// console.log("message", msg);
this.res = msg;
console.log("res set =",this.res);
},
error: (err: any) => {
console.error(err);
},
complete: () => {
console.log('complete');
}
})
let obs = new Observable<any>(observer => {
this.socket.on('connect', () => {
console.log("connected to ", user, room);
this.isConnected = true;
this.socket.emit('subscribe', {
room: room,
user: user
});
observer.next({connect: this.isConnected});
});
});
return obs;
}
public listenTo<T>(topic: string): Observable<T> {
return this.subject.pipe(
filter((msg: any) => msg.topic === topic),
share()
);
onConnection = () => this.isConnected;
leaveRoom(user: string, room: string){
this.socket.emit("unsubscribe", {
user: user,
room: room
});
}
public data = this.subject.pipe(
share()
);
getPayload(topic: string){
let obs = new Observable<any>(observer => {
this.socket.on(topic, (payload: any) => {
console.log("getPayload", topic, payload);
observer.next(payload);
});
});
public send(url: any){
this.subject.next(url);
return obs;
// if(this.isConnected){
// }
// return null;
}
sendTopic(topic: string, args: any){
// if(this.isConnected){
// }
console.log("sending to topic", topic, args);
this.socket.emit(topic, args);
}
}