Files
Server/frontend/src/lib/modals/TriggerModal.svelte
T
gisle f00575fd7f
continuous-integration/drone/push Build is passing
fix hue, some ui tweaks.
2023-10-15 21:23:11 +02:00

181 lines
6.5 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script lang="ts">
import { runCommand } from "$lib/client/lucifer";
import HSplit from "$lib/components/HSplit.svelte";
import HSplitPart from "$lib/components/HSplitPart.svelte";
import Modal from "$lib/components/Modal.svelte";
import ModalBody from "$lib/components/ModalBody.svelte";
import ModalSection from "$lib/components/ModalSection.svelte";
import ScriptLineBlock from "$lib/components/scripting/ScriptLineBlock.svelte";
import { getModalContext } from "$lib/contexts/ModalContext.svelte";
import { getStateContext } from "$lib/contexts/StateContext.svelte";
import { fromEditableTrigger, newEditableScriptLine, newEditableTrigger, toEditableScriptLine, toEditableTrigger, type TriggerEditable } from "$lib/models/script";
const { state, deviceList, maskList } = getStateContext();
const { modal } = getModalContext();
let show = false;
let disabled = false;
let selectedTrigger = "";
let deleteCount = 3;
let current: TriggerEditable = newEditableTrigger("*", "");
async function submitForm() {
disabled = true;
try {
const before = Object.keys($state.triggers);
await runCommand({updateTrigger: fromEditableTrigger(current)});
if (current.id === null) {
await new Promise(resolve => setTimeout(resolve, 1000));
const after = Object.keys($state.triggers);
selectedTrigger = after.find(id => !before.includes(id)) || triggerList[0].id;
}
} catch(_) {}
deleteCount = 3;
disabled = false;
}
async function deleteTrigger() {
deleteCount -= 1;
if (deleteCount <= 0) {
try {
await runCommand({deleteTrigger: {id: selectedTrigger}});
await new Promise(resolve => setTimeout(resolve, 1000));
selectedTrigger = triggerList[0]?.id || "";
} catch(_) {}
}
}
function loadTrigger(id: string) {
deleteCount = 3;
if (id !== "") {
current = toEditableTrigger($state.triggers[id]);
} else {
current = {...current, id: null};
}
}
function addPreLine() {
current.scriptPre = [...current.scriptPre, newEditableScriptLine()]
}
function addPostLine() {
current.scriptPost = [...current.scriptPost, newEditableScriptLine()]
}
function ensureButton(buttonList: string[]) {
if (!buttonList.includes(current.button)) {
current.button = buttonList[0];
}
}
$: loadTrigger(selectedTrigger);
$: triggerList = Object.keys($state.triggers).map(k => $state.triggers[k]).sort((a, b) => (
a.event.localeCompare(b.event)
|| a.deviceMatch.localeCompare(b.deviceMatch)
|| a.parameter.localeCompare(b.parameter)
));
$: buttonList = $deviceList.filter(d => d.aliases.includes(current.deviceMatch))
.flatMap(d => d.hwState?.buttons||[])
.sort()
.filter((e,i,a) => a[i-1] !== e);
$: scriptList = Object.keys($state.scripts).sort();
$: maskGroups = $maskList.map(s => s.split(":")[1]).filter((e, i, a) => a[i-1] !== e).sort().reverse();
$: show = ($modal.kind === "trigger.edit");
$: if (scriptList.length > 0 && current.scriptName === "") { current.scriptName = scriptList[0]; };
$: ensureButton(buttonList);
</script>
<form novalidate on:submit|preventDefault={submitForm}>
<Modal
ultrawide closable show={show}
titleText="Trigger Editor"
disabled={disabled}
submitText="Save Trigger"
>
<ModalBody>
<HSplit>
<HSplitPart weight={1}>
<label for="mask">Trigger</label>
<select bind:value={selectedTrigger}>
{#each triggerList as trigger (trigger.id)}
<option value={trigger.id}>{trigger.name || `${trigger.deviceMatch} – ${trigger.event} ${trigger.parameter}`}</option>
{/each}
<option value="">New Trigger</option>
</select>
</HSplitPart>
<HSplitPart weight={2}>
</HSplitPart>
</HSplit>
<HSplit>
<HSplitPart weight={1}>
<label for="mask">Event</label>
<select bind:value={current.event}>
<option value="Button">Button Pressed</option>
<option value="Time">Time Changed</option>
</select>
</HSplitPart>
<HSplitPart weight={1}>
{#if current.event === "Button"}
<label for="mask">Button</label>
<select bind:value={current.button}>
{#each buttonList as buttonOption}
<option value={buttonOption}>{buttonOption}</option>
{/each}
</select>
{:else}
<label for="mask">Time</label>
<input type="time" bind:value={current.time} />
{/if}
</HSplitPart>
<HSplitPart weight={1}>
{#if current.event === "Button"}
<label for="mask">Device</label>
<select bind:value={current.deviceMatch}>
{#each maskGroups as g}
<optgroup label="{g.slice(0, 1).toUpperCase() + g.slice(1)}">
{#each $maskList.filter(m => m.split(":")[1] === g) as mask}
<option value={mask}>{mask}</option>
{/each}
</optgroup>
{/each}
</select>
{/if}
</HSplitPart>
</HSplit>
<HSplit>
<HSplitPart weight={1}>
<label for="mask">Run Script</label>
<select bind:value={current.scriptName}>
{#each scriptList as script}
<option value={script}>{script}</option>
{/each}
</select>
</HSplitPart>
<HSplitPart weight={1}>
<label for="mask">Script Target</label>
<select bind:value={current.scriptTarget}>
{#each maskGroups as g}
<optgroup label="{g.slice(0, 1).toUpperCase() + g.slice(1)}">
{#each $maskList.filter(m => m.split(":")[1] === g) as mask}
<option value={mask}>{mask}</option>
{/each}
</optgroup>
{/each}
</select>
</HSplitPart>
<HSplitPart weight={1}>
</HSplitPart>
</HSplit>
<ModalSection expanded disableExpandToggle title="Trigger-Specific Scripting">
<ScriptLineBlock add on:add={addPreLine} label="Before Script" bind:value={current.scriptPre} />
<ScriptLineBlock add on:add={addPostLine} label="After Script" bind:value={current.scriptPost} />
</ModalSection>
</ModalBody>
<button slot="secondary-button-1" disabled={disabled || selectedTrigger === ""} on:click|preventDefault={deleteTrigger}>Delete ({deleteCount})</button>
</Modal>
</form>