diff --git a/package.json b/package.json
index 6992829..ee952f9 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "lightcontrol",
- "version": "0.0.4",
- "description": "A Quasar Project",
+ "version": "0.0.14",
+ "description": "A Tecamino App",
"productName": "Light Control",
"author": "A. Zuercher",
"type": "module",
diff --git a/src/components/dbm/DBMTree.vue b/src/components/dbm/DBMTree.vue
index 711fd25..d2adc7d 100644
--- a/src/components/dbm/DBMTree.vue
+++ b/src/components/dbm/DBMTree.vue
@@ -10,6 +10,7 @@
no-transition
:default-expand-all="false"
v-model:expanded="expanded"
+ @update:expanded="onExpandedChange"
@lazy-load="onLazyLoad"
>
@@ -52,7 +53,7 @@
diff --git a/src/components/lights/MovingHead.vue b/src/components/lights/MovingHead.vue
index 6ea0b61..cb91c94 100644
--- a/src/components/lights/MovingHead.vue
+++ b/src/components/lights/MovingHead.vue
@@ -21,49 +21,59 @@ select
@@ -102,8 +114,6 @@ import type { Settings } from 'src/models/MovingHead';
const $q = useQuasar();
const brightness = updateBrightnessValue('MovingHead:Brightness');
-const pan = updateValue('MovingHead:Pan', true);
-const tilt = updateValue('MovingHead:Tilt', true);
const state = updateValue('MovingHead:State');
const settings = ref({
show: false,
@@ -125,7 +135,7 @@ onMounted(() => {
.then((response) => {
console.log(response);
if (response?.subscribe) {
- dbmData.value = buildTree(response.subscribe ?? []);
+ dbmData.splice(0, dbmData.length, ...buildTree(response.subscribe));
} else {
NotifyResponse($q, response);
}
@@ -149,7 +159,7 @@ onUnmounted(() => {
function changeState() {
if (brightness.value === 0) {
if (state.value === 0) {
- brightness.value = 100;
+ brightness.value = 255;
return;
}
brightness.value = state.value;
@@ -164,14 +174,13 @@ function updateValue(path: string, isDouble = false) {
get() {
const sub = getSubscriptionsByPath(path);
const value = sub ? Number(sub.value ?? 0) : 0;
- return isDouble ? Math.round((100 / 255) * value) : Math.round((100 / 255) * value);
+ return isDouble ? value : value;
},
set(val) {
- const baseValue = Math.round((255 / 100) * val);
- const setPaths = [{ path, value: baseValue }];
+ const setPaths = [{ path, value: val }];
if (isDouble) {
- setPaths.push({ path: `${path}Fine`, value: baseValue });
+ setPaths.push({ path: `${path}Fine`, value: val });
}
setValues(setPaths)
@@ -186,12 +195,11 @@ function updateBrightnessValue(path: string) {
get() {
const sub = getSubscriptionsByPath(path);
const value = sub ? Number(sub.value ?? 0) : 0;
- return Math.round((100 / 255) * value);
+ return value;
},
set(val) {
- const baseValue = Math.round((255 / 100) * val);
- const setPaths = [{ path, value: baseValue }];
- setPaths.push({ path: `${path}Fine`, value: baseValue });
+ const setPaths = [{ path, value: val }];
+ setPaths.push({ path: `${path}Fine`, value: val });
setPaths.push({ path: `MovingHead:Strobe`, value: 255 });
setValues(setPaths)
diff --git a/src/components/scenes/ScenesTab.vue b/src/components/scenes/ScenesTab.vue
new file mode 100644
index 0000000..6f2294c
--- /dev/null
+++ b/src/components/scenes/ScenesTab.vue
@@ -0,0 +1,292 @@
+
+
+
+
+
+ {{ dialogLabel }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Add New Scene
+
+ Name
+ Description
+
+
+ {{ item.name }}
+ {{ item.description }}
+
+
+
+
+
+
+
+
+
+
+
No scenes available
+
Add First Scene
+
+
+
+
diff --git a/src/composables/dbm/dbmTree.ts b/src/composables/dbm/dbmTree.ts
index ff0d18a..13871f6 100644
--- a/src/composables/dbm/dbmTree.ts
+++ b/src/composables/dbm/dbmTree.ts
@@ -1,12 +1,13 @@
-import type { Subs } from 'src/models/Subscribe';
-import { ref, nextTick, computed } from 'vue';
+import type { Subs, Subscribe } from 'src/models/Subscribe';
+import type { Ref } from 'vue';
+import { nextTick, computed, reactive, ref } from 'vue';
import { setValues } from 'src/services/websocket';
import { NotifyResponse } from 'src/composables/notify';
import type { QVueGlobals } from 'quasar';
-const Subscriptions = ref([]);
+const Subscriptions = reactive>({});
-export const dbmData = ref([]);
+export const dbmData = reactive([]);
export interface TreeNode {
path: string | undefined;
@@ -28,9 +29,10 @@ export function buildTree(subs: Subs): TreeNode[] {
const root: TreeMap = {};
- Subscriptions.value = subs;
-
for (const item of subs) {
+ if (item.path) {
+ Subscriptions[item.path] = item;
+ }
const pathParts = item.path?.split(':') ?? [];
let current = root;
@@ -54,13 +56,15 @@ export function buildTree(subs: Subs): TreeNode[] {
}
function convert(map: TreeMap): TreeNode[] {
- return Object.entries(map).map(([path, node]) => ({
- path,
- key: node.uuid ?? path, // `key` is used by QTree
- value: node.value,
- lazy: node.lazy,
- children: convert(node.__children),
- }));
+ return reactive(
+ Object.entries(map).map(([path, node]) => ({
+ path,
+ key: node.uuid ?? path, // `key` is used by QTree
+ value: node.value,
+ lazy: node.lazy,
+ children: convert(node.__children),
+ })),
+ );
}
return [
@@ -74,24 +78,32 @@ export function buildTree(subs: Subs): TreeNode[] {
}
export function getTreeElementByPath(path: string) {
- return dbmData.value.find((s) => s.path === path);
+ const sub = dbmData.find((s) => s.path === path);
+ return ref(sub);
}
-export function getSubscriptionsByUuid(uid: string | undefined) {
- return Subscriptions.value.find((s) => s.uuid === uid);
+export function getSubscriptionsByUuid(uid: string) {
+ const sub = Object.values(Subscriptions).find((sub) => sub.uuid === uid);
+ return ref(sub);
}
export function addChildrentoTree(subs: Subs) {
const ZERO_UUID = '00000000-0000-0000-0000-000000000000';
- const existingIds = new Set(Subscriptions.value.map((sub) => sub.uuid));
+ const existingIds = new Set(Object.values(Subscriptions).map((sub) => sub.uuid));
const newSubs = subs
.filter((sub) => sub.uuid !== ZERO_UUID) // Skip UUIDs with all zeroes
.filter((sub) => !existingIds.has(sub.uuid));
- Subscriptions.value.push(...newSubs);
+ for (const sub of newSubs) {
+ if (sub.path !== undefined) {
+ Subscriptions[sub.path] = sub;
+ } else {
+ console.warn('Skipping sub with undefined path', sub);
+ }
+ }
void nextTick(() => {
- dbmData.value = buildTree(Subscriptions.value);
+ dbmData.splice(0, dbmData.length, ...buildTree(Object.values(Subscriptions)));
});
}
@@ -111,39 +123,44 @@ export function removeSubtreeByParentKey(parentKey: string) {
return false;
}
- removeChildrenAndMarkLazy(dbmData.value, parentKey);
+ removeChildrenAndMarkLazy(dbmData, parentKey);
}
-export function getSubscriptionsByPath(path: string | undefined) {
- return Subscriptions.value.find((s) => s.path === path);
+export function getSubscriptionsByPath(path: string) {
+ return ref(Subscriptions[path]);
}
export function getAllSubscriptions() {
- return Subscriptions.value;
+ return Object.values(Subscriptions);
}
export function updateValue(
path1: string,
$q: QVueGlobals,
+ toggle?: Ref,
path2?: string,
path3?: string,
value3?: number,
) {
return computed({
get() {
- const sub = getSubscriptionsByPath(path1);
- const value = sub ? Number(sub.value ?? 0) : 0;
- return Math.round((100 / 255) * value);
+ const sub = getSubscriptionsByPath(toggle?.value && path2 ? path2 : path1);
+ const value = sub?.value ? Number(sub.value.value ?? 0) : 0;
+ return value;
},
set(val) {
- const baseValue = Math.round((255 / 100) * val);
- const setPaths = [{ path: path1, value: baseValue }];
- if (path2) {
+ const baseValue = val;
+ const setPaths = [];
+ if (toggle?.value && path2) {
setPaths.push({ path: path2, value: baseValue });
+ } else {
+ setPaths.push({ path: path1, value: baseValue });
}
+
if (path3) {
setPaths.push({ path: path3, value: value3 ? value3 : baseValue });
}
+
setValues(setPaths)
.then((response) => NotifyResponse($q, response))
.catch((err) => {
diff --git a/src/composables/notify.ts b/src/composables/notify.ts
index 8511431..d8b8072 100644
--- a/src/composables/notify.ts
+++ b/src/composables/notify.ts
@@ -16,7 +16,7 @@ export function NotifyResponse(
icon = 'warning';
break;
case 'error':
- color = 'orange';
+ color = 'red';
icon = 'error';
break;
}
@@ -26,8 +26,9 @@ export function NotifyResponse(
if (message === '') {
return;
}
- color = typeof response === 'string' ? response : response?.error ? 'red' : color;
- icon = typeof response === 'string' ? response : response?.error ? 'error' : icon;
+
+ color = typeof response === 'string' ? color : response?.error ? 'red' : color;
+ icon = typeof response === 'string' ? icon : response?.error ? 'error' : icon;
$q?.notify({
message: message,
color: color,
@@ -37,3 +38,30 @@ export function NotifyResponse(
});
}
}
+
+export function NotifyDialog(
+ $q: QVueGlobals,
+ title: string,
+ text: string,
+ okText?: string,
+ cancelText?: string,
+) {
+ return new Promise((resolve) => {
+ $q.dialog({
+ title: title,
+ message: text,
+ persistent: true,
+ ok: okText ?? 'OK',
+ cancel: cancelText ?? 'CANCEL',
+ })
+ .onOk(() => {
+ resolve(true);
+ })
+ .onCancel(() => {
+ resolve(false);
+ })
+ .onDismiss(() => {
+ resolve(false);
+ });
+ });
+}
diff --git a/src/models/Scene.ts b/src/models/Scene.ts
new file mode 100644
index 0000000..d93c54a
--- /dev/null
+++ b/src/models/Scene.ts
@@ -0,0 +1,9 @@
+import type { Value } from './Value';
+
+export interface Scene {
+ name: string;
+ description?: string;
+ movingHead: boolean;
+ lightBar: boolean;
+ values?: Value[];
+}
diff --git a/src/models/Set.ts b/src/models/Set.ts
index f966c15..94a937d 100644
--- a/src/models/Set.ts
+++ b/src/models/Set.ts
@@ -2,7 +2,7 @@ export type Set = {
uuid?: string | undefined;
path: string;
type?: string;
- value: number | boolean | undefined;
+ value: string | number | boolean | undefined;
create?: boolean;
};
diff --git a/src/models/Subscribe.ts b/src/models/Subscribe.ts
index 04cda90..d3dc684 100644
--- a/src/models/Subscribe.ts
+++ b/src/models/Subscribe.ts
@@ -1,8 +1,9 @@
+// API type (from backend)
export type Subscribe = {
- uuid?: string | undefined;
- path?: string | undefined;
+ uuid?: string;
+ path?: string;
depth?: number;
- value?: string | number | boolean | undefined;
+ value?: string | number | boolean;
hasChild?: boolean;
};
diff --git a/src/models/Value.ts b/src/models/Value.ts
new file mode 100644
index 0000000..f5aa642
--- /dev/null
+++ b/src/models/Value.ts
@@ -0,0 +1,7 @@
+import type { UUID } from 'crypto';
+
+export interface Value {
+ uuid?: UUID;
+ path: string;
+ value: number | string | undefined;
+}
diff --git a/src/pages/DataPage.vue b/src/pages/DataPage.vue
index 8848c6f..84afd57 100644
--- a/src/pages/DataPage.vue
+++ b/src/pages/DataPage.vue
@@ -10,6 +10,7 @@ import { NotifyResponse } from 'src/composables/notify';
import { useQuasar } from 'quasar';
const $q = useQuasar();
+
function saveDBM() {
api
.get('saveData')
diff --git a/src/pages/IndexPage.vue b/src/pages/MainPage.vue
similarity index 100%
rename from src/pages/IndexPage.vue
rename to src/pages/MainPage.vue
diff --git a/src/router/routes.ts b/src/router/routes.ts
index a2a06a2..3227cbf 100644
--- a/src/router/routes.ts
+++ b/src/router/routes.ts
@@ -5,8 +5,9 @@ const routes: RouteRecordRaw[] = [
path: '/',
component: () => import('layouts/MainLayout.vue'),
children: [
- { path: '', component: () => import('pages/IndexPage.vue') },
+ { path: '', component: () => import('pages/MainPage.vue') },
{ path: '/data', component: () => import('pages/DataPage.vue') },
+ { path: '/scenes', component: () => import('components/scenes/ScenesTab.vue') },
],
},