ADD: Profile drag&drop (includes config restructure)

This commit is contained in:
Robert Kossessa
2024-02-06 16:47:28 +01:00
parent fffa22afea
commit 287444e9b7
4 changed files with 550 additions and 513 deletions

View File

@@ -7,7 +7,7 @@
v-if="nameEditable && editing" v-if="nameEditable && editing"
class="flex-1 flex h-full text-left whitespace-nowrap overflow-hidden" class="flex-1 flex h-full text-left whitespace-nowrap overflow-hidden"
:class="{'bg-zinc-300' : selected}" :class="{'bg-zinc-300' : selected}"
@submit.prevent="profile.name = nameInput; editing=false"> @submit.prevent="store.renameProfile(profile.id, nameInput); editing=false">
<input <input
ref="profileNameInput" v-model="nameInput" ref="profileNameInput" v-model="nameInput"
onfocus="this.select()" :placeholder="$t('profiles.name_placeholder')" onfocus="this.select()" :placeholder="$t('profiles.name_placeholder')"
@@ -30,7 +30,7 @@
'hover:bg-zinc-900 bg-opacity-50 text-muted-foreground': !selected}" 'hover:bg-zinc-900 bg-opacity-50 text-muted-foreground': !selected}"
class="flex-1 h-12 rounded-r-lg text-left text-sm whitespace-nowrap overflow-hidden text-ellipsis pr-4 transition-all" class="flex-1 h-12 rounded-r-lg text-left text-sm whitespace-nowrap overflow-hidden text-ellipsis pr-4 transition-all"
@click="!editing && $emit('select') && $refs.profileTitle.scramble()"> @click="!editing && $emit('select') && $refs.profileTitle.scramble()">
<span class="ml-2 w-4 mr-2" :class="{'ml-2': !draggable}"> <span class="ml-2 w-4 mr-2 cursor-grab" :class="{'ml-2': !draggable}">
<GripHorizontal <GripHorizontal
v-if="draggable" v-if="draggable"
:class="{'text-zinc-600': selected, :class="{'text-zinc-600': selected,
@@ -98,21 +98,23 @@
import { Check, Copy, PenLine, Trash2, X, GripHorizontal } from 'lucide-vue-next' import { Check, Copy, PenLine, Trash2, X, GripHorizontal } from 'lucide-vue-next'
import ScrambleText from '@/components/common/ScrambleText.vue' import ScrambleText from '@/components/common/ScrambleText.vue'
import { nextTick, ref } from 'vue' import { nextTick, ref } from 'vue'
import { useStore } from '@/store'
const store = useStore()
defineEmits(['select', 'duplicate', 'delete']) defineEmits(['select', 'duplicate', 'delete'])
const nameSubmitButton = ref(null) const nameSubmitButton = ref(null)
const profile = defineModel({
type: Object,
required: true,
default: () => ({
id: '1234',
name: 'Profile Name',
}),
})
const props = defineProps({ const props = defineProps({
profile: {
type: Object,
default: () => ({
id: '1234',
name: 'Profile Name',
}),
required: true,
},
selected: { selected: {
type: Boolean, type: Boolean,
default: false, default: false,
@@ -149,7 +151,7 @@ function onNameInputBlur(e) {
const profileNameInput = ref(null) const profileNameInput = ref(null)
const nameInput = ref(profile.value.name) const nameInput = ref(props.profile.name)
const editing = ref(props.initEditing) const editing = ref(props.initEditing)

View File

@@ -52,23 +52,35 @@
</div> </div>
<div v-else> <div v-else>
<Collapsible <Collapsible
v-for="[profileTag, tagProfiles] in filteredProfilesByTag" :key="profileTag" v-for="(category, categoryIndex) in store.profileCategories" :key="categoryIndex"
v-model:open="collapse[profileTag]" v-model:open="collapse[index]"
:default-open="true"> :default-open="true">
<!-- TODO: Make profile groups computed instead defining them of using v-for --> <!-- TODO: Make profile groups computed instead defining them of using v-for -->
<CollapsibleTrigger <CollapsibleTrigger
class="w-full h-12 py-2 text-left text-muted-foreground text-sm bg-zinc-900 border-0 border-b"> class="w-full h-12 py-2 text-left text-muted-foreground text-sm bg-zinc-900 border-0 border-b">
<ChevronRight class="chevrot h-4 w-4 mb-0.5 ml-4 inline-block transition-transform" /> <ChevronRight class="chevrot h-4 w-4 mb-0.5 ml-4 inline-block transition-transform" />
{{ profileTag }}<span class="font-heading text-sm text-zinc-600"> ({{ tagProfiles.length }})</span> {{ category.name }}<span class="font-heading text-sm text-zinc-600"> ({{ category.profiles?.length || 0
}})</span>
</CollapsibleTrigger> </CollapsibleTrigger>
<CollapsibleContent> <CollapsibleContent>
<draggable
:list="category.profiles"
group="profiles"
item-key="name"
v-bind="dragOptions"
@change="(event)=>onProfileDrop(event, categoryIndex)"
>
<template #item="{ element }">
<ProfileButton
:key="element.id"
:profile="element"
:selected="store.selectedProfile?.id === element.id"
@select="store.selectProfile(element.id); showProfileList=false"
@duplicate="store.duplicateProfile(element.id)"
@delete="store.removeProfile(element.id)" />
</template>
</draggable>
<!-- TODO: Insert draggable component here --> <!-- TODO: Insert draggable component here -->
<ProfileButton
v-for="(profile, index) in tagProfiles" :key="profile.id" v-model="tagProfiles[index]"
:selected="store.selectedProfile?.id === profile.id"
@select="store.selectProfile(profile.id); showProfileList=false"
@duplicate="store.duplicateProfile(profile.id)"
@delete="store.deleteProfile(profile.id)" />
</CollapsibleContent> </CollapsibleContent>
</Collapsible> </Collapsible>
</div> </div>
@@ -88,6 +100,7 @@ import ScrambleText from '@/components/common/ScrambleText.vue'
import { useStore } from '@/store.js' import { useStore } from '@/store.js'
import ProfileButton from '@/components/profile/ProfileButton.vue' import ProfileButton from '@/components/profile/ProfileButton.vue'
import ProfileConfig from '@/components/profile/ProfileConfig.vue' import ProfileConfig from '@/components/profile/ProfileConfig.vue'
import draggable from 'vuedraggable'
defineProps({ defineProps({
showFilter: { showFilter: {
@@ -129,6 +142,25 @@ const filteredProfilesByTag = computed(() => {
return map return map
}) })
const onProfileDrop = (event, categoryIndex) => {
if (event.moved) {
const profile = event.moved.element
const oldIndex = event.moved.oldIndex
const newIndex = event.moved.newIndex
store.moveProfile(profile.id, oldIndex, newIndex)
}
if (event.added) {
const profile = event.added.element
const newIndex = event.added.newIndex
store.changeProfileCategory(profile.id, categoryIndex, newIndex)
}
}
const dragOptions = {
group: 'profiles',
animation: 150,
}
</script> </script>
<style scoped> <style scoped>
[data-state=open] > .chevrot { [data-state=open] > .chevrot {

View File

@@ -1,423 +1,443 @@
{ {
"profiles": [ "categories": [
{ {
"id": "1732", "name": "Binaris",
"name": "Official Profile #1", "profiles": [
"profileTag": "Binaris", {
"profileConfig": { "id": "1732",
"profileDesc": "KORG MINILOGUE OSCILLATOR 1", "name": "Official Profile #1",
"profileType": 1, "profileTag": "Binaris",
"showDesc": true "profileConfig": {
}, "profileDesc": "KORG MINILOGUE OSCILLATOR 1",
"feedbackConfig": { "profileType": 1,
"feedbackEn": true, "showDesc": true
"feedbackType": "fd", },
"multiRev": false, "feedbackConfig": {
"feedbackStrength": 1, "feedbackEn": true,
"endstopStrength": 1, "feedbackType": "fd",
"outputRamp": 10000, "multiRev": false,
"pos": 140, "feedbackStrength": 1,
"secondaryHaptic": true, "endstopStrength": 1,
"secondaryVol": 5 "outputRamp": 10000,
}, "pos": 140,
"mappingConfig": { "secondaryHaptic": true,
"internalMacro": false, "secondaryVol": 5
"knobMap": "arrL", },
"switchA": "shift", "mappingConfig": {
"switchB": "ctrl", "internalMacro": false,
"switchC": "alt", "knobMap": "arrL",
"switchD": "esc" "switchA": "shift",
}, "switchB": "ctrl",
"ledConfig": { "switchC": "alt",
"ledEnable": true, "switchD": "esc"
"ledBrightness": 100, },
"ledMode": 1, "ledConfig": {
"primary": { "ledEnable": true,
"h": 255, "ledBrightness": 100,
"s": 255, "ledMode": 1,
"v": 100 "primary": {
"h": 255,
"s": 255,
"v": 100
},
"secondary": {
"h": 255,
"s": 255,
"v": 100
},
"pointer": {
"h": 255,
"s": 255,
"v": 10
}
},
"guiConfig": {
"guiEnable": true
}
}, },
"secondary": { {
"h": 255, "id": "1232",
"s": 255, "name": "DUPLICATE ID",
"v": 100 "profileTag": "Binaris",
}, "profileConfig": {
"pointer": { "profileDesc": "KORG MINILOGUE OSCILLATOR 1",
"h": 255, "profileType": 1,
"s": 255, "showDesc": true
"v": 10 },
"feedbackConfig": {
"feedbackEn": true,
"feedbackType": "fd",
"multiRev": false,
"feedbackStrength": 1,
"endstopStrength": 1,
"outputRamp": 10000,
"pos": 140,
"secondaryHaptic": true,
"secondaryVol": 5
},
"mappingConfig": {
"internalMacro": false,
"knobMap": "arrL",
"switchA": "shift",
"switchB": "ctrl",
"switchC": "alt",
"switchD": "esc"
},
"ledConfig": {
"ledEnable": true,
"ledBrightness": 100,
"ledMode": 1,
"primary": {
"h": 255,
"s": 255,
"v": 100
},
"secondary": {
"h": 255,
"s": 255,
"v": 100
},
"pointer": {
"h": 255,
"s": 255,
"v": 10
}
},
"guiConfig": {
"guiEnable": true
}
} }
}, ]
"guiConfig": {
"guiEnable": true
}
}, },
{ {
"id": "5867", "name": "Third Party",
"name": "My First Profile 😳", "profiles": [
"profileTag": "Custom", {
"profileConfig": { "id": "2891",
"profileDesc": "KORG MINILOGUE OSCILLATOR 1", "name": "Color Grading M-2",
"profileType": 1, "profileTag": "Third Party",
"showDesc": true "profileConfig": {
}, "profileDesc": "KORG MINILOGUE OSCILLATOR 1",
"feedbackConfig": { "profileType": 1,
"feedbackEn": true, "showDesc": true
"feedbackType": "fd", },
"multiRev": false, "feedbackConfig": {
"feedbackStrength": 1, "feedbackEn": true,
"endstopStrength": 1, "feedbackType": "fd",
"outputRamp": 10000, "multiRev": false,
"pos": 140, "feedbackStrength": 1,
"secondaryHaptic": true, "endstopStrength": 1,
"secondaryVol": 5 "outputRamp": 10000,
}, "pos": 140,
"mappingConfig": { "secondaryHaptic": true,
"internalMacro": false, "secondaryVol": 5
"knobMap": "arrL", },
"switchA": "shift", "mappingConfig": {
"switchB": "ctrl", "internalMacro": false,
"switchC": "alt", "knobMap": "arrL",
"switchD": "esc" "switchA": "shift",
}, "switchB": "ctrl",
"ledConfig": { "switchC": "alt",
"ledEnable": true, "switchD": "esc"
"ledBrightness": 100, },
"ledMode": 1, "ledConfig": {
"primary": { "ledEnable": true,
"h": 255, "ledBrightness": 100,
"s": 255, "ledMode": 1,
"v": 100 "primary": {
}, "h": 255,
"secondary": { "s": 255,
"h": 255, "v": 100
"s": 255, },
"v": 100 "secondary": {
}, "h": 255,
"pointer": { "s": 255,
"h": 255, "v": 100
"s": 255, },
"v": 10 "pointer": {
"h": 255,
"s": 255,
"v": 10
}
},
"guiConfig": {
"guiEnable": true
}
} }
}, ]
"guiConfig": {
"guiEnable": true
}
}, },
{ {
"id": "1232", "name": "Custom",
"name": "AN0Th3R Pr0f1l3", "profiles": [
"profileTag": "Custom", {
"profileConfig": { "id": "5867",
"profileDesc": "KORG MINILOGUE OSCILLATOR 1", "name": "My First Profile 😳",
"profileType": 1, "profileTag": "Custom",
"showDesc": true "profileConfig": {
}, "profileDesc": "KORG MINILOGUE OSCILLATOR 1",
"feedbackConfig": { "profileType": 1,
"feedbackEn": true, "showDesc": true
"feedbackType": "fd", },
"multiRev": false, "feedbackConfig": {
"feedbackStrength": 1, "feedbackEn": true,
"endstopStrength": 1, "feedbackType": "fd",
"outputRamp": 10000, "multiRev": false,
"pos": 140, "feedbackStrength": 1,
"secondaryHaptic": true, "endstopStrength": 1,
"secondaryVol": 5 "outputRamp": 10000,
}, "pos": 140,
"mappingConfig": { "secondaryHaptic": true,
"internalMacro": false, "secondaryVol": 5
"knobMap": "arrL", },
"switchA": "shift", "mappingConfig": {
"switchB": "ctrl", "internalMacro": false,
"switchC": "alt", "knobMap": "arrL",
"switchD": "esc" "switchA": "shift",
}, "switchB": "ctrl",
"ledConfig": { "switchC": "alt",
"ledEnable": true, "switchD": "esc"
"ledBrightness": 100, },
"ledMode": 1, "ledConfig": {
"primary": { "ledEnable": true,
"h": 255, "ledBrightness": 100,
"s": 255, "ledMode": 1,
"v": 100 "primary": {
"h": 255,
"s": 255,
"v": 100
},
"secondary": {
"h": 255,
"s": 255,
"v": 100
},
"pointer": {
"h": 255,
"s": 255,
"v": 10
}
},
"guiConfig": {
"guiEnable": true
}
}, },
"secondary": { {
"h": 255, "id": "1232",
"s": 255, "name": "AN0Th3R Pr0f1l3",
"v": 100 "profileTag": "Custom",
"profileConfig": {
"profileDesc": "KORG MINILOGUE OSCILLATOR 1",
"profileType": 1,
"showDesc": true
},
"feedbackConfig": {
"feedbackEn": true,
"feedbackType": "fd",
"multiRev": false,
"feedbackStrength": 1,
"endstopStrength": 1,
"outputRamp": 10000,
"pos": 140,
"secondaryHaptic": true,
"secondaryVol": 5
},
"mappingConfig": {
"internalMacro": false,
"knobMap": "arrL",
"switchA": "shift",
"switchB": "ctrl",
"switchC": "alt",
"switchD": "esc"
},
"ledConfig": {
"ledEnable": true,
"ledBrightness": 100,
"ledMode": 1,
"primary": {
"h": 255,
"s": 255,
"v": 100
},
"secondary": {
"h": 255,
"s": 255,
"v": 100
},
"pointer": {
"h": 255,
"s": 255,
"v": 10
}
},
"guiConfig": {
"guiEnable": true
}
}, },
"pointer": { {
"h": 255, "id": "1337",
"s": 255, "name": "Brought to you by...",
"v": 10 "profileTag": "Custom",
"profileConfig": {
"profileDesc": "Hwhawdhuawhdaddjwidjaiwdiawjdijaidjiawjdj",
"profileType": 1,
"showDesc": true
},
"feedbackConfig": {
"feedbackEn": true,
"feedbackType": "fd",
"multiRev": false,
"feedbackStrength": 1,
"endstopStrength": 1,
"outputRamp": 10000,
"pos": 140,
"secondaryHaptic": true,
"secondaryVol": 5
},
"mappingConfig": {
"internalMacro": false,
"knobMap": "arrL",
"switchA": "shift",
"switchB": "ctrl",
"switchC": "alt",
"switchD": "esc"
},
"ledConfig": {
"ledEnable": true,
"ledBrightness": 100,
"ledMode": 1,
"primary": {
"h": 255,
"s": 255,
"v": 100
},
"secondary": {
"h": 255,
"s": 255,
"v": 100
},
"pointer": {
"h": 255,
"s": 255,
"v": 10
}
},
"guiConfig": {
"guiEnable": true
}
},
{
"id": "0420",
"name": "Overflow Testing Inc.",
"profileTag": "Custom",
"profileConfig": {
"profileDesc": "whaduwhawhdwadhwaudhuwahdu huwadhuawhduhwadhuawhu dwaijdwajiawjdijawidiwajidawidiawjddhawgdjzgesfgkhsfsza",
"profileType": 1,
"showDesc": true
},
"feedbackConfig": {
"feedbackEn": true,
"feedbackType": "fd",
"multiRev": false,
"feedbackStrength": 1,
"endstopStrength": 1,
"outputRamp": 10000,
"pos": 140,
"secondaryHaptic": true,
"secondaryVol": 5
},
"mappingConfig": {
"internalMacro": false,
"knobMap": "arrL",
"switchA": "shift",
"switchB": "ctrl",
"switchC": "alt",
"switchD": "esc"
},
"ledConfig": {
"ledEnable": true,
"ledBrightness": 100,
"ledMode": 1,
"primary": {
"h": 255,
"s": 255,
"v": 100
},
"secondary": {
"h": 255,
"s": 255,
"v": 100
},
"pointer": {
"h": 255,
"s": 255,
"v": 10
}
},
"guiConfig": {
"guiEnable": true
}
} }
}, ]
"guiConfig": {
"guiEnable": true
}
}, },
{ {
"id": "1232", "name": "Uncategorized",
"name": "DUPLICATE ID", "profiles": [
"profileTag": "Binaris", {
"profileConfig": { "id": "5238",
"profileDesc": "KORG MINILOGUE OSCILLATOR 1", "name": "sdfsdf (Invalid)",
"profileType": 1, "profileTag": "Uncategorized",
"showDesc": true "profileConfig": {
}, "profileDesc": "",
"feedbackConfig": { "profileType": 1,
"feedbackEn": true, "showDesc": true
"feedbackType": "fd", },
"multiRev": false, "feedbackConfig": {
"feedbackStrength": 1, "feedbackEn": true,
"endstopStrength": 1, "feedbackType": "fd",
"outputRamp": 10000, "multiRev": false,
"pos": 140, "feedbackStrength": 1,
"secondaryHaptic": true, "endstopStrength": 1,
"secondaryVol": 5 "outputRamp": 10000,
}, "minMaxPos": [
"mappingConfig": { 0,
"internalMacro": false, 156
"knobMap": "arrL", ],
"switchA": "shift", "secondaryHaptic": true,
"switchB": "ctrl", "secondaryVol": 5
"switchC": "alt", },
"switchD": "esc" "mappingConfig": {
}, "internalMacro": false,
"ledConfig": { "knobMap": "arrL",
"ledEnable": true, "switchA": "shift",
"ledBrightness": 100, "switchB": "ctrl",
"ledMode": 1, "switchC": "alt",
"primary": { "switchD": "esc"
"h": 255, },
"s": 255, "ledConfig": {
"v": 100 "ledEnable": true,
}, "ledBrightness": 100,
"secondary": { "ledMode": 1,
"h": 255, "primary": {
"s": 255, "h": 100,
"v": 100 "s": 100,
}, "v": 100
"pointer": { },
"h": 255, "secondary": {
"s": 255, "h": 120,
"v": 10 "s": 120,
"v": 120
},
"pointer": {
"h": 255,
"s": 255,
"v": 255
}
},
"guiConfig": {
"guiEnable": true
}
} }
}, ]
"guiConfig": {
"guiEnable": true
}
},
{
"id": "2891",
"name": "Color Grading M-2",
"profileTag": "Third Party",
"profileConfig": {
"profileDesc": "KORG MINILOGUE OSCILLATOR 1",
"profileType": 1,
"showDesc": true
},
"feedbackConfig": {
"feedbackEn": true,
"feedbackType": "fd",
"multiRev": false,
"feedbackStrength": 1,
"endstopStrength": 1,
"outputRamp": 10000,
"pos": 140,
"secondaryHaptic": true,
"secondaryVol": 5
},
"mappingConfig": {
"internalMacro": false,
"knobMap": "arrL",
"switchA": "shift",
"switchB": "ctrl",
"switchC": "alt",
"switchD": "esc"
},
"ledConfig": {
"ledEnable": true,
"ledBrightness": 100,
"ledMode": 1,
"primary": {
"h": 255,
"s": 255,
"v": 100
},
"secondary": {
"h": 255,
"s": 255,
"v": 100
},
"pointer": {
"h": 255,
"s": 255,
"v": 10
}
},
"guiConfig": {
"guiEnable": true
}
},
{
"id": "5238",
"name": "sdfsdf (Invalid)",
"profileTag": "Uncategorized",
"profileConfig": {
"profileDesc": "",
"profileType": 1,
"showDesc": true
},
"feedbackConfig": {
"feedbackEn": true,
"feedbackType": "fd",
"multiRev": false,
"feedbackStrength": 1,
"endstopStrength": 1,
"outputRamp": 10000,
"minMaxPos": [
0,
156
],
"secondaryHaptic": true,
"secondaryVol": 5
},
"mappingConfig": {
"internalMacro": false,
"knobMap": "arrL",
"switchA": "shift",
"switchB": "ctrl",
"switchC": "alt",
"switchD": "esc"
},
"ledConfig": {
"ledEnable": true,
"ledBrightness": 100,
"ledMode": 1,
"primary": {
"h": 100,
"s": 100,
"v": 100
},
"secondary": {
"h": 120,
"s": 120,
"v": 120
},
"pointer": {
"h": 255,
"s": 255,
"v": 255
}
},
"guiConfig": {
"guiEnable": true
}
},
{
"id": "1337",
"name": "Brought to you by...",
"profileTag": "Custom",
"profileConfig": {
"profileDesc": "Hwhawdhuawhdaddjwidjaiwdiawjdijaidjiawjdj",
"profileType": 1,
"showDesc": true
},
"feedbackConfig": {
"feedbackEn": true,
"feedbackType": "fd",
"multiRev": false,
"feedbackStrength": 1,
"endstopStrength": 1,
"outputRamp": 10000,
"pos": 140,
"secondaryHaptic": true,
"secondaryVol": 5
},
"mappingConfig": {
"internalMacro": false,
"knobMap": "arrL",
"switchA": "shift",
"switchB": "ctrl",
"switchC": "alt",
"switchD": "esc"
},
"ledConfig": {
"ledEnable": true,
"ledBrightness": 100,
"ledMode": 1,
"primary": {
"h": 255,
"s": 255,
"v": 100
},
"secondary": {
"h": 255,
"s": 255,
"v": 100
},
"pointer": {
"h": 255,
"s": 255,
"v": 10
}
},
"guiConfig": {
"guiEnable": true
}
},
{
"id": "0420",
"name": "Overflow Testing Inc.",
"profileTag": "Custom",
"profileConfig": {
"profileDesc": "whaduwhawhdwadhwaudhuwahdu huwadhuawhduhwadhuawhu dwaijdwajiawjdijawidiwajidawidiawjddhawgdjzgesfgkhsfsza",
"profileType": 1,
"showDesc": true
},
"feedbackConfig": {
"feedbackEn": true,
"feedbackType": "fd",
"multiRev": false,
"feedbackStrength": 1,
"endstopStrength": 1,
"outputRamp": 10000,
"pos": 140,
"secondaryHaptic": true,
"secondaryVol": 5
},
"mappingConfig": {
"internalMacro": false,
"knobMap": "arrL",
"switchA": "shift",
"switchB": "ctrl",
"switchC": "alt",
"switchD": "esc"
},
"ledConfig": {
"ledEnable": true,
"ledBrightness": 100,
"ledMode": 1,
"primary": {
"h": 255,
"s": 255,
"v": 100
},
"secondary": {
"h": 255,
"s": 255,
"v": 100
},
"pointer": {
"h": 255,
"s": 255,
"v": 10
}
},
"guiConfig": {
"guiEnable": true
}
} }
] ]
} }

View File

@@ -13,7 +13,7 @@ const ajv = new Ajv()
export const useStore = defineStore('main', { export const useStore = defineStore('main', {
state: () => { state: () => {
return { return {
profiles: [], profileCategories: [],
selectedProfileId: null, selectedProfileId: null,
connected: false, connected: false,
selectedFeature: 'knob', selectedFeature: 'knob',
@@ -22,108 +22,97 @@ export const useStore = defineStore('main', {
configPages: { configPages: {
knob: { knob: {
mapping: { mapping: {
titleKey: 'config_options.mapping_configuration.title', titleKey: 'config_options.mapping_configuration.title', component: MappingConfig,
component: MappingConfig, }, feedback: {
titleKey: 'config_options.feedback_designer.title', component: KnobFeedbackConfig,
}, lighting: {
titleKey: 'config_options.light_designer.title', component: KnobLightConfig,
}, },
feedback: { }, key: {
titleKey: 'config_options.feedback_designer.title',
component: KnobFeedbackConfig,
},
lighting: {
titleKey: 'config_options.light_designer.title',
component: KnobLightConfig,
},
},
key: {
mapping: { mapping: {
titleKey: 'config_options.mapping_configuration.title', titleKey: 'config_options.mapping_configuration.title', component: MappingConfig,
component: MappingConfig, }, lighting: {
}, titleKey: 'config_options.light_designer.title', component: KeyLightConfig,
lighting: {
titleKey: 'config_options.light_designer.title',
component: KeyLightConfig,
}, },
}, },
}, },
} }
}, }, getters: {
getters: profiles: (state) => state.profileCategories.flatMap(c => c.profiles),
{ profileIds: (state) => state.profiles.map(p => p.id),
profileIds: (state) => state.profiles.map(p => p.id), selectedProfileCategory: (state) => state.profileCategories.find(c => c.profiles.find(p => p.id === state.selectedProfileId)),
selectedProfile: (state) => state.profiles.find(p => p.id === state.selectedProfileId), selectedProfile: (state) => state.profiles.find(p => p.id === state.selectedProfileId),
currentConfigComponent: (state) => state.configPages[state.selectedFeature][state.currentConfigPage]?.component || WIP, currentConfigComponent: (state) => state.configPages[state.selectedFeature][state.currentConfigPage]?.component || WIP,
currentConfigPages: (state) => state.configPages[state.selectedFeature] || {}, currentConfigPages: (state) => state.configPages[state.selectedFeature] || {},
} }, actions: {
,
actions: {
selectProfile(id) { selectProfile(id) {
if (!this.profileIds.includes(id)) return false if (!this.profileIds.includes(id)) return false
this.selectedProfileId = id this.selectedProfileId = id
return true return true
} }, addProfile(profile, categoryIndex, newIndex) {
, const category = this.profileCategories[categoryIndex]
addProfile() { category.profiles.splice(newIndex, 0, profile)
console.log('addProfile is not implemented') }, removeProfile(profileId) {
} const category = this.profileCategories.find(c => c.profiles.find(p => p.id === profileId))
, const index = category.profiles.findIndex(p => p.id === profileId)
duplicateProfile(id) { category.profiles.splice(index, 1)
const originalProfile = this.profiles.find(p => p.id === id) }, duplicateProfile(profileId) {
const originalProfile = this.profiles.find(p => p.id === profileId)
const newProfile = JSON.parse(JSON.stringify(originalProfile)) const newProfile = JSON.parse(JSON.stringify(originalProfile))
newProfile.id = this.newProfileId(originalProfile.id) newProfile.id = this.newProfileId(originalProfile.id)
newProfile.name = this.newProfileName(originalProfile.name) newProfile.name = this.newProfileName(originalProfile.name)
this.profiles.push(newProfile) const category = this.categories.find(c => c.profiles.find(p => p.id === profileId))
this.selectedProfileId = newProfile.id category.profiles.push(newProfile)
return newProfile.id return newProfile.id
} }, moveProfile(profileId, oldIndex, newIndex) {
, // Find the profile category, then swap the profiles at the old and new indices
deleteProfile(id) { const category = this.profileCategories.find(c => c.profiles.find(p => p.id === profileId))
const index = this.profiles.findIndex(p => p.id === id) const tmpProfile = category.profiles[newIndex]
if (index >= 0) { category.profiles[newIndex] = category.profiles[oldIndex]
this.profiles.splice(index, 1) category.profiles[newIndex] = tmpProfile
if (this.selectedProfileId === id) { }, changeProfileCategory(profileId, newCategoryIndex, newIndex) {
this.selectedProfileId = this.profiles[0]?.id || null const profile = this.profiles.find(p => p.id === profileId)
} const oldCategory = this.profileCategories.find(c => c.profiles.find(p => p.id === profileId))
return true const newCategory = this.profileCategories[newCategoryIndex]
} oldCategory.profiles = oldCategory.profiles.filter(p => p.id !== profileId)
return false newCategory.profiles.splice(newIndex, 0, profile)
} }, renameProfile(profileId, newName) {
, const profile = this.profiles.find(p => p.id === profileId)
fetchProfiles() { profile.name = newName
Axios.get('http://localhost:3001/profiles').then((res) => { }, fetchProfiles() {
const profiles = res.data Axios.get('http://localhost:3001/categories').then((res) => {
console.log(profiles) const categories = res.data
console.log(categories)
const ids = new Set() const ids = new Set()
const validate = ajv.compile(schema) const validate = ajv.compile(schema)
this.$patch({ this.$patch({
profiles: profiles.filter((profile) => { profileCategories: categories.map((category) => ({
if (!validate(profile)) { name: category.name, profiles: category.profiles.filter((profile) => {
console.error('Failed to validate profile: ' + profile.name, validate.errors) // TODO: Validation seems to be broken right now
return false if (!validate(profile)) {
} console.error('Failed to validate profile: ' + profile.name, validate.errors)
if (ids.has(profile.id)) { return false
console.error('Duplicate profile id: ' + profile.id + ' for profile: ' + profile.name) }
return false if (ids.has(profile.id)) {
} console.error('Duplicate profile id: ' + profile.id + ' for profile: ' + profile.name)
ids.add(profile.id) return false
return true }
}), ids.add(profile.id)
//selectedProfileId: profiles[0]?.id || null, return true
}),
})), selectedProfileId: categories[0]?.profiles[0]?.id || null,
}) })
}).catch((err) => { }).catch((err) => {
console.error(err) console.error(err)
}) })
} }, newProfileName(originalName = '') {
,
newProfileName(originalName = '') {
let name = originalName let name = originalName
let i = 1 let i = 1
while (this.profiles.find(p => p.name === name)) { while (this.profiles.find(p => p.name === name)) {
name = `${originalName} (${i++})` name = `${originalName} (${i++})`
} }
return name return name
} }, newProfileId(originalId = '') {
,
newProfileId(originalId = '') {
let id = originalId let id = originalId
if (originalId) { if (originalId) {
do { do {
@@ -135,21 +124,15 @@ export const useStore = defineStore('main', {
} while (this.profileIds.includes(id)) } while (this.profileIds.includes(id))
} }
return id return id
} }, selectConfigFeature(feature) {
,
selectConfigFeature(feature) {
this.selectedFeature = feature this.selectedFeature = feature
if (!this.currentConfigPages[this.currentConfigPage]) if (!this.currentConfigPages[this.currentConfigPage]) this.setCurrentConfigPage('mapping')
this.setCurrentConfigPage('mapping') }, selectKey(key) {
},
selectKey(key) {
this.selectedKey = key this.selectedKey = key
this.selectConfigFeature('key') this.selectConfigFeature('key')
}, }, setCurrentConfigPage(page) {
setCurrentConfigPage(page) {
this.currentConfigPage = page this.currentConfigPage = page
}, }, setConnected(connected) {
setConnected(connected) {
this.connected = connected this.connected = connected
}, },
}, },