Merge branch 'master' into 'dev'
# Conflicts: # src/lib/core/handlers/adbPayloadHandler.ts # src/lib/core/handlers/messageHandler.ts # src/routes/(authed)/tools/brew/+page.svelte
This commit is contained in:
commit
58b496d5c8
9 changed files with 304 additions and 42 deletions
|
|
@ -5,6 +5,7 @@
|
||||||
import Input from '$lib/components/ui/input/input.svelte';
|
import Input from '$lib/components/ui/input/input.svelte';
|
||||||
import Button from '$lib/components/ui/button/button.svelte';
|
import Button from '$lib/components/ui/button/button.svelte';
|
||||||
import Spinner from '$lib/components/ui/spinner/spinner.svelte';
|
import Spinner from '$lib/components/ui/spinner/spinner.svelte';
|
||||||
|
import Checkbox from '$lib/components/ui/checkbox/checkbox.svelte';
|
||||||
import { Badge } from '$lib/components/ui/badge/index';
|
import { Badge } from '$lib/components/ui/badge/index';
|
||||||
import * as Item from '$lib/components/ui/item/index';
|
import * as Item from '$lib/components/ui/item/index';
|
||||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
|
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
|
||||||
|
|
@ -272,22 +273,28 @@
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
|
|
||||||
<Card.Content class="grid gap-6">
|
<Card.Content class="grid gap-6">
|
||||||
<div class="grid grid-flow-row gap-3">
|
<div class="grid grid-cols-2 gap-6">
|
||||||
<Label for="tabs-menu-name">Name</Label>
|
<div class="grid grid-flow-row gap-3">
|
||||||
<Input id="tabs-menu-name" value={recipeData['name'] ?? ''} />
|
<Label for="tabs-menu-name">Name</Label>
|
||||||
<Label for="tabs-menu-other-name">Other Name</Label>
|
<Input id="tabs-menu-name" value={recipeData['name'] ?? ''} />
|
||||||
<Input id="tabs-menu-other-name" value={recipeData['otherName'] ?? ''} />
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-flow-row gap-3">
|
||||||
|
<Label for="tabs-menu-other-name">Other Name</Label>
|
||||||
|
<Input id="tabs-menu-other-name" value={recipeData['otherName'] ?? ''} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid gap-3">
|
<div class="grid grid-cols-2 gap-3">
|
||||||
<!-- price -->
|
<!-- price -->
|
||||||
<Label for="tabs-menu-price"
|
|
||||||
>Price
|
<div>
|
||||||
{#if isMenuHideByPrice}
|
<Label for="tabs-menu-price">Price</Label>
|
||||||
<b> Disabled </b>
|
<Input id="tabs-menu-price" value={menuCurrentPrice} />
|
||||||
{/if}
|
</div>
|
||||||
</Label>
|
|
||||||
<Input id="tabs-menu-price" value={menuCurrentPrice} />
|
<b> Disabled </b>
|
||||||
|
<Checkbox id="disable-menu-by-price" checked={isMenuHideByPrice} />
|
||||||
</div>
|
</div>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
machineInfoStore,
|
machineInfoStore,
|
||||||
updateMachineStatus
|
updateMachineStatus
|
||||||
} from '$lib/core/stores/machineInfoStore';
|
} from '$lib/core/stores/machineInfoStore';
|
||||||
|
import { formatCustomDate } from '$lib/helpers/formatDate';
|
||||||
|
|
||||||
const isDesktop = new MediaQuery('(min-width: 768px)');
|
const isDesktop = new MediaQuery('(min-width: 768px)');
|
||||||
|
|
||||||
|
|
@ -125,7 +126,7 @@
|
||||||
|
|
||||||
ready_to_send_brew.push(new_change);
|
ready_to_send_brew.push(new_change);
|
||||||
|
|
||||||
callback_revert_value_if_not_save = (save: any) => {
|
callback_revert_value_if_not_save = async (save: any) => {
|
||||||
if (!save) {
|
if (!save) {
|
||||||
latestRecipeToppingData.set(topping_value_for_revert);
|
latestRecipeToppingData.set(topping_value_for_revert);
|
||||||
console.log('revert change', get(latestRecipeToppingData));
|
console.log('revert change', get(latestRecipeToppingData));
|
||||||
|
|
@ -141,6 +142,16 @@
|
||||||
// currentData['ToppingSet'] = latestRecipeToppingData;
|
// currentData['ToppingSet'] = latestRecipeToppingData;
|
||||||
|
|
||||||
// console.log('current data', currentData);
|
// console.log('current data', currentData);
|
||||||
|
let curr_user = get(auth);
|
||||||
|
|
||||||
|
let user_info: any;
|
||||||
|
if (curr_user) {
|
||||||
|
user_info = {
|
||||||
|
displayName: curr_user.displayName,
|
||||||
|
email: curr_user.email,
|
||||||
|
uid: curr_user.uid
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (get(referenceFromPage) == 'brew') {
|
if (get(referenceFromPage) == 'brew') {
|
||||||
// send change to machine
|
// send change to machine
|
||||||
|
|
@ -164,11 +175,29 @@
|
||||||
data: ready_to_send_brew[0]
|
data: ready_to_send_brew[0]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let country = await adb.pull('/sdcard/coffeevending/country/short');
|
||||||
|
let box_id = await adb.pull('/sdcard/coffeevending/.bid');
|
||||||
|
|
||||||
|
// update last change
|
||||||
|
// format 16-Feb-2026 10:31:18
|
||||||
|
let date = new Date();
|
||||||
|
let formatted = formatCustomDate(date);
|
||||||
|
ready_to_send_brew[0].LastChange = formatted;
|
||||||
|
|
||||||
|
sendMessage({
|
||||||
|
type: 'save_recipe',
|
||||||
|
payload: {
|
||||||
|
user_info,
|
||||||
|
country: `${country?.toLowerCase() ?? 'unknown'}_${box_id ?? ''}`,
|
||||||
|
values: ready_to_send_brew[0]
|
||||||
|
}
|
||||||
|
});
|
||||||
} else if (get(referenceFromPage) == 'overview') {
|
} else if (get(referenceFromPage) == 'overview') {
|
||||||
sendMessage({
|
sendMessage({
|
||||||
type: 'save_recipe',
|
type: 'save_recipe',
|
||||||
payload: {
|
payload: {
|
||||||
user: get(auth)?.displayName ?? 'unknown',
|
user_info,
|
||||||
country: get(departmentStore) ?? 'unknown',
|
country: get(departmentStore) ?? 'unknown',
|
||||||
values: currentData
|
values: currentData
|
||||||
}
|
}
|
||||||
|
|
@ -322,31 +351,33 @@
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
// interval check 1s
|
// interval check 1s
|
||||||
// machine
|
// machine
|
||||||
interval_get_machine_status = setInterval(() => {
|
if (refPage === 'brew') {
|
||||||
if (
|
interval_get_machine_status = setInterval(() => {
|
||||||
getMachineStatus() == undefined ||
|
if (
|
||||||
getMachineStatus() == null ||
|
getMachineStatus() == undefined ||
|
||||||
$machineInfoStore?.status === undefined
|
getMachineStatus() == null ||
|
||||||
) {
|
$machineInfoStore?.status === undefined
|
||||||
// set default now
|
) {
|
||||||
updateMachineStatus('');
|
// set default now
|
||||||
}
|
updateMachineStatus('');
|
||||||
|
|
||||||
console.log(
|
|
||||||
'machine status pinging recipe editor dialog',
|
|
||||||
getMachineStatus(),
|
|
||||||
$machineInfoStore?.status
|
|
||||||
);
|
|
||||||
|
|
||||||
// update machine status
|
|
||||||
// check-connection
|
|
||||||
sendToAndroid({
|
|
||||||
type: 'check-connection',
|
|
||||||
payload: {
|
|
||||||
start: new Date().toLocaleTimeString()
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}, 1000);
|
console.log(
|
||||||
|
'machine status pinging recipe editor dialog',
|
||||||
|
getMachineStatus(),
|
||||||
|
$machineInfoStore?.status
|
||||||
|
);
|
||||||
|
|
||||||
|
// update machine status
|
||||||
|
// check-connection
|
||||||
|
sendToAndroid({
|
||||||
|
type: 'check-connection',
|
||||||
|
payload: {
|
||||||
|
start: new Date().toLocaleTimeString()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { get } from 'svelte/store';
|
||||||
import { updateMachineStatus } from '../stores/machineInfoStore';
|
import { updateMachineStatus } from '../stores/machineInfoStore';
|
||||||
import { addNotification } from '../stores/noti';
|
import { addNotification } from '../stores/noti';
|
||||||
import {
|
import {
|
||||||
|
|
@ -6,6 +7,7 @@ import {
|
||||||
} from '../services/androidRecipeExportService';
|
} from '../services/androidRecipeExportService';
|
||||||
import { handleIncomingMessages } from './messageHandler';
|
import { handleIncomingMessages } from './messageHandler';
|
||||||
import { setMenuSaved, setMenuSaveError } from '../stores/menuSaveStore';
|
import { setMenuSaved, setMenuSaveError } from '../stores/menuSaveStore';
|
||||||
|
import { recipeFromMachineQuery } from '../stores/recipeStore';
|
||||||
|
|
||||||
type AdbPayload = { type: string; payload: any };
|
type AdbPayload = { type: string; payload: any };
|
||||||
|
|
||||||
|
|
@ -104,9 +106,21 @@ async function handleAdbPayload(raw_payload: string) {
|
||||||
let plist = payload.payload.split('/');
|
let plist = payload.payload.split('/');
|
||||||
let pd = plist[0] ?? '';
|
let pd = plist[0] ?? '';
|
||||||
let total_time = plist[1] ?? '';
|
let total_time = plist[1] ?? '';
|
||||||
|
let mode_ref = plist[2] ?? '';
|
||||||
|
|
||||||
// update recipe data store
|
// update recipe data store
|
||||||
console.log('brewing finish', pd, 'total time', total_time);
|
console.log('brewing finish', pd, 'total time', total_time);
|
||||||
|
|
||||||
|
// update recipe from brew now
|
||||||
|
let recipeDevSnapshot = get(recipeFromMachineQuery) ?? {};
|
||||||
|
let recipe01Snap = recipeDevSnapshot['recipe'];
|
||||||
|
if (recipe01Snap) {
|
||||||
|
recipe01Snap[pd].total_time =
|
||||||
|
mode_ref != 'sim' ? total_time : recipe01Snap[pd].total_time;
|
||||||
|
|
||||||
|
recipeDevSnapshot['recipe'] = recipe01Snap;
|
||||||
|
recipeFromMachineQuery.set(recipeDevSnapshot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { get, writable } from 'svelte/store';
|
||||||
import { addNotification, notiStore } from '../stores/noti';
|
import { addNotification, notiStore } from '../stores/noti';
|
||||||
import {
|
import {
|
||||||
currentRecipeVersionsSelector,
|
currentRecipeVersionsSelector,
|
||||||
|
lastRequestSheetPrice,
|
||||||
materialFromServerQuery,
|
materialFromServerQuery,
|
||||||
priceRecipeData,
|
priceRecipeData,
|
||||||
recipeData,
|
recipeData,
|
||||||
|
|
@ -9,6 +10,8 @@ import {
|
||||||
recipeLoading,
|
recipeLoading,
|
||||||
recipeOverviewData,
|
recipeOverviewData,
|
||||||
recipeStreamMeta,
|
recipeStreamMeta,
|
||||||
|
streamingRawData,
|
||||||
|
streamingRawMeta,
|
||||||
toppingGroupFromServerQuery,
|
toppingGroupFromServerQuery,
|
||||||
toppingListFromServerQuery
|
toppingListFromServerQuery
|
||||||
} from '../stores/recipeStore';
|
} from '../stores/recipeStore';
|
||||||
|
|
@ -36,13 +39,16 @@ import { type RecipeVersion } from '$lib/models/recipe_version.model';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { socketAlreadySendHeartbeat, socketConnectionOfflineCount } from '../stores/websocketStore';
|
import { socketAlreadySendHeartbeat, socketConnectionOfflineCount } from '../stores/websocketStore';
|
||||||
import type { RecipePrice } from '$lib/models/price.model';
|
import type { RecipePrice } from '$lib/models/price.model';
|
||||||
import { sendMessage } from './ws_messageSender';
|
import { sendCommandRequest, sendMessage } from './ws_messageSender';
|
||||||
import { auth as authStore } from '../stores/auth';
|
import { auth as authStore } from '../stores/auth';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import { handleSheetResponseFromNoti } from './sheetNotiHandler';
|
||||||
|
|
||||||
export const messages = writable<string[]>([]);
|
export const messages = writable<string[]>([]);
|
||||||
|
|
||||||
type WSMessage = { type: string; payload: any };
|
type WSMessage = { type: string; payload: any };
|
||||||
|
|
||||||
|
// MAXIMUM LIMIT = 1814355
|
||||||
const handlers: Record<string, (payload: any) => void> = {
|
const handlers: Record<string, (payload: any) => void> = {
|
||||||
chat: (p) => messages.update((m) => [...m, p]),
|
chat: (p) => messages.update((m) => [...m, p]),
|
||||||
ping: (p) => console.log('ping from server'),
|
ping: (p) => console.log('ping from server'),
|
||||||
|
|
@ -311,6 +317,9 @@ const handlers: Record<string, (payload: any) => void> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default notification handling
|
// Default notification handling
|
||||||
|
let from_service = p.from ?? '';
|
||||||
|
let ref_service = p.ref ?? '';
|
||||||
|
|
||||||
if (target) {
|
if (target) {
|
||||||
let currentUsername = auth.currentUser?.displayName;
|
let currentUsername = auth.currentUser?.displayName;
|
||||||
if (currentUsername && currentUsername === target) {
|
if (currentUsername && currentUsername === target) {
|
||||||
|
|
@ -353,11 +362,91 @@ const handlers: Record<string, (payload: any) => void> = {
|
||||||
console.log('get price length: ', content.length);
|
console.log('get price length: ', content.length);
|
||||||
|
|
||||||
let current_price = get(priceRecipeData);
|
let current_price = get(priceRecipeData);
|
||||||
|
let lastRequestPriceInstance = get(lastRequestSheetPrice);
|
||||||
|
let saved_product_code_to_get_from_sheet = [];
|
||||||
|
let current_meta = get(recipeStreamMeta);
|
||||||
|
lastRequestPriceInstance[current_meta?.country ?? 'unknown'] = {};
|
||||||
for (const c of content) {
|
for (const c of content) {
|
||||||
current_price[c.ProductCode] = c.NewPrice + (c.StringParam ? `,${c.StringParam}` : '');
|
current_price[c.ProductCode] = c.NewPrice + (c.StringParam ? `,${c.StringParam}` : '');
|
||||||
|
lastRequestPriceInstance[current_meta?.country ?? 'unknown'][c.ProductCode] = '';
|
||||||
|
saved_product_code_to_get_from_sheet.push({
|
||||||
|
product_code: c.ProductCode
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
priceRecipeData.set(current_price);
|
priceRecipeData.set(current_price);
|
||||||
|
|
||||||
|
console.log('check length', saved_product_code_to_get_from_sheet.length);
|
||||||
|
// set command request to stream mode so
|
||||||
|
let request_id = uuidv4();
|
||||||
|
|
||||||
|
lastRequestPriceInstance[request_id] = current_meta?.country ?? '';
|
||||||
|
let current_streaming_instance = get(streamingRawData);
|
||||||
|
current_streaming_instance[request_id] = '';
|
||||||
|
streamingRawData.set(current_streaming_instance);
|
||||||
|
|
||||||
|
sendCommandRequest('sheet', {
|
||||||
|
country: current_meta?.country ?? '',
|
||||||
|
content: saved_product_code_to_get_from_sheet,
|
||||||
|
param: 'price',
|
||||||
|
stream: true,
|
||||||
|
request_id
|
||||||
|
});
|
||||||
|
|
||||||
|
lastRequestSheetPrice.set(lastRequestPriceInstance);
|
||||||
|
},
|
||||||
|
raw_stream: (p) => {
|
||||||
|
let streamRawInstance = get(streamingRawData);
|
||||||
|
let sub_type = p.sub_type;
|
||||||
|
let request_id = p.request_id;
|
||||||
|
let size_per_chunk = p.size_per_chunk;
|
||||||
|
let total_chunks = p.total_chunks;
|
||||||
|
let idx = p.idx;
|
||||||
|
|
||||||
|
switch (sub_type) {
|
||||||
|
case 'price':
|
||||||
|
streamingRawMeta.set({
|
||||||
|
id: request_id,
|
||||||
|
total_size: total_chunks,
|
||||||
|
chunk_size: size_per_chunk,
|
||||||
|
progress: 0
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'chunk_price':
|
||||||
|
streamingRawMeta.set({
|
||||||
|
id: request_id,
|
||||||
|
total_size: total_chunks,
|
||||||
|
chunk_size: size_per_chunk,
|
||||||
|
progress: idx
|
||||||
|
});
|
||||||
|
|
||||||
|
let raw_payload = p.raw ?? '';
|
||||||
|
streamRawInstance[request_id] += raw_payload;
|
||||||
|
streamingRawData.set(streamRawInstance);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'end_price':
|
||||||
|
let lastRequestPriceInstance = get(lastRequestSheetPrice);
|
||||||
|
let country = lastRequestPriceInstance[request_id];
|
||||||
|
|
||||||
|
try {
|
||||||
|
let raw_payload = JSON.parse(streamRawInstance[request_id]);
|
||||||
|
let ref_from_raw = raw_payload.payload.ref ?? '';
|
||||||
|
let from_service_raw = raw_payload.payload.from ?? '';
|
||||||
|
let parsed_payload = raw_payload.payload ?? '';
|
||||||
|
|
||||||
|
if (from_service_raw == 'sheet-service') {
|
||||||
|
handleSheetResponseFromNoti(parsed_payload, ref_from_raw, country);
|
||||||
|
delete streamRawInstance[request_id];
|
||||||
|
streamingRawData.set(streamRawInstance);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(`end price process error: ${e}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
},
|
},
|
||||||
heartbeat: (p) => {
|
heartbeat: (p) => {
|
||||||
socketConnectionOfflineCount.set(0);
|
socketConnectionOfflineCount.set(0);
|
||||||
|
|
@ -395,5 +484,14 @@ export function handleIncomingMessages(raw: string) {
|
||||||
addNotification('ERR:No response from server');
|
addNotification('ERR:No response from server');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// raw streaming type
|
||||||
|
if (msg.type.startsWith('raw_stream')) {
|
||||||
|
// convert
|
||||||
|
let sub_type = msg.type.replace('raw_stream_', '');
|
||||||
|
msg.payload.sub_type = sub_type;
|
||||||
|
msg.type = 'raw_stream';
|
||||||
|
}
|
||||||
|
|
||||||
handlers[msg.type]?.(msg.payload);
|
handlers[msg.type]?.(msg.payload);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
79
src/lib/core/handlers/sheetNotiHandler.ts
Normal file
79
src/lib/core/handlers/sheetNotiHandler.ts
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
import { lastRequestSheetPrice } from '../stores/recipeStore';
|
||||||
|
|
||||||
|
export interface PayloadFromSheet {
|
||||||
|
header: string[];
|
||||||
|
key: string;
|
||||||
|
payload?: GristCell[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GristCell {
|
||||||
|
cells?: {
|
||||||
|
coord: {
|
||||||
|
col: number;
|
||||||
|
row: number;
|
||||||
|
};
|
||||||
|
value: string;
|
||||||
|
}[];
|
||||||
|
row_index?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PRICE_SHEET_DEFINITION_BY_COUNTRY: any = {
|
||||||
|
ltu: {
|
||||||
|
expect_header: ['Name', 'Price in Euro'],
|
||||||
|
get_header_idx: (x: string[]) => {
|
||||||
|
let result = [];
|
||||||
|
for (const header of PRICE_SHEET_DEFINITION_BY_COUNTRY['ltu'].expect_header) {
|
||||||
|
let found = x.findIndex((y) => y == header);
|
||||||
|
result.push(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function handleSheetResponseFromNoti(raw_payload: any, ref: string, country?: string) {
|
||||||
|
switch (ref) {
|
||||||
|
case 'price':
|
||||||
|
let price_contents: PayloadFromSheet[] = raw_payload.content;
|
||||||
|
console.log(`price content length: ${price_contents.length}`);
|
||||||
|
let header_idx = PRICE_SHEET_DEFINITION_BY_COUNTRY[country ?? 'unknown'].get_header_idx(
|
||||||
|
price_contents[0].header
|
||||||
|
);
|
||||||
|
console.log(`header idx: ${header_idx}`);
|
||||||
|
|
||||||
|
let lastRequestSheetInstance = get(lastRequestSheetPrice);
|
||||||
|
let products = lastRequestSheetInstance[country ?? 'unknown'];
|
||||||
|
|
||||||
|
for (let c of price_contents) {
|
||||||
|
let curr_product_code = c.key;
|
||||||
|
// price idx should be last
|
||||||
|
let price_idx = header_idx[header_idx.length - 1];
|
||||||
|
let price_rows = c.payload;
|
||||||
|
if (!price_rows) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// get last because last row will always override
|
||||||
|
let expected_row = price_rows[price_rows.length - 1];
|
||||||
|
if (expected_row != undefined && expected_row.cells != undefined) {
|
||||||
|
let price_col = expected_row.cells[price_idx];
|
||||||
|
products[curr_product_code] = price_col;
|
||||||
|
console.log(`[handleSheetPrice][country] ${curr_product_code} --> ${price_col}`);
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
`[handleSheetPrice][country] ${curr_product_code} not found cell, ${JSON.stringify(price_rows)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastRequestSheetInstance[country ?? 'unknown'] = products;
|
||||||
|
lastRequestSheetPrice.set({
|
||||||
|
...lastRequestSheetInstance,
|
||||||
|
products
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,17 @@ export const recipeOverviewData = writable<RecipeOverview[] | null>(null);
|
||||||
export const materialData = writable<Material | undefined>();
|
export const materialData = writable<Material | undefined>();
|
||||||
// price from recipe repo
|
// price from recipe repo
|
||||||
export const priceRecipeData = writable<{ [key: string]: any }>({});
|
export const priceRecipeData = writable<{ [key: string]: any }>({});
|
||||||
|
export const lastRequestSheetPrice = writable<{ [key: string]: any }>({});
|
||||||
|
|
||||||
|
// Streaming raw
|
||||||
|
export const streamingRawData = writable<{ [key: string]: any }>({});
|
||||||
|
export const streamingRawMeta = writable<{
|
||||||
|
id: string;
|
||||||
|
total_size: number;
|
||||||
|
chunk_size: number;
|
||||||
|
progress: number;
|
||||||
|
country?: string;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
// machine recipe
|
// machine recipe
|
||||||
export const recipeFromMachine = writable<any>(null);
|
export const recipeFromMachine = writable<any>(null);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { permission } from './permissions';
|
||||||
|
|
||||||
let socket: WebSocket | null = null;
|
let socket: WebSocket | null = null;
|
||||||
let reconnectTimeout: any;
|
let reconnectTimeout: any;
|
||||||
|
let socketCheck: any;
|
||||||
const ENABLE_WS_DEBUG: boolean = false;
|
const ENABLE_WS_DEBUG: boolean = false;
|
||||||
|
|
||||||
export const socketConnectionOfflineCount = writable<number>(0);
|
export const socketConnectionOfflineCount = writable<number>(0);
|
||||||
|
|
@ -95,7 +96,7 @@ export function connectToWebsocket(id_token?: string) {
|
||||||
console.log(socket);
|
console.log(socket);
|
||||||
|
|
||||||
// heartbeat 10s
|
// heartbeat 10s
|
||||||
setInterval(() => {
|
socketCheck = setInterval(() => {
|
||||||
if (get(socketAlreadySendHeartbeat) > 0) {
|
if (get(socketAlreadySendHeartbeat) > 0) {
|
||||||
let heartbeat_may_offline_count = get(socketConnectionOfflineCount);
|
let heartbeat_may_offline_count = get(socketConnectionOfflineCount);
|
||||||
|
|
||||||
|
|
@ -143,6 +144,8 @@ export function connectToWebsocket(id_token?: string) {
|
||||||
socketStore.set(null);
|
socketStore.set(null);
|
||||||
socket = null;
|
socket = null;
|
||||||
|
|
||||||
|
clearInterval(socketCheck);
|
||||||
|
|
||||||
if (auth.currentUser && !socket) {
|
if (auth.currentUser && !socket) {
|
||||||
console.log('try reconnect websocket ...');
|
console.log('try reconnect websocket ...');
|
||||||
// retry again
|
// retry again
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,10 @@ export type OutMessage =
|
||||||
| {
|
| {
|
||||||
type: 'save_recipe';
|
type: 'save_recipe';
|
||||||
payload: {
|
payload: {
|
||||||
user: string;
|
user_info: any;
|
||||||
country: string;
|
country: string;
|
||||||
values: any;
|
values: any;
|
||||||
|
plugins?: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
|
|
|
||||||
18
src/lib/helpers/formatDate.ts
Normal file
18
src/lib/helpers/formatDate.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
export function formatCustomDate(date: Date): string {
|
||||||
|
const formatter = new Intl.DateTimeFormat('en-GB', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: 'short',
|
||||||
|
year: 'numeric',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit',
|
||||||
|
hour12: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extract all the formatted parts into an object
|
||||||
|
const parts = formatter.formatToParts(date);
|
||||||
|
const partMap = Object.fromEntries(parts.map((p) => [p.type, p.value]));
|
||||||
|
|
||||||
|
// Construct your exact string: 16-Feb-2026 10:31:18
|
||||||
|
return `${partMap.day}-${partMap.month}-${partMap.year} ${partMap.hour}:${partMap.minute}:${partMap.second}`;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue