CreatBotMainsail/src/components/settings/SettingsWebcamsTab.vue
Stefan Dej d12f1cbb32 refactor: rename webcamTab to webcamsTab in settings menu
Signed-off-by: Stefan Dej <meteyou@gmail.com>
2021-11-07 17:05:19 +01:00

309 lines
14 KiB
Vue

<template>
<div>
<v-card flat v-if="!form.bool">
<v-card-text>
<h3 class="text-h5 mb-3">{{ $t('Settings.WebcamsTab.Webcams') }}</h3>
<div v-for="(webcam) in webcams" v-bind:key="webcam.id">
<v-divider class="my-2"></v-divider>
<settings-row :title="webcam.name" :icon="webcam.icon" :sub-title="getSubtitle(webcam)">
<v-btn small outlined @click="editWebcam(webcam)">
<v-icon small left>mdi-pencil</v-icon> {{ $t('Settings.Edit') }}
</v-btn>
<v-btn small outlined @click="deleteWebcam(webcam.id)" class="ml-3 minwidth-0 px-2" color="error">
<v-icon small>mdi-delete</v-icon>
</v-btn>
</settings-row>
</div>
</v-card-text>
<v-card-actions class="d-flex justify-end">
<v-btn text color="primary" @click="createWebcam">{{ $t("Settings.WebcamsTab.AddWebcam")}}</v-btn>
</v-card-actions>
</v-card>
<v-card flat v-else>
<v-form v-model="form.valid" @submit.prevent="saveWebcam">
<v-card-title>
{{ form.id === null ? $t("Settings.WebcamsTab.CreateWebcam") : $t("Settings.WebcamsTab.EditWebcam") }}
</v-card-title>
<v-card-text>
<v-row>
<v-col class="col-12 col-sm-6">
<v-row>
<v-col class="col-2">
<v-item-group>
<v-menu :offset-y="true" title="Icon">
<template v-slot:activator="{ on, attrs }">
<v-btn class="px-2 minwidth-0" color="transparent" v-bind="attrs" v-on="on" elevation="0">
<v-icon>{{ form.icon }}</v-icon>
</v-btn>
</template>
<v-list dense class="py-0">
<v-list-item v-for="icon of this.iconItems" v-bind:key="icon.value" link @click="setFormIcon(icon.value)">
<v-list-item-icon class="mr-0">
<v-icon small>{{ icon.value }}</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title v-text="icon.text"></v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
</v-item-group>
</v-col>
<v-col class="col-10">
<v-text-field
v-model="form.name"
:label="$t('Settings.WebcamsTab.Name')"
hide-details="auto"
:rules="[rules.required, rules.unique]"
dense
></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col class="py-1">
<v-text-field
v-model="form.urlStream"
:label="$t('Settings.WebcamsTab.UrlStream')"
hide-details="auto"
:rules="[rules.required]"
></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col class="py-1">
<v-text-field
v-model="form.urlSnapshot"
:label="$t('Settings.WebcamsTab.UrlSnapshot')"
hide-details="auto"
:rules="[rules.requiredMjpegAdaptive]"
></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col class="py-1">
<v-select
v-model="form.service"
:items="serviceItems"
hide-details
:label="$t('Settings.WebcamsTab.Service')"
></v-select>
</v-col>
</v-row>
<v-row v-if="form.service === 'mjpegstreamer-adaptive'">
<v-col class="py-1">
<v-text-field
v-model="form.targetFps"
hide-details
:label="$t('Settings.WebcamsTab.TargetFPS')"
></v-text-field>
</v-col>
</v-row>
<v-row>
<v-col class="py-1">
<v-checkbox
v-model="form.flipX"
hide-details
class="mt-1"
:label="$t('Settings.WebcamsTab.FlipHorizontally')"
></v-checkbox>
</v-col>
</v-row>
<v-row>
<v-col class="py-1">
<v-checkbox
v-model="form.flipY"
hide-details
class="mt-1"
:label="$t('Settings.WebcamsTab.FlipVertically')"
></v-checkbox>
</v-col>
</v-row>
</v-col>
<v-col class="col-12 col-sm-6 text-center" align-self="center">
<vue-load-image v-if="['mjpegstreamer', 'mjpegstreamer-adaptive', 'uv4l-mjpeg'].includes(form.service)">
<img slot="image" :src="form.service === 'mjpegstreamer-adaptive' ? form.urlSnapshot : form.urlStream" alt="Preview" :style="webcamStyle" class="webcamImage" />
<v-progress-circular slot="preloader" indeterminate color="primary"></v-progress-circular>
<template slot="error">
<v-icon x-large>mdi-webcam-off</v-icon>
<div class="subtitle-1 mt-2">{{ $t('Settings.WebcamsTab.UrlNotAvailable') }}</div>
</template>
</vue-load-image>
<video v-if="['ipstream'].includes(form.service)" :src="form.urlStream" autoplay :style="webcamStyle" />
</v-col>
</v-row>
</v-card-text>
<v-card-actions class="d-flex justify-end">
<v-btn
text
@click="form.bool = false"
>
{{ $t('Settings.Cancel') }}
</v-btn>
<v-btn
color="primary"
text
type="submit"
>
{{ form.id === null ? $t("Settings.WebcamsTab.SaveWebcam") : $t("Settings.WebcamsTab.UpdateWebcam") }}
</v-btn>
</v-card-actions>
</v-form>
</v-card>
</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 {GuiWebcamStateWebcam} from '@/store/gui/webcams/types'
interface webcamForm {
bool: boolean
id: string | null
valid: boolean
name: string
icon: string
service: string
targetFps: number
urlStream: string
urlSnapshot: string
flipX: boolean
flipY: boolean
}
@Component({
components: {SettingsRow}
})
export default class SettingsWebcamsTab extends Mixins(BaseMixin) {
private form: webcamForm = {
bool: false,
id: null,
valid: false,
name: '',
icon: '',
service: '',
targetFps: 15,
urlStream: '',
urlSnapshot: '',
flipX: false,
flipY: false,
}
private rules = {
required: (value: string) => value !== '' || this.$t('Settings.WebcamsTab.Required'),
requiredMjpegAdaptive: (value: string) => (value !== '' && this.form.service === 'mjpegstreamer-adaptive') || this.$t('Settings.WebcamsTab.Required'),
unique: (value: string) => !this.existsWebcamName(value) || this.$t('Settings.WebcamsTab.NameAlreadyExists'),
}
get webcams() {
return this.$store.getters['gui/webcams/getWebcams'] ?? []
}
get iconItems() {
return [
{ value: 'mdi-printer-3d', text: this.$t('Settings.WebcamsTab.IconPrinter') },
{ value: 'mdi-printer-3d-nozzle', text: this.$t('Settings.WebcamsTab.IconNozzle') },
{ value: 'mdi-radiator-disabled', text: this.$t('Settings.WebcamsTab.IconBed') },
{ value: 'mdi-webcams', text: this.$t('Settings.WebcamsTab.IconCam') },
{ value: 'mdi-album', text: this.$t('Settings.WebcamsTab.IconFilament') },
{ value: 'mdi-door', text: this.$t('Settings.WebcamsTab.IconDoor') },
{ value: 'mdi-raspberry-pi', text: this.$t('Settings.WebcamsTab.IconMcu') },
{ value: 'mdi-campfire', text: this.$t('Settings.WebcamsTab.IconHot') },
]
}
get serviceItems() {
return [
{ value: 'mjpegstreamer', text: this.$t('Settings.WebcamsTab.Mjpegstreamer')},
{ value: 'mjpegstreamer-adaptive', text: this.$t('Settings.WebcamsTab.MjpegstreamerAdaptive') },
{ value: 'uv4l-mjpeg', text: this.$t('Settings.WebcamsTab.Uv4lMjpeg') },
{ value: 'ipstream', text: this.$t('Settings.WebcamsTab.Ipstream') },
]
}
get webcamStyle() {
let transforms = ''
if (this.form.flipX) transforms += ' scaleX(-1)'
if (this.form.flipY) transforms += ' scaleY(-1)'
if (transforms.trimLeft().length) {
return { transform: transforms.trimLeft() }
}
return ''
}
getSubtitle(webcam: GuiWebcamStateWebcam) {
return 'URL: '+ (webcam.service === 'mjpegstreamer-adaptive' ? webcam.urlSnapshot : webcam.urlStream)
}
existsWebcamName(name: string) {
return (this.webcams.findIndex((webcam: GuiWebcamStateWebcam) => webcam.name === name && webcam.id !== this.form.id) !== -1)
}
createWebcam() {
this.clearDialog()
this.form.bool = true
}
editWebcam(webcam: GuiWebcamStateWebcam) {
this.form.id = webcam.id ?? null
this.form.name = webcam.name
this.form.icon = webcam.icon
this.form.service = webcam.service
this.form.targetFps = webcam.targetFps
this.form.urlStream = webcam.urlStream
this.form.urlSnapshot = webcam.urlSnapshot
this.form.flipX = webcam.flipX
this.form.flipY = webcam.flipY
this.form.bool = true
this.form.valid = false
}
saveWebcam() {
if (this.form.valid) {
const values = {
name: this.form.name,
icon: this.form.icon,
service: this.form.service,
targetFps: this.form.targetFps,
urlStream: this.form.urlStream,
urlSnapshot: this.form.urlSnapshot,
flipX: this.form.flipX,
flipY: this.form.flipY,
}
if (this.form.id !== null) this.$store.dispatch('gui/webcam/update', { id: this.form.id, values: values })
else this.$store.dispatch('gui/webcam/store', { values })
this.clearDialog()
}
}
deleteWebcam(id: string) {
this.$store.dispatch('gui/webcam/delete', id)
}
clearDialog() {
this.form.bool = false
this.form.id = null
this.form.name = ''
this.form.icon = 'mdi-webcams'
this.form.service = 'mjpegstreamer-adaptive'
this.form.targetFps = 15
this.form.urlStream = '/webcams/?action=stream'
this.form.urlSnapshot = '/webcams/?action=snapshot'
this.form.flipX = false
this.form.flipY = false
}
setFormIcon(icon: string) {
this.form.icon = icon
}
}
</script>