-
Notifications
You must be signed in to change notification settings - Fork 141
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Basic setting panel rework * refactor * Style the setting item * Reject invalid value * nit * nit * Sort settings by label * info chip as icon * nit
- Loading branch information
Showing
10 changed files
with
379 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,116 +1,119 @@ | ||
<template> | ||
<table class="comfy-modal-content comfy-table"> | ||
<tbody> | ||
<tr v-for="setting in sortedSettings" :key="setting.id"> | ||
<td> | ||
<span> | ||
{{ setting.name }} | ||
</span> | ||
<Chip | ||
v-if="setting.tooltip" | ||
icon="pi pi-info-circle" | ||
severity="secondary" | ||
v-tooltip="setting.tooltip" | ||
class="info-chip" | ||
/> | ||
</td> | ||
<td> | ||
<component | ||
:is="markRaw(getSettingComponent(setting))" | ||
:id="setting.id" | ||
:modelValue="settingStore.get(setting.id)" | ||
@update:modelValue="updateSetting(setting, $event)" | ||
v-bind="getSettingAttrs(setting)" | ||
/> | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
<div class="settings-container"> | ||
<div class="settings-sidebar"> | ||
<Listbox | ||
v-model="activeCategory" | ||
:options="categories" | ||
optionLabel="label" | ||
scrollHeight="100%" | ||
:pt="{ root: { class: 'border-none' } }" | ||
/> | ||
</div> | ||
<Divider layout="vertical" /> | ||
<div class="settings-content" v-if="activeCategory"> | ||
<Tabs :value="activeCategory.label"> | ||
<TabPanels> | ||
<TabPanel | ||
v-for="category in categories" | ||
:key="category.key" | ||
:value="category.label" | ||
> | ||
<SettingGroup | ||
v-for="group in sortedGroups(category)" | ||
:key="group.label" | ||
:group="{ | ||
label: group.label, | ||
settings: flattenTree<SettingParams>(group) | ||
}" | ||
/> | ||
</TabPanel> | ||
</TabPanels> | ||
</Tabs> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { type Component, computed, markRaw } from 'vue' | ||
import InputText from 'primevue/inputtext' | ||
import InputNumber from 'primevue/inputnumber' | ||
import Select from 'primevue/select' | ||
import Chip from 'primevue/chip' | ||
import ToggleSwitch from 'primevue/toggleswitch' | ||
import { useSettingStore } from '@/stores/settingStore' | ||
import { ref, computed, onMounted, watch } from 'vue' | ||
import Listbox from 'primevue/listbox' | ||
import Tabs from 'primevue/tabs' | ||
import TabPanels from 'primevue/tabpanels' | ||
import TabPanel from 'primevue/tabpanel' | ||
import Divider from 'primevue/divider' | ||
import { SettingTreeNode, useSettingStore } from '@/stores/settingStore' | ||
import { SettingParams } from '@/types/settingTypes' | ||
import CustomSettingValue from '@/components/dialog/content/setting/CustomSettingValue.vue' | ||
import InputSlider from '@/components/dialog/content/setting/InputSlider.vue' | ||
import SettingGroup from './setting/SettingGroup.vue' | ||
import { flattenTree } from '@/utils/treeUtil' | ||
const settingStore = useSettingStore() | ||
const sortedSettings = computed<SettingParams[]>(() => { | ||
return Object.values(settingStore.settings) | ||
.filter((setting: SettingParams) => setting.type !== 'hidden') | ||
.sort((a, b) => a.name.localeCompare(b.name)) | ||
}) | ||
function getSettingAttrs(setting: SettingParams) { | ||
const attrs = { ...(setting.attrs || {}) } | ||
const settingType = setting.type | ||
if (typeof settingType === 'function') { | ||
attrs['renderFunction'] = () => | ||
settingType( | ||
setting.name, | ||
(v) => updateSetting(setting, v), | ||
settingStore.get(setting.id), | ||
setting.attrs | ||
) | ||
} | ||
switch (setting.type) { | ||
case 'combo': | ||
attrs['options'] = setting.options | ||
if (typeof setting.options[0] !== 'string') { | ||
attrs['optionLabel'] = 'text' | ||
attrs['optionValue'] = 'value' | ||
} | ||
break | ||
} | ||
const settingRoot = computed<SettingTreeNode>(() => settingStore.settingTree) | ||
const categories = computed<SettingTreeNode[]>( | ||
() => settingRoot.value.children || [] | ||
) | ||
attrs['class'] += ' comfy-vue-setting-input' | ||
return attrs | ||
} | ||
const activeCategory = ref<SettingTreeNode | null>(null) | ||
function getSettingComponent(setting: SettingParams): Component { | ||
if (typeof setting.type === 'function') { | ||
// return setting.type( | ||
// setting.name, (v) => updateSetting(setting, v), settingStore.get(setting.id), setting.attrs) | ||
return CustomSettingValue | ||
} | ||
switch (setting.type) { | ||
case 'boolean': | ||
return ToggleSwitch | ||
case 'number': | ||
return InputNumber | ||
case 'slider': | ||
return InputSlider | ||
case 'combo': | ||
return Select | ||
default: | ||
return InputText | ||
watch(activeCategory, (newCategory, oldCategory) => { | ||
if (newCategory === null) { | ||
activeCategory.value = oldCategory | ||
} | ||
} | ||
}) | ||
const updateSetting = (setting: SettingParams, value: any) => { | ||
if (setting.onChange) setting.onChange(value, settingStore.get(setting.id)) | ||
onMounted(() => { | ||
activeCategory.value = categories.value[0] | ||
}) | ||
settingStore.set(setting.id, value) | ||
const sortedGroups = (category: SettingTreeNode) => { | ||
return [...(category.children || [])].sort((a, b) => | ||
a.label.localeCompare(b.label) | ||
) | ||
} | ||
</script> | ||
|
||
<style> | ||
.info-chip { | ||
background: transparent !important; | ||
} | ||
.comfy-vue-setting-input { | ||
width: 100%; | ||
/* Remove after we have tailwind setup */ | ||
.border-none { | ||
border: none !important; | ||
} | ||
</style> | ||
|
||
<style scoped> | ||
.comfy-table { | ||
.settings-container { | ||
display: flex; | ||
height: 80vh; | ||
width: 60vw; | ||
max-width: 1000px; | ||
overflow: hidden; | ||
/* Prevents container from scrolling */ | ||
} | ||
.settings-sidebar { | ||
width: 250px; | ||
flex-shrink: 0; | ||
/* Prevents sidebar from shrinking */ | ||
overflow-y: auto; | ||
padding: 10px; | ||
} | ||
.settings-content { | ||
flex-grow: 1; | ||
overflow-y: auto; | ||
/* Allows vertical scrolling */ | ||
} | ||
/* Ensure the Listbox takes full width of the sidebar */ | ||
.settings-sidebar :deep(.p-listbox) { | ||
width: 100%; | ||
} | ||
/* Optional: Style scrollbars for webkit browsers */ | ||
.settings-sidebar::-webkit-scrollbar, | ||
.settings-content::-webkit-scrollbar { | ||
width: 1px; | ||
} | ||
.settings-sidebar::-webkit-scrollbar-thumb, | ||
.settings-content::-webkit-scrollbar-thumb { | ||
background-color: transparent; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.