feat: save recipe in progress
Signed-off-by: pakintada@gmail.com <Pakin>
This commit is contained in:
parent
916e056389
commit
230d4abe0c
11 changed files with 310 additions and 41 deletions
20
ISSUES.txt
Normal file
20
ISSUES.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
Idea, Issue, Work Tracking
|
||||
|
||||
[TODO]
|
||||
|
||||
|
||||
[Pending]
|
||||
|
||||
- [] #2: Send change value from editing in recipe to machine
|
||||
- [] #3: Save value to recipe
|
||||
- [] #5: revert value on close dialog recipe
|
||||
|
||||
|
||||
[Rejected]
|
||||
- [] #4: From #1, will do sync value from server, so that user could save their current edit too
|
||||
|
||||
|
||||
[Done]
|
||||
- [x] #1: Topping value saving bug, fix by snapshot value
|
||||
|
||||
|
||||
|
|
@ -47,9 +47,12 @@
|
|||
authStore.set(null);
|
||||
|
||||
let socket = get(socketStore);
|
||||
if (socket) {
|
||||
socket.close(1000, 'logout');
|
||||
}
|
||||
|
||||
try {
|
||||
if (socket) {
|
||||
socket.close(1000, 'logout');
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
socketStore.set(null);
|
||||
if (browser && 'cookieStore' in window) await cookieStore.delete('logged_in');
|
||||
|
|
|
|||
|
|
@ -112,9 +112,11 @@ export const columns: ColumnDef<RecipelistMaterial>[] = [
|
|||
row_uid: row.original.id,
|
||||
mat_id: row.original.material_id,
|
||||
onEditValue: (changes: any) => {
|
||||
// console.log('triggered on edit value', changes);
|
||||
|
||||
recipeDataEvent.set({
|
||||
event_type: 'edit_change_value_rpl',
|
||||
payload: changes,
|
||||
payload: JSON.parse(changes),
|
||||
index: row.original.id
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
import { columns, type RecipelistMaterial } from './columns';
|
||||
import { get, readable, writable } from 'svelte/store';
|
||||
import {
|
||||
currentEditingRecipeProductCode,
|
||||
latestRecipeToppingData,
|
||||
materialFromMachineQuery,
|
||||
materialFromServerQuery
|
||||
|
|
@ -29,8 +30,9 @@
|
|||
let {
|
||||
recipeData,
|
||||
onPendingChange,
|
||||
productCode,
|
||||
refPage
|
||||
}: { recipeData: any; onPendingChange: any; refPage: string } = $props();
|
||||
}: { recipeData: any; onPendingChange: any; productCode: string; refPage: string } = $props();
|
||||
|
||||
let menuName: string = $state('');
|
||||
|
||||
|
|
@ -126,7 +128,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
async function saveRecipe() {}
|
||||
async function saveRecipe() {
|
||||
recipeDetailDispatch('saveRecipe');
|
||||
}
|
||||
|
||||
async function sendTriggerBrewNow() {
|
||||
// check queue ready
|
||||
|
|
@ -155,8 +159,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
async function checkChanges(original: any) {
|
||||
console.log('old', original, 'updated', recipeListMatState);
|
||||
async function checkChanges(productCode: string, original: any) {
|
||||
// console.log('old', original, 'updated', recipeListMatState);
|
||||
if (recipeListOriginal.length == 0) {
|
||||
recipeListOriginal = original;
|
||||
}
|
||||
|
|
@ -164,6 +168,7 @@
|
|||
if (original !== recipeListMatState) {
|
||||
await onPendingChange({
|
||||
target: 'recipeList',
|
||||
ref_pd: productCode,
|
||||
value: original
|
||||
});
|
||||
}
|
||||
|
|
@ -187,6 +192,8 @@
|
|||
|
||||
latestRecipeToppingData.set(toppingSlotState);
|
||||
|
||||
currentEditingRecipeProductCode.set(productCode);
|
||||
|
||||
// save old value\
|
||||
}
|
||||
});
|
||||
|
|
@ -237,7 +244,12 @@
|
|||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="details">
|
||||
<RecipelistTable data={recipeListMatState} {columns} onStateChange={checkChanges} />
|
||||
<RecipelistTable
|
||||
data={recipeListMatState}
|
||||
{columns}
|
||||
onStateChange={checkChanges}
|
||||
{productCode}
|
||||
/>
|
||||
</Tabs.Content>
|
||||
</Tabs.Root>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -42,11 +42,13 @@
|
|||
let {
|
||||
data,
|
||||
columns,
|
||||
onStateChange
|
||||
onStateChange,
|
||||
productCode
|
||||
}: {
|
||||
data: RecipelistMaterial[];
|
||||
columns: ColumnDef<any, any>[];
|
||||
onStateChange: any;
|
||||
productCode: string;
|
||||
} = $props();
|
||||
|
||||
let sorting = $state<SortingState>([]);
|
||||
|
|
@ -75,7 +77,10 @@
|
|||
getFacetedRowModel: getFacetedRowModel(),
|
||||
onStateChange: async (updater) => {
|
||||
console.log('table state change', data);
|
||||
await onStateChange(table.getRowModel().rows.map((x) => x.original));
|
||||
await onStateChange(
|
||||
productCode,
|
||||
table.getRowModel().rows.map((x) => x.original)
|
||||
);
|
||||
},
|
||||
onSortingChange: async (updater) => {
|
||||
console.log('triggering sorting');
|
||||
|
|
@ -84,7 +89,10 @@
|
|||
} else {
|
||||
sorting = updater;
|
||||
}
|
||||
await onStateChange(table.getRowModel().rows.map((x) => x.original));
|
||||
await onStateChange(
|
||||
productCode,
|
||||
table.getRowModel().rows.map((x) => x.original)
|
||||
);
|
||||
},
|
||||
onRowSelectionChange: async (updater) => {
|
||||
// table.getRowModel().rows.find((x) => x.original.id == )
|
||||
|
|
@ -92,11 +100,14 @@
|
|||
rowSelection = updater(rowSelection);
|
||||
let rows = table.getRowModel().rows;
|
||||
|
||||
console.log('state size', data, rows);
|
||||
// console.log('state size', data, rows);
|
||||
} else {
|
||||
rowSelection = updater;
|
||||
}
|
||||
await onStateChange(table.getRowModel().rows.map((x) => x.original));
|
||||
await onStateChange(
|
||||
productCode,
|
||||
table.getRowModel().rows.map((x) => x.original)
|
||||
);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@
|
|||
|
||||
function saveEditingValue() {
|
||||
console.log('saving value ...', value_event_state);
|
||||
if (value_event_state === ValueEvent.EDITED) {
|
||||
if (value_event_state === ValueEvent.EDITED || value_event_state === ValueEvent.SAVED) {
|
||||
let payload = {
|
||||
source: current_editing_data,
|
||||
change: changed_data
|
||||
|
|
@ -209,28 +209,36 @@
|
|||
|
||||
function handleToppingGroupChange(v: any) {
|
||||
console.log('change topping group');
|
||||
|
||||
// TODO: clear topping list, otherwise, it will continue to append filter to list by each navigate back and forth
|
||||
|
||||
selected_category_id = v.groupID;
|
||||
// get default
|
||||
selected_topping_list_id = v.idDefault ?? 0;
|
||||
|
||||
// set to edit state even if selected same group again
|
||||
value_event_state = ValueEvent.EDITED;
|
||||
if (current_editing_data['toppings'] == undefined || current_editing_data['toppings'] == null) {
|
||||
if (
|
||||
current_editing_data['toppings'] !== undefined ||
|
||||
current_editing_data['toppings'] !== null
|
||||
) {
|
||||
let toppings_length = current_editing_data['toppings'].length;
|
||||
if (changed_data['toppings'] == undefined || changed_data['toppings'] == null) {
|
||||
changed_data['toppings'] = new Array<any>(toppings_length);
|
||||
|
||||
// console.log('filling change topping', JSON.stringify(changed_data));
|
||||
console.log('filling change topping', JSON.stringify(changed_data));
|
||||
}
|
||||
}
|
||||
|
||||
console.log('current editing data', current_editing_data['toppings']);
|
||||
|
||||
let idx = getToppingSlotIndex(current_editing_data['mat_id']);
|
||||
|
||||
// get old state topping idx
|
||||
let current_selection = current_editing_data['toppings'][idx];
|
||||
|
||||
// let default_from_recipe = current_editing_data['toppings'][idx]['ListGroupID'][0];
|
||||
// console.log(`Current TG: `, JSON.stringify(current_selection));
|
||||
console.log(`Current TG: `, JSON.stringify(current_selection));
|
||||
if (current_selection['groupID'] !== undefined || current_selection['groupID'] !== null) {
|
||||
try {
|
||||
changed_data['toppings'][idx] = current_selection;
|
||||
|
|
@ -250,7 +258,10 @@
|
|||
// set to edit state even if selected same group again
|
||||
value_event_state = ValueEvent.EDITED;
|
||||
let idx = getToppingSlotIndex(current_editing_data['mat_id']);
|
||||
if (current_editing_data['toppings'] == undefined || current_editing_data['toppings'] == null) {
|
||||
if (
|
||||
current_editing_data['toppings'] !== undefined ||
|
||||
current_editing_data['toppings'] !== null
|
||||
) {
|
||||
let toppings_length = current_editing_data['toppings'].length;
|
||||
// case: topping not init
|
||||
if (changed_data['toppings'] == null || changed_data['toppings'] == undefined) {
|
||||
|
|
@ -590,12 +601,12 @@
|
|||
</ScrollArea>
|
||||
|
||||
<!-- final -->
|
||||
<!-- <Field.Field orientation="horizontal">
|
||||
<Button type="button" onclick={() => saveEditingValue()}>Save</Button>
|
||||
<Button variant="outline" type="button" onclick={() => (sheetOpenState = false)}
|
||||
<Field.Field orientation="horizontal">
|
||||
<Button type="button" onclick={() => saveEditingValue()}>Apply</Button>
|
||||
<!-- <Button variant="outline" type="button" onclick={() => (sheetOpenState = false)}
|
||||
>{warnUserNotSaveChange ? 'Discard Changes' : 'Cancel'}</Button
|
||||
>
|
||||
</Field.Field> -->
|
||||
> -->
|
||||
</Field.Field>
|
||||
</Field.Group>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
import Input from '../ui/input/input.svelte';
|
||||
import Separator from '$lib/components/ui/separator/separator.svelte';
|
||||
import Button from '../ui/button/button.svelte';
|
||||
import { PencilIcon } from '@lucide/svelte/icons';
|
||||
import { PencilIcon, Undo } from '@lucide/svelte/icons';
|
||||
import * as Tooltip from '../ui/tooltip/index';
|
||||
import {
|
||||
latestRecipeToppingData,
|
||||
|
|
@ -22,6 +22,9 @@
|
|||
referenceFromPage
|
||||
} from '$lib/core/stores/recipeStore';
|
||||
import { get } from 'svelte/store';
|
||||
import { sendMessage } from '$lib/core/handlers/ws_messageSender';
|
||||
import { auth } from '$lib/core/stores/auth';
|
||||
import { departmentStore } from '$lib/core/stores/departments';
|
||||
|
||||
let {
|
||||
row_uid,
|
||||
|
|
@ -51,11 +54,16 @@
|
|||
|
||||
// toppings
|
||||
let currentToppings: any = $state([]);
|
||||
let oldToppings: any = $state(null);
|
||||
// current topping of this row
|
||||
let currentToppingInRow: any = $state();
|
||||
let selectableToppingInGroup: any[] = $state([]);
|
||||
|
||||
let currentToppingNamesOnly = $state('');
|
||||
let oldToppingNamesOnly = $state(null);
|
||||
|
||||
let unsubRecipeDataEvent: any;
|
||||
let unsubRecipeTopping: any;
|
||||
|
||||
function isToppingId(mat_id: string): boolean {
|
||||
let mat_num = extractMaterialIdFromDisplay(mat_id);
|
||||
|
|
@ -118,21 +126,54 @@
|
|||
refFrom === 'overview' ? toppingListFromServerQuery : toppingListFromMachineQuery
|
||||
);
|
||||
|
||||
// console.log(JSON.stringify(groupQuery[0]));
|
||||
// console.log(JSON.stringify(listQuery[0]));
|
||||
console.log('old topping', oldToppings[getToppingSlot()]);
|
||||
|
||||
console.log('current topping', current_row_topping);
|
||||
oldToppingNamesOnly = null; // reset first
|
||||
if (oldToppings[getToppingSlot()] != current_row_topping) {
|
||||
console.log('detect change on topping row', row_uid);
|
||||
|
||||
let groupIDchange =
|
||||
oldToppings[getToppingSlot()]['groupID'] !== current_row_topping['groupID'];
|
||||
let defaultIDchange =
|
||||
oldToppings[getToppingSlot()]['defaultIDSelect'] !== current_row_topping['defaultIDSelect'];
|
||||
|
||||
console.log('group change', groupIDchange, 'default id change', defaultIDchange);
|
||||
|
||||
if (!groupIDchange && !defaultIDchange) {
|
||||
oldToppingNamesOnly = null;
|
||||
} else {
|
||||
// has change, display old name
|
||||
let oldGroupData = groupQuery.find(
|
||||
(x: any) => x.groupID.toString() === oldToppings[getToppingSlot()]['groupID']
|
||||
);
|
||||
let oldListData = listQuery.filter(
|
||||
(x: any) =>
|
||||
oldGroupData != undefined &&
|
||||
Object.keys(oldGroupData).includes('idInGroup') &&
|
||||
oldGroupData['idInGroup'].split(',').includes(x.id.toString())
|
||||
);
|
||||
oldToppingNamesOnly = oldGroupData['otherName'];
|
||||
}
|
||||
} else {
|
||||
oldToppingNamesOnly = null;
|
||||
}
|
||||
|
||||
let groupData = groupQuery.find(
|
||||
(x: any) => x.groupID.toString() === current_row_topping['groupID']
|
||||
);
|
||||
let listData = listQuery.filter(
|
||||
(x: any) =>
|
||||
groupData &&
|
||||
groupData != undefined &&
|
||||
Object.keys(groupData).includes('idInGroup') &&
|
||||
groupData['idInGroup'].split(',').includes(x.id.toString())
|
||||
);
|
||||
|
||||
console.log('topping data', JSON.stringify(groupData), 'list', listData.length);
|
||||
|
||||
currentToppingNamesOnly = groupData ? (groupData['otherName'] ?? '-') : '-';
|
||||
|
||||
// NOTE: send topping data to value editor
|
||||
currentToppingInRow =
|
||||
current_row_topping['groupID'] === 0 || current_row_topping['groupID'] === '0'
|
||||
? {
|
||||
|
|
@ -178,13 +219,20 @@
|
|||
}
|
||||
|
||||
function initialize() {
|
||||
currentToppings = get(latestRecipeToppingData);
|
||||
|
||||
hasMixOrder = mix_order == 1;
|
||||
|
||||
extractStringParam();
|
||||
|
||||
if (isToppingId(mat_id) && onDetectToppingSlot) {
|
||||
// FIXME: this should not be updated yet, must be updated after user pressed save only
|
||||
let latest_topping_data_snapshot = $state.snapshot(get(latestRecipeToppingData));
|
||||
currentToppings = latest_topping_data_snapshot;
|
||||
// console.log('current topping in initialize', currentToppings);
|
||||
if (oldToppings == null) {
|
||||
// console.log('saving original topping', oldToppings);
|
||||
oldToppings = $state.snapshot(currentToppings);
|
||||
}
|
||||
|
||||
currentMaterialType = 'topping';
|
||||
|
||||
getToppingDisplay();
|
||||
|
|
@ -200,9 +248,9 @@
|
|||
// console.log('type get', mat_type_t1, mat_type_t2);
|
||||
currentMaterialType = mat_type_t1 === mat_type_t2 ? mat_type_t1 : mat_type_t2;
|
||||
|
||||
if (hasMixOrder) {
|
||||
console.log('detect mix order', mat_num);
|
||||
}
|
||||
// if (hasMixOrder) {
|
||||
// console.log('detect mix order', mat_num);
|
||||
// }
|
||||
|
||||
// if (feed.parameter > 0 || feed.pattern > 0) {
|
||||
// console.log('has feed fields', JSON.stringify(feed));
|
||||
|
|
@ -210,6 +258,19 @@
|
|||
}
|
||||
}
|
||||
|
||||
function applyChanges(value: any) {
|
||||
let keys = Object.keys(value);
|
||||
|
||||
for (const key of keys) {
|
||||
if (key == 'toppings' && currentMaterialType == 'topping') {
|
||||
let topping_change = value[key][getToppingSlot()];
|
||||
console.log('topping applying', topping_change);
|
||||
currentToppings[getToppingSlot()] = topping_change;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleEvents(event: { event_type: string; payload: any; index: number | undefined }) {
|
||||
// console.log('triggered event', event.event_type, JSON.stringify(event.payload));
|
||||
if (event.event_type === 'mat_change') {
|
||||
|
|
@ -217,6 +278,10 @@
|
|||
initialize();
|
||||
} else if (event.event_type === 'edit_mat_field') {
|
||||
console.log('request edit mat');
|
||||
|
||||
// fix bug: topping instant change by unlink topping
|
||||
let _current_toppings = $state.snapshot(currentToppings);
|
||||
|
||||
// pack all shown data
|
||||
recipeDataEvent.set({
|
||||
event_type: 'edit_mat_field_prep',
|
||||
|
|
@ -225,7 +290,7 @@
|
|||
mat_type: currentMaterialType,
|
||||
mat_name: mat_id,
|
||||
params: currentStringParams,
|
||||
toppings: currentToppings,
|
||||
toppings: _current_toppings,
|
||||
current_topping_group: currentToppingInRow,
|
||||
current_topping_list: selectableToppingInGroup,
|
||||
has_mix_ord: hasMixOrder,
|
||||
|
|
@ -244,6 +309,23 @@
|
|||
// apply now
|
||||
let keys = Object.keys(change_values);
|
||||
console.log('change keys', JSON.stringify(keys));
|
||||
let _current_toppings = $state.snapshot(currentToppings);
|
||||
|
||||
// initialize();
|
||||
applyChanges(change_values);
|
||||
|
||||
event.payload = {
|
||||
current_toppings: _current_toppings,
|
||||
...event.payload
|
||||
};
|
||||
|
||||
// console.log('check on change before trigger', change_values);
|
||||
|
||||
if (onEditValue) onEditValue(JSON.stringify(event.payload));
|
||||
} else if (event.event_type === 'revert_change') {
|
||||
// console.log('revert back ...', row_uid);
|
||||
|
||||
currentToppings = oldToppings;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -255,11 +337,23 @@
|
|||
handleEvents(event);
|
||||
}
|
||||
});
|
||||
|
||||
unsubRecipeTopping = latestRecipeToppingData.subscribe((payload) => {
|
||||
// console.log('topping data subscribe', payload);
|
||||
});
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (unsubRecipeDataEvent) {
|
||||
// do last event before destroy
|
||||
// console.log('trigger last event before destroy', get(latestRecipeToppingData));
|
||||
handleEvents(get(recipeDataEvent) ?? { event_type: '', payload: {}, index: -1 });
|
||||
|
||||
unsubRecipeDataEvent();
|
||||
// console.log('destroy recipe data event listener');
|
||||
}
|
||||
if (unsubRecipeTopping) {
|
||||
unsubRecipeTopping();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
@ -275,6 +369,14 @@
|
|||
{getCurrentSelectedToppingGroup()}
|
||||
</b>, {getCurrentSelectedToppingList()}
|
||||
</p>
|
||||
{#if oldToppingNamesOnly != null}
|
||||
<br />
|
||||
<Button variant="outline" class="font-bold text-red-500">
|
||||
<!-- old topping -->
|
||||
<Undo />
|
||||
<!-- {oldToppingNamesOnly} -->
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
<script lang="ts">
|
||||
import { recipeFromMachineQuery, recipeFromServerQuery } from '$lib/core/stores/recipeStore';
|
||||
import {
|
||||
currentEditingRecipeProductCode,
|
||||
latestRecipeToppingData,
|
||||
recipeFromMachineQuery,
|
||||
recipeFromServerQuery,
|
||||
referenceFromPage
|
||||
} from '$lib/core/stores/recipeStore';
|
||||
import { onMount } from 'svelte';
|
||||
import { MediaQuery } from 'svelte/reactivity';
|
||||
import { get } from 'svelte/store';
|
||||
|
|
@ -12,6 +18,12 @@
|
|||
import { addNotification } from '$lib/core/stores/noti';
|
||||
import { sendToAndroid } from '$lib/core/stores/adbWriter';
|
||||
import { env } from '$env/dynamic/public';
|
||||
|
||||
import { recipeDataEvent } from '$lib/core/stores/recipeStore';
|
||||
import { sendMessage } from '$lib/core/handlers/ws_messageSender';
|
||||
import { auth } from '$lib/core/stores/auth';
|
||||
import { departmentStore } from '$lib/core/stores/departments';
|
||||
|
||||
const isDesktop = new MediaQuery('(min-width: 768px)');
|
||||
|
||||
let currentData: any = $state();
|
||||
|
|
@ -30,7 +42,11 @@
|
|||
|
||||
let ready_to_send_brew: any[] = $state([]);
|
||||
|
||||
async function onPendingChange(newChange: { target: string; value: any }) {
|
||||
let change_value_rpl: any = $state(null);
|
||||
let callback_revert_value_if_not_save: any = $state(() => {});
|
||||
let save_change: boolean = $state(false);
|
||||
|
||||
async function onPendingChange(newChange: { target: string; value: any; ref_pd: string }) {
|
||||
console.log('detect pending change', matchMenuStatus(currentData.MenuStatus));
|
||||
hasPendingChange = true;
|
||||
|
||||
|
|
@ -52,10 +68,65 @@
|
|||
//
|
||||
// TODO: build into structure, flatten fields into 1 layer, strip off `id` (row id)
|
||||
console.log('pending change recipe list', newChange);
|
||||
}
|
||||
|
||||
ready_to_send_brew = [];
|
||||
ready_to_send_brew.push([env.PUBLIC_BREW_CURRENT_RECIPE, JSON.stringify(currentData)]);
|
||||
let isMatchedProduct = newChange.ref_pd == productCode;
|
||||
|
||||
// get latest edit
|
||||
let latest_event = get(recipeDataEvent);
|
||||
// expect edit_change_value_rpl
|
||||
console.log('latest data event', latest_event);
|
||||
|
||||
let topping_value_for_revert = latest_event?.payload.current_toppings;
|
||||
let new_topping_value_for_save = latest_event?.payload.source.toppings;
|
||||
|
||||
// console.log(
|
||||
// 'topping_data_latest',
|
||||
// get(latestRecipeToppingData),
|
||||
// 'topping_old',
|
||||
// topping_value_for_revert,
|
||||
// 'current product code',
|
||||
// get(currentEditingRecipeProductCode)
|
||||
// );
|
||||
|
||||
callback_revert_value_if_not_save = (save: any) => {
|
||||
if (!save) {
|
||||
latestRecipeToppingData.set(topping_value_for_revert);
|
||||
console.log('revert change', get(latestRecipeToppingData));
|
||||
recipeDataEvent.set({
|
||||
event_type: 'revert_change',
|
||||
payload: {},
|
||||
index: -1
|
||||
});
|
||||
} else {
|
||||
// topping part
|
||||
latestRecipeToppingData.set(new_topping_value_for_save);
|
||||
console.log('save change', get(latestRecipeToppingData));
|
||||
currentData['ToppingSet'] = latestRecipeToppingData;
|
||||
|
||||
console.log('current data', currentData);
|
||||
|
||||
if (get(referenceFromPage) == 'brew') {
|
||||
// send change to machine
|
||||
sendToAndroid({
|
||||
type: 'save_recipe_machine',
|
||||
payload: {
|
||||
time: new Date().toLocaleTimeString(),
|
||||
data: currentData
|
||||
}
|
||||
});
|
||||
} else if (get(referenceFromPage) == 'overview') {
|
||||
sendMessage({
|
||||
type: 'save_recipe',
|
||||
payload: {
|
||||
user: get(auth)?.displayName ?? 'unknown',
|
||||
country: get(departmentStore) ?? 'unknown',
|
||||
values: currentData
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// await adb.push('/sdcard/coffeevending/.curr.brewing.json', JSON.stringify(currentData));
|
||||
//
|
||||
|
|
@ -82,7 +153,17 @@
|
|||
}
|
||||
}
|
||||
|
||||
function onCloseDialog() {
|
||||
currentEditingRecipeProductCode.set('');
|
||||
callback_revert_value_if_not_save(save_change);
|
||||
|
||||
// reset back
|
||||
save_change = false;
|
||||
callback_revert_value_if_not_save = () => {};
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
save_change = false;
|
||||
//
|
||||
if (refPage === 'brew') {
|
||||
// fetch from store
|
||||
|
|
@ -109,7 +190,7 @@
|
|||
</script>
|
||||
|
||||
{#if isDesktop.current}
|
||||
<Dialog.Root>
|
||||
<Dialog.Root onOpenChangeComplete={(_cc) => onCloseDialog()}>
|
||||
<Dialog.Trigger class="w-full text-start" onselect={(e) => e.preventDefault()}
|
||||
>View</Dialog.Trigger
|
||||
>
|
||||
|
|
@ -126,8 +207,16 @@
|
|||
<RecipeDetail
|
||||
recipeData={currentData}
|
||||
{onPendingChange}
|
||||
{productCode}
|
||||
{refPage}
|
||||
on:brewNow={async () => sendBrewNow()}
|
||||
on:saveRecipe={async () => {
|
||||
save_change = true;
|
||||
|
||||
console.log('save change, check state', callback_revert_value_if_not_save);
|
||||
|
||||
addNotification('INFO:Save recipe');
|
||||
}}
|
||||
/>
|
||||
</Dialog.Content>
|
||||
</Dialog.Root>
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ export const recipeFromMachineQuery = writable<any>({});
|
|||
export const materialFromMachineQuery = writable<any>({});
|
||||
|
||||
export const referenceFromPage = writable<string>('');
|
||||
export const currentEditingRecipeProductCode = writable<string>('');
|
||||
|
||||
let worker: Worker | null = null;
|
||||
let initialized = false;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { browser } from '$app/environment';
|
|||
import { env } from '$env/dynamic/public';
|
||||
import { get, writable } from 'svelte/store';
|
||||
import { handleIncomingMessages } from '../handlers/messageHandler';
|
||||
import { queue as msgQueue } from '../handlers/ws_messageSender';
|
||||
import { queue as msgQueue, sendMessage } from '../handlers/ws_messageSender';
|
||||
import { auth } from '../client/firebase';
|
||||
import { addNotification } from './noti';
|
||||
|
||||
|
|
@ -31,6 +31,16 @@ export function connectToWebsocket() {
|
|||
msgQueue.set(queue);
|
||||
}
|
||||
}
|
||||
|
||||
// heartbeat 10s
|
||||
setInterval(() => {
|
||||
if (socket) {
|
||||
sendMessage({
|
||||
type: 'heartbeat',
|
||||
payload: {}
|
||||
});
|
||||
}
|
||||
}, 10000);
|
||||
});
|
||||
|
||||
socket.addEventListener('message', (event) => {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,14 @@ export type OutMessage =
|
|||
values: any;
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: 'save_recipe';
|
||||
payload: {
|
||||
user: string;
|
||||
country: string;
|
||||
values: any;
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: 'heartbeat';
|
||||
payload: {};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue