diff --git a/.gitignore b/.gitignore index 85dd33c5f..acffdf238 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ design *.log packages/test dist +dev-dist temp .vuerc .version diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c96e03b4..ea0a17a75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,39 @@ # Changelog All notable changes to Mainsail will be documented in this file. +## [2.6.1](https://github.com/mainsail-crew/mainsail/releases/tag/v2.6.1) - 2023-07-24 +### Bug Fixes and Improvements + +- Show delete dialog for single files too (#1442) | [7da3352](7da33523d1ec7c4a3206400fb92803685176167e) +- Remove variable check in klipper config StreamParser (#1435) | [6e7ef65](6e7ef6554ec88ceb29f66b4d6a5d5f21ef77671b) +- Fix condition in restartServiceNameExists check (#1450) | [a7e70c7](a7e70c75d0009ffed14e8717ad8286f91e4e7e8a) +- Avoid hitting 100% before print is complete (#1455) | [3959000](39590004da7ca22fef82fbd148b31683c462bb13) +- Fix issue with ETA and 12h time format (#1463) | [039a446](039a446944f05ea241574c65040d520bbbef0e9b) +- Fix issue with CSV separator in contents (#1460) | [1895d2d](1895d2d90591946c792faaf3f62c52865f27cd62) +- Fix issue with webcams in farm printers (#1469) | [5b2bea5](5b2bea51aab79aabfab02825cdce45be351c1c6f) + +### Refactor + +- Build version file for moonraker (#1449) | [21d3d39](21d3d395039ec855d062a5ee5e5b43e2d858f402) +- Use moonraker webcam api instead of direct DB access (#1445) | [7c81690](7c81690c1e299c804edb4ede0acab7d77d1dedbe) +- Change SettingsGeneralTab file (#1475) | [db09bbe](db09bbe043b2e43053779709f5260c7275bc4969) +- Extract Presets and Settings from TemperaturePanel (#1465) | [be25316](be253165a003c50fd992f43c586ce5315dc2352d) +- Display errors and warnings in the update_manager (#1453) | [0cefa24](0cefa24e766c568a56127bfd55272735383cb45e) + +### Localization + +- **pl**: Update Polish translation (#1434) | [73e503f](73e503fc6448ae174dd7f9d59236c820bd4b6631) +- **pl**: Update Polish translation (#1447) | [d844125](d8441254db04d672fe2137f64e39127f524c4769) +- **pl**: Update polish locale (#1471) | [a58bef2](a58bef2a03479262b4ee5db2b5d103e8dc2194c5) +- **pl**: Update Polish translation (#1476) | [6758049](6758049d29c7410bcdedec689eaca503952b2c7e) +- **tr**: Update turkish locale (#1480) | [f52b94c](f52b94c459ad759e160a568d3b6f366b0e65f484) +- **zh**: Update Chinese (zh) localization (#1459) | [bcbef2f](bcbef2f19af4746b941ddcb29c98ff5f071611d0) + +### Other + +- **pwa**: Remove debug warnings in browser console (#1441) | [2962df2](2962df21e512baad6976dc502d6234c2969da686) +- Add dev-dist to .gitignore (#1451) | [ef2d17c](ef2d17cadde566e8b713031cb7292d65ca1bec12) + ## [2.6.0](https://github.com/mainsail-crew/mainsail/releases/tag/v2.6.0) - 2023-06-19 ### Features diff --git a/package-lock.json b/package-lock.json index 83dc5cb1d..82137c852 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mainsail", - "version": "2.6.0", + "version": "2.6.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mainsail", - "version": "2.6.0", + "version": "2.6.1", "dependencies": { "@codemirror/commands": "^6.0.1", "@codemirror/lang-css": "^6.0.0", @@ -10253,9 +10253,9 @@ } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -17924,9 +17924,9 @@ } }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true }, "workbox-background-sync": { diff --git a/package.json b/package.json index 181eb4ea7..8eb715712 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mainsail", - "version": "2.6.0", + "version": "2.6.1", "private": true, "decription": "a klipper web interface", "author": { diff --git a/src/App.vue b/src/App.vue index f24eebf0a..24aacef7b 100644 --- a/src/App.vue +++ b/src/App.vue @@ -170,7 +170,7 @@ export default class App extends Mixins(BaseMixin) { } get print_percent(): number { - return Math.round(this.$store.getters['printer/getPrintPercent'] * 100) + return Math.floor(this.$store.getters['printer/getPrintPercent'] * 100) } @Watch('language') diff --git a/src/components/TheEditor.vue b/src/components/TheEditor.vue index 75420cad1..63463ab87 100644 --- a/src/components/TheEditor.vue +++ b/src/components/TheEditor.vue @@ -239,25 +239,33 @@ export default class TheEditor extends Mixins(BaseMixin) { if (!this.isWriteable) return null if (['printing', 'paused'].includes(this.printer_state)) return null + // check for generic services .conf (like moonraker.conf, crowsnest.conf, sonar.conf) if (this.availableServices.includes(this.filenameWithoutExtension) && this.fileExtension === 'conf') return this.filenameWithoutExtension + + // old webcam service DEPRECATED if (this.filename.startsWith('webcam') && ['conf', 'txt'].includes(this.fileExtension)) return 'webcamd' + + // check for mooncord config files if (this.filename.startsWith('mooncord') && this.fileExtension === 'json') return 'mooncord' - if (this.filename === 'moonraker.conf') return this.moonrakerRestartInstance ?? 'moonraker' + // fallback for moonraker with multi instances + if (this.filename === 'moonraker.conf') return 'moonraker' + + // all .cfg files will be klipper config files if (this.fileExtension === 'cfg') return 'klipper' return null } get restartServiceNameExists() { - if (this.restartServiceName) return true + // hide the button, if there is no service found + if (this.restartServiceName === null) return false - return this.availableServices.includes(this.restartServiceName) - } + // klipper and moonraker uses specific api calls instead of generic service restart + if (['klipper', 'moonraker'].includes(this.restartServiceName)) return true - get moonrakerRestartInstance() { - return this.$store.state.gui.editor.moonrakerRestartInstance + return this.availableServices.includes(this.restartServiceName) } get confirmUnsavedChanges() { diff --git a/src/components/TheUpdateDialog.vue b/src/components/TheUpdateDialog.vue index fc45f2b06..946d9f374 100644 --- a/src/components/TheUpdateDialog.vue +++ b/src/components/TheUpdateDialog.vue @@ -161,10 +161,14 @@ export default class TheUpdateDialog extends Mixins(BaseMixin) { this.complete && ['client', 'mainsail', 'full'].includes(this.application.toLowerCase()) ) - window.location.reload(true) + window.location.reload() else { this.$store.commit('server/updateManager/resetUpdateResponse') - this.$socket.emit('machine.update.status', { refresh: false }, { action: 'server/updateManager/getStatus' }) + this.$socket.emit( + 'machine.update.status', + { refresh: false }, + { action: 'server/updateManager/onUpdateStatus' } + ) } } diff --git a/src/components/charts/TempChart.vue b/src/components/charts/TempChart.vue index bb4c994a5..50619df51 100644 --- a/src/components/charts/TempChart.vue +++ b/src/components/charts/TempChart.vue @@ -14,11 +14,12 @@ import { convertName } from '@/plugins/helpers' import Component from 'vue-class-component' import { Mixins, Watch } from 'vue-property-decorator' import BaseMixin from '../mixins/base' -import { PrinterTempHistoryStateSerie, PrinterTempHistoryStateSourceEntry } from '@/store/printer/tempHistory/types' +import { PrinterTempHistoryStateSourceEntry } from '@/store/printer/tempHistory/types' import type { ECharts } from 'echarts/core' import type { ECBasicOption } from 'echarts/types/dist/shared.d' import { mdiClock } from '@mdi/js' +import { datasetTypesInPercents } from '@/store/variables' interface echartsTooltipObj { [key: string]: any @@ -33,11 +34,48 @@ export default class TempChart extends Mixins(BaseMixin) { } private isVisible = true - public chartOptions: ECBasicOption = { - darkMode: true, - renderer: 'svg', - animation: false, - tooltip: { + get chartOptions(): ECBasicOption { + return { + darkMode: true, + renderer: 'svg', + animation: false, + tooltip: this.tooltip, + grid: { + top: 35, + right: this.gridRight, + bottom: 30, + left: 25, + }, + legend: { + animation: false, + show: false, + selected: this.selectedLegends, + }, + xAxis: { + type: 'time', + splitNumber: 5, + minInterval: 60 * 1000, + splitLine: { + show: true, + lineStyle: { + color: 'rgba(255, 255, 255, 0.06)', + }, + }, + axisLabel: { + color: 'rgba(255, 255, 255, 0.24)', + margin: 10, + formatter: this.timeFormat, + }, + }, + yAxis: this.yAxis, + media: this.media, + dataset: { source: this.source }, + series: this.series, + } + } + + get tooltip() { + return { animation: false, trigger: 'axis', backgroundColor: 'rgba(0,0,0,0.9)', @@ -57,38 +95,11 @@ export default class TempChart extends Mixins(BaseMixin) { obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 5 return obj }, - }, - grid: { - top: 35, - right: 15, - bottom: 30, - left: 25, - }, - legend: { - animation: false, - show: false, - selected: {}, - }, - /*dataZoom: [{ - type: 'inside', - }],*/ - xAxis: { - type: 'time', - splitNumber: 5, - minInterval: 60 * 1000, - splitLine: { - show: true, - lineStyle: { - color: 'rgba(255, 255, 255, 0.06)', - }, - }, - axisLabel: { - color: 'rgba(255, 255, 255, 0.24)', - margin: 10, - formatter: this.timeFormat, - }, - }, - yAxis: [ + } + } + + get yAxis() { + return [ { name: this.$t('Panels.TemperaturePanel.TemperaturesInChart'), type: 'value', @@ -158,15 +169,18 @@ export default class TempChart extends Mixins(BaseMixin) { }, }, }, - ], - media: [ + ] + } + + get media() { + return [ { query: { minWidth: 500, }, option: { grid: { - right: 15, + right: this.optionGridRight, left: 40, }, yAxis: [ @@ -188,11 +202,7 @@ export default class TempChart extends Mixins(BaseMixin) { ], }, }, - ], - dataset: { - source: [], - }, - series: [], + ] } get chart(): ECharts | null { @@ -241,85 +251,32 @@ export default class TempChart extends Mixins(BaseMixin) { } } - mounted() { - this.initChart() - this.chartOptions.xAxis.axisLabel.formatter = this.timeFormat + get gridRight() { + return this.boolDisplayPwmAxis ? 25 : 15 } - beforeDestroy() { - if (typeof window === 'undefined') return - if (this.chart) this.chart.dispose() - } - - initChart() { - this.chartOptions.series = this.series - this.chartOptions.legend.selected = this.selectedLegends - this.updateChartPwmAxis() - } - - updateChart() { - if (this.chart && this.isVisible) { - //const t0 = performance.now() - const limitDate = new Date(Date.now() - this.maxHistory * 1000) - let newSource = [...this.source].filter((entry: PrinterTempHistoryStateSourceEntry) => { - return entry.date >= limitDate - }) - - this.chart?.setOption( - { - dataset: { - source: newSource, - }, - }, - false, - true - ) + get optionGridRight() { + if (this.boolDisplayPwmAxis) return 35 - //const t1 = performance.now() - //window.console.debug('calc chart', (t1-t0).toFixed(), newSource.length, this.source.length) - - // reset tempHistory if working sources are smaller than 80% - if (this.source.length > 0 && newSource.length < this.maxHistory * 0.8) { - this.$socket.emit('server.temperature_store', {}, { action: 'printer/tempHistory/init' }) - } - } + return 15 } - updateChartPwmAxis() { - if (this.boolDisplayPwmAxis) { - this.chartOptions.yAxis[1].show = true - this.chartOptions.grid.right = 25 - this.chartOptions.media[0].option.grid.right = 35 - } else { - this.chartOptions.yAxis[1].show = false - this.chartOptions.grid.right = 15 - this.chartOptions.media[0].option.grid.right = 15 - } + beforeDestroy() { + if (typeof window === 'undefined') return + if (this.chart) this.chart.dispose() } visibilityChanged(isVisible: boolean) { this.isVisible = isVisible - - if (isVisible) { - this.initChart() - } } tooltipFormatter(datasets: any) { let output = '' - const mainDatasets = datasets.filter((dataset: any) => { - if (dataset.seriesName === 'date') return false - - const lastIndex = dataset.seriesName.lastIndexOf('-') - if (lastIndex === -1) return true - - const suffix = dataset.seriesName.slice(lastIndex + 1) - return !['target', 'power', 'speed'].includes(suffix) - }) + const mainDatasets = datasets.filter((dataset: any) => dataset.seriesName.endsWith('-temperature')) if (datasets.length) { let outputTime = datasets[0]['axisValueLabel'] - outputTime = outputTime.substr(outputTime.indexOf(' ')) + outputTime = outputTime.substring(outputTime.indexOf(' ')) output += '
' + @@ -338,24 +295,35 @@ export default class TempChart extends Mixins(BaseMixin) { } mainDatasets.forEach((dataset: any) => { + const baseSeriesName = dataset.seriesName.substring(0, dataset.seriesName.lastIndexOf('-')) + let displayName = baseSeriesName + if (displayName.indexOf(' ') !== -1) { + displayName = displayName.substring(displayName.indexOf(' ') + 1) + } + output += '
' output += '
' output += dataset.marker - output += "" + convertName(dataset.seriesName) + ':' + output += "" + convertName(displayName) + ':' output += '
' output += '
' - if (dataset.seriesName in dataset.value) output += dataset.value[dataset.seriesName].toFixed(1) - if (dataset.seriesName + '-target' in dataset.value) - output += ' / ' + dataset.value[dataset.seriesName + '-target'].toFixed(1) + const seriesNameTemperature = `${baseSeriesName}-temperature` + const seriesNameTarget = `${baseSeriesName}-target` + + if (seriesNameTemperature in dataset.value) output += dataset.value[seriesNameTemperature].toFixed(1) + if (seriesNameTarget in dataset.value) output += ' / ' + dataset.value[seriesNameTarget].toFixed(1) output += '°C' - if (dataset.seriesName + '-power' in dataset.value) - output += ' [ ' + (dataset.value[dataset.seriesName + '-power'] * 100).toFixed(0) + '% ]' - if (dataset.seriesName + '-speed' in dataset.value) - output += ' [ ' + (dataset.value[dataset.seriesName + '-speed'] * 100).toFixed(0) + '% ]' + datasetTypesInPercents.forEach((attrKey) => { + const seriesName = `${baseSeriesName}-${attrKey}` + if (!(seriesName in dataset.value)) return + + const value = (dataset.value[seriesName] * 100).toFixed(0) + output += ` [ ${value}% ]` + }) output += '
' output += '
' @@ -364,26 +332,6 @@ export default class TempChart extends Mixins(BaseMixin) { return output } - @Watch('series', { deep: true }) - seriesChanged(newVal: PrinterTempHistoryStateSerie[]) { - if (this.chart && this.chart?.isDisposed() !== true) { - this.chart.setOption( - { - series: newVal, - }, - false, - true - ) - } - } - - @Watch('source') - sourceChanged() { - if (this.chart?.isDisposed() !== true) { - this.updateChart() - } - } - @Watch('selectedLegends') selectedLegendsChanged(newVal: any, oldVal: any) { if (this.chart?.isDisposed() !== true) { @@ -396,14 +344,20 @@ export default class TempChart extends Mixins(BaseMixin) { } } - @Watch('boolDisplayPwmAxis') - boolDisplayPwmAxisChanged() { - this.updateChartPwmAxis() - } + @Watch('source') + sourceChanged(newVal: PrinterTempHistoryStateSourceEntry[]) { + // break if chart isn't initialized or not visible + if (!this.chart || !this.isVisible) return + + const limitDate = new Date(Date.now() - this.maxHistory * 1000) + let newSource = newVal.filter((entry: PrinterTempHistoryStateSourceEntry) => { + return entry.date >= limitDate + }) - @Watch('hours12Format') - hours12FormatChanged() { - this.chartOptions.xAxis.axisLabel.formatter = this.timeFormat + // reset tempHistory if working sources are smaller than 80% + if (newVal.length > 0 && newSource.length < this.maxHistory * 0.8) { + this.$socket.emit('server.temperature_store', {}, { action: 'printer/tempHistory/init' }) + } } } diff --git a/src/components/mixins/base.ts b/src/components/mixins/base.ts index 69902e850..8bc9ce571 100644 --- a/src/components/mixins/base.ts +++ b/src/components/mixins/base.ts @@ -175,13 +175,13 @@ export default class BaseMixin extends Vue { } get browserLocale() { - return navigator.languages && navigator.languages.length ? navigator.languages[0] : navigator.language + return navigator.language } get hours12Format() { const setting = this.$store.state.gui.general.timeFormat if (setting === '12hours') return true - if (setting === null && this.browserLocale === 'en_us') return true + if (setting === null && this.browserLocale === 'en-US') return true return false } diff --git a/src/components/mixins/webcam.ts b/src/components/mixins/webcam.ts index 5f8870f12..0508a3b8d 100644 --- a/src/components/mixins/webcam.ts +++ b/src/components/mixins/webcam.ts @@ -1,4 +1,3 @@ -import Vue from 'vue' import Component from 'vue-class-component' import { mdiAlbum, @@ -10,9 +9,23 @@ import { mdiRaspberryPi, mdiWebcam, } from '@mdi/js' +import { Mixins } from 'vue-property-decorator' +import BaseMixin from '@/components/mixins/base' @Component -export default class WebcamMixin extends Vue { +export default class WebcamMixin extends Mixins(BaseMixin) { + convertUrl(baseUrl: string, printerUrl: string | null) { + let url = new URL(baseUrl, this.hostUrl.toString()) + + // use printerURL if it exists + if (printerUrl !== null) url = new URL(baseUrl, printerUrl) + + // overwrite url to baseUrl, if it is an absolute URL + if (baseUrl.startsWith('http') || baseUrl.startsWith('://')) url = new URL(baseUrl) + + return decodeURIComponent(url.toString()) + } + convertWebcamIcon(iconName: string): string { switch (iconName) { case 'mdiAlbum': diff --git a/src/components/panels/FarmPrinterPanel.vue b/src/components/panels/FarmPrinterPanel.vue index 6d5222052..00125b2c4 100644 --- a/src/components/panels/FarmPrinterPanel.vue +++ b/src/components/panels/FarmPrinterPanel.vue @@ -2,10 +2,8 @@ - + {{ mdiWebcamOff }} @@ -27,9 +25,9 @@ + @click="currentCamName = webcam.name"> {{ convertWebcamIcon(webcam.icon) }} @@ -47,12 +45,12 @@
- +
0 + if (this.printer_webcams.length == 0) return false + + return this.printer.socket.isConnected } - get printer_webcams() { + get printer_webcams(): GuiWebcamStateWebcam[] { return this.$store.getters['farm/' + this.printer._namespace + '/getPrinterWebcams'] } - get currentWebcam() { - const currentCam = this.printer_webcams.find((webcam: any) => webcam.id === this.currentCamId) + get currentWebcam(): GuiWebcamStateWebcam | null { + const currentCam = this.printer_webcams?.find( + (webcam: GuiWebcamStateWebcam) => webcam.name === this.currentCamName + ) if (currentCam) return currentCam - return false + return null + } + + get panelClass(): string[] { + let output = [] + + if (!this.printer.socket.isConnected && !this.printer.socket.isConnecting) output.push('disabledPrinter') + + return output } clickPrinter() { @@ -268,10 +279,8 @@ export default class FarmPrinterPanel extends Mixins(BaseMixin, WebcamMixin) { .v-overlay { top: 48px; } - - diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index 40776039b..4b41adfa1 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -962,7 +962,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { } exportHistory() { - const checkString = parseFloat('1.23').toLocaleString() + const checkString = parseFloat('1.23').toLocaleString(this.browserLocale) const decimalSeparator = checkString.indexOf(',') >= 0 ? ',' : '.' const csvSeperator = decimalSeparator === ',' ? ';' : ',' @@ -1011,7 +1011,14 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { }) } - const csvContent = 'data:text/csv;charset=utf-8,' + content.map((e) => e.join(csvSeperator)).join('\n') + // escape fields with the csvSeperator in the content + // prettier-ignore + const csvContent = + 'data:text/csv;charset=utf-8,' + + content.map((entry) => + entry.map((field) => (field.indexOf(csvSeperator) === -1 ? field : `"${field}"`)).join(csvSeperator) + ).join('\n') + const link = document.createElement('a') link.setAttribute('href', encodeURI(csvContent)) link.setAttribute('download', 'print_history.csv') @@ -1044,7 +1051,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { default: switch (typeof value) { case 'number': - return value?.toLocaleString(undefined, { useGrouping: false }) ?? 0 + return value?.toLocaleString(this.browserLocale, { useGrouping: false }) ?? 0 case 'string': if (escapeChar !== null && value.includes(escapeChar)) value = '"' + value + '"' diff --git a/src/components/panels/Machine/UpdatePanel.vue b/src/components/panels/Machine/UpdatePanel.vue index ea786b893..18645e19d 100644 --- a/src/components/panels/Machine/UpdatePanel.vue +++ b/src/components/panels/Machine/UpdatePanel.vue @@ -1,63 +1,3 @@ - - - - - - -
- - - - {{ 'name' in value ? value.name : key }} -
- - - {{ mdiInformation }} - - {{ getVersionOutput(value) }} - -
- - - - -
-
- + + diff --git a/src/components/panels/Machine/UpdatePanel/Entry.vue b/src/components/panels/Machine/UpdatePanel/Entry.vue new file mode 100644 index 000000000..707199e96 --- /dev/null +++ b/src/components/panels/Machine/UpdatePanel/Entry.vue @@ -0,0 +1,366 @@ + + + + + diff --git a/src/components/panels/Machine/UpdatePanel/EntryAll.vue b/src/components/panels/Machine/UpdatePanel/EntryAll.vue new file mode 100644 index 000000000..3f1dce834 --- /dev/null +++ b/src/components/panels/Machine/UpdatePanel/EntryAll.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/components/panels/Machine/UpdatePanel/EntrySystem.vue b/src/components/panels/Machine/UpdatePanel/EntrySystem.vue new file mode 100644 index 000000000..887f92119 --- /dev/null +++ b/src/components/panels/Machine/UpdatePanel/EntrySystem.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/src/components/panels/Machine/UpdatePanel/GitCommitsList.vue b/src/components/panels/Machine/UpdatePanel/GitCommitsList.vue new file mode 100644 index 000000000..cf1624b40 --- /dev/null +++ b/src/components/panels/Machine/UpdatePanel/GitCommitsList.vue @@ -0,0 +1,164 @@ + + + + + diff --git a/src/components/panels/Machine/UpdatePanel/GitCommitsListDay.vue b/src/components/panels/Machine/UpdatePanel/GitCommitsListDay.vue new file mode 100644 index 000000000..a7012e074 --- /dev/null +++ b/src/components/panels/Machine/UpdatePanel/GitCommitsListDay.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/src/components/panels/Machine/UpdatePanel/GitCommitsListDayCommit.vue b/src/components/panels/Machine/UpdatePanel/GitCommitsListDayCommit.vue new file mode 100644 index 000000000..47df5d42e --- /dev/null +++ b/src/components/panels/Machine/UpdatePanel/GitCommitsListDayCommit.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/src/components/panels/Machine/UpdatePanel/SystemPackagesList.vue b/src/components/panels/Machine/UpdatePanel/SystemPackagesList.vue new file mode 100644 index 000000000..1faedafc6 --- /dev/null +++ b/src/components/panels/Machine/UpdatePanel/SystemPackagesList.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/src/components/panels/Machine/UpdatePanel/UpdateHint.vue b/src/components/panels/Machine/UpdatePanel/UpdateHint.vue new file mode 100644 index 000000000..8720e2f77 --- /dev/null +++ b/src/components/panels/Machine/UpdatePanel/UpdateHint.vue @@ -0,0 +1,71 @@ + + + diff --git a/src/components/panels/Machine/UpdatePanel/UpdateHintAlert.vue b/src/components/panels/Machine/UpdatePanel/UpdateHintAlert.vue new file mode 100644 index 000000000..15a38f9e1 --- /dev/null +++ b/src/components/panels/Machine/UpdatePanel/UpdateHintAlert.vue @@ -0,0 +1,91 @@ + + + diff --git a/src/components/panels/Machine/UpdatePanel/UpdateHintAll.vue b/src/components/panels/Machine/UpdatePanel/UpdateHintAll.vue new file mode 100644 index 000000000..87c3f7f27 --- /dev/null +++ b/src/components/panels/Machine/UpdatePanel/UpdateHintAll.vue @@ -0,0 +1,105 @@ + + + diff --git a/src/components/panels/StatusPanel.vue b/src/components/panels/StatusPanel.vue index 190e6ab0b..a7e793541 100644 --- a/src/components/panels/StatusPanel.vue +++ b/src/components/panels/StatusPanel.vue @@ -185,7 +185,7 @@ export default class StatusPanel extends Mixins(BaseMixin) { } get printPercent() { - return Math.round(this.$store.getters['printer/getPrintPercent'] * 100) + return Math.floor(this.$store.getters['printer/getPrintPercent'] * 100) } get printerStateOutput() { diff --git a/src/components/panels/Temperature/TemperaturePanelList.vue b/src/components/panels/Temperature/TemperaturePanelList.vue new file mode 100644 index 000000000..837feb0f9 --- /dev/null +++ b/src/components/panels/Temperature/TemperaturePanelList.vue @@ -0,0 +1,137 @@ + + + + + diff --git a/src/components/panels/Temperature/TemperaturePanelListItem.vue b/src/components/panels/Temperature/TemperaturePanelListItem.vue new file mode 100644 index 000000000..ca7c16542 --- /dev/null +++ b/src/components/panels/Temperature/TemperaturePanelListItem.vue @@ -0,0 +1,274 @@ + + + + + diff --git a/src/components/panels/Temperature/TemperaturePanelListItemAdditionalSensor.vue b/src/components/panels/Temperature/TemperaturePanelListItemAdditionalSensor.vue new file mode 100644 index 000000000..40f1afd7e --- /dev/null +++ b/src/components/panels/Temperature/TemperaturePanelListItemAdditionalSensor.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/components/panels/Temperature/TemperaturePanelListItemAdditionalSensorValue.vue b/src/components/panels/Temperature/TemperaturePanelListItemAdditionalSensorValue.vue new file mode 100644 index 000000000..aadc033b1 --- /dev/null +++ b/src/components/panels/Temperature/TemperaturePanelListItemAdditionalSensorValue.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/components/panels/Temperature/TemperaturePanelListItemEdit.vue b/src/components/panels/Temperature/TemperaturePanelListItemEdit.vue new file mode 100644 index 000000000..275c26c8e --- /dev/null +++ b/src/components/panels/Temperature/TemperaturePanelListItemEdit.vue @@ -0,0 +1,90 @@ + + + diff --git a/src/components/panels/Temperature/TemperaturePanelListItemEditAdditionalSensor.vue b/src/components/panels/Temperature/TemperaturePanelListItemEditAdditionalSensor.vue new file mode 100644 index 000000000..1c9d110bd --- /dev/null +++ b/src/components/panels/Temperature/TemperaturePanelListItemEditAdditionalSensor.vue @@ -0,0 +1,40 @@ + + + diff --git a/src/components/panels/Temperature/TemperaturePanelListItemEditChartSerie.vue b/src/components/panels/Temperature/TemperaturePanelListItemEditChartSerie.vue new file mode 100644 index 000000000..ddfbea12f --- /dev/null +++ b/src/components/panels/Temperature/TemperaturePanelListItemEditChartSerie.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/components/panels/Temperature/TemperaturePanelPresets.vue b/src/components/panels/Temperature/TemperaturePanelPresets.vue new file mode 100644 index 000000000..f434e89cd --- /dev/null +++ b/src/components/panels/Temperature/TemperaturePanelPresets.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/src/components/panels/Temperature/TemperaturePanelSettings.vue b/src/components/panels/Temperature/TemperaturePanelSettings.vue new file mode 100644 index 000000000..ad9cfc8a8 --- /dev/null +++ b/src/components/panels/Temperature/TemperaturePanelSettings.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/components/panels/TemperaturePanel.vue b/src/components/panels/TemperaturePanel.vue index 50d4702e0..4acf4e9e8 100644 --- a/src/components/panels/TemperaturePanel.vue +++ b/src/components/panels/TemperaturePanel.vue @@ -1,433 +1,49 @@ - + @change="changeNamespace('timelapse')" /> @@ -149,7 +131,7 @@ @@ -172,32 +154,26 @@ :label="db.label" hide-details class="mt-0" - @change="changeNamespace(db.name)"> + @change="changeNamespace(db.name)" /> - + @change="changeNamespace('timelapse')" /> + @change="changeNamespace('history_jobs')" /> + @change="changeNamespace('history_totals')" /> @@ -215,7 +191,7 @@ @@ -238,7 +214,7 @@ :label="db.label" hide-details class="mt-0" - @change="changeNamespace(db.name)"> + @change="changeNamespace(db.name)" /> @@ -291,63 +267,59 @@ export default class SettingsGeneralTab extends Mixins(BaseMixin) { return [ { name: 'general', - label: this.$t('Settings.GeneralTab.General').toString(), + label: this.$t('Settings.GeneralTab.General'), }, { name: 'console', - label: this.$t('Settings.ConsoleTab.Console').toString(), + label: this.$t('Settings.ConsoleTab.Console'), }, { name: 'control', - label: this.$t('Settings.ControlTab.Control').toString(), + label: this.$t('Settings.ControlTab.Control'), }, { name: 'dashboard', - label: this.$t('Settings.DashboardTab.Dashboard').toString(), + label: this.$t('Settings.DashboardTab.Dashboard'), }, { name: 'editor', - label: this.$t('Settings.EditorTab.Editor').toString(), + label: this.$t('Settings.EditorTab.Editor'), }, { name: 'gcodeViewer', - label: this.$t('Settings.GCodeViewerTab.GCodeViewer').toString(), + label: this.$t('Settings.GCodeViewerTab.GCodeViewer'), }, { name: 'gcodehistory', - label: this.$t('Settings.GeneralTab.DbConsoleHistory').toString(), + label: this.$t('Settings.GeneralTab.DbConsoleHistory'), }, { name: 'macros', - label: this.$t('Settings.MacrosTab.Macros').toString(), + label: this.$t('Settings.MacrosTab.Macros'), }, { name: 'notifications', - label: this.$t('App.Notifications.Notifications').toString(), + label: this.$t('App.Notifications.Notifications'), }, { name: 'presets', - label: this.$t('Settings.PresetsTab.PreheatPresets').toString(), + label: this.$t('Settings.PresetsTab.PreheatPresets'), }, { name: 'remoteprinters', - label: this.$t('Settings.RemotePrintersTab.RemotePrinters').toString(), + label: this.$t('Settings.RemotePrintersTab.RemotePrinters'), }, { name: 'timelapse', - label: this.$t('Settings.TimelapseTab.Timelapse').toString(), + label: this.$t('Settings.TimelapseTab.Timelapse'), }, { name: 'uiSettings', - label: this.$t('Settings.UiSettingsTab.UiSettings').toString(), + label: this.$t('Settings.UiSettingsTab.UiSettings'), }, { name: 'view', - label: this.$t('Settings.GeneralTab.DbView').toString(), - }, - { - name: 'webcams', - label: this.$t('Settings.WebcamsTab.Webcams').toString(), + label: this.$t('Settings.GeneralTab.DbView'), }, ] } @@ -429,13 +401,13 @@ export default class SettingsGeneralTab extends Mixins(BaseMixin) { value: '24hours', text: this.$t('Settings.GeneralTab.24hours', { time: date.toLocaleTimeString(userLocale, { hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }), - }).toString(), + }), }, { value: '12hours', text: this.$t('Settings.GeneralTab.12hours', { time: date.toLocaleTimeString(userLocale, { hour: '2-digit', minute: '2-digit', hourCycle: 'h12' }), - }).toString(), + }), }, ] } diff --git a/src/components/settings/SettingsRow.vue b/src/components/settings/SettingsRow.vue index 179b21e7b..b9782dcbf 100644 --- a/src/components/settings/SettingsRow.vue +++ b/src/components/settings/SettingsRow.vue @@ -3,7 +3,7 @@ - + {{ icon }} @@ -15,7 +15,7 @@ - + @@ -23,6 +23,7 @@ - + diff --git a/src/components/settings/Webcams/WebcamForm.vue b/src/components/settings/Webcams/WebcamForm.vue new file mode 100644 index 000000000..55ae5a5e9 --- /dev/null +++ b/src/components/settings/Webcams/WebcamForm.vue @@ -0,0 +1,324 @@ + + + + + diff --git a/src/components/settings/Webcams/WebcamListEntry.vue b/src/components/settings/Webcams/WebcamListEntry.vue new file mode 100644 index 000000000..9afbb906c --- /dev/null +++ b/src/components/settings/Webcams/WebcamListEntry.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/src/components/ui/Panel.vue b/src/components/ui/Panel.vue index 15f6284f9..e54c3b40f 100644 --- a/src/components/ui/Panel.vue +++ b/src/components/ui/Panel.vue @@ -96,6 +96,15 @@ export default class Panel extends Mixins(BaseMixin) { .icon-rotate-90 { transform: rotate(90deg); } + +.panel-toolbar { + overflow-y: hidden; +} + +::v-deep .panel-toolbar .v-btn { + height: 100% !important; + max-height: none; +} - @@ -11,28 +5,25 @@ + + diff --git a/src/components/webcams/JMuxerStream.vue b/src/components/webcams/JMuxerStream.vue index 9323ae0bf..58f38f9b7 100644 --- a/src/components/webcams/JMuxerStream.vue +++ b/src/components/webcams/JMuxerStream.vue @@ -14,30 +14,29 @@ import JMuxer from 'jmuxer' import { Component, Mixins, Prop, Watch } from 'vue-property-decorator' import BaseMixin from '@/components/mixins/base' +import { GuiWebcamStateWebcam } from '@/store/gui/webcams/types' +import WebcamMixin from '@/components/mixins/webcam' @Component -export default class JMuxerStreamer extends Mixins(BaseMixin) { +export default class JMuxerStreamer extends Mixins(BaseMixin, WebcamMixin) { private jmuxer: JMuxer | null = null private status: string = 'connecting' - @Prop({ required: true }) - camSettings: any - - @Prop() - printerUrl: string | undefined + @Prop({ required: true }) readonly camSettings!: GuiWebcamStateWebcam + @Prop({ default: null }) readonly printerUrl!: string | null declare $refs: { video: HTMLVideoElement } get url() { - return this.camSettings.urlStream || '' + return this.convertUrl(this.camSettings?.stream_url, this.printerUrl) } get webcamStyle() { let transforms = '' - if ('flipX' in this.camSettings && this.camSettings.flipX) transforms += ' scaleX(-1)' - if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)' + if ('flipX' in this.camSettings && this.camSettings.flip_horizontal) transforms += ' scaleX(-1)' + if ('flipX' in this.camSettings && this.camSettings.flip_vertical) transforms += ' scaleY(-1)' if (transforms.trimStart().length) return { transform: transforms.trimStart() } return '' @@ -59,7 +58,7 @@ export default class JMuxerStreamer extends Mixins(BaseMixin) { } const video = this.$refs.video - const targetFps = this.camSettings.targetFps || 10 + const targetFps = this.camSettings.target_fps || 10 this.jmuxer = new JMuxer({ node: video, diff --git a/src/components/webcams/JanusStreamer.vue b/src/components/webcams/JanusStreamer.vue index e7ac9a693..74e39ad04 100644 --- a/src/components/webcams/JanusStreamer.vue +++ b/src/components/webcams/JanusStreamer.vue @@ -23,6 +23,7 @@ import { Component, Mixins, Prop, Ref, Watch } from 'vue-property-decorator' import { JanusJs, JanusSession, JanusStreamingPlugin } from 'typed_janus_js' import BaseMixin from '@/components/mixins/base' import { ConstructorOptions } from 'typed_janus_js/src/interfaces/janus' +import { GuiWebcamStateWebcam } from '@/store/gui/webcams/types' @Component export default class JanusStreamer extends Mixins(BaseMixin) { @@ -33,15 +34,12 @@ export default class JanusStreamer extends Mixins(BaseMixin) { private aspectRatio: null | number = null private status: string = 'connecting' - @Prop({ required: true }) - camSettings: any - + @Prop({ required: true }) readonly camSettings!: GuiWebcamStateWebcam @Prop({ default: null }) declare readonly printerUrl: string | null - @Ref() declare stream: HTMLVideoElement get url() { - const baseUrl = this.camSettings.urlStream + const baseUrl = this.camSettings.stream_url let url = new URL(baseUrl, this.printerUrl === null ? this.hostUrl.toString() : this.printerUrl) url.port = '8188' url.protocol = this.printerUrl?.startsWith('https') ? 'wss' : 'ws' @@ -56,7 +54,7 @@ export default class JanusStreamer extends Mixins(BaseMixin) { } get streamId() { - const pathnameParts = new URL(this.camSettings.urlStream).pathname.split('/') + const pathnameParts = new URL(this.camSettings.stream_url).pathname.split('/') return pathnameParts[pathnameParts.length - 1] } @@ -67,8 +65,8 @@ export default class JanusStreamer extends Mixins(BaseMixin) { } let transforms = '' - if ('flipX' in this.camSettings && this.camSettings.flipX) transforms += ' scaleX(-1)' - if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)' + if ('flipX' in this.camSettings && this.camSettings.flip_horizontal) transforms += ' scaleX(-1)' + if ('flipX' in this.camSettings && this.camSettings.flip_vertical) transforms += ' scaleY(-1)' if (transforms.trimStart().length) output.transform = transforms.trimStart() if (this.aspectRatio) output.aspectRatio = this.aspectRatio @@ -132,7 +130,7 @@ export default class JanusStreamer extends Mixins(BaseMixin) { @Watch('url') async changedUrl() { await this.session?.destroy({}) - this.startStream() + await this.startStream() } } diff --git a/src/components/webcams/Mjpegstreamer.vue b/src/components/webcams/Mjpegstreamer.vue index cb389f1bb..1e64a04d4 100644 --- a/src/components/webcams/Mjpegstreamer.vue +++ b/src/components/webcams/Mjpegstreamer.vue @@ -14,12 +14,14 @@ import Component from 'vue-class-component' import { Mixins, Prop, Watch } from 'vue-property-decorator' import BaseMixin from '@/components/mixins/base' +import { GuiWebcamStateWebcam } from '@/store/gui/webcams/types' +import WebcamMixin from '@/components/mixins/webcam' const CONTENT_LENGTH = 'content-length' const TYPE_JPEG = 'image/jpeg' @Component -export default class Mjpegstreamer extends Mixins(BaseMixin) { +export default class Mjpegstreamer extends Mixins(BaseMixin, WebcamMixin) { private currentFPS = 0 private streamState = false private aspectRatio: null | number = null @@ -32,11 +34,8 @@ export default class Mjpegstreamer extends Mixins(BaseMixin) { private isVisibleViewport = false private isVisibleDocument = true - @Prop({ required: true }) - camSettings: any - - @Prop() - printerUrl: string | undefined + @Prop({ required: true }) readonly camSettings!: GuiWebcamStateWebcam + @Prop({ default: null }) readonly printerUrl!: string | null @Prop({ default: true }) declare showFps: boolean @@ -46,11 +45,7 @@ export default class Mjpegstreamer extends Mixins(BaseMixin) { } get url() { - const baseUrl = this.camSettings.urlStream - let url = new URL(baseUrl, this.printerUrl === undefined ? this.hostUrl.toString() : this.printerUrl) - if (baseUrl.startsWith('http') || baseUrl.startsWith('://')) url = new URL(baseUrl) - - return decodeURIComponent(url.toString()) + return this.convertUrl(this.camSettings?.stream_url, this.printerUrl) } get webcamStyle() { @@ -62,8 +57,8 @@ export default class Mjpegstreamer extends Mixins(BaseMixin) { } let transforms = '' - if ('flipX' in this.camSettings && this.camSettings.flipX) transforms += ' scaleX(-1)' - if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)' + if ('flipX' in this.camSettings && this.camSettings.flip_horizontal) transforms += ' scaleX(-1)' + if ('flipX' in this.camSettings && this.camSettings.flip_vertical) transforms += ' scaleY(-1)' if (transforms.trimStart().length) output.transform = transforms.trimStart() if (this.aspectRatio) { diff --git a/src/components/webcams/MjpegstreamerAdaptive.vue b/src/components/webcams/MjpegstreamerAdaptive.vue index 2eb71ebd2..40d2c77f8 100644 --- a/src/components/webcams/MjpegstreamerAdaptive.vue +++ b/src/components/webcams/MjpegstreamerAdaptive.vue @@ -20,6 +20,7 @@ import Component from 'vue-class-component' import { Mixins, Prop, Watch } from 'vue-property-decorator' import BaseMixin from '@/components/mixins/base' +import { GuiWebcamStateWebcam } from '@/store/gui/webcams/types' @Component export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) { @@ -44,8 +45,8 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) { mjpegstreamerAdaptive: any } - @Prop({ required: true }) declare camSettings: any - @Prop() declare printerUrl: string | undefined + @Prop({ required: true }) declare camSettings: GuiWebcamStateWebcam + @Prop({ default: null }) readonly printerUrl!: string | null @Prop({ default: true }) declare showFps: boolean get webcamStyle() { @@ -57,9 +58,9 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) { } let transforms = '' - if (this.camSettings.flipX ?? false) transforms += ' scaleX(-1)' - if (this.camSettings.flipY ?? false) transforms += ' scaleY(-1)' - if ((this.camSettings.rotate ?? 0) === 180) transforms += ' rotate(180deg)' + if (this.camSettings.flip_horizontal ?? false) transforms += ' scaleX(-1)' + if (this.camSettings.flip_vertical ?? false) transforms += ' scaleY(-1)' + if ((this.camSettings.rotation ?? 0) === 180) transforms += ' rotate(180deg)' if (transforms.trimStart().length) output.transform = transforms.trimStart() if (this.aspectRatio) { @@ -75,7 +76,7 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) { } get rotate() { - return [90, 270].includes(this.camSettings.rotate ?? 0) + return [90, 270].includes(this.camSettings.rotation ?? 0) } refreshFrame() { @@ -86,9 +87,9 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) { } async setFrame() { - const baseUrl = this.camSettings.urlSnapshot + const baseUrl = this.camSettings.snapshot_url - let url = new URL(baseUrl, this.printerUrl === undefined ? this.hostUrl.toString() : this.printerUrl) + let url = new URL(baseUrl, this.printerUrl === null ? this.hostUrl.toString() : this.printerUrl) if (baseUrl.startsWith('http') || baseUrl.startsWith('://')) url = new URL(baseUrl) url.searchParams.append('bypassCache', this.refresh.toString()) @@ -115,7 +116,7 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) { const x = canvas.width / 2 const y = canvas.height / 2 ctx.translate(x, y) - ctx.rotate((this.camSettings.rotate * Math.PI) / 180) + ctx.rotate((this.camSettings.rotation * Math.PI) / 180) await ctx?.drawImage( frame, (-frame.width / 2) * scale, @@ -123,7 +124,7 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) { frame.width * scale, frame.height * scale ) - ctx.rotate(-((this.camSettings.rotate * Math.PI) / 180)) + ctx.rotate(-((this.camSettings.rotation * Math.PI) / 180)) ctx.translate(-x, -y) } else await ctx?.drawImage(frame, 0, 0, frame.width, frame.height, 0, 0, canvas.width, canvas.height) @@ -138,7 +139,7 @@ export default class MjpegstreamerAdaptive extends Mixins(BaseMixin) { onLoad() { this.isLoaded = true - const targetFps = this.camSettings.targetFps || 10 + const targetFps = this.camSettings.target_fps || 10 const end_time = performance.now() const current_time = end_time - this.start_time this.time = this.time * this.time_smoothing + current_time * (1.0 - this.time_smoothing) diff --git a/src/components/webcams/Uv4lMjpeg.vue b/src/components/webcams/Uv4lMjpeg.vue index b342cfa8b..c1795e41f 100644 --- a/src/components/webcams/Uv4lMjpeg.vue +++ b/src/components/webcams/Uv4lMjpeg.vue @@ -13,27 +13,24 @@ import { Component, Mixins, Prop, Watch } from 'vue-property-decorator' import BaseMixin from '@/components/mixins/base' import { GuiWebcamStateWebcam } from '@/store/gui/webcams/types' +import WebcamMixin from '@/components/mixins/webcam' @Component -export default class Uv4lMjpeg extends Mixins(BaseMixin) { +export default class Uv4lMjpeg extends Mixins(BaseMixin, WebcamMixin) { private aspectRatio: null | number = null private isVisible = false private isVisibleViewport = false private isVisibleDocument = true @Prop({ required: true }) declare readonly camSettings: GuiWebcamStateWebcam - @Prop() declare printerUrl: string | undefined + @Prop({ default: null }) readonly printerUrl!: string | null declare $refs: { webcamUv4lMjpegImage: HTMLImageElement } get url() { - const baseUrl = this.camSettings.urlStream - let url = new URL(baseUrl, this.printerUrl === undefined ? this.hostUrl.toString() : this.printerUrl) - if (baseUrl.startsWith('http') || baseUrl.startsWith('://')) url = new URL(baseUrl) - - return decodeURIComponent(url.toString()) + return this.convertUrl(this.camSettings?.stream_url, this.printerUrl) } get webcamStyle() { @@ -45,8 +42,8 @@ export default class Uv4lMjpeg extends Mixins(BaseMixin) { } let transforms = '' - if ('flipX' in this.camSettings && this.camSettings.flipX) transforms += ' scaleX(-1)' - if ('flipX' in this.camSettings && this.camSettings.flipY) transforms += ' scaleY(-1)' + if ('flipX' in this.camSettings && this.camSettings.flip_horizontal) transforms += ' scaleX(-1)' + if ('flipX' in this.camSettings && this.camSettings.flip_vertical) transforms += ' scaleY(-1)' if (transforms.trimStart().length) output.transform = transforms.trimStart() if (this.aspectRatio) { diff --git a/src/components/webcams/WebcamWrapper.vue b/src/components/webcams/WebcamWrapper.vue index 9ad383716..cd2dfb679 100644 --- a/src/components/webcams/WebcamWrapper.vue +++ b/src/components/webcams/WebcamWrapper.vue @@ -3,14 +3,14 @@
@@ -30,6 +30,7 @@ import WebcamWrapperItem from '@/components/webcams/WebcamWrapperItem.vue' export default class WebcamWrapper extends Mixins(BaseMixin) { @Prop({ type: Object, required: true }) webcam!: GuiWebcamStateWebcam @Prop({ type: Boolean, default: true }) showFps!: Boolean + @Prop({ type: String, default: null }) printerUrl!: string | null get webcams(): GuiWebcamStateWebcam[] { return this.$store.getters['gui/webcams/getWebcams'] diff --git a/src/components/webcams/WebcamWrapperItem.vue b/src/components/webcams/WebcamWrapperItem.vue index ec944e4e4..baee260c6 100644 --- a/src/components/webcams/WebcamWrapperItem.vue +++ b/src/components/webcams/WebcamWrapperItem.vue @@ -1,31 +1,31 @@