* test vue-echarts and dataset>source instead of series>data Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix disposed state of chart & delete update interval of settings page Signed-off-by: Stefan Dej <meteyou@gmail.com> * init TS migation & dashboard Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: dashbaord console Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: add "disabled" status to the filament runout sensor on the dashboard Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix klipper restart process Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix status panel during a print Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert g-code files to typescript Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert history files to typescript Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert machine limits to typescript Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert update manager to typescript Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert endstops & logfiles to typescript Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix temp display in tools panel Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert machine > config files to TS Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert select printer dialog to TS Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert select printer menu to TS Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert farm page to TS Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix debug output of farm printer getters Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix import webcam streams in farm view Signed-off-by: Stefan Dej <meteyou@gmail.com> * better handling when changing printers Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert heightmap to TS Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert heightmap to TS Signed-off-by: Stefan Dej <meteyou@gmail.com> * Console QOL (#300) * CHORE Signed-off-by: Eike Ahmels <eike.ahmels@tu-dortmund.de> * NEW: console ts refactor, linux autocomplete, gui helplist, multiline Signed-off-by: Eike Ahmels <eike.ahmels@tu-dortmund.de> * FIX: console autocomplete flood fix Signed-off-by: Eike Ahmels <eike.ahmels@tu-dortmund.de> * fix merged console Signed-off-by: Stefan Dej <meteyou@gmail.com> * fixed return of ConsoleTable.vue isCommand Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: add toast after creating file in ConfigFilesPanel.vue Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: file upload message Signed-off-by: Stefan Dej <meteyou@gmail.com> * add toolbar to files panels Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: disable scrollbars in TempChart.vue Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: sidebar z-index and farm printer toolbar Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: sidebar & topbar z-index and farm printer toolbar Signed-off-by: Stefan Dej <meteyou@gmail.com> * update toolbars in gcode-files and history Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: new settings dialog (#302) * create settings dialog and integrate general, console, control, marcos, presets, webcams Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: renamed webcam gui state variable Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: temperature_fan chamber in farm printers dashboard Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: only display RPM in tools panel, when its available Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: reading empty remote printers list Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: loading additionalSensors in temp panel Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: bed_mesh loading rework heightmap settings save heightmap settings in moonraker db Signed-off-by: Stefan Dej <meteyou@gmail.com> * add remote printers to settings Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix types Signed-off-by: Stefan Dej <meteyou@gmail.com> * add beforeDestroy to echarts Signed-off-by: Stefan Dej <meteyou@gmail.com> * add heightmap visualMap scaling and format tooltip Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: logo & primary color customizing Signed-off-by: Stefan Dej <meteyou@gmail.com> * remove keep-alive in app.vue Signed-off-by: Stefan Dej <meteyou@gmail.com> * round tempchart data Signed-off-by: Stefan Dej <meteyou@gmail.com> * normalize toolbar buttons Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix series attributes & update echarts-gl Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix hostname in sidebar Signed-off-by: Stefan Dej <meteyou@gmail.com> * rework websocket loadings Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix rework websocket loadings Signed-off-by: Stefan Dej <meteyou@gmail.com> * Fixes for console QOL PR (#301) * FIX: command help dialog added Signed-off-by: Eike Ahmels <eike.ahmels@tu-dortmund.de> * FIX: console fixes Signed-off-by: Eike Ahmels <eike.ahmels@tu-dortmund.de> * rework events store Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: check customFilters if string or array Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: edit preset dont work (existing name check) Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: save webcam with index 0 Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: tool combobox input dont work Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: tooltip position & z-index Signed-off-by: Stefan Dej <meteyou@gmail.com> * rework console Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix output name of filament sensor Signed-off-by: Stefan Dej <meteyou@gmail.com> * store performance updates and StatusPanel.vue optimizing Signed-off-by: Stefan Dej <meteyou@gmail.com> * console bugfixes Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix icon-rotate in temperatures panel Signed-off-by: Stefan Dej <meteyou@gmail.com> * add auto-grow to console input fields Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix dialog action button colors Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix refreshMetadata of gcocde files Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: add multi fileupload to drag&drop upload Signed-off-by: Stefan Dej <meteyou@gmail.com> * convert SystemPanel to TS Signed-off-by: Stefan Dej <meteyou@gmail.com> * add init and getters for system panels Signed-off-by: Stefan Dej <meteyou@gmail.com> * add init and getters for system panels Signed-off-by: Stefan Dej <meteyou@gmail.com> * finish SystemPanel.vue Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: raspberry throttled flags in topbar Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: fix type in TheThrottledStates.vue Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: add new editor (#307) * init test Signed-off-by: Stefan Dej <meteyou@gmail.com> * theme test Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: switch to codemirror editor Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: fix type in TheThrottledStates.vue Signed-off-by: Stefan Dej <meteyou@gmail.com> * reformat flags output and deactivate debug output Signed-off-by: Stefan Dej <meteyou@gmail.com> * add types to throttle states Signed-off-by: Stefan Dej <meteyou@gmail.com> * display "dirty" in the board firmware version string Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix mini console array cut Signed-off-by: Stefan Dej <meteyou@gmail.com> * delete old comment Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix config files on small devices Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: display macro description in settings tab Signed-off-by: Stefan Dej <meteyou@gmail.com> * change settings icons Signed-off-by: Stefan Dej <meteyou@gmail.com> * rename dashboard panel & change slider text in settings Signed-off-by: Stefan Dej <meteyou@gmail.com> * responsive optimations for settings Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix throttled state flags filter Signed-off-by: Stefan Dej <meteyou@gmail.com> * Code highlighting for codemirror (#309) * init test Signed-off-by: Stefan Dej <meteyou@gmail.com> * theme test Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: switch to codemirror editor Signed-off-by: Stefan Dej <meteyou@gmail.com> * NEW: klipper_config editor theme Signed-off-by: Eike Ahmels <eike.ahmels@tu-dortmund.de> * NEW: code highlighting for codemirror Signed-off-by: Eike Ahmels <eike.ahmels@tu-dortmund.de> Co-authored-by: Stefan Dej <meteyou@gmail.com> * feature: hide/show jobs with special print status Signed-off-by: Stefan Dej <meteyou@gmail.com> * redesign console help modal Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: default state of sidebar was wrong on mobile devices Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: mobile view interface settings Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: optimize mobile view interface settings Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: block empty console commands Signed-off-by: Stefan Dej <meteyou@gmail.com> * push version number Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: add current / max flow in status panel Signed-off-by: Stefan Dej <meteyou@gmail.com> * feature: add big gcode thumbnail to status panel Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: fix favicon and setting tab names Signed-off-by: Stefan Dej <meteyou@gmail.com> * cleanup old editor Signed-off-by: Stefan Dej <meteyou@gmail.com> * bugfix: add redirect for updates from 1.6.0 to 2.0.0 Signed-off-by: Stefan Dej <meteyou@gmail.com> Co-authored-by: Eike Ahmels <hui_buh-@gmx.net>
581 lines
25 KiB
Vue
581 lines
25 KiB
Vue
<style scoped>
|
|
.vertical_align_center {
|
|
margin: auto 0;
|
|
}
|
|
|
|
.statusPanel-image-preview {
|
|
width: 100%;
|
|
}
|
|
|
|
.v-btn.minwidth-0 {
|
|
min-width: auto !important;
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
<v-card v-if="klipperState === 'ready'" class="mb-6">
|
|
<v-toolbar flat dense>
|
|
<v-toolbar-title>
|
|
<span class="subheading align-baseline">
|
|
<v-progress-circular
|
|
:rotate="-90"
|
|
:size="30"
|
|
:width="5"
|
|
:value="printPercent"
|
|
v-if="['paused', 'printing'].includes(printer_state)"
|
|
color="primary"
|
|
class="mr-1"
|
|
>
|
|
</v-progress-circular>
|
|
<v-icon
|
|
v-if="!['paused', 'printing'].includes(printer_state)"
|
|
left
|
|
>
|
|
mdi-information
|
|
</v-icon>
|
|
{{ printerStateOutput }}
|
|
</span>
|
|
</v-toolbar-title>
|
|
<v-spacer></v-spacer>
|
|
<template >
|
|
<v-btn
|
|
v-for="button in filteredToolbarButtons"
|
|
v-bind:key="button.loadingName"
|
|
class="px-2 minwidth-0 ml-3"
|
|
:color="button.color"
|
|
@click="button.click"
|
|
:loading="loadings.includes(button.loadingName)"
|
|
small
|
|
>
|
|
<v-tooltip top>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<v-icon v-bind="attrs" v-on="on" small>{{ button.icon }}</v-icon>
|
|
</template>
|
|
<span>{{ button.text }}</span>
|
|
</v-tooltip>
|
|
</v-btn>
|
|
</template>
|
|
</v-toolbar>
|
|
<v-card-text class="px-0 py-0 content">
|
|
<template v-if="boolBigThumbnail">
|
|
<v-img
|
|
height="250px"
|
|
:src="thumbnailBig"
|
|
class="d-flex align-end"
|
|
>
|
|
<v-card-title class="white--text py-2 px-2" style="background-color: rgba(0,0,0,0.3); backdrop-filter: blur(3px);">
|
|
<v-row>
|
|
<v-col style="width: 100px">
|
|
<span class="subtitle-2 text-truncate px-0 text--disabled d-block"><v-icon small class="mr-2">mdi-file-outline</v-icon>{{ current_filename }}</span>
|
|
</v-col>
|
|
</v-row>
|
|
</v-card-title>
|
|
</v-img>
|
|
</template>
|
|
<template v-if="display_message || print_stats_message">
|
|
<v-container>
|
|
<v-row>
|
|
<v-col class="py-2">
|
|
<span class="subtitle-2 d-block px-0 text--disabled"><v-icon class="mr-2" small>mdi-message-processing-outline</v-icon>{{ print_stats_message ? print_stats_message : display_message }}</span>
|
|
</v-col>
|
|
<v-col class="col-auto py-2">
|
|
<v-icon class="text--disabled cursor-pointer" @click="clearDisplayMessage" small>mdi-close-circle</v-icon>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
<v-divider class="mt-0 mb-0" ></v-divider>
|
|
</template>
|
|
<template v-if="current_filename && !boolBigThumbnail">
|
|
<v-container>
|
|
<v-row>
|
|
<v-col :class="thumbnailSmall ? 'py-3' : 'py-2'" :style="(thumbnailSmall ? 'width: calc(100% - 40px);' : '')">
|
|
<span class="subtitle-2 text-truncate d-block px-0 text--disabled"><v-icon small class="mr-2">mdi-file-outline</v-icon>{{ current_filename }}</span>
|
|
</v-col>
|
|
<v-col class="pa-2 pl-0 col-auto" v-if="thumbnailSmall">
|
|
<template v-if="thumbnailSmall && thumbnailBig">
|
|
<v-tooltip top content-class="tooltip__content-opacity1">
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<vue-load-image class="d-flex">
|
|
<img slot="image" :src="thumbnailSmall" width="32" height="32" v-bind="attrs" v-on="on" />
|
|
<v-progress-circular slot="preloader" indeterminate color="primary"></v-progress-circular>
|
|
<v-icon slot="error">mdi-file</v-icon>
|
|
</vue-load-image>
|
|
</template>
|
|
<span><img :src="thumbnailBig" width="250" /></span>
|
|
</v-tooltip>
|
|
</template>
|
|
<template v-else-if="thumbnailSmall">
|
|
<vue-load-image>
|
|
<img slot="image" :src="thumbnailSmall" width="32" height="32" />
|
|
<v-progress-circular slot="preloader" indeterminate color="primary"></v-progress-circular>
|
|
<v-icon slot="error">mdi-file</v-icon>
|
|
</vue-load-image>
|
|
</template>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
<v-divider class="mt-0 mb-0" ></v-divider>
|
|
</template>
|
|
<v-container class="py-0">
|
|
<v-row :class="'text-center '+(!['printing', 'paused', 'error', 'complete', 'cancelled'].includes(printer_state) ? 'pt-5 pb-2 mb-0' : 'py-5')" align="center">
|
|
<v-col class="col-3 pa-0">
|
|
<strong>{{ $t("Panels.StatusPanel.Position") }}</strong><br />
|
|
{{ coordinates }}
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<strong>{{ $t("Panels.StatusPanel.X") }}</strong><br />
|
|
{{ positions.x }}
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<strong>{{ $t("Panels.StatusPanel.Y") }}</strong><br />
|
|
{{ positions.y }}
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<v-tooltip top>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<div v-bind="attrs" v-on="on" class="text-center">
|
|
<strong>{{ $t("Panels.StatusPanel.Z") }}</strong><br />
|
|
{{ positions.z }}
|
|
</div>
|
|
</template>
|
|
<span>G-Code: {{ positions.gcode_z }}mm</span>
|
|
</v-tooltip>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
<template v-if="['printing', 'paused', 'error'].includes(printer_state)">
|
|
<v-divider class="my-0"></v-divider>
|
|
<v-container class="py-0">
|
|
<v-row class="text-center py-5" align="center">
|
|
<v-col class="col-3 pa-0">
|
|
<strong>{{ $t("Panels.StatusPanel.Speed") }}</strong><br />
|
|
<span class="text-no-wrap">{{ requested_speed }} mm/s</span>
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<v-tooltip top>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<div v-bind="attrs" v-on="on">
|
|
<strong>{{ $t("Panels.StatusPanel.Flow") }}</strong><br />
|
|
<span class="d-block text-center text-no-wrap">{{ maxFlow.lastValue ? maxFlow.lastValue.toFixed(1)+" mm³/s" : "--" }}</span>
|
|
</div>
|
|
</template>
|
|
<span>{{ $t("Panels.StatusPanel.Max") }}: {{ maxFlow.maxValue ? maxFlow.maxValue.toFixed(1)+" mm³/s" : "--" }}</span>
|
|
</v-tooltip>
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<v-tooltip top>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<div v-bind="attrs" v-on="on">
|
|
<strong>{{ $t("Panels.StatusPanel.Filament") }}</strong><br />
|
|
<span class="d-block text-center text-no-wrap">{{ filament_used >= 1000 ? (filament_used / 1000).toFixed(2)+" m" : filament_used.toFixed(2)+" mm" }}</span>
|
|
</div>
|
|
</template>
|
|
<span v-if="'filament_total' in current_file">{{ (filament_used / 1000).toFixed(2) }} / {{ (current_file.filament_total / 1000).toFixed(2) }} m = {{ ( 100 / current_file.filament_total * filament_used).toFixed(0) }} % </span>
|
|
</v-tooltip>
|
|
</v-col>
|
|
<v-col class="col-3 pa-0 text-center">
|
|
<v-tooltip top>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<div v-bind="attrs" v-on="on" class="text-center">
|
|
<strong>{{ $t("Panels.StatusPanel.Layer") }}</strong><br />
|
|
<span class="text-no-wrap">{{ current_layer }} of {{ max_layers }}</span>
|
|
</div>
|
|
</template>
|
|
<span v-if="'object_height' in current_file && current_file.object_height > 0">{{ $t("Panels.StatusPanel.ObjectHeight") }}: {{ current_file.object_height }} mm</span>
|
|
</v-tooltip>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
<v-divider class="my-0"></v-divider>
|
|
<v-container class="py-0">
|
|
<v-row class="text-center pt-5 pb-2 mb-0" align="center">
|
|
<v-col class="col-3 pa-0">
|
|
<v-tooltip top>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<div v-bind="attrs" v-on="on" class="text-center">
|
|
<strong>{{ $t("Panels.StatusPanel.Estimate") }}</strong><br />
|
|
<span class="text-no-wrap">{{ estimated_time_avg ? formatTime(estimated_time_avg) : '--' }}</span>
|
|
</div>
|
|
</template>
|
|
<div class="text-right">
|
|
{{ $t("Panels.StatusPanel.File") }}: {{ estimated_time_file ? formatTime(estimated_time_file) : '--' }}<br />
|
|
{{ $t("Panels.StatusPanel.Filament") }}: {{ estimated_time_filament ? formatTime(estimated_time_filament) : '--' }}
|
|
</div>
|
|
</v-tooltip>
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<strong>{{ $t("Panels.StatusPanel.Slicer") }}</strong><br />
|
|
<span class="text-no-wrap">{{ estimated_time_slicer ? formatTime(estimated_time_slicer) : '--' }}</span>
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<v-tooltip top>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<div v-bind="attrs" v-on="on" class="text-center">
|
|
<strong>{{ $t("Panels.StatusPanel.Total") }}</strong><br />
|
|
<span class="text-no-wrap">{{ print_time_total ? formatTime(print_time_total) : '--' }}</span>
|
|
</div>
|
|
</template>
|
|
<div class="text-right">
|
|
{{ $t("Panels.StatusPanel.Print") }}: {{ print_time ? formatTime(print_time) : '--' }}<br />
|
|
{{ $t("Panels.StatusPanel.Difference") }}: {{ print_time && print_time_total ? formatTime(print_time_total - print_time) : '--' }}
|
|
</div>
|
|
</v-tooltip>
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<strong>{{ $t("Panels.StatusPanel.ETA") }}</strong><br />
|
|
<span class="text-no-wrap">{{ eta ? formatDateTime(eta) : '--' }}</span>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
</template>
|
|
<template v-if="['complete'].includes(printer_state)">
|
|
<v-divider class="my-0"></v-divider>
|
|
<v-container class="py-0">
|
|
<v-row class="text-center pt-5 pb-2 mb-0" align="center">
|
|
<v-col class="col-3 pa-0">
|
|
<strong>{{ $t("Panels.StatusPanel.Filament") }}</strong><br />
|
|
<span class="text-no-wrap">{{ filament_used >= 1000 ? (filament_used / 1000).toFixed(2)+" m" : filament_used.toFixed(2)+" mm" }}</span>
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<strong>{{ $t("Panels.StatusPanel.Slicer") }}</strong><br />
|
|
<span class="text-no-wrap">{{ 'estimated_time' in current_file ? formatTime(current_file.estimated_time) : '--' }}</span>
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<strong>{{ $t("Panels.StatusPanel.Print") }}</strong><br />
|
|
<span class="text-no-wrap">{{ print_time ? formatTime(print_time) : '--' }}</span>
|
|
</v-col>
|
|
<v-col class="col-3 pa-0">
|
|
<strong>{{ $t("Panels.StatusPanel.Total") }}</strong><br />
|
|
<span class="text-no-wrap">{{ print_time_total ? formatTime(print_time_total) : '--' }}</span>
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
</template>
|
|
</v-card-text>
|
|
</v-card>
|
|
</template>
|
|
|
|
<script>
|
|
import Component from 'vue-class-component'
|
|
import { Mixins, Watch } from 'vue-property-decorator'
|
|
import BaseMixin from '@/components/mixins/base'
|
|
import VueLoadImage from "vue-load-image"
|
|
|
|
@Component({
|
|
VueLoadImage
|
|
})
|
|
export default class StatusPanel extends Mixins(BaseMixin) {
|
|
maxFlow = {
|
|
intervalTimer: null,
|
|
lastExtruderPos: 0,
|
|
lastTime: 0,
|
|
lastValue: 0,
|
|
maxValue: 0,
|
|
}
|
|
|
|
get current_filename() {
|
|
return this.$store.state.printer.print_stats?.filename ?? ""
|
|
}
|
|
|
|
get display_message() {
|
|
return this.$store.state.printer.display_status?.message ?? ""
|
|
}
|
|
|
|
get print_stats_message() {
|
|
return this.$store.state.printer.print_stats?.message ?? ""
|
|
}
|
|
|
|
get positions() {
|
|
return this.$store.getters['printer/getPositions']
|
|
}
|
|
|
|
get coordinates() {
|
|
return this.positions.coordinates ? this.$t("Panels.StatusPanel.Absolute") : this.$t("Panels.StatusPanel.Relative")
|
|
}
|
|
|
|
get filament_used() {
|
|
return this.$store.state.printer.print_stats?.filament_used ?? 0
|
|
}
|
|
|
|
get current_file() {
|
|
return this.$store.state.printer.current_file ?? {}
|
|
}
|
|
|
|
get print_time() {
|
|
return this.$store.state.printer.print_stats?.print_duration ?? 0
|
|
}
|
|
|
|
get print_time_total() {
|
|
return this.$store.state.printer.print_stats?.total_duration ?? 0
|
|
}
|
|
|
|
get printPercent() {
|
|
return Math.round(this.$store.getters["printer/getPrintPercent"] * 100)
|
|
}
|
|
|
|
get printerStateOutput() {
|
|
if (this.printer_state !== "") {
|
|
const idle_timeout_state = this.$store.state.printer.idle_timeout?.state
|
|
|
|
if (
|
|
this.printer_state === "standby" &&
|
|
idle_timeout_state === "Printing"
|
|
) return "Busy"
|
|
|
|
if (this.printer_state !== "" && ['paused', 'printing'].includes(this.printer_state)) {
|
|
return this.printPercent+"% "+this.printer_state.charAt(0).toUpperCase() + this.printer_state.slice(1)
|
|
}
|
|
|
|
return this.printer_state.charAt(0).toUpperCase() + this.printer_state.slice(1)
|
|
}
|
|
|
|
return this.$t("Panels.StatusPanel.Unknown")
|
|
}
|
|
|
|
get toolbarButtons() {
|
|
return [
|
|
{
|
|
text: this.$t("Panels.StatusPanel.PausePrint"),
|
|
color: "orange",
|
|
icon: "mdi-pause",
|
|
loadingName: "statusPrintPause",
|
|
status: ['printing'],
|
|
click: this.btnPauseJob
|
|
}, {
|
|
text: this.$t("Panels.StatusPanel.ResumePrint"),
|
|
color: "orange",
|
|
icon: "mdi-play",
|
|
loadingName: "statusPrintResume",
|
|
status: ['paused'],
|
|
click: this.btnResumeJob
|
|
}, {
|
|
text: this.$t("Panels.StatusPanel.CancelPrint"),
|
|
color: "red",
|
|
icon: "mdi-stop",
|
|
loadingName: "statusPrintCancel",
|
|
status: this.$store.state.gui.general.displayCancelPrint ? ['paused', 'printing'] : ['paused'],
|
|
click: this.btnCancelJob
|
|
}, {
|
|
text: this.$t("Panels.StatusPanel.ClearPrintStats"),
|
|
color: "primary",
|
|
icon: "mdi-broom",
|
|
loadingName: "statusPrintClear",
|
|
status: ['error', 'complete', 'cancelled'],
|
|
click: this.btnClearJob
|
|
}, {
|
|
text: this.$t("Panels.StatusPanel.ReprintJob"),
|
|
color: "primary",
|
|
icon: "mdi-printer",
|
|
loadingName: "statusPrintReprint",
|
|
status: ['error', 'complete', 'cancelled'],
|
|
click: this.btnReprintJob
|
|
}
|
|
]
|
|
}
|
|
|
|
get filteredToolbarButtons() {
|
|
return this.toolbarButtons.filter((button) => {
|
|
return button.status.includes(this.printer_state)
|
|
})
|
|
}
|
|
|
|
get requested_speed() {
|
|
const requested_speed = this.$store.state.printer.gcode_move?.speed ?? 0
|
|
const speed_factor = this.$store.state.printer.gcode_move?.speed_factor ?? 0
|
|
const max_velocity = this.$store.state.printer.toolhead?.max_velocity ?? 0
|
|
|
|
const speed = requested_speed / 60 * speed_factor
|
|
if (speed > max_velocity) return max_velocity
|
|
|
|
return speed.toFixed(0)
|
|
}
|
|
|
|
get max_layers() {
|
|
if (
|
|
'first_layer_height' in this.current_file &&
|
|
'layer_height' in this.current_file &&
|
|
'object_height' in this.current_file
|
|
) {
|
|
const max = Math.ceil((this.current_file.object_height - this.current_file.first_layer_height) / this.current_file.layer_height + 1)
|
|
return max > 0 ? max : 0
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
get current_layer() {
|
|
if (
|
|
this.print_time > 0 &&
|
|
'first_layer_height' in this.current_file &&
|
|
'layer_height' in this.current_file
|
|
) {
|
|
let current_layer = Math.ceil((this.positions.gcode_z - this.current_file.first_layer_height) / this.current_file.layer_height + 1)
|
|
current_layer = (current_layer <= this.max_layers) ? current_layer : this.max_layers
|
|
|
|
return current_layer > 0 ? current_layer : 0
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
get estimated_time_file() {
|
|
return this.$store.getters["printer/getEstimatedTimeFile"]
|
|
}
|
|
|
|
get estimated_time_filament() {
|
|
return this.$store.getters["printer/getEstimatedTimeFilament"]
|
|
}
|
|
|
|
get estimated_time_slicer() {
|
|
return this.$store.getters["printer/getEstimatedTimeSlicer"]
|
|
}
|
|
|
|
get estimated_time_avg() {
|
|
return this.$store.getters["printer/getEstimatedTimeAvg"]
|
|
}
|
|
|
|
get eta() {
|
|
return this.$store.getters["printer/getEstimatedTimeETA"]
|
|
}
|
|
|
|
get filament_diameter() {
|
|
return this.$store.state.printer.configfile?.settings?.extruder?.filament_diameter ?? 1.75
|
|
}
|
|
|
|
get thumbnailSmall() {
|
|
if (
|
|
"thumbnails" in this.current_file &&
|
|
this.current_file.thumbnails.length
|
|
) {
|
|
const thumbnail = this.current_file.thumbnails.find(thumb =>
|
|
thumb.width >= 32 && thumb.width <= 64 &&
|
|
thumb.height >= 32 && thumb.height <= 64
|
|
)
|
|
|
|
if (thumbnail && 'relative_path' in thumbnail) {
|
|
let relative_url = ""
|
|
if (this.current_file.filename.lastIndexOf("/") !== -1) {
|
|
relative_url = this.current_file.filename.substr(0, this.current_file.filename.lastIndexOf("/")+1)
|
|
}
|
|
|
|
if (thumbnail && 'relative_path' in thumbnail) return this.apiUrl+"/server/files/gcodes/"+relative_url+thumbnail.relative_path
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
get thumbnailBig() {
|
|
if (
|
|
"thumbnails" in this.current_file &&
|
|
this.current_file.thumbnails.length
|
|
) {
|
|
const thumbnail = this.current_file.thumbnails.find(thumb => thumb.width >= 300 && thumb.width <= 400)
|
|
|
|
if (thumbnail && 'relative_path' in thumbnail) {
|
|
let relative_url = ""
|
|
if (this.current_file.filename.lastIndexOf("/") !== -1) {
|
|
relative_url = this.current_file.filename.substr(0, this.current_file.filename.lastIndexOf("/")+1)
|
|
}
|
|
|
|
if (thumbnail && 'relative_path' in thumbnail) return this.apiUrl+"/server/files/gcodes/"+relative_url+thumbnail.relative_path
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
get boolBigThumbnail() {
|
|
const setting = this.$store.state.gui.dashboard.boolBigThumbnail ?? true
|
|
|
|
return this.current_filename && setting && this.thumbnailBig
|
|
}
|
|
|
|
btnPauseJob() {
|
|
this.$socket.emit('printer.print.pause', { }, { loading: 'statusPrintPause' })
|
|
}
|
|
|
|
btnResumeJob() {
|
|
this.$socket.emit('printer.print.resume', { }, { loading: 'statusPrintResume' })
|
|
}
|
|
|
|
btnCancelJob() {
|
|
this.$socket.emit('printer.print.cancel', { }, { loading: 'statusPrintCancel' })
|
|
}
|
|
|
|
btnClearJob() {
|
|
this.$socket.emit('printer.gcode.script', {script: 'SDCARD_RESET_FILE'}, { loading: 'statusPrintClear' });
|
|
}
|
|
|
|
btnReprintJob() {
|
|
this.$socket.emit('printer.print.start', { filename: this.current_filename }, { loading: 'statusPrintReprint' });
|
|
}
|
|
|
|
clearDisplayMessage() {
|
|
this.$socket.emit('printer.gcode.script', {script: 'M117'})
|
|
}
|
|
|
|
formatTime(seconds) {
|
|
let h = Math.floor(seconds / 3600);
|
|
seconds %= 3600;
|
|
let m = ("0" + Math.floor(seconds / 60)).slice(-2);
|
|
let s = ("0" + (seconds % 60).toFixed(0)).slice(-2);
|
|
|
|
return h+':'+m+':'+s;
|
|
}
|
|
|
|
formatDateTime(msec) {
|
|
const date = new Date(msec)
|
|
const h = date.getHours() >= 10 ? date.getHours() : "0"+date.getHours()
|
|
const m = date.getMinutes() >= 10 ? date.getMinutes() : "0"+date.getMinutes()
|
|
|
|
const diff = msec - new Date().getTime()
|
|
return h+":"+m+((diff > 60*60*24*1000) ? "+"+parseInt(diff / (60*60*24*1000)) : "")
|
|
}
|
|
|
|
calcMaxFlow() {
|
|
const newExtruderPos = parseFloat(this.filament_used)
|
|
|
|
if (
|
|
this.maxFlow.lastExtruderPos &&
|
|
this.maxFlow.lastExtruderPos < newExtruderPos &&
|
|
this.maxFlow.lastTime
|
|
) {
|
|
const timeDiff = (new Date().getTime() - this.maxFlow.lastTime) / 1000
|
|
const filamentDiff = newExtruderPos - this.maxFlow.lastExtruderPos
|
|
const filamentCrossSection = Math.pow(this.filament_diameter / 2, 2) * Math.PI
|
|
|
|
if (timeDiff < 5000) {
|
|
this.maxFlow.lastValue = filamentCrossSection * filamentDiff / timeDiff
|
|
|
|
if (this.maxFlow.maxValue < this.maxFlow.lastValue) this.maxFlow.maxValue = this.maxFlow.lastValue
|
|
}
|
|
}
|
|
|
|
this.maxFlow.lastExtruderPos = newExtruderPos
|
|
this.maxFlow.lastTime = new Date().getTime()
|
|
}
|
|
|
|
created() {
|
|
this.maxFlow.intervalTimer = setInterval(() => {
|
|
this.calcMaxFlow()
|
|
}, 3000)
|
|
}
|
|
|
|
beforeDestroy() {
|
|
if (this.maxFlow.intervalTimer) {
|
|
clearInterval(this.maxFlow.intervalTimer)
|
|
this.maxFlow.intervalTimer = null
|
|
}
|
|
}
|
|
|
|
@Watch('printerState')
|
|
printerStateChange(newVal) {
|
|
if (['complete', 'cancel', 'error', 'standby'].includes(newVal)) {
|
|
this.maxFlow.lastValue = 0
|
|
this.maxFlow.maxValue = 0
|
|
this.maxFlow.lastTime = 0
|
|
}
|
|
}
|
|
}
|
|
</script> |