Improving all side of app
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import { h, Fragment } from 'preact';
|
||||
import { useState, useEffect } from 'preact/hooks';
|
||||
import { wsClient } from './lib/ws';
|
||||
import { controlDialogs, dismissControlDialog, type ControlDialog } from './lib/controldialogs';
|
||||
|
||||
// Renders dialogs pushed by server-side control-logic action.dialog nodes over
|
||||
// the WebSocket. Mounted once globally (App) since these are addressed to the
|
||||
// connected user, independent of which panel is open. info/error dialogs are
|
||||
// acknowledgements; input dialogs send a numeric response back to the server.
|
||||
export default function ControlDialogs() {
|
||||
const [reqs, setReqs] = useState<ControlDialog[]>([]);
|
||||
useEffect(() => controlDialogs.subscribe(setReqs), []);
|
||||
if (reqs.length === 0) return null;
|
||||
return <Fragment>{reqs.map(r => <ControlDialogModal key={r.id} req={r} />)}</Fragment>;
|
||||
}
|
||||
|
||||
function ControlDialogModal({ req }: { req: ControlDialog; key?: string }) {
|
||||
const isInput = req.kind === 'input';
|
||||
const [val, setVal] = useState('');
|
||||
|
||||
function ok() {
|
||||
if (isInput) {
|
||||
const n = parseFloat(val);
|
||||
wsClient.sendDialogResponse(req.id, Number.isFinite(n) ? n : null);
|
||||
}
|
||||
dismissControlDialog(req.id);
|
||||
}
|
||||
function cancel() {
|
||||
if (isInput) wsClient.sendDialogResponse(req.id, null);
|
||||
dismissControlDialog(req.id);
|
||||
}
|
||||
|
||||
function onKey(e: KeyboardEvent) {
|
||||
if (e.key === 'Enter') { e.preventDefault(); ok(); }
|
||||
if (e.key === 'Escape') { e.preventDefault(); cancel(); }
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="logic-dialog-backdrop" onKeyDown={onKey}>
|
||||
<div class={`logic-dialog logic-dialog-${req.kind}`} role="dialog">
|
||||
<div class="logic-dialog-header">
|
||||
{req.title || (req.kind === 'error' ? 'Error' : isInput ? 'Input required' : 'Info')}
|
||||
</div>
|
||||
{req.message && <div class="logic-dialog-message">{req.message}</div>}
|
||||
{isInput && (
|
||||
<div class="logic-dialog-field">
|
||||
<input class="prop-input logic-dialog-input" type="number"
|
||||
autoFocus value={val}
|
||||
onInput={(e) => setVal((e.target as HTMLInputElement).value)}
|
||||
onKeyDown={onKey} />
|
||||
</div>
|
||||
)}
|
||||
<div class="logic-dialog-actions">
|
||||
{isInput && <button class="panel-btn" onClick={cancel}>Cancel</button>}
|
||||
<button class="panel-btn panel-btn-primary" onClick={ok}>OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user