feat: add LED / Neopixel support (#1050)
This commit is contained in:
parent
128baea88c
commit
a88c9ba083
43
package-lock.json
generated
43
package-lock.json
generated
@ -16,6 +16,7 @@
|
|||||||
"@codemirror/search": "^6.0.0",
|
"@codemirror/search": "^6.0.0",
|
||||||
"@codemirror/state": "^6.1.0",
|
"@codemirror/state": "^6.1.0",
|
||||||
"@codemirror/view": "^6.0.3",
|
"@codemirror/view": "^6.0.3",
|
||||||
|
"@jaames/iro": "^5.5.2",
|
||||||
"@lezer/highlight": "^1.0.0",
|
"@lezer/highlight": "^1.0.0",
|
||||||
"@sindarius/gcodeviewer": "^3.1.4",
|
"@sindarius/gcodeviewer": "^3.1.4",
|
||||||
"@types/node": "^18.0.0",
|
"@types/node": "^18.0.0",
|
||||||
@ -2419,6 +2420,20 @@
|
|||||||
"node": ">= 14"
|
"node": ">= 14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@irojs/iro-core": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@irojs/iro-core/-/iro-core-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-p2OvsBSSmidsDsTSkID6jEyXDF7lcyxPrkh3qBzasBZFpjkYd6kZ3yMWai3MlAaQ3F7li/Et7rSJVV09Fpei+A=="
|
||||||
|
},
|
||||||
|
"node_modules/@jaames/iro": {
|
||||||
|
"version": "5.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jaames/iro/-/iro-5.5.2.tgz",
|
||||||
|
"integrity": "sha512-Fbi5U4Vdkw6UsF+R3oMlPONqkvUDMkwzh+mX718gQsDFt3+1r1jvGsrfCbedmXAAy0WsjDHOrefK0BkDk99TQg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@irojs/iro-core": "^1.2.1",
|
||||||
|
"preact": "^10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
|
||||||
@ -7617,6 +7632,15 @@
|
|||||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/preact": {
|
||||||
|
"version": "10.10.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/preact/-/preact-10.10.6.tgz",
|
||||||
|
"integrity": "sha512-w0mCL5vICUAZrh1DuHEdOWBjxdO62lvcO++jbzr8UhhYcTbFkpegLH9XX+7MadjTl/y0feoqwQ/zAnzkc/EGog==",
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/preact"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prelude-ls": {
|
"node_modules/prelude-ls": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||||
@ -11667,6 +11691,20 @@
|
|||||||
"@intlify/shared": "9.2.2"
|
"@intlify/shared": "9.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@irojs/iro-core": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@irojs/iro-core/-/iro-core-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-p2OvsBSSmidsDsTSkID6jEyXDF7lcyxPrkh3qBzasBZFpjkYd6kZ3yMWai3MlAaQ3F7li/Et7rSJVV09Fpei+A=="
|
||||||
|
},
|
||||||
|
"@jaames/iro": {
|
||||||
|
"version": "5.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jaames/iro/-/iro-5.5.2.tgz",
|
||||||
|
"integrity": "sha512-Fbi5U4Vdkw6UsF+R3oMlPONqkvUDMkwzh+mX718gQsDFt3+1r1jvGsrfCbedmXAAy0WsjDHOrefK0BkDk99TQg==",
|
||||||
|
"requires": {
|
||||||
|
"@irojs/iro-core": "^1.2.1",
|
||||||
|
"preact": "^10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@jridgewell/gen-mapping": {
|
"@jridgewell/gen-mapping": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
|
||||||
@ -15422,6 +15460,11 @@
|
|||||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"preact": {
|
||||||
|
"version": "10.10.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/preact/-/preact-10.10.6.tgz",
|
||||||
|
"integrity": "sha512-w0mCL5vICUAZrh1DuHEdOWBjxdO62lvcO++jbzr8UhhYcTbFkpegLH9XX+7MadjTl/y0feoqwQ/zAnzkc/EGog=="
|
||||||
|
},
|
||||||
"prelude-ls": {
|
"prelude-ls": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
"@codemirror/search": "^6.0.0",
|
"@codemirror/search": "^6.0.0",
|
||||||
"@codemirror/state": "^6.1.0",
|
"@codemirror/state": "^6.1.0",
|
||||||
"@codemirror/view": "^6.0.3",
|
"@codemirror/view": "^6.0.3",
|
||||||
|
"@jaames/iro": "^5.5.2",
|
||||||
"@lezer/highlight": "^1.0.0",
|
"@lezer/highlight": "^1.0.0",
|
||||||
"@sindarius/gcodeviewer": "^3.1.4",
|
"@sindarius/gcodeviewer": "^3.1.4",
|
||||||
"@types/node": "^18.0.0",
|
"@types/node": "^18.0.0",
|
||||||
|
@ -97,7 +97,9 @@ import {
|
|||||||
mdiTune,
|
mdiTune,
|
||||||
mdiVideo3d,
|
mdiVideo3d,
|
||||||
mdiWebcam,
|
mdiWebcam,
|
||||||
|
mdiDipSwitch,
|
||||||
} from '@mdi/js'
|
} from '@mdi/js'
|
||||||
|
import SettingsMiscellaneousTab from '@/components/settings/SettingsMiscellaneousTab.vue'
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
Panel,
|
Panel,
|
||||||
@ -113,6 +115,7 @@ import {
|
|||||||
SettingsGCodeViewerTab,
|
SettingsGCodeViewerTab,
|
||||||
SettingsEditorTab,
|
SettingsEditorTab,
|
||||||
SettingsTimelapseTab,
|
SettingsTimelapseTab,
|
||||||
|
SettingsMiscellaneousTab,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class TheSettingsMenu extends Mixins(BaseMixin) {
|
export default class TheSettingsMenu extends Mixins(BaseMixin) {
|
||||||
@ -186,6 +189,11 @@ export default class TheSettingsMenu extends Mixins(BaseMixin) {
|
|||||||
name: 'editor',
|
name: 'editor',
|
||||||
title: this.$t('Settings.EditorTab.Editor'),
|
title: this.$t('Settings.EditorTab.Editor'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: mdiDipSwitch,
|
||||||
|
name: 'miscellaneous',
|
||||||
|
title: this.$t('Settings.MiscellaneousTab.Miscellaneous'),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
if (this.moonrakerComponents.includes('timelapse')) {
|
if (this.moonrakerComponents.includes('timelapse')) {
|
||||||
|
63
src/components/inputs/ColorPicker.vue
Normal file
63
src/components/inputs/ColorPicker.vue
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div ref="picker"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Mixins, Prop, Ref, Watch } from 'vue-property-decorator'
|
||||||
|
import BaseMixin from '@/components/mixins/base'
|
||||||
|
import iro from '@jaames/iro'
|
||||||
|
import { IroColor } from '@irojs/iro-core'
|
||||||
|
import { ColorPickerProps, IroColorPicker as IroCP } from '@jaames/iro/dist/ColorPicker.d'
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class ColorPicker extends Mixins(BaseMixin) {
|
||||||
|
colorPicker: IroCP | null = null
|
||||||
|
|
||||||
|
@Ref('picker')
|
||||||
|
readonly picker!: HTMLElement
|
||||||
|
|
||||||
|
@Prop({ type: [Object, String], default: '#ffffff' })
|
||||||
|
readonly color!: IroColor
|
||||||
|
|
||||||
|
@Prop({ type: Object, default: () => ({}) })
|
||||||
|
readonly options!: ColorPickerProps
|
||||||
|
|
||||||
|
@Watch('color', { deep: true })
|
||||||
|
colorChanged(value: string) {
|
||||||
|
if (this.colorPicker && this.colorPicker.color.rgbString !== value) {
|
||||||
|
this.colorPicker.color.rgbString = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get internalOptions(): ColorPickerProps {
|
||||||
|
return {
|
||||||
|
...this.options,
|
||||||
|
color: this.color,
|
||||||
|
borderWidth: 2,
|
||||||
|
sliderSize: 16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emitColorChange(color: IroColor) {
|
||||||
|
this.$emit('change', color)
|
||||||
|
this.$emit('update:color', color)
|
||||||
|
}
|
||||||
|
|
||||||
|
onColorChange(color: IroColor) {
|
||||||
|
this.emitColorChange(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.colorPicker = iro.ColorPicker(this.picker, this.internalOptions)
|
||||||
|
this.colorPicker.on('color:change', this.onColorChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
this.colorPicker?.off('color:change', this.onColorChange)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
519
src/components/inputs/MiscellaneousLight.vue
Normal file
519
src/components/inputs/MiscellaneousLight.vue
Normal file
@ -0,0 +1,519 @@
|
|||||||
|
<template>
|
||||||
|
<v-container :class="containerClass">
|
||||||
|
<v-row>
|
||||||
|
<v-col class="pb-3">
|
||||||
|
<v-subheader class="_light-subheader">
|
||||||
|
<v-icon v-if="(!root || groups.length === 0) && isOn" small left @click="off">
|
||||||
|
{{ mdiLightbulbOnOutline }}
|
||||||
|
</v-icon>
|
||||||
|
<v-icon v-else-if="!root || groups.length === 0" small left @click="on">
|
||||||
|
{{ mdiLightbulbOutline }}
|
||||||
|
</v-icon>
|
||||||
|
<span>{{ name }}</span>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<span
|
||||||
|
v-if="!root || groups.length === 0"
|
||||||
|
class="_currentState"
|
||||||
|
:style="currentStateStyle"
|
||||||
|
@click="boolDialog = true"></span>
|
||||||
|
</v-subheader>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<template v-if="root && groups.length">
|
||||||
|
<miscellaneous-light v-for="group in groups" :key="group.id" :object="object" :group="group" />
|
||||||
|
</template>
|
||||||
|
<v-dialog v-model="boolDialog" persistent :width="400">
|
||||||
|
<panel
|
||||||
|
:title="name"
|
||||||
|
:icon="mdiLightbulbOutline"
|
||||||
|
card-class="temperature-edit-heater-dialog"
|
||||||
|
:margin-bottom="false">
|
||||||
|
<template #buttons>
|
||||||
|
<v-btn icon tile @click="boolDialog = false">
|
||||||
|
<v-icon>{{ mdiCloseThick }}</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-card-text class="pt-6">
|
||||||
|
<template v-if="presets.length">
|
||||||
|
<v-row>
|
||||||
|
<v-col class="light-presets-container pt-0 d-flex flex-wrap flex-row justify-center">
|
||||||
|
<v-tooltip v-for="preset in presets" :key="preset.id" top>
|
||||||
|
<template #activator="{ on, attrs }">
|
||||||
|
<div
|
||||||
|
:style="presetStyle(preset)"
|
||||||
|
v-bind="attrs"
|
||||||
|
v-on="on"
|
||||||
|
@click="usePreset(preset)"></div>
|
||||||
|
</template>
|
||||||
|
<span>{{ preset.name }}</span>
|
||||||
|
</v-tooltip>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-divider class="my-3"></v-divider>
|
||||||
|
</template>
|
||||||
|
<v-row>
|
||||||
|
<v-col class="text-center">
|
||||||
|
<color-picker
|
||||||
|
:color="colorRGB"
|
||||||
|
:options="colorPickerOptions"
|
||||||
|
@update:color="onColorRGBChanged" />
|
||||||
|
<color-picker
|
||||||
|
v-if="existWhite"
|
||||||
|
:color="colorRGBW"
|
||||||
|
:options="colorPickerWhiteOptions"
|
||||||
|
class="mt-3"
|
||||||
|
@update:color="onColorWhiteChanged" />
|
||||||
|
</v-col>
|
||||||
|
<v-col>
|
||||||
|
<v-row v-if="existRed">
|
||||||
|
<v-col>
|
||||||
|
<number-input
|
||||||
|
:label="$t('Panels.MiscellaneousPanel.Light.Red')"
|
||||||
|
param="red"
|
||||||
|
:target="redInt"
|
||||||
|
:default-value="Math.round(object.initialRed * 255)"
|
||||||
|
:min="0"
|
||||||
|
:max="255"
|
||||||
|
:dec="1"
|
||||||
|
:step="1"
|
||||||
|
:output-error-msg="true"
|
||||||
|
:has-spinner="true"
|
||||||
|
@submit="onColorInput" />
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row v-if="existGreen">
|
||||||
|
<v-col>
|
||||||
|
<number-input
|
||||||
|
:label="$t('Panels.MiscellaneousPanel.Light.Green')"
|
||||||
|
param="green"
|
||||||
|
:target="greenInt"
|
||||||
|
:default-value="Math.round(object.initialGreen * 255)"
|
||||||
|
:min="0"
|
||||||
|
:max="255"
|
||||||
|
:dec="1"
|
||||||
|
:step="1"
|
||||||
|
:has-spinner="true"
|
||||||
|
@submit="onColorInput" />
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row v-if="existBlue">
|
||||||
|
<v-col>
|
||||||
|
<number-input
|
||||||
|
:label="$t('Panels.MiscellaneousPanel.Light.Blue')"
|
||||||
|
param="blue"
|
||||||
|
:target="blueInt"
|
||||||
|
:default-value="Math.round(object.initialBlue * 255)"
|
||||||
|
:min="0"
|
||||||
|
:max="255"
|
||||||
|
:dec="1"
|
||||||
|
:step="1"
|
||||||
|
:has-spinner="true"
|
||||||
|
@submit="onColorInput" />
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row v-if="existWhite">
|
||||||
|
<v-col>
|
||||||
|
<number-input
|
||||||
|
:label="$t('Panels.MiscellaneousPanel.Light.White')"
|
||||||
|
param="white"
|
||||||
|
:target="whiteInt"
|
||||||
|
:default-value="Math.round(object.initialWhite * 255)"
|
||||||
|
:min="0"
|
||||||
|
:max="255"
|
||||||
|
:dec="1"
|
||||||
|
:step="1"
|
||||||
|
:has-spinner="true"
|
||||||
|
@submit="onColorInput" />
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card-text>
|
||||||
|
</panel>
|
||||||
|
</v-dialog>
|
||||||
|
</v-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { convertName } from '@/plugins/helpers'
|
||||||
|
import { Component, Mixins, Prop } from 'vue-property-decorator'
|
||||||
|
import BaseMixin from '@/components/mixins/base'
|
||||||
|
import { mdiCloseThick, mdiLightbulbOutline, mdiLightbulbOnOutline } from '@mdi/js'
|
||||||
|
import { PrinterStateLight } from '@/store/printer/types'
|
||||||
|
import ColorPicker from '@/components/inputs/ColorPicker.vue'
|
||||||
|
import { ColorPickerProps } from '@jaames/iro/dist/ColorPicker.d'
|
||||||
|
import { Debounce } from 'vue-debounce-decorator'
|
||||||
|
import iro from '@jaames/iro'
|
||||||
|
import { IroColor } from '@irojs/iro-core'
|
||||||
|
import { GuiMiscellaneousStateEntryLightgroup, GuiMiscellaneousStateEntryPreset } from '@/store/gui/miscellaneous/types'
|
||||||
|
|
||||||
|
interface ColorData {
|
||||||
|
red: number | null
|
||||||
|
green: number | null
|
||||||
|
blue: number | null
|
||||||
|
white: number | null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
ColorPicker,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class MiscellaneousLight extends Mixins(BaseMixin) {
|
||||||
|
mdiCloseThick = mdiCloseThick
|
||||||
|
mdiLightbulbOutline = mdiLightbulbOutline
|
||||||
|
mdiLightbulbOnOutline = mdiLightbulbOnOutline
|
||||||
|
|
||||||
|
@Prop({ type: Object, required: true })
|
||||||
|
declare object: PrinterStateLight
|
||||||
|
|
||||||
|
@Prop({ type: Boolean, default: false }) readonly root!: boolean
|
||||||
|
@Prop(Object) readonly group!: GuiMiscellaneousStateEntryLightgroup | undefined
|
||||||
|
|
||||||
|
private boolDialog = false
|
||||||
|
private inputValue = 0
|
||||||
|
|
||||||
|
get name() {
|
||||||
|
if (this.group) return convertName(this.group.name)
|
||||||
|
|
||||||
|
return convertName(this.object.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
get colorPickerOptions() {
|
||||||
|
let options: ColorPickerProps = {
|
||||||
|
width: 200,
|
||||||
|
margin: 15,
|
||||||
|
layout: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.existRed) {
|
||||||
|
// @ts-ignore
|
||||||
|
options?.layout.push({
|
||||||
|
component: iro.ui.Slider,
|
||||||
|
options: {
|
||||||
|
sliderType: 'red',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.existGreen) {
|
||||||
|
// @ts-ignore
|
||||||
|
options?.layout.push({
|
||||||
|
component: iro.ui.Slider,
|
||||||
|
options: {
|
||||||
|
sliderType: 'green',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.existBlue) {
|
||||||
|
// @ts-ignore
|
||||||
|
options?.layout.push({
|
||||||
|
component: iro.ui.Slider,
|
||||||
|
options: {
|
||||||
|
sliderType: 'blue',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.existRed && this.existGreen && this.existBlue) {
|
||||||
|
options.layout = [
|
||||||
|
{
|
||||||
|
component: iro.ui.Wheel,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: iro.ui.Slider,
|
||||||
|
options: {
|
||||||
|
sliderType: 'value',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
get colorPickerWhiteOptions() {
|
||||||
|
let options: ColorPickerProps = {
|
||||||
|
width: 200,
|
||||||
|
margin: 15,
|
||||||
|
layout: [
|
||||||
|
{
|
||||||
|
component: iro.ui.Slider,
|
||||||
|
options: {
|
||||||
|
sliderType: 'alpha',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
get optionsColors() {
|
||||||
|
let output: string[] = []
|
||||||
|
|
||||||
|
this.presets.forEach((preset: GuiMiscellaneousStateEntryPreset) => {
|
||||||
|
output.push(`rgb(${preset.red}%, ${preset.green}%, ${preset.blue}%)`)
|
||||||
|
})
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
get current() {
|
||||||
|
const color: ColorData = {
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
white: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.existWhite) color.white = 0
|
||||||
|
if (this.object.colorData.length === 0) return color
|
||||||
|
|
||||||
|
const firstColorData = this.object.colorData[(this.group?.start ?? 1) - 1]
|
||||||
|
color.red = firstColorData[0] * 255
|
||||||
|
color.green = firstColorData[1] * 255
|
||||||
|
color.blue = firstColorData[2] * 255
|
||||||
|
if (this.object.colorOrder.indexOf('W') !== -1) color.white = firstColorData[3] * 255
|
||||||
|
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
|
||||||
|
get isOn() {
|
||||||
|
return (
|
||||||
|
(this.current.red ?? 0) +
|
||||||
|
(this.current?.green ?? 0) +
|
||||||
|
(this.current.blue ?? 0) +
|
||||||
|
(this.current.white ?? 0) >
|
||||||
|
0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get existRed() {
|
||||||
|
return this.object.colorOrder.indexOf('R') !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
get existGreen() {
|
||||||
|
return this.object.colorOrder.indexOf('G') !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
get existBlue() {
|
||||||
|
return this.object.colorOrder.indexOf('B') !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
get existWhite() {
|
||||||
|
return this.object.colorOrder.indexOf('W') !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentStateStyle() {
|
||||||
|
let output = this.colorRGB
|
||||||
|
|
||||||
|
if (this.current.white !== null && this.current.red == 0 && this.current.green == 0 && this.current.blue == 0)
|
||||||
|
output = `rgb(${this.current.white * 255}, ${this.current.white * 255}, ${this.current.white * 255})`
|
||||||
|
|
||||||
|
return {
|
||||||
|
'background-color': output,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get colorRGB() {
|
||||||
|
return `rgb(${Math.round(this.current.red ?? 0)}, ${Math.round(this.current.green ?? 0)}, ${Math.round(
|
||||||
|
this.current.blue ?? 0
|
||||||
|
)})`
|
||||||
|
}
|
||||||
|
|
||||||
|
get colorRGBW() {
|
||||||
|
return `rgba(255, 255, 255, ${(this.current.white ?? 0) / 255})`
|
||||||
|
}
|
||||||
|
|
||||||
|
get redInt() {
|
||||||
|
return Math.round(this.current.red ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
get greenInt() {
|
||||||
|
return Math.round(this.current.green ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
get blueInt() {
|
||||||
|
return Math.round(this.current.blue ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
get whiteInt() {
|
||||||
|
return Math.round(this.current.white ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
get groups() {
|
||||||
|
return (
|
||||||
|
this.$store.getters['gui/miscellaneous/getEntryLightgroups']({
|
||||||
|
type: this.object.type,
|
||||||
|
name: this.object.name,
|
||||||
|
}) ?? []
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get presets() {
|
||||||
|
return (
|
||||||
|
this.$store.getters['gui/miscellaneous/getEntryPresets']({
|
||||||
|
type: this.object.type,
|
||||||
|
name: this.object.name,
|
||||||
|
}) ?? []
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
get containerClass() {
|
||||||
|
let output = ['px-0']
|
||||||
|
|
||||||
|
output.push(this.root ? 'py-2' : 'pt-2 pb-0')
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
colorChanged(color: ColorData) {
|
||||||
|
if (
|
||||||
|
Math.round(color.red ?? 0) === Math.round(this.current.red ?? 0) &&
|
||||||
|
Math.round(color.green ?? 0) === Math.round(this.current.green ?? 0) &&
|
||||||
|
Math.round(color.blue ?? 0) === Math.round(this.current.blue ?? 0) &&
|
||||||
|
Math.round(color.white ?? 0) === Math.round(this.current.white ?? 0)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
const red = Math.round(((color.red ?? 0) / 255) * 10000) / 10000
|
||||||
|
const green = Math.round(((color.green ?? 0) / 255) * 10000) / 10000
|
||||||
|
const blue = Math.round(((color.blue ?? 0) / 255) * 10000) / 10000
|
||||||
|
const white = Math.round(((color.white ?? 0) / 255) * 10000) / 10000
|
||||||
|
|
||||||
|
let gcode = `SET_LED LED="${this.object.name}" RED=${red} GREEN=${green} BLUE=${blue}`
|
||||||
|
if (this.existWhite) gcode += ` WHITE=${white}`
|
||||||
|
gcode += ` SYNC=0`
|
||||||
|
|
||||||
|
if (this.group) {
|
||||||
|
const tmp = gcode
|
||||||
|
|
||||||
|
for (let i = this.group.start; i <= this.group.end; i++) {
|
||||||
|
if (i === this.group.start) {
|
||||||
|
gcode += ` INDEX=${i}`
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
gcode += `\n${tmp} INDEX=${i}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gcode += ` TRANSMIT=1`
|
||||||
|
|
||||||
|
this.$store.dispatch('server/addEvent', {
|
||||||
|
message: gcode,
|
||||||
|
type: 'command',
|
||||||
|
})
|
||||||
|
this.$socket.emit('printer.gcode.script', { script: gcode })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Debounce({ time: 500 })
|
||||||
|
onColorRGBChanged(payload: IroColor) {
|
||||||
|
const color: ColorData = {
|
||||||
|
red: payload.red,
|
||||||
|
green: payload.green,
|
||||||
|
blue: payload.blue,
|
||||||
|
white: this.current.white,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.colorChanged(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Debounce({ time: 500 })
|
||||||
|
onColorWhiteChanged(payload: IroColor) {
|
||||||
|
const color: ColorData = {
|
||||||
|
red: this.current.red,
|
||||||
|
green: this.current.green,
|
||||||
|
blue: this.current.blue,
|
||||||
|
white: this.current.white,
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
color.white = payload.alpha * 255
|
||||||
|
|
||||||
|
this.colorChanged(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Debounce({ time: 500 })
|
||||||
|
onColorInput(payload: { name: string; value: number }) {
|
||||||
|
const color: ColorData = {
|
||||||
|
red: this.current.red,
|
||||||
|
green: this.current.green,
|
||||||
|
blue: this.current.blue,
|
||||||
|
white: this.current.white,
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
color[payload.name] = payload.value
|
||||||
|
|
||||||
|
this.colorChanged(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
off() {
|
||||||
|
const color: ColorData = {
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0,
|
||||||
|
white: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.colorChanged(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
on() {
|
||||||
|
const color: ColorData = {
|
||||||
|
red: 255,
|
||||||
|
green: 255,
|
||||||
|
blue: 255,
|
||||||
|
white: 255,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.colorChanged(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
presetStyle(preset: GuiMiscellaneousStateEntryPreset) {
|
||||||
|
if ((preset?.red ?? 0) + (preset?.green ?? 0) + (preset?.blue ?? 0) === 0 && (preset?.white ?? 0) > 0) {
|
||||||
|
return {
|
||||||
|
backgroundColor: `rgb(${preset.white}%, ${preset.white}%, ${preset.white}%)`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
backgroundColor: `rgb(${preset.red}%, ${preset.green}%, ${preset.blue}%)`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usePreset(preset: GuiMiscellaneousStateEntryPreset) {
|
||||||
|
const color: ColorData = { ...preset }
|
||||||
|
|
||||||
|
this.colorChanged(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
._light-subheader {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
._currentState {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid lightgray;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-presets-container {
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-presets-container > div {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
@ -3,7 +3,18 @@
|
|||||||
<v-row>
|
<v-row>
|
||||||
<v-col :class="pwm ? 'pb-1' : 'pb-3'">
|
<v-col :class="pwm ? 'pb-1' : 'pb-3'">
|
||||||
<v-subheader class="_fan-slider-subheader">
|
<v-subheader class="_fan-slider-subheader">
|
||||||
<v-icon v-if="type !== 'output_pin'" small :class="fanClasses">{{ mdiFan }}</v-icon>
|
<v-icon
|
||||||
|
v-if="type === 'led' && target > 0"
|
||||||
|
class="mr-2"
|
||||||
|
small
|
||||||
|
:retain-focus-on-click="true"
|
||||||
|
@click="ledOff">
|
||||||
|
{{ mdiLightbulbOnOutline }}
|
||||||
|
</v-icon>
|
||||||
|
<v-icon v-else-if="type === 'led'" class="mr-2" small :retain-focus-on-click="true" @click="ledOn">
|
||||||
|
{{ mdiLightbulbOutline }}
|
||||||
|
</v-icon>
|
||||||
|
<v-icon v-else-if="type !== 'output_pin'" small :class="fanClasses">{{ mdiFan }}</v-icon>
|
||||||
<span>{{ convertName(name) }}</span>
|
<span>{{ convertName(name) }}</span>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<small v-if="rpm !== null" :class="rpmClasses">{{ Math.round(rpm ?? 0) }} RPM</small>
|
<small v-if="rpm !== null" :class="rpmClasses">{{ Math.round(rpm ?? 0) }} RPM</small>
|
||||||
@ -87,6 +98,8 @@ import {
|
|||||||
mdiPlus,
|
mdiPlus,
|
||||||
mdiToggleSwitch,
|
mdiToggleSwitch,
|
||||||
mdiToggleSwitchOffOutline,
|
mdiToggleSwitchOffOutline,
|
||||||
|
mdiLightbulbOutline,
|
||||||
|
mdiLightbulbOnOutline,
|
||||||
} from '@mdi/js'
|
} from '@mdi/js'
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@ -98,6 +111,8 @@ export default class MiscellaneousSlider extends Mixins(BaseMixin) {
|
|||||||
mdiLockOpenVariantOutline = mdiLockOpenVariantOutline
|
mdiLockOpenVariantOutline = mdiLockOpenVariantOutline
|
||||||
mdiMinus = mdiMinus
|
mdiMinus = mdiMinus
|
||||||
mdiPlus = mdiPlus
|
mdiPlus = mdiPlus
|
||||||
|
mdiLightbulbOutline = mdiLightbulbOutline
|
||||||
|
mdiLightbulbOnOutline = mdiLightbulbOnOutline
|
||||||
|
|
||||||
convertName = convertName
|
convertName = convertName
|
||||||
private declare timeout: ReturnType<typeof setTimeout>
|
private declare timeout: ReturnType<typeof setTimeout>
|
||||||
@ -135,6 +150,9 @@ export default class MiscellaneousSlider extends Mixins(BaseMixin) {
|
|||||||
@Prop({ type: Number, default: 0 })
|
@Prop({ type: Number, default: 0 })
|
||||||
declare off_below: number
|
declare off_below: number
|
||||||
|
|
||||||
|
@Prop({ type: String, default: '' })
|
||||||
|
declare colorOrder: string
|
||||||
|
|
||||||
get value(): number {
|
get value(): number {
|
||||||
return Math.round((this.target / this.max) * 100) / 100
|
return Math.round((this.target / this.max) * 100) / 100
|
||||||
}
|
}
|
||||||
@ -187,6 +205,8 @@ export default class MiscellaneousSlider extends Mixins(BaseMixin) {
|
|||||||
if (this.type === 'fan') gcode = `M106 S${newVal.toFixed(0)}`
|
if (this.type === 'fan') gcode = `M106 S${newVal.toFixed(0)}`
|
||||||
if (this.type === 'fan_generic') gcode = `SET_FAN_SPEED FAN=${this.name} SPEED=${newVal}`
|
if (this.type === 'fan_generic') gcode = `SET_FAN_SPEED FAN=${this.name} SPEED=${newVal}`
|
||||||
if (this.type === 'output_pin') gcode = `SET_PIN PIN=${this.name} VALUE=${newVal.toFixed(2)}`
|
if (this.type === 'output_pin') gcode = `SET_PIN PIN=${this.name} VALUE=${newVal.toFixed(2)}`
|
||||||
|
if (this.type === 'led')
|
||||||
|
gcode = `SET_LED LED=${this.name} ${this.ledChannelName}=${newVal.toFixed(2)} SYNC=0 TRANSMIT=1`
|
||||||
|
|
||||||
if (gcode !== '') {
|
if (gcode !== '') {
|
||||||
this.$store.dispatch('server/addEvent', { message: gcode, type: 'command' })
|
this.$store.dispatch('server/addEvent', { message: gcode, type: 'command' })
|
||||||
@ -196,6 +216,14 @@ export default class MiscellaneousSlider extends Mixins(BaseMixin) {
|
|||||||
this.startLockTimer()
|
this.startLockTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ledOff() {
|
||||||
|
this.sendCmd(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
ledOn() {
|
||||||
|
this.sendCmd(1)
|
||||||
|
}
|
||||||
|
|
||||||
switchOutputPin(): void {
|
switchOutputPin(): void {
|
||||||
const newVal = this.value ? 0 : 1
|
const newVal = this.value ? 0 : 1
|
||||||
const gcode = `SET_PIN PIN=${this.name} VALUE=${(newVal * this.multi).toFixed(2)}`
|
const gcode = `SET_PIN PIN=${this.name} VALUE=${(newVal * this.multi).toFixed(2)}`
|
||||||
@ -266,6 +294,14 @@ export default class MiscellaneousSlider extends Mixins(BaseMixin) {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get ledChannelName() {
|
||||||
|
if (this.colorOrder === 'R') return 'RED'
|
||||||
|
if (this.colorOrder === 'G') return 'GREEN'
|
||||||
|
if (this.colorOrder === 'B') return 'BLUE'
|
||||||
|
|
||||||
|
return 'WHITE'
|
||||||
|
}
|
||||||
|
|
||||||
submitInput(): void {
|
submitInput(): void {
|
||||||
if (this.errors.length > 0) return
|
if (this.errors.length > 0) return
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<panel
|
<panel
|
||||||
v-if="klipperReadyForGui && (miscellaneous.length || filamentSensors.length)"
|
v-if="showMiscellaneousPanel"
|
||||||
:icon="mdiDipSwitch"
|
:icon="mdiDipSwitch"
|
||||||
:title="$t('Panels.MiscellaneousPanel.Headline')"
|
:title="$t('Panels.MiscellaneousPanel.Headline')"
|
||||||
:collapsible="true"
|
:collapsible="true"
|
||||||
@ -20,8 +20,21 @@
|
|||||||
:max="object.max_power"
|
:max="object.max_power"
|
||||||
:multi="parseInt(object.scale)"></miscellaneous-slider>
|
:multi="parseInt(object.scale)"></miscellaneous-slider>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="(sensor, index) of filamentSensors" :key="'sensor_' + index">
|
<div v-for="(light, index) of lights" :key="'light_' + light.name">
|
||||||
<v-divider v-if="index || miscellaneous.length"></v-divider>
|
<v-divider v-if="index || miscellaneous.length"></v-divider>
|
||||||
|
<miscellaneous-slider
|
||||||
|
v-if="light.type === 'led' && light.colorOrder.length === 1"
|
||||||
|
:name="light.name"
|
||||||
|
type="led"
|
||||||
|
:rpm="null"
|
||||||
|
:controllable="true"
|
||||||
|
:pwm="true"
|
||||||
|
:target="light.singleChannelTarget"
|
||||||
|
:color-order="light.colorOrder" />
|
||||||
|
<miscellaneous-light v-else :object="light" :root="true" />
|
||||||
|
</div>
|
||||||
|
<div v-for="(sensor, index) of filamentSensors" :key="'sensor_' + index">
|
||||||
|
<v-divider v-if="index || miscellaneous.length || lights.length"></v-divider>
|
||||||
<filament-sensor
|
<filament-sensor
|
||||||
:name="sensor.name"
|
:name="sensor.name"
|
||||||
:enabled="sensor.enabled"
|
:enabled="sensor.enabled"
|
||||||
@ -34,21 +47,32 @@
|
|||||||
import { Component, Mixins } from 'vue-property-decorator'
|
import { Component, Mixins } from 'vue-property-decorator'
|
||||||
import BaseMixin from '@/components/mixins/base'
|
import BaseMixin from '@/components/mixins/base'
|
||||||
import MiscellaneousSlider from '@/components/inputs/MiscellaneousSlider.vue'
|
import MiscellaneousSlider from '@/components/inputs/MiscellaneousSlider.vue'
|
||||||
|
import MiscellaneousLight from '@/components/inputs/MiscellaneousLight.vue'
|
||||||
import FilamentSensor from '@/components/inputs/FilamentSensor.vue'
|
import FilamentSensor from '@/components/inputs/FilamentSensor.vue'
|
||||||
import Panel from '@/components/ui/Panel.vue'
|
import Panel from '@/components/ui/Panel.vue'
|
||||||
import { mdiDipSwitch } from '@mdi/js'
|
import { mdiDipSwitch } from '@mdi/js'
|
||||||
@Component({
|
@Component({
|
||||||
components: { Panel, FilamentSensor, MiscellaneousSlider },
|
components: { Panel, FilamentSensor, MiscellaneousSlider, MiscellaneousLight },
|
||||||
})
|
})
|
||||||
export default class MiscellaneousPanel extends Mixins(BaseMixin) {
|
export default class MiscellaneousPanel extends Mixins(BaseMixin) {
|
||||||
mdiDipSwitch = mdiDipSwitch
|
mdiDipSwitch = mdiDipSwitch
|
||||||
|
|
||||||
|
get filamentSensors() {
|
||||||
|
return this.$store.getters['printer/getFilamentSensors'] ?? []
|
||||||
|
}
|
||||||
|
|
||||||
get miscellaneous() {
|
get miscellaneous() {
|
||||||
return this.$store.getters['printer/getMiscellaneous'] ?? []
|
return this.$store.getters['printer/getMiscellaneous'] ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
get filamentSensors() {
|
get lights() {
|
||||||
return this.$store.getters['printer/getFilamentSensors'] ?? []
|
return this.$store.getters['printer/getLights'] ?? []
|
||||||
|
}
|
||||||
|
|
||||||
|
get showMiscellaneousPanel() {
|
||||||
|
return (
|
||||||
|
this.klipperReadyForGui && (this.miscellaneous.length || this.filamentSensors.length || this.lights.length)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
81
src/components/settings/SettingsMiscellaneousTab.vue
Normal file
81
src/components/settings/SettingsMiscellaneousTab.vue
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<settings-miscellaneous-tab-light-groups
|
||||||
|
v-if="editLightGroupObject"
|
||||||
|
:light="editLightGroupObject"
|
||||||
|
@close="editLightGroupObject = null" />
|
||||||
|
<settings-miscellaneous-tab-light-presets
|
||||||
|
v-else-if="editLightPresetObject"
|
||||||
|
:light="editLightPresetObject"
|
||||||
|
@close="editLightPresetObject = null" />
|
||||||
|
<v-card-text v-else>
|
||||||
|
<h3 class="text-h5 mb-3">{{ $t('Settings.MiscellaneousTab.Miscellaneous') }}</h3>
|
||||||
|
<template v-if="filteredLights.length">
|
||||||
|
<div v-for="(light, index) in filteredLights" :key="index">
|
||||||
|
<v-divider v-if="index" class="my-2"></v-divider>
|
||||||
|
<settings-row :title="convertName(light.name)" :dynamic-slot-width="true">
|
||||||
|
<v-btn
|
||||||
|
v-if="light.chainCount > 1"
|
||||||
|
small
|
||||||
|
outlined
|
||||||
|
class="ml-3"
|
||||||
|
@click="editLightGroupObject = light">
|
||||||
|
<v-icon left small>{{ mdiPencil }}</v-icon>
|
||||||
|
{{ $t('Settings.MiscellaneousTab.Groups') }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn small outlined class="ml-3" @click="editLightPresetObject = light">
|
||||||
|
<v-icon left small>{{ mdiPalette }}</v-icon>
|
||||||
|
{{ $t('Settings.MiscellaneousTab.Presets') }}
|
||||||
|
</v-btn>
|
||||||
|
</settings-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<p class="mb-0 text-center font-italic">{{ $t('Settings.MiscellaneousTab.NoDevicesFound') }}</p>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</template>
|
||||||
|
</v-card-text>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Mixins } from 'vue-property-decorator'
|
||||||
|
import BaseMixin from '../mixins/base'
|
||||||
|
import SettingsRow from '@/components/settings/SettingsRow.vue'
|
||||||
|
import { mdiDelete, mdiPalette, mdiPencil } from '@mdi/js'
|
||||||
|
import { convertName } from '@/plugins/helpers'
|
||||||
|
import SettingsMiscellaneousTabLightGroups from '@/components/settings/SettingsMiscellaneousTabLightGroups.vue'
|
||||||
|
import SettingsMiscellaneousTabLightPresets from '@/components/settings/SettingsMiscellaneousTabLightPresets.vue'
|
||||||
|
import { PrinterStateLight } from '@/store/printer/types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
SettingsRow,
|
||||||
|
SettingsMiscellaneousTabLightGroups,
|
||||||
|
SettingsMiscellaneousTabLightPresets,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class SettingsMiscellaneousTab extends Mixins(BaseMixin) {
|
||||||
|
mdiDelete = mdiDelete
|
||||||
|
mdiPalette = mdiPalette
|
||||||
|
mdiPencil = mdiPencil
|
||||||
|
|
||||||
|
convertName = convertName
|
||||||
|
|
||||||
|
editLightGroupObject: PrinterStateLight | null = null
|
||||||
|
editLightPresetObject: PrinterStateLight | null = null
|
||||||
|
|
||||||
|
get lights() {
|
||||||
|
return this.$store.getters['printer/getLights'] ?? []
|
||||||
|
}
|
||||||
|
|
||||||
|
get filteredLights() {
|
||||||
|
return this.lights.filter((light: PrinterStateLight) => light.colorOrder.length > 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
236
src/components/settings/SettingsMiscellaneousTabLightGroups.vue
Normal file
236
src/components/settings/SettingsMiscellaneousTabLightGroups.vue
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<template v-if="boolForm">
|
||||||
|
<v-card-text>
|
||||||
|
<h3 class="text-h5 mb-3">{{ $t('Settings.MiscellaneousTab.CreateGroup') }}</h3>
|
||||||
|
<settings-row :title="$t('Settings.MiscellaneousTab.Name').toString()">
|
||||||
|
<v-text-field
|
||||||
|
v-model="form.name"
|
||||||
|
hide-details="auto"
|
||||||
|
:rules="[rules.required, rules.groupUnique]"
|
||||||
|
dense
|
||||||
|
outlined></v-text-field>
|
||||||
|
</settings-row>
|
||||||
|
<v-divider class="my-2"></v-divider>
|
||||||
|
<settings-row
|
||||||
|
:title="$t('Settings.MiscellaneousTab.Start').toString()"
|
||||||
|
:sub-title="$t('Settings.MiscellaneousTab.StartDescription').toString()">
|
||||||
|
<v-text-field
|
||||||
|
v-model="form.start"
|
||||||
|
hide-details="auto"
|
||||||
|
type="number"
|
||||||
|
step="1"
|
||||||
|
:rules="[rules.minStart, rules.max]"
|
||||||
|
dense
|
||||||
|
outlined></v-text-field>
|
||||||
|
</settings-row>
|
||||||
|
<v-divider class="my-2"></v-divider>
|
||||||
|
<settings-row
|
||||||
|
:title="$t('Settings.MiscellaneousTab.End').toString()"
|
||||||
|
:sub-title="$t('Settings.MiscellaneousTab.EndDescription').toString()">
|
||||||
|
<v-text-field
|
||||||
|
v-model="form.end"
|
||||||
|
hide-details="auto"
|
||||||
|
type="number"
|
||||||
|
step="1"
|
||||||
|
:rules="[rules.minEnd, rules.max]"
|
||||||
|
dense
|
||||||
|
outlined></v-text-field>
|
||||||
|
</settings-row>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions class="d-flex justify-end">
|
||||||
|
<v-btn text @click="closeForm">{{ $t('Settings.Cancel') }}</v-btn>
|
||||||
|
<v-btn v-if="form.id !== null" text color="primary" @click="updateGroup">
|
||||||
|
{{ $t('Settings.Update') }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn v-else text color="primary" @click="storeGroup">{{ $t('Settings.Store') }}</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<v-card-text>
|
||||||
|
<h3 class="text-h5 mb-3">{{ $t('Settings.MiscellaneousTab.LightGroups', { name: light.name }) }}</h3>
|
||||||
|
<template v-if="light">
|
||||||
|
<template v-if="groups.length">
|
||||||
|
<div v-for="(group, index) in groups" :key="group.id">
|
||||||
|
<v-divider v-if="index" class="my-2"></v-divider>
|
||||||
|
<settings-row
|
||||||
|
:title="group.name"
|
||||||
|
:sub-title="
|
||||||
|
$t('Settings.MiscellaneousTab.GroupSubTitle', {
|
||||||
|
start: group.start,
|
||||||
|
end: group.end,
|
||||||
|
}).toString()
|
||||||
|
"
|
||||||
|
:dynamic-slot-width="true">
|
||||||
|
<v-btn small outlined class="ml-3" @click="editGroup(group)">
|
||||||
|
<v-icon left small>{{ mdiPencil }}</v-icon>
|
||||||
|
{{ $t('Settings.Edit') }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
small
|
||||||
|
outlined
|
||||||
|
class="ml-3 minwidth-0 px-2"
|
||||||
|
color="error"
|
||||||
|
@click="deleteGroup(group.id)">
|
||||||
|
<v-icon small>{{ mdiDelete }}</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</settings-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<p class="mb-0 text-center font-italic">
|
||||||
|
{{ $t('Settings.MiscellaneousTab.NoGroupFound') }}
|
||||||
|
</p>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<p class="mb-0 text-center font-italic">
|
||||||
|
{{ $t('Settings.MiscellaneousTab.UnableToLoadLight') }}
|
||||||
|
</p>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</template>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions class="d-flex justify-end">
|
||||||
|
<v-btn text @click="$emit('close')">{{ $t('Settings.Close') }}</v-btn>
|
||||||
|
<v-btn text color="primary" @click="createGroup">
|
||||||
|
{{ $t('Settings.MiscellaneousTab.AddGroup') }}
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Mixins, Prop } from 'vue-property-decorator'
|
||||||
|
import BaseMixin from '../mixins/base'
|
||||||
|
import SettingsRow from '@/components/settings/SettingsRow.vue'
|
||||||
|
import { mdiDelete, mdiPalette, mdiPencil } from '@mdi/js'
|
||||||
|
import { caseInsensitiveSort, convertName } from '@/plugins/helpers'
|
||||||
|
import { PrinterStateLight } from '@/store/printer/types'
|
||||||
|
import { GuiMacrosStateMacrogroup } from '@/store/gui/macros/types'
|
||||||
|
import { GuiMiscellaneousStateEntry, GuiMiscellaneousStateEntryLightgroup } from '@/store/gui/miscellaneous/types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
SettingsRow,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class SettingsMiscellaneousTabLightGroups extends Mixins(BaseMixin) {
|
||||||
|
mdiDelete = mdiDelete
|
||||||
|
mdiPalette = mdiPalette
|
||||||
|
mdiPencil = mdiPencil
|
||||||
|
|
||||||
|
convertName = convertName
|
||||||
|
|
||||||
|
private boolForm = false
|
||||||
|
|
||||||
|
private form: {
|
||||||
|
id: string | null
|
||||||
|
name: string
|
||||||
|
start: number
|
||||||
|
end: number
|
||||||
|
} = {
|
||||||
|
id: null,
|
||||||
|
name: '',
|
||||||
|
start: 1,
|
||||||
|
end: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
private rules = {
|
||||||
|
required: (value: string) => value !== '' || 'required',
|
||||||
|
groupUnique: (value: string) => !this.existsGroupName(value) || 'Name already exists',
|
||||||
|
minStart: (value: number) => value > 0 || 'smaller than 1',
|
||||||
|
minEnd: (value: number) => value >= this.form.start || 'smaller than start value',
|
||||||
|
max: (value: number) => value <= (this.light?.chainCount ?? 1) || 'higher than chain_count',
|
||||||
|
}
|
||||||
|
|
||||||
|
@Prop({ type: Object, default: null })
|
||||||
|
declare light: PrinterStateLight | null
|
||||||
|
|
||||||
|
get entry() {
|
||||||
|
return this.$store.getters['gui/miscellaneous/getEntry']({
|
||||||
|
type: this.light?.type,
|
||||||
|
name: this.light?.name,
|
||||||
|
}) as GuiMiscellaneousStateEntry | null
|
||||||
|
}
|
||||||
|
|
||||||
|
get groups() {
|
||||||
|
if (!this.entry) return []
|
||||||
|
|
||||||
|
const groups: GuiMiscellaneousStateEntryLightgroup[] = []
|
||||||
|
Object.entries(this.entry.lightgroups).forEach(([key, lightgroup]) => {
|
||||||
|
groups.push({
|
||||||
|
name: lightgroup.name,
|
||||||
|
start: lightgroup.start,
|
||||||
|
end: lightgroup.end,
|
||||||
|
id: key,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
window.console.log('getEntryLightgroups', groups)
|
||||||
|
|
||||||
|
return caseInsensitiveSort(groups, 'name')
|
||||||
|
}
|
||||||
|
|
||||||
|
createGroup() {
|
||||||
|
this.form.id = null
|
||||||
|
this.form.name = ''
|
||||||
|
this.form.start = 1
|
||||||
|
this.form.end = this.light?.chainCount ?? 1
|
||||||
|
this.boolForm = true
|
||||||
|
}
|
||||||
|
|
||||||
|
editGroup(group: GuiMiscellaneousStateEntryLightgroup) {
|
||||||
|
this.form.id = group.id ?? null
|
||||||
|
this.form.name = group.name
|
||||||
|
this.form.start = group.start
|
||||||
|
this.form.end = group.end
|
||||||
|
this.boolForm = true
|
||||||
|
}
|
||||||
|
|
||||||
|
closeForm() {
|
||||||
|
this.boolForm = false
|
||||||
|
}
|
||||||
|
|
||||||
|
storeGroup() {
|
||||||
|
this.$store.dispatch('gui/miscellaneous/storeLightgroup', {
|
||||||
|
entry: this.light,
|
||||||
|
lightgroup: this.form,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.boolForm = false
|
||||||
|
}
|
||||||
|
|
||||||
|
updateGroup() {
|
||||||
|
this.$store.dispatch('gui/miscellaneous/updateLightgroup', {
|
||||||
|
entry: this.light,
|
||||||
|
lightgroup: this.form,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.boolForm = false
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteGroup(groupId: string) {
|
||||||
|
this.$store.dispatch('gui/miscellaneous/deleteLightgroup', {
|
||||||
|
entry: this.light,
|
||||||
|
lightgroupId: groupId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
existsGroupName(name: string) {
|
||||||
|
return (
|
||||||
|
this.groups.findIndex(
|
||||||
|
(group: GuiMacrosStateMacrogroup) => group.name === name && group.id != this.form.id
|
||||||
|
) >= 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
467
src/components/settings/SettingsMiscellaneousTabLightPresets.vue
Normal file
467
src/components/settings/SettingsMiscellaneousTabLightPresets.vue
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<template v-if="boolForm">
|
||||||
|
<v-card-text>
|
||||||
|
<h3 class="text-h5 mb-3">{{ $t('Settings.MiscellaneousTab.CreatePreset') }}</h3>
|
||||||
|
<settings-row :title="$t('Settings.MiscellaneousTab.Name').toString()">
|
||||||
|
<v-text-field
|
||||||
|
v-model="form.name"
|
||||||
|
hide-details="auto"
|
||||||
|
:rules="[rules.required, rules.presetUnique]"
|
||||||
|
dense
|
||||||
|
outlined></v-text-field>
|
||||||
|
</settings-row>
|
||||||
|
<v-divider class="my-2"></v-divider>
|
||||||
|
<settings-row :title="$t('Settings.MiscellaneousTab.Color').toString()">
|
||||||
|
<v-row>
|
||||||
|
<v-col class="text-center">
|
||||||
|
<color-picker
|
||||||
|
:color="colorRGB"
|
||||||
|
:options="colorPickerOptions"
|
||||||
|
@update:color="onColorRGBChanged" />
|
||||||
|
<color-picker
|
||||||
|
v-if="existWhite"
|
||||||
|
:color="colorRGBW"
|
||||||
|
:options="colorPickerWhiteOptions"
|
||||||
|
class="mt-3"
|
||||||
|
@update:color="onColorWhiteChanged" />
|
||||||
|
</v-col>
|
||||||
|
<v-col>
|
||||||
|
<v-row v-if="existRed">
|
||||||
|
<v-col>
|
||||||
|
<number-input
|
||||||
|
:label="$t('Panels.MiscellaneousPanel.Light.Red')"
|
||||||
|
param="red"
|
||||||
|
:target="redInt"
|
||||||
|
:min="0"
|
||||||
|
:max="255"
|
||||||
|
:dec="1"
|
||||||
|
:step="1"
|
||||||
|
:output-error-msg="true"
|
||||||
|
:has-spinner="true"
|
||||||
|
@submit="onColorInput" />
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row v-if="existGreen">
|
||||||
|
<v-col>
|
||||||
|
<number-input
|
||||||
|
:label="$t('Panels.MiscellaneousPanel.Light.Green')"
|
||||||
|
param="green"
|
||||||
|
:target="greenInt"
|
||||||
|
:min="0"
|
||||||
|
:max="255"
|
||||||
|
:dec="1"
|
||||||
|
:step="1"
|
||||||
|
:has-spinner="true"
|
||||||
|
@submit="onColorInput" />
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row v-if="existBlue">
|
||||||
|
<v-col>
|
||||||
|
<number-input
|
||||||
|
:label="$t('Panels.MiscellaneousPanel.Light.Blue')"
|
||||||
|
param="blue"
|
||||||
|
:target="blueInt"
|
||||||
|
:min="0"
|
||||||
|
:max="255"
|
||||||
|
:dec="1"
|
||||||
|
:step="1"
|
||||||
|
:has-spinner="true"
|
||||||
|
@submit="onColorInput" />
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row v-if="existWhite">
|
||||||
|
<v-col>
|
||||||
|
<number-input
|
||||||
|
:label="$t('Panels.MiscellaneousPanel.Light.White')"
|
||||||
|
param="white"
|
||||||
|
:target="whiteInt"
|
||||||
|
:min="0"
|
||||||
|
:max="255"
|
||||||
|
:dec="1"
|
||||||
|
:step="1"
|
||||||
|
:has-spinner="true"
|
||||||
|
@submit="onColorInput" />
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</settings-row>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions class="d-flex justify-end">
|
||||||
|
<v-btn text @click="closeForm">{{ $t('Settings.Cancel') }}</v-btn>
|
||||||
|
<v-btn v-if="form.id !== null" text color="primary" @click="updatePreset">
|
||||||
|
{{ $t('Settings.Update') }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn v-else text color="primary" @click="storePreset">{{ $t('Settings.Store') }}</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<v-card-text>
|
||||||
|
<h3 class="text-h5 mb-3">{{ $t('Settings.MiscellaneousTab.LightPresets', { name: light.name }) }}</h3>
|
||||||
|
<template v-if="light">
|
||||||
|
<template v-if="presets.length">
|
||||||
|
<div v-for="(preset, index) in presets" :key="preset.id">
|
||||||
|
<v-divider v-if="index" class="my-2"></v-divider>
|
||||||
|
<settings-row
|
||||||
|
:title="preset.name"
|
||||||
|
:sub-title="entryDescriptionText(preset)"
|
||||||
|
:dynamic-slot-width="true">
|
||||||
|
<v-btn small outlined class="ml-3" @click="editPreset(preset)">
|
||||||
|
<v-icon left small>{{ mdiPencil }}</v-icon>
|
||||||
|
{{ $t('Settings.Edit') }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
small
|
||||||
|
outlined
|
||||||
|
class="ml-3 minwidth-0 px-2"
|
||||||
|
color="error"
|
||||||
|
@click="deletePreset(preset.id)">
|
||||||
|
<v-icon small>{{ mdiDelete }}</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</settings-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<p class="mb-0 text-center font-italic">
|
||||||
|
{{ $t('Settings.MiscellaneousTab.NoPresetFound') }}
|
||||||
|
</p>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<p class="mb-0 text-center font-italic">
|
||||||
|
{{ $t('Settings.MiscellaneousTab.UnableToLoadPreset') }}
|
||||||
|
</p>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</template>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions class="d-flex justify-end">
|
||||||
|
<v-btn text @click="$emit('close')">{{ $t('Settings.Close') }}</v-btn>
|
||||||
|
<v-btn text color="primary" @click="createPreset">
|
||||||
|
{{ $t('Settings.MiscellaneousTab.AddPreset') }}
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Mixins, Prop } from 'vue-property-decorator'
|
||||||
|
import BaseMixin from '../mixins/base'
|
||||||
|
import SettingsRow from '@/components/settings/SettingsRow.vue'
|
||||||
|
import { mdiDelete, mdiPencil } from '@mdi/js'
|
||||||
|
import { caseInsensitiveSort, convertName } from '@/plugins/helpers'
|
||||||
|
import { PrinterStateLight } from '@/store/printer/types'
|
||||||
|
import { GuiMiscellaneousStateEntry, GuiMiscellaneousStateEntryPreset } from '@/store/gui/miscellaneous/types'
|
||||||
|
import { ColorPickerProps } from '@jaames/iro/dist/ColorPicker.d'
|
||||||
|
import iro from '@jaames/iro'
|
||||||
|
import { Debounce } from 'vue-debounce-decorator'
|
||||||
|
import { IroColor } from '@irojs/iro-core'
|
||||||
|
|
||||||
|
interface ColorData {
|
||||||
|
red: number | null
|
||||||
|
green: number | null
|
||||||
|
blue: number | null
|
||||||
|
white: number | null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
SettingsRow,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class SettingsMiscellaneousTabLightPresets extends Mixins(BaseMixin) {
|
||||||
|
mdiDelete = mdiDelete
|
||||||
|
mdiPencil = mdiPencil
|
||||||
|
|
||||||
|
convertName = convertName
|
||||||
|
|
||||||
|
private boolForm = false
|
||||||
|
|
||||||
|
private form: {
|
||||||
|
id: string | null
|
||||||
|
name: string
|
||||||
|
red: number | null
|
||||||
|
green: number | null
|
||||||
|
blue: number | null
|
||||||
|
white: number | null
|
||||||
|
} = {
|
||||||
|
id: null,
|
||||||
|
name: '',
|
||||||
|
red: null,
|
||||||
|
green: null,
|
||||||
|
blue: null,
|
||||||
|
white: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
private rules = {
|
||||||
|
required: (value: string) => value !== '' || 'required',
|
||||||
|
presetUnique: (value: string) => !this.existsPresetName(value) || 'Name already exists',
|
||||||
|
min: (value: number) => value >= 0 || 'Must be minimum 0',
|
||||||
|
max: (value: number) => value <= 255 || 'Must be smaller then 256',
|
||||||
|
}
|
||||||
|
|
||||||
|
@Prop({ type: Object, default: null })
|
||||||
|
declare light: PrinterStateLight | null
|
||||||
|
|
||||||
|
get entry() {
|
||||||
|
return this.$store.getters['gui/miscellaneous/getEntry']({
|
||||||
|
type: this.light?.type,
|
||||||
|
name: this.light?.name,
|
||||||
|
}) as GuiMiscellaneousStateEntry | null
|
||||||
|
}
|
||||||
|
|
||||||
|
get presets() {
|
||||||
|
if (!this.entry) return []
|
||||||
|
|
||||||
|
const presets: GuiMiscellaneousStateEntryPreset[] = []
|
||||||
|
Object.entries(this.entry.presets).forEach(([key, preset]) => {
|
||||||
|
presets.push({
|
||||||
|
...preset,
|
||||||
|
id: key,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
window.console.log('getEntryPresets', presets)
|
||||||
|
|
||||||
|
return caseInsensitiveSort(presets, 'name')
|
||||||
|
}
|
||||||
|
|
||||||
|
get existRed() {
|
||||||
|
return this.light?.colorOrder.indexOf('R') !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
get existGreen() {
|
||||||
|
return this.light?.colorOrder.indexOf('G') !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
get existBlue() {
|
||||||
|
return this.light?.colorOrder.indexOf('B') !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
get existWhite() {
|
||||||
|
return this.light?.colorOrder.indexOf('W') !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
get colorRGB() {
|
||||||
|
return `rgb(${Math.round(this.form.red ?? 0)}, ${Math.round(this.form.green ?? 0)}, ${Math.round(
|
||||||
|
this.form.blue ?? 0
|
||||||
|
)})`
|
||||||
|
}
|
||||||
|
|
||||||
|
get colorRGBW() {
|
||||||
|
return `rgba(255, 255, 255, ${(this.form.white ?? 0) / 255})`
|
||||||
|
}
|
||||||
|
|
||||||
|
get redInt() {
|
||||||
|
return Math.round(this.form.red ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
get greenInt() {
|
||||||
|
return Math.round(this.form.green ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
get blueInt() {
|
||||||
|
return Math.round(this.form.blue ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
get whiteInt() {
|
||||||
|
return Math.round(this.form.white ?? 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
get colorPickerOptions() {
|
||||||
|
let options: ColorPickerProps = {
|
||||||
|
width: 200,
|
||||||
|
margin: 15,
|
||||||
|
layout: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.existRed) {
|
||||||
|
// @ts-ignore
|
||||||
|
options?.layout.push({
|
||||||
|
component: iro.ui.Slider,
|
||||||
|
options: {
|
||||||
|
sliderType: 'red',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.existGreen) {
|
||||||
|
// @ts-ignore
|
||||||
|
options?.layout.push({
|
||||||
|
component: iro.ui.Slider,
|
||||||
|
options: {
|
||||||
|
sliderType: 'green',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.existBlue) {
|
||||||
|
// @ts-ignore
|
||||||
|
options?.layout.push({
|
||||||
|
component: iro.ui.Slider,
|
||||||
|
options: {
|
||||||
|
sliderType: 'blue',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.existRed && this.existGreen && this.existBlue) {
|
||||||
|
options.layout = [
|
||||||
|
{
|
||||||
|
component: iro.ui.Wheel,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: iro.ui.Slider,
|
||||||
|
options: {
|
||||||
|
sliderType: 'value',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
get colorPickerWhiteOptions() {
|
||||||
|
let options: ColorPickerProps = {
|
||||||
|
width: 200,
|
||||||
|
margin: 15,
|
||||||
|
layout: [
|
||||||
|
{
|
||||||
|
component: iro.ui.Slider,
|
||||||
|
options: {
|
||||||
|
sliderType: 'alpha',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
return options
|
||||||
|
}
|
||||||
|
|
||||||
|
entryDescriptionText(preset: GuiMiscellaneousStateEntryPreset) {
|
||||||
|
let output: string[] = []
|
||||||
|
|
||||||
|
if (this.light?.colorOrder.includes('R')) output.push(`R: ${preset.red}`)
|
||||||
|
if (this.light?.colorOrder.includes('G')) output.push(`G: ${preset.green}`)
|
||||||
|
if (this.light?.colorOrder.includes('B')) output.push(`B: ${preset.blue}`)
|
||||||
|
if (this.light?.colorOrder.includes('W')) output.push(`W: ${preset.white}`)
|
||||||
|
|
||||||
|
return output.join(', ')
|
||||||
|
}
|
||||||
|
|
||||||
|
createPreset() {
|
||||||
|
this.form.id = null
|
||||||
|
this.form.name = ''
|
||||||
|
this.form.red = this.light?.colorOrder.indexOf('R') != -1 ? 0 : null
|
||||||
|
this.form.green = this.light?.colorOrder.indexOf('G') != -1 ? 0 : null
|
||||||
|
this.form.blue = this.light?.colorOrder.indexOf('B') != -1 ? 0 : null
|
||||||
|
this.form.white = this.light?.colorOrder.indexOf('W') != -1 ? 0 : null
|
||||||
|
this.boolForm = true
|
||||||
|
}
|
||||||
|
|
||||||
|
editPreset(preset: GuiMiscellaneousStateEntryPreset) {
|
||||||
|
this.form.id = preset.id ?? null
|
||||||
|
this.form.name = preset.name
|
||||||
|
this.form.red = this.light?.colorOrder.indexOf('R') != -1 ? preset.red : null
|
||||||
|
this.form.green = this.light?.colorOrder.indexOf('G') != -1 ? preset.green : null
|
||||||
|
this.form.blue = this.light?.colorOrder.indexOf('B') != -1 ? preset.blue : null
|
||||||
|
this.form.white = this.light?.colorOrder.indexOf('W') != -1 ? preset.white : null
|
||||||
|
this.boolForm = true
|
||||||
|
}
|
||||||
|
|
||||||
|
closeForm() {
|
||||||
|
this.boolForm = false
|
||||||
|
}
|
||||||
|
|
||||||
|
storePreset() {
|
||||||
|
this.$store.dispatch('gui/miscellaneous/storePreset', {
|
||||||
|
entry: this.light,
|
||||||
|
preset: this.form,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.boolForm = false
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePreset() {
|
||||||
|
this.$store.dispatch('gui/miscellaneous/updatePreset', {
|
||||||
|
entry: this.light,
|
||||||
|
preset: this.form,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.boolForm = false
|
||||||
|
}
|
||||||
|
|
||||||
|
deletePreset(presetId: string) {
|
||||||
|
this.$store.dispatch('gui/miscellaneous/deletePreset', {
|
||||||
|
entry: this.light,
|
||||||
|
presetId: presetId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
existsPresetName(name: string) {
|
||||||
|
return (
|
||||||
|
this.presets.findIndex(
|
||||||
|
(group: GuiMiscellaneousStateEntryPreset) => group.name === name && group.id != this.form.id
|
||||||
|
) >= 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Debounce({ time: 250 })
|
||||||
|
onColorRGBChanged(payload: IroColor) {
|
||||||
|
const color: ColorData = {
|
||||||
|
red: payload.red,
|
||||||
|
green: payload.green,
|
||||||
|
blue: payload.blue,
|
||||||
|
white: this.form.white,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.colorChanged(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Debounce({ time: 250 })
|
||||||
|
onColorWhiteChanged(payload: IroColor) {
|
||||||
|
const color: ColorData = {
|
||||||
|
red: this.form.red,
|
||||||
|
green: this.form.green,
|
||||||
|
blue: this.form.blue,
|
||||||
|
white: this.form.white,
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
color.white = payload.alpha * 255
|
||||||
|
|
||||||
|
this.colorChanged(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
onColorInput(payload: { name: string; value: number }) {
|
||||||
|
const color: ColorData = {
|
||||||
|
red: this.form.red,
|
||||||
|
green: this.form.green,
|
||||||
|
blue: this.form.blue,
|
||||||
|
white: this.form.white,
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
color[payload.name] = payload.value
|
||||||
|
|
||||||
|
this.colorChanged(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
colorChanged(color: ColorData) {
|
||||||
|
this.form.red = color.red
|
||||||
|
this.form.green = color.green
|
||||||
|
this.form.blue = color.blue
|
||||||
|
this.form.white = color.white
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
@ -948,7 +948,6 @@
|
|||||||
"EditWebcam": "Rediger Webcam",
|
"EditWebcam": "Rediger Webcam",
|
||||||
"FlipWebcam": "Vend webcam-billedet:",
|
"FlipWebcam": "Vend webcam-billedet:",
|
||||||
"Horizontally": "horisontalt",
|
"Horizontally": "horisontalt",
|
||||||
"Vertically": "vertikalt",
|
|
||||||
"IconBed": "Bed",
|
"IconBed": "Bed",
|
||||||
"IconCam": "Kamera",
|
"IconCam": "Kamera",
|
||||||
"IconDoor": "Dør",
|
"IconDoor": "Dør",
|
||||||
@ -971,6 +970,7 @@
|
|||||||
"UrlSnapshot": "URL Snapshot",
|
"UrlSnapshot": "URL Snapshot",
|
||||||
"UrlStream": "URL Stream",
|
"UrlStream": "URL Stream",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "vertikalt",
|
||||||
"Webcams": "Webcams"
|
"Webcams": "Webcams"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -530,6 +530,12 @@
|
|||||||
},
|
},
|
||||||
"MiscellaneousPanel": {
|
"MiscellaneousPanel": {
|
||||||
"Headline": "Sonstiges",
|
"Headline": "Sonstiges",
|
||||||
|
"Light": {
|
||||||
|
"Blue": "blau",
|
||||||
|
"Green": "grün",
|
||||||
|
"Red": "rot",
|
||||||
|
"White": "weiß"
|
||||||
|
},
|
||||||
"RunoutSensor": {
|
"RunoutSensor": {
|
||||||
"Detected": "erkannt",
|
"Detected": "erkannt",
|
||||||
"Disabled": "deaktiviert",
|
"Disabled": "deaktiviert",
|
||||||
@ -833,6 +839,30 @@
|
|||||||
"UnknownGroup": "Unbekannte Gruppe",
|
"UnknownGroup": "Unbekannte Gruppe",
|
||||||
"Warning": "Warnung"
|
"Warning": "Warnung"
|
||||||
},
|
},
|
||||||
|
"MiscellaneousTab": {
|
||||||
|
"AddGroup": "Gruppe hinzufügen",
|
||||||
|
"AddPreset": "Voreinstellung hinzufügen",
|
||||||
|
"Color": "Farbe",
|
||||||
|
"CreateGroup": "Gruppe erstellen",
|
||||||
|
"CreatePreset": "Voreinstellung erstellen",
|
||||||
|
"End": "Ende",
|
||||||
|
"EndDescription": "Letzte LED von dieser Gruppe.",
|
||||||
|
"Groups": "Gruppen",
|
||||||
|
"GroupSubTitle": "Start: {start}, Ende: {end}",
|
||||||
|
"LightGroups": "{name} - Gruppen",
|
||||||
|
"LightPresets": "{name} - Voreinstellungen",
|
||||||
|
"Miscellaneous": "Sonstiges",
|
||||||
|
"Name": "Name",
|
||||||
|
"NoDevicesFound": "Keine Komponente gefunden",
|
||||||
|
"NoGroupFound": "Keine Gruppe gefunden",
|
||||||
|
"NoPresetFound": "Keine Voreinstellungen gefunden",
|
||||||
|
"Presets": "Voreinstellungen",
|
||||||
|
"PresetSubTitle": "R: {red}, G: {green}, B: {blue}, W: {white}",
|
||||||
|
"Start": "Start",
|
||||||
|
"StartDescription": "Erste LED von dieser Gruppe.",
|
||||||
|
"UnableToLoadLight": "Licht konnte nicht geladen werden",
|
||||||
|
"UnableToLoadPreset": "Voreinstellung konnte nicht geladen werden"
|
||||||
|
},
|
||||||
"PresetsTab": {
|
"PresetsTab": {
|
||||||
"AddPreset": "Preset hinzufügen",
|
"AddPreset": "Preset hinzufügen",
|
||||||
"Cooldown": "Abkühlen",
|
"Cooldown": "Abkühlen",
|
||||||
@ -860,6 +890,7 @@
|
|||||||
"UpdatePrinter": "Drucker aktualisieren",
|
"UpdatePrinter": "Drucker aktualisieren",
|
||||||
"UseConfigJson": "InstanceDB = JSON erkannt. Bitte bearbeite die config.json um die Druckerliste zu modifizieren."
|
"UseConfigJson": "InstanceDB = JSON erkannt. Bitte bearbeite die config.json um die Druckerliste zu modifizieren."
|
||||||
},
|
},
|
||||||
|
"Store": "anlegen",
|
||||||
"TimelapseTab": {
|
"TimelapseTab": {
|
||||||
"Autorender": "Autorender",
|
"Autorender": "Autorender",
|
||||||
"AutorenderDescription": "Wenn diese Option aktiviert ist, wird das Zeitraffervideo am Ende des Druckvorgangs automatisch gerendert",
|
"AutorenderDescription": "Wenn diese Option aktiviert ist, wird das Zeitraffervideo am Ende des Druckvorgangs automatisch gerendert",
|
||||||
@ -954,6 +985,7 @@
|
|||||||
"ShowWebcamInNavigation": "Zeige Webcam in der Navigation",
|
"ShowWebcamInNavigation": "Zeige Webcam in der Navigation",
|
||||||
"UiSettings": "UI-Einstellungen"
|
"UiSettings": "UI-Einstellungen"
|
||||||
},
|
},
|
||||||
|
"Update": "speichern",
|
||||||
"WebcamsTab": {
|
"WebcamsTab": {
|
||||||
"AddWebcam": "Webcam hinzufügen",
|
"AddWebcam": "Webcam hinzufügen",
|
||||||
"CreateWebcam": "Erstelle Webcam",
|
"CreateWebcam": "Erstelle Webcam",
|
||||||
@ -961,7 +993,6 @@
|
|||||||
"EditWebcam": "Webcam bearbeiten",
|
"EditWebcam": "Webcam bearbeiten",
|
||||||
"FlipWebcam": "Webcam-Bild spiegeln:",
|
"FlipWebcam": "Webcam-Bild spiegeln:",
|
||||||
"Horizontally": "horizontal",
|
"Horizontally": "horizontal",
|
||||||
"Vertically": "vertikal",
|
|
||||||
"IconBed": "Bett",
|
"IconBed": "Bett",
|
||||||
"IconCam": "Kamera",
|
"IconCam": "Kamera",
|
||||||
"IconDoor": "Tür",
|
"IconDoor": "Tür",
|
||||||
@ -984,6 +1015,7 @@
|
|||||||
"UrlSnapshot": "Schnappschuss URL",
|
"UrlSnapshot": "Schnappschuss URL",
|
||||||
"UrlStream": "Stream URL",
|
"UrlStream": "Stream URL",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "vertikal",
|
||||||
"Webcams": "Webcams"
|
"Webcams": "Webcams"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -530,6 +530,12 @@
|
|||||||
},
|
},
|
||||||
"MiscellaneousPanel": {
|
"MiscellaneousPanel": {
|
||||||
"Headline": "Miscellaneous",
|
"Headline": "Miscellaneous",
|
||||||
|
"Light": {
|
||||||
|
"Blue": "blue",
|
||||||
|
"Green": "green",
|
||||||
|
"Red": "red",
|
||||||
|
"White": "white"
|
||||||
|
},
|
||||||
"RunoutSensor": {
|
"RunoutSensor": {
|
||||||
"Detected": "detected",
|
"Detected": "detected",
|
||||||
"Disabled": "disabled",
|
"Disabled": "disabled",
|
||||||
@ -837,6 +843,30 @@
|
|||||||
"UnknownGroup": "Unknown Group",
|
"UnknownGroup": "Unknown Group",
|
||||||
"Warning": "warning"
|
"Warning": "warning"
|
||||||
},
|
},
|
||||||
|
"MiscellaneousTab": {
|
||||||
|
"AddGroup": "add group",
|
||||||
|
"AddPreset": "add preset",
|
||||||
|
"Color": "Color",
|
||||||
|
"CreateGroup": "Create group",
|
||||||
|
"CreatePreset": "Create preset",
|
||||||
|
"End": "End",
|
||||||
|
"EndDescription": "Last LED of this group.",
|
||||||
|
"Groups": "Groups",
|
||||||
|
"GroupSubTitle": "Start: {start}, End: {end}",
|
||||||
|
"LightGroups": "{name} - Groups",
|
||||||
|
"LightPresets": "{name} - Presets",
|
||||||
|
"Miscellaneous": "Miscellaneous",
|
||||||
|
"Name": "Name",
|
||||||
|
"NoDevicesFound": "No devices found",
|
||||||
|
"NoGroupFound": "No group found",
|
||||||
|
"NoPresetFound": "No preset found",
|
||||||
|
"Presets": "Presets",
|
||||||
|
"PresetSubTitle": "R: {red}, G: {green}, B: {blue}, W: {white}",
|
||||||
|
"Start": "Start",
|
||||||
|
"StartDescription": "First LED of this group.",
|
||||||
|
"UnableToLoadLight": "Unable to load light",
|
||||||
|
"UnableToLoadPreset": "Unable to load preset"
|
||||||
|
},
|
||||||
"PresetsTab": {
|
"PresetsTab": {
|
||||||
"AddPreset": "add preset",
|
"AddPreset": "add preset",
|
||||||
"Cooldown": "Cooldown",
|
"Cooldown": "Cooldown",
|
||||||
@ -864,6 +894,7 @@
|
|||||||
"UpdatePrinter": "Update Printer",
|
"UpdatePrinter": "Update Printer",
|
||||||
"UseConfigJson": "InstanceDB = JSON detected. Please use the config.json to modify the printers list."
|
"UseConfigJson": "InstanceDB = JSON detected. Please use the config.json to modify the printers list."
|
||||||
},
|
},
|
||||||
|
"Store": "store",
|
||||||
"TimelapseTab": {
|
"TimelapseTab": {
|
||||||
"Autorender": "Autorender",
|
"Autorender": "Autorender",
|
||||||
"AutorenderDescription": "If enabled, the timelapse video will automatically render at the end of the print",
|
"AutorenderDescription": "If enabled, the timelapse video will automatically render at the end of the print",
|
||||||
@ -958,6 +989,7 @@
|
|||||||
"ShowWebcamInNavigation": "Show Webcam in navigation",
|
"ShowWebcamInNavigation": "Show Webcam in navigation",
|
||||||
"UiSettings": "UI-Settings"
|
"UiSettings": "UI-Settings"
|
||||||
},
|
},
|
||||||
|
"Update": "update",
|
||||||
"WebcamsTab": {
|
"WebcamsTab": {
|
||||||
"AddWebcam": "add webcam",
|
"AddWebcam": "add webcam",
|
||||||
"CreateWebcam": "Create Webcam",
|
"CreateWebcam": "Create Webcam",
|
||||||
@ -965,7 +997,6 @@
|
|||||||
"EditWebcam": "Edit Webcam",
|
"EditWebcam": "Edit Webcam",
|
||||||
"FlipWebcam": "Flip webcam image:",
|
"FlipWebcam": "Flip webcam image:",
|
||||||
"Horizontally": "horizontally",
|
"Horizontally": "horizontally",
|
||||||
"Vertically": "vertically",
|
|
||||||
"IconBed": "Bed",
|
"IconBed": "Bed",
|
||||||
"IconCam": "Cam",
|
"IconCam": "Cam",
|
||||||
"IconDoor": "Door",
|
"IconDoor": "Door",
|
||||||
@ -988,6 +1019,7 @@
|
|||||||
"UrlSnapshot": "URL Snapshot",
|
"UrlSnapshot": "URL Snapshot",
|
||||||
"UrlStream": "URL Stream",
|
"UrlStream": "URL Stream",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "vertically",
|
||||||
"Webcams": "Webcams"
|
"Webcams": "Webcams"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -929,7 +929,6 @@
|
|||||||
"EditWebcam": "Editar cámara web",
|
"EditWebcam": "Editar cámara web",
|
||||||
"FlipWebcam": "Voltear la imagen de la cámara web:",
|
"FlipWebcam": "Voltear la imagen de la cámara web:",
|
||||||
"Horizontally": "horizontalmente",
|
"Horizontally": "horizontalmente",
|
||||||
"Vertically": "verticalmente",
|
|
||||||
"IconBed": "Cama",
|
"IconBed": "Cama",
|
||||||
"IconCam": "Cámara",
|
"IconCam": "Cámara",
|
||||||
"IconDoor": "Puerta",
|
"IconDoor": "Puerta",
|
||||||
@ -951,6 +950,7 @@
|
|||||||
"UrlSnapshot": "URL Snapshot",
|
"UrlSnapshot": "URL Snapshot",
|
||||||
"UrlStream": "URL Stream",
|
"UrlStream": "URL Stream",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "verticalmente",
|
||||||
"Webcams": "Cámaras web"
|
"Webcams": "Cámaras web"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -953,7 +953,6 @@
|
|||||||
"EditWebcam": "Editer caméra",
|
"EditWebcam": "Editer caméra",
|
||||||
"FlipWebcam": "Miroir l'image de la webcam:",
|
"FlipWebcam": "Miroir l'image de la webcam:",
|
||||||
"Horizontally": "horizontal",
|
"Horizontally": "horizontal",
|
||||||
"Vertically": "vertical",
|
|
||||||
"IconBed": "Plateau",
|
"IconBed": "Plateau",
|
||||||
"IconCam": "Caméra",
|
"IconCam": "Caméra",
|
||||||
"IconDoor": "Porte",
|
"IconDoor": "Porte",
|
||||||
@ -976,6 +975,7 @@
|
|||||||
"UrlSnapshot": "URL des instantanés",
|
"UrlSnapshot": "URL des instantanés",
|
||||||
"UrlStream": "URL du flux",
|
"UrlStream": "URL du flux",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "vertical",
|
||||||
"Webcams": "Caméras"
|
"Webcams": "Caméras"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -929,7 +929,6 @@
|
|||||||
"EditWebcam": "Webkamera szerkesztése",
|
"EditWebcam": "Webkamera szerkesztése",
|
||||||
"FlipWebcam": "Webkamera tükrözése:",
|
"FlipWebcam": "Webkamera tükrözése:",
|
||||||
"Horizontally": "vízszintes",
|
"Horizontally": "vízszintes",
|
||||||
"Vertically": "függőleges",
|
|
||||||
"IconBed": "Asztal",
|
"IconBed": "Asztal",
|
||||||
"IconCam": "Kamera",
|
"IconCam": "Kamera",
|
||||||
"IconDoor": "Ajtó",
|
"IconDoor": "Ajtó",
|
||||||
@ -951,6 +950,7 @@
|
|||||||
"UrlSnapshot": "Snapshot URL-je ",
|
"UrlSnapshot": "Snapshot URL-je ",
|
||||||
"UrlStream": "Stream URL-je ",
|
"UrlStream": "Stream URL-je ",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "függőleges",
|
||||||
"Webcams": "Webkamerák"
|
"Webcams": "Webkamerák"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -796,7 +796,6 @@
|
|||||||
"EditWebcam": "Modifica Webcam",
|
"EditWebcam": "Modifica Webcam",
|
||||||
"FlipWebcam": "Specchio dell'immagine della webcam:",
|
"FlipWebcam": "Specchio dell'immagine della webcam:",
|
||||||
"Horizontally": "orizzontalmente",
|
"Horizontally": "orizzontalmente",
|
||||||
"Vertically": "verticalmente",
|
|
||||||
"IconBed": "Letto",
|
"IconBed": "Letto",
|
||||||
"IconCam": "Cam",
|
"IconCam": "Cam",
|
||||||
"IconDoor": "Porta",
|
"IconDoor": "Porta",
|
||||||
@ -818,6 +817,7 @@
|
|||||||
"UrlSnapshot": "URL Snaphot",
|
"UrlSnapshot": "URL Snaphot",
|
||||||
"UrlStream": "URL Stream",
|
"UrlStream": "URL Stream",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "verticalmente",
|
||||||
"Webcams": "Webcam"
|
"Webcams": "Webcam"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -952,7 +952,6 @@
|
|||||||
"EditWebcam": "Bewerk Webcam",
|
"EditWebcam": "Bewerk Webcam",
|
||||||
"FlipWebcam": "Flip webcam beeld:",
|
"FlipWebcam": "Flip webcam beeld:",
|
||||||
"Horizontally": "horizontaal",
|
"Horizontally": "horizontaal",
|
||||||
"Vertically": "verticaal",
|
|
||||||
"IconBed": "Bed",
|
"IconBed": "Bed",
|
||||||
"IconCam": "Camera",
|
"IconCam": "Camera",
|
||||||
"IconDoor": "Deur",
|
"IconDoor": "Deur",
|
||||||
@ -975,6 +974,7 @@
|
|||||||
"UrlSnapshot": "URL Snapshot",
|
"UrlSnapshot": "URL Snapshot",
|
||||||
"UrlStream": "URL Stream",
|
"UrlStream": "URL Stream",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "verticaal",
|
||||||
"Webcams": "Webcams"
|
"Webcams": "Webcams"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -930,7 +930,6 @@
|
|||||||
"EditWebcam": "Edytuj kamerę",
|
"EditWebcam": "Edytuj kamerę",
|
||||||
"FlipWebcam": "Odwróć widok kamery:",
|
"FlipWebcam": "Odwróć widok kamery:",
|
||||||
"Horizontally": "poziomo",
|
"Horizontally": "poziomo",
|
||||||
"Vertically": "pionowo",
|
|
||||||
"IconBed": "Stół",
|
"IconBed": "Stół",
|
||||||
"IconCam": "Kamera",
|
"IconCam": "Kamera",
|
||||||
"IconDoor": "Drzwi",
|
"IconDoor": "Drzwi",
|
||||||
@ -952,6 +951,7 @@
|
|||||||
"UrlSnapshot": "Migawka URL",
|
"UrlSnapshot": "Migawka URL",
|
||||||
"UrlStream": "Transmisja po URL",
|
"UrlStream": "Transmisja po URL",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "pionowo",
|
||||||
"Webcams": "Kamery"
|
"Webcams": "Kamery"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -930,7 +930,6 @@
|
|||||||
"EditWebcam": "Редактирование веб-камеры",
|
"EditWebcam": "Редактирование веб-камеры",
|
||||||
"FlipWebcam": "Зеркальное отображение веб-камеры:",
|
"FlipWebcam": "Зеркальное отображение веб-камеры:",
|
||||||
"Horizontally": "горизонтально",
|
"Horizontally": "горизонтально",
|
||||||
"Vertically": "вертикально",
|
|
||||||
"IconBed": "Кровать",
|
"IconBed": "Кровать",
|
||||||
"IconCam": "Камера",
|
"IconCam": "Камера",
|
||||||
"IconDoor": "Дверь",
|
"IconDoor": "Дверь",
|
||||||
@ -952,6 +951,7 @@
|
|||||||
"UrlSnapshot": "URL моментального снимка",
|
"UrlSnapshot": "URL моментального снимка",
|
||||||
"UrlStream": "URL потока",
|
"UrlStream": "URL потока",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "вертикально",
|
||||||
"Webcams": "Веб-камеры"
|
"Webcams": "Веб-камеры"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -824,7 +824,6 @@
|
|||||||
"EditWebcam": "Redigera webbkamera",
|
"EditWebcam": "Redigera webbkamera",
|
||||||
"FlipWebcam": "Vänd webbkamerabilden",
|
"FlipWebcam": "Vänd webbkamerabilden",
|
||||||
"Horizontally": "horisontellt",
|
"Horizontally": "horisontellt",
|
||||||
"Vertically": "vertikalt",
|
|
||||||
"IconBed": "Bädd",
|
"IconBed": "Bädd",
|
||||||
"IconCam": "Kamera",
|
"IconCam": "Kamera",
|
||||||
"IconDoor": "Dörr",
|
"IconDoor": "Dörr",
|
||||||
@ -846,6 +845,7 @@
|
|||||||
"UrlSnapshot": "Ögonblicksbild av webbadressen",
|
"UrlSnapshot": "Ögonblicksbild av webbadressen",
|
||||||
"UrlStream": "Webbadressström",
|
"UrlStream": "Webbadressström",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "vertikalt",
|
||||||
"Webcams": "Webbkameror"
|
"Webcams": "Webbkameror"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -951,7 +951,6 @@
|
|||||||
"EditWebcam": "Web Kamerası Düzenle",
|
"EditWebcam": "Web Kamerası Düzenle",
|
||||||
"FlipWebcam": "Web kamerasını çevirin:",
|
"FlipWebcam": "Web kamerasını çevirin:",
|
||||||
"Horizontally": "yatay olarak",
|
"Horizontally": "yatay olarak",
|
||||||
"Vertically": "dikey olarak",
|
|
||||||
"IconBed": "Yatak",
|
"IconBed": "Yatak",
|
||||||
"IconCam": "Kamera",
|
"IconCam": "Kamera",
|
||||||
"IconDoor": "Kapı",
|
"IconDoor": "Kapı",
|
||||||
@ -974,6 +973,7 @@
|
|||||||
"UrlSnapshot": "URL Anlık Görüntüsü",
|
"UrlSnapshot": "URL Anlık Görüntüsü",
|
||||||
"UrlStream": "URL Akışı",
|
"UrlStream": "URL Akışı",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "dikey olarak",
|
||||||
"Webcams": "Web kameraları"
|
"Webcams": "Web kameraları"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -952,7 +952,6 @@
|
|||||||
"EditWebcam": "Редагувати веб-камеру",
|
"EditWebcam": "Редагувати веб-камеру",
|
||||||
"FlipWebcam": "Повернути веб-камеру:",
|
"FlipWebcam": "Повернути веб-камеру:",
|
||||||
"Horizontally": "горизонтально",
|
"Horizontally": "горизонтально",
|
||||||
"Vertically": "вертикально",
|
|
||||||
"IconBed": "Ліжко",
|
"IconBed": "Ліжко",
|
||||||
"IconCam": "Cam",
|
"IconCam": "Cam",
|
||||||
"IconDoor": "Двері",
|
"IconDoor": "Двері",
|
||||||
@ -975,6 +974,7 @@
|
|||||||
"UrlSnapshot": "URL-адреса Знімку",
|
"UrlSnapshot": "URL-адреса Знімку",
|
||||||
"UrlStream": "URL-адреса Потоку",
|
"UrlStream": "URL-адреса Потоку",
|
||||||
"Uv4lMjpeg": "UV4L-MJPEG",
|
"Uv4lMjpeg": "UV4L-MJPEG",
|
||||||
|
"Vertically": "вертикально",
|
||||||
"Webcams": "Веб-камери"
|
"Webcams": "Веб-камери"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -9,6 +9,7 @@ import { defaultLogoColor, defaultPrimaryColor } from '@/store/variables'
|
|||||||
import { console } from '@/store/gui/console'
|
import { console } from '@/store/gui/console'
|
||||||
import { gcodehistory } from '@/store/gui/gcodehistory'
|
import { gcodehistory } from '@/store/gui/gcodehistory'
|
||||||
import { macros } from '@/store/gui/macros'
|
import { macros } from '@/store/gui/macros'
|
||||||
|
import { miscellaneous } from '@/store/gui/miscellaneous'
|
||||||
import { presets } from '@/store/gui/presets'
|
import { presets } from '@/store/gui/presets'
|
||||||
import { remoteprinters } from '@/store/gui/remoteprinters'
|
import { remoteprinters } from '@/store/gui/remoteprinters'
|
||||||
import { webcams } from '@/store/gui/webcams'
|
import { webcams } from '@/store/gui/webcams'
|
||||||
@ -255,6 +256,7 @@ export const gui: Module<GuiState, any> = {
|
|||||||
console,
|
console,
|
||||||
gcodehistory,
|
gcodehistory,
|
||||||
macros,
|
macros,
|
||||||
|
miscellaneous,
|
||||||
notifications,
|
notifications,
|
||||||
presets,
|
presets,
|
||||||
remoteprinters,
|
remoteprinters,
|
||||||
|
133
src/store/gui/miscellaneous/actions.ts
Normal file
133
src/store/gui/miscellaneous/actions.ts
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import { ActionTree } from 'vuex'
|
||||||
|
import { RootState } from '@/store/types'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import Vue from 'vue'
|
||||||
|
import {
|
||||||
|
GuiMiscellaneousState,
|
||||||
|
GuiMiscellaneousStateEntryLightgroup,
|
||||||
|
GuiMiscellaneousStateEntryPreset,
|
||||||
|
} from '@/store/gui/miscellaneous/types'
|
||||||
|
|
||||||
|
export const actions: ActionTree<GuiMiscellaneousState, RootState> = {
|
||||||
|
reset({ commit }) {
|
||||||
|
commit('reset')
|
||||||
|
},
|
||||||
|
|
||||||
|
upload({ state }, id) {
|
||||||
|
Vue.$socket.emit('server.database.post_item', {
|
||||||
|
namespace: 'mainsail',
|
||||||
|
key: 'miscellaneous.entries.' + id,
|
||||||
|
value: state.entries[id],
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
async store({ commit, dispatch }, payload: payloadStore) {
|
||||||
|
const id = uuidv4()
|
||||||
|
|
||||||
|
await commit('store', { id, values: payload })
|
||||||
|
await dispatch('upload', id)
|
||||||
|
|
||||||
|
return id
|
||||||
|
},
|
||||||
|
|
||||||
|
async storeLightgroup({ commit, dispatch, getters }, payload: payloadStoreLightgroup) {
|
||||||
|
let entryId = getters['getId'](payload.entry)
|
||||||
|
if (entryId === null) entryId = await dispatch('store', payload.entry)
|
||||||
|
|
||||||
|
const lightgroupId = uuidv4()
|
||||||
|
await commit('updateLightgroup', { entryId, lightgroupId, values: payload.lightgroup })
|
||||||
|
|
||||||
|
await dispatch('upload', entryId)
|
||||||
|
|
||||||
|
return lightgroupId
|
||||||
|
},
|
||||||
|
|
||||||
|
async updateLightgroup({ commit, dispatch, getters }, payload: payloadStoreLightgroup) {
|
||||||
|
const entryId = getters['getId'](payload.entry)
|
||||||
|
if (entryId === null) return
|
||||||
|
|
||||||
|
await commit('updateLightgroup', { entryId, lightgroupId: payload.lightgroup.id, values: payload.lightgroup })
|
||||||
|
|
||||||
|
await dispatch('upload', entryId)
|
||||||
|
|
||||||
|
return payload.lightgroup.id
|
||||||
|
},
|
||||||
|
|
||||||
|
async deleteLightgroup({ commit, dispatch, getters }, payload: payloadDeleteLightgroup) {
|
||||||
|
const entryId = getters['getId'](payload.entry)
|
||||||
|
if (entryId === null) return
|
||||||
|
|
||||||
|
await commit('destroyLightgroup', { entryId, lightgroupId: payload.lightgroupId })
|
||||||
|
|
||||||
|
await dispatch('upload', entryId)
|
||||||
|
},
|
||||||
|
|
||||||
|
async storePreset({ commit, dispatch, getters }, payload: payloadStorePreset) {
|
||||||
|
let entryId = getters['getId'](payload.entry)
|
||||||
|
if (entryId === null) entryId = await dispatch('store', payload.entry)
|
||||||
|
|
||||||
|
const presetId = uuidv4()
|
||||||
|
await commit('updatePreset', { entryId, presetId, values: payload.preset })
|
||||||
|
|
||||||
|
await dispatch('upload', entryId)
|
||||||
|
|
||||||
|
return presetId
|
||||||
|
},
|
||||||
|
|
||||||
|
async updatePreset({ commit, dispatch, getters }, payload: payloadStorePreset) {
|
||||||
|
const entryId = getters['getId'](payload.entry)
|
||||||
|
if (entryId === null) return
|
||||||
|
|
||||||
|
await commit('updatePreset', { entryId, presetId: payload.preset.id, values: payload.preset })
|
||||||
|
|
||||||
|
await dispatch('upload', entryId)
|
||||||
|
|
||||||
|
return payload.preset.id
|
||||||
|
},
|
||||||
|
|
||||||
|
async deletePreset({ commit, dispatch, getters }, payload: payloadDeletePreset) {
|
||||||
|
const entryId = getters['getId'](payload.entry)
|
||||||
|
if (entryId === null) return
|
||||||
|
|
||||||
|
await commit('destroyPreset', { entryId, presetId: payload.presetId })
|
||||||
|
|
||||||
|
await dispatch('upload', entryId)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
interface payloadStore {
|
||||||
|
type: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface payloadStoreLightgroup {
|
||||||
|
entry: {
|
||||||
|
type: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
lightgroup: GuiMiscellaneousStateEntryLightgroup
|
||||||
|
}
|
||||||
|
|
||||||
|
interface payloadDeleteLightgroup {
|
||||||
|
entry: {
|
||||||
|
type: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
lightgroupId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface payloadStorePreset {
|
||||||
|
entry: {
|
||||||
|
type: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
preset: GuiMiscellaneousStateEntryPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
interface payloadDeletePreset {
|
||||||
|
entry: {
|
||||||
|
type: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
presetId: string
|
||||||
|
}
|
75
src/store/gui/miscellaneous/getters.ts
Normal file
75
src/store/gui/miscellaneous/getters.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { GetterTree } from 'vuex'
|
||||||
|
import {
|
||||||
|
GuiMiscellaneousState,
|
||||||
|
GuiMiscellaneousStateEntry,
|
||||||
|
GuiMiscellaneousStateEntryLightgroup,
|
||||||
|
GuiMiscellaneousStateEntryPreset,
|
||||||
|
} from '@/store/gui/miscellaneous/types'
|
||||||
|
import { caseInsensitiveSort } from '@/plugins/helpers'
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
export const getters: GetterTree<GuiMiscellaneousState, any> = {
|
||||||
|
getEntries: (state) => {
|
||||||
|
const output: GuiMiscellaneousStateEntry[] = []
|
||||||
|
|
||||||
|
Object.entries(state.entries).forEach(([key, values]) => {
|
||||||
|
output.push({
|
||||||
|
id: key,
|
||||||
|
name: values.name,
|
||||||
|
type: values.type,
|
||||||
|
lightgroups: { ...values.lightgroups },
|
||||||
|
presets: { ...values.presets },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return output
|
||||||
|
},
|
||||||
|
|
||||||
|
getEntry: (state, getters) => (payload: { type: string; name: string }) => {
|
||||||
|
return getters.getEntries.find(
|
||||||
|
(entry: GuiMiscellaneousStateEntry) => entry.name === payload.name && entry.type === payload.type
|
||||||
|
) as GuiMiscellaneousStateEntry
|
||||||
|
},
|
||||||
|
|
||||||
|
getId: (state, getters) => (payload: { type: string; name: string }) => {
|
||||||
|
return getters.getEntry(payload)?.id ?? null
|
||||||
|
},
|
||||||
|
|
||||||
|
getEntryLightgroups: (state, getters) => (payload: { type: string; name: string }) => {
|
||||||
|
const entry = getters.getEntry(payload) as GuiMiscellaneousStateEntry | null
|
||||||
|
|
||||||
|
if (!entry) return []
|
||||||
|
|
||||||
|
const groups: GuiMiscellaneousStateEntryLightgroup[] = []
|
||||||
|
Object.entries(entry.lightgroups).forEach(([key, lightgroup]) => {
|
||||||
|
groups.push({
|
||||||
|
name: lightgroup.name,
|
||||||
|
start: lightgroup.start,
|
||||||
|
end: lightgroup.end,
|
||||||
|
id: key,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return caseInsensitiveSort(groups, 'name')
|
||||||
|
},
|
||||||
|
|
||||||
|
getEntryPresets: (state, getters) => (payload: { type: string; name: string }) => {
|
||||||
|
const entry = getters.getEntry(payload) as GuiMiscellaneousStateEntry | null
|
||||||
|
|
||||||
|
if (!entry) return []
|
||||||
|
|
||||||
|
const presets: GuiMiscellaneousStateEntryPreset[] = []
|
||||||
|
Object.entries(entry.presets).forEach(([key, preset]) => {
|
||||||
|
presets.push({
|
||||||
|
name: preset.name,
|
||||||
|
red: preset.red,
|
||||||
|
green: preset.green,
|
||||||
|
blue: preset.blue,
|
||||||
|
white: preset.white,
|
||||||
|
id: key,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return caseInsensitiveSort(presets, 'name')
|
||||||
|
},
|
||||||
|
}
|
23
src/store/gui/miscellaneous/index.ts
Normal file
23
src/store/gui/miscellaneous/index.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Module } from 'vuex'
|
||||||
|
import { actions } from '@/store/gui/miscellaneous/actions'
|
||||||
|
import { mutations } from '@/store/gui/miscellaneous/mutations'
|
||||||
|
import { getters } from '@/store/gui/miscellaneous/getters'
|
||||||
|
import { GuiMiscellaneousState } from '@/store/gui/miscellaneous/types'
|
||||||
|
|
||||||
|
export const getDefaultState = (): GuiMiscellaneousState => {
|
||||||
|
return {
|
||||||
|
entries: {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// initial state
|
||||||
|
const state = getDefaultState()
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
export const miscellaneous: Module<GuiMiscellaneousState, any> = {
|
||||||
|
namespaced: true,
|
||||||
|
state,
|
||||||
|
getters,
|
||||||
|
actions,
|
||||||
|
mutations,
|
||||||
|
}
|
92
src/store/gui/miscellaneous/mutations.ts
Normal file
92
src/store/gui/miscellaneous/mutations.ts
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import { getDefaultState } from './index'
|
||||||
|
import { MutationTree } from 'vuex'
|
||||||
|
import Vue from 'vue'
|
||||||
|
import {
|
||||||
|
GuiMiscellaneousState,
|
||||||
|
GuiMiscellaneousStateEntry,
|
||||||
|
GuiMiscellaneousStateEntryLightgroup,
|
||||||
|
GuiMiscellaneousStateEntryPreset,
|
||||||
|
} from '@/store/gui/miscellaneous/types'
|
||||||
|
|
||||||
|
export const mutations: MutationTree<GuiMiscellaneousState> = {
|
||||||
|
reset(state) {
|
||||||
|
Object.assign(state, getDefaultState())
|
||||||
|
},
|
||||||
|
|
||||||
|
store(state, payload: payloadStore) {
|
||||||
|
const values: GuiMiscellaneousStateEntry = {
|
||||||
|
name: payload.values.name,
|
||||||
|
type: payload.values.type,
|
||||||
|
lightgroups: {},
|
||||||
|
presets: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.set(state.entries, payload.id, values)
|
||||||
|
},
|
||||||
|
|
||||||
|
updateLightgroup(state, payload: payloadUpdateLightgroup) {
|
||||||
|
const lightgroup: GuiMiscellaneousStateEntryLightgroup = {
|
||||||
|
name: payload.values.name,
|
||||||
|
start: parseInt(payload.values.start.toString()),
|
||||||
|
end: parseInt(payload.values.end.toString()),
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.set(state.entries[payload.entryId].lightgroups, payload.lightgroupId, lightgroup)
|
||||||
|
},
|
||||||
|
|
||||||
|
destroyLightgroup(state, payload: payloadDestroyLightgroup) {
|
||||||
|
const entries = { ...state.entries }
|
||||||
|
delete entries[payload.entryId].lightgroups[payload.lightgroupId]
|
||||||
|
|
||||||
|
Vue.set(state, 'entries', entries)
|
||||||
|
},
|
||||||
|
|
||||||
|
updatePreset(state, payload: payloadUpdatePreset) {
|
||||||
|
const preset: GuiMiscellaneousStateEntryPreset = {
|
||||||
|
name: payload.values.name,
|
||||||
|
red: payload.values.red,
|
||||||
|
green: payload.values.green,
|
||||||
|
blue: payload.values.blue,
|
||||||
|
white: payload.values.white,
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.set(state.entries[payload.entryId].presets, payload.presetId, preset)
|
||||||
|
},
|
||||||
|
|
||||||
|
destroyPreset(state, payload: payloadDestroyPreset) {
|
||||||
|
const entries = { ...state.entries }
|
||||||
|
delete entries[payload.entryId].presets[payload.presetId]
|
||||||
|
|
||||||
|
Vue.set(state, 'entries', entries)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
interface payloadStore {
|
||||||
|
id: string
|
||||||
|
values: {
|
||||||
|
type: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface payloadUpdateLightgroup {
|
||||||
|
entryId: string
|
||||||
|
lightgroupId: string
|
||||||
|
values: GuiMiscellaneousStateEntryLightgroup
|
||||||
|
}
|
||||||
|
|
||||||
|
interface payloadDestroyLightgroup {
|
||||||
|
entryId: string
|
||||||
|
lightgroupId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface payloadUpdatePreset {
|
||||||
|
entryId: string
|
||||||
|
presetId: string
|
||||||
|
values: GuiMiscellaneousStateEntryPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
interface payloadDestroyPreset {
|
||||||
|
entryId: string
|
||||||
|
presetId: string
|
||||||
|
}
|
33
src/store/gui/miscellaneous/types.ts
Normal file
33
src/store/gui/miscellaneous/types.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
export interface GuiMiscellaneousState {
|
||||||
|
entries: {
|
||||||
|
[key: string]: GuiMiscellaneousStateEntry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GuiMiscellaneousStateEntry {
|
||||||
|
id?: string
|
||||||
|
type: string
|
||||||
|
name: string
|
||||||
|
lightgroups: {
|
||||||
|
[key: string]: GuiMiscellaneousStateEntryLightgroup
|
||||||
|
}
|
||||||
|
presets: {
|
||||||
|
[key: string]: GuiMiscellaneousStateEntryPreset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GuiMiscellaneousStateEntryLightgroup {
|
||||||
|
id?: string
|
||||||
|
name: string
|
||||||
|
start: number
|
||||||
|
end: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GuiMiscellaneousStateEntryPreset {
|
||||||
|
id?: string
|
||||||
|
name: string
|
||||||
|
red: number | null
|
||||||
|
blue: number | null
|
||||||
|
green: number | null
|
||||||
|
white: number | null
|
||||||
|
}
|
@ -21,6 +21,8 @@ import {
|
|||||||
PrinterStateTemperatureSensor,
|
PrinterStateTemperatureSensor,
|
||||||
PrinterStateToolchangeMacro,
|
PrinterStateToolchangeMacro,
|
||||||
PrinterStateAdditionalSensor,
|
PrinterStateAdditionalSensor,
|
||||||
|
PrinterGetterObject,
|
||||||
|
PrinterStateLight,
|
||||||
} from '@/store/printer/types'
|
} from '@/store/printer/types'
|
||||||
import { caseInsensitiveSort, formatFrequency, getMacroParams } from '@/plugins/helpers'
|
import { caseInsensitiveSort, formatFrequency, getMacroParams } from '@/plugins/helpers'
|
||||||
import { RootState } from '@/store/types'
|
import { RootState } from '@/store/types'
|
||||||
@ -139,6 +141,29 @@ export const getters: GetterTree<PrinterState, RootState> = {
|
|||||||
return 0
|
return 0
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getPrinterObjects: (state) => (supportedObjects: string[]) => {
|
||||||
|
const outputObjects: PrinterGetterObject[] = []
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(state)) {
|
||||||
|
let type = key.substring(0, key.indexOf(' ')).trimEnd()
|
||||||
|
let name = key.substring(key.indexOf(' ') + 1).trimStart()
|
||||||
|
|
||||||
|
if (key.indexOf(' ') === -1) type = name = key
|
||||||
|
|
||||||
|
if (supportedObjects.includes(type)) {
|
||||||
|
outputObjects.push({
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
state: { ...value },
|
||||||
|
config: state.configfile?.config[key] ?? {},
|
||||||
|
settings: state.configfile?.settings[key] ?? {},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputObjects
|
||||||
|
},
|
||||||
|
|
||||||
getMacros: (state) => {
|
getMacros: (state) => {
|
||||||
const array: PrinterStateMacro[] = []
|
const array: PrinterStateMacro[] = []
|
||||||
const config = state.configfile?.config ?? {}
|
const config = state.configfile?.config ?? {}
|
||||||
@ -429,26 +454,21 @@ export const getters: GetterTree<PrinterState, RootState> = {
|
|||||||
return 'fan' in state ? state.fan.speed : 0
|
return 'fan' in state ? state.fan.speed : 0
|
||||||
},
|
},
|
||||||
|
|
||||||
getFans: (state) => {
|
getFans: (state, getters) => {
|
||||||
const fans: PrinterStateFan[] = []
|
const fans: PrinterStateFan[] = []
|
||||||
const supportedFans = ['temperature_fan', 'controller_fan', 'heater_fan', 'fan_generic', 'fan']
|
const supportedFans = ['temperature_fan', 'controller_fan', 'heater_fan', 'fan_generic', 'fan']
|
||||||
|
const objects = getters.getPrinterObjects(supportedFans)
|
||||||
|
|
||||||
const controllableFans = ['fan_generic', 'fan']
|
const controllableFans = ['fan_generic', 'fan']
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(state)) {
|
objects.foreach((object: PrinterGetterObject) => {
|
||||||
const nameSplit = key.split(' ')
|
fans.push({
|
||||||
|
name: object.name,
|
||||||
if (supportedFans.includes(nameSplit[0])) {
|
type: object.type,
|
||||||
const name = nameSplit.length > 1 ? nameSplit[1] : nameSplit[0]
|
speed: object.state.speed ?? 0,
|
||||||
|
controllable: controllableFans.includes(object.type),
|
||||||
fans.push({
|
})
|
||||||
name: name,
|
})
|
||||||
type: nameSplit[0],
|
|
||||||
speed: 'speed' in value ? value.speed : 0,
|
|
||||||
controllable: controllableFans.includes(nameSplit[0]),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fans.sort((a, b) => {
|
return fans.sort((a, b) => {
|
||||||
if (a.controllable < b.controllable) return 1
|
if (a.controllable < b.controllable) return 1
|
||||||
@ -464,6 +484,86 @@ export const getters: GetterTree<PrinterState, RootState> = {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getLights: (state, getters) => {
|
||||||
|
const lights: PrinterStateLight[] = []
|
||||||
|
const supportedObjects = ['dotstar', 'led', 'neopixel', 'pca9533', 'pca9632']
|
||||||
|
const objects = getters.getPrinterObjects(supportedObjects)
|
||||||
|
|
||||||
|
objects
|
||||||
|
.filter((object: PrinterGetterObject) => {
|
||||||
|
return !object.name.startsWith('_')
|
||||||
|
})
|
||||||
|
.forEach((object: PrinterGetterObject) => {
|
||||||
|
let colorOrder = 'RGB'
|
||||||
|
let singleChannelTarget = null
|
||||||
|
const colorData = object.state.color_data ?? []
|
||||||
|
|
||||||
|
if ('color_order' in object.settings) colorOrder = object.settings.color_order[0] ?? ''
|
||||||
|
|
||||||
|
if (object.type === 'led') {
|
||||||
|
colorOrder = ''
|
||||||
|
if ('red_pin' in object.config) colorOrder += 'R'
|
||||||
|
if ('green_pin' in object.config) colorOrder += 'G'
|
||||||
|
if ('blue_pin' in object.config) colorOrder += 'B'
|
||||||
|
if ('white_pin' in object.config) colorOrder += 'W'
|
||||||
|
}
|
||||||
|
|
||||||
|
let initialRed = object.settings.initial_red ?? null
|
||||||
|
if (!('initial_red' in object.config)) initialRed = null
|
||||||
|
|
||||||
|
let initialGreen = object.settings.initial_green ?? null
|
||||||
|
if (!('initial_green' in object.config)) initialGreen = null
|
||||||
|
|
||||||
|
let initialBlue = object.settings.initial_blue ?? null
|
||||||
|
if (!('initial_blue' in object.config)) initialBlue = null
|
||||||
|
|
||||||
|
let initialWhite = object.settings.initial_white ?? null
|
||||||
|
if (!('initial_white' in object.config)) initialWhite = null
|
||||||
|
|
||||||
|
if (object.type === 'led' && colorOrder.length === 1) {
|
||||||
|
const firstColorData = colorData[0] ?? []
|
||||||
|
|
||||||
|
switch (colorOrder) {
|
||||||
|
case 'R':
|
||||||
|
singleChannelTarget = firstColorData[0] ?? 0
|
||||||
|
break
|
||||||
|
case 'G':
|
||||||
|
singleChannelTarget = firstColorData[1] ?? 0
|
||||||
|
break
|
||||||
|
case 'B':
|
||||||
|
singleChannelTarget = firstColorData[2] ?? 0
|
||||||
|
break
|
||||||
|
case 'W':
|
||||||
|
singleChannelTarget = firstColorData[3] ?? 0
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lights.push({
|
||||||
|
name: object.name,
|
||||||
|
type: object.type as PrinterStateLight['type'],
|
||||||
|
chainCount: object.settings.chain_count ?? 1,
|
||||||
|
colorOrder,
|
||||||
|
initialRed,
|
||||||
|
initialGreen,
|
||||||
|
initialBlue,
|
||||||
|
initialWhite,
|
||||||
|
colorData,
|
||||||
|
singleChannelTarget,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return lights.sort((a, b) => {
|
||||||
|
const nameA = a.name.toUpperCase()
|
||||||
|
const nameB = b.name.toUpperCase()
|
||||||
|
|
||||||
|
if (nameA < nameB) return -1
|
||||||
|
if (nameA > nameB) return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
getMiscellaneous: (state) => {
|
getMiscellaneous: (state) => {
|
||||||
const output: PrinterStateMiscellaneous[] = []
|
const output: PrinterStateMiscellaneous[] = []
|
||||||
const supportedObjects = ['controller_fan', 'heater_fan', 'fan_generic', 'fan', 'output_pin']
|
const supportedObjects = ['controller_fan', 'heater_fan', 'fan_generic', 'fan', 'output_pin']
|
||||||
|
@ -108,6 +108,32 @@ export interface PrinterStateFan {
|
|||||||
controllable: boolean
|
controllable: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PrinterStateLight {
|
||||||
|
name: string
|
||||||
|
type: 'led' | 'neopixel' | 'dotstar' | 'pca9533' | 'pca9632'
|
||||||
|
colorOrder: string
|
||||||
|
chainCount: number
|
||||||
|
initialRed: number | null
|
||||||
|
initialGreen: number | null
|
||||||
|
initialBlue: number | null
|
||||||
|
initialWhite: number | null
|
||||||
|
colorData: number[][]
|
||||||
|
singleChannelTarget: number | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PrinterStateLight {
|
||||||
|
name: string
|
||||||
|
type: 'led' | 'neopixel' | 'dotstar' | 'pca9533' | 'pca9632'
|
||||||
|
colorOrder: string
|
||||||
|
chainCount: number
|
||||||
|
initialRed: number | null
|
||||||
|
initialGreen: number | null
|
||||||
|
initialBlue: number | null
|
||||||
|
initialWhite: number | null
|
||||||
|
colorData: number[][]
|
||||||
|
singleChannelTarget: number | null
|
||||||
|
}
|
||||||
|
|
||||||
export interface PrinterStateMiscellaneous {
|
export interface PrinterStateMiscellaneous {
|
||||||
name: string
|
name: string
|
||||||
type: string
|
type: string
|
||||||
@ -227,3 +253,17 @@ export interface PrinterStateToolchangeMacro {
|
|||||||
name: string
|
name: string
|
||||||
active: boolean
|
active: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PrinterGetterObject {
|
||||||
|
name: string
|
||||||
|
type: string
|
||||||
|
state: {
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
config: {
|
||||||
|
[key: string]: string
|
||||||
|
}
|
||||||
|
settings: {
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user