feature: collapsable and normalize panels (#372)
* feature: add panel component to normalize all panels * feature: add expand function to panel component * chore: remove not used computed value * feature: add slot for override the icon in the panel * chore: remove unused package (vue2-collapse) * feature: change StatusPanel.vue to panel component * feature: add prop to change toolbar color * feature: change MinSettingsPanel.vue to panel component * feature: change MoonrakerStatePanel.vue to panel component * feature: change KlippyStatePanel.vue to panel component * feature: change KlipperWarningsPanel.vue to panel component * feature: change ControlPanel.vue to panel component * feature: change PrintsettingsPanel.vue to panel component * feature: change MiscellaneousPanel.vue to panel component * feature: change ToolsPanel.vue to panel component * feature: change MacrosPanel.vue to panel component * feature: change MiniconsolePanel.vue to panel component * feature: change FarmPrinterPanel.vue to panel component * bugfix: add toolbar zindex to fix panel hover overlay * bugfix: remove toolbar zindex and modify hover effect * bugfix: farmprinter loading state (remove debug output) * feature: add prop to disable margin botton of panel component * feature: change HistoryListPanel.vue to panel component * feature: move history statistics in HistoryStatisticsPanel.vue and use panel component * feature: change ZoffsetPanel.vue to panel component * feature: add slot after toolbar title in panel component * feature: change Heightmap.vue to panel component * feature: change Files.vue to panel component * feature: change Viewer.vue to panel component * feature: add buttons before toolbar in panel component * feature: change ConfigFilesPanel.vue to panel component * feature: change EndstopPanel.vue to panel component * chore: fix typo in card class from ConfigFilesPanel.vue * feature: change LimitsPanel.vue to panel component * feature: change LogfilesPanel.vue to panel component * feature: change SystemPanel.vue to panel component * feature: change UpdatePanel.vue to panel component
This commit is contained in:
@@ -39,15 +39,11 @@
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<v-card>
|
||||
<v-toolbar flat dense>
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-video-3d</v-icon>{{ $t('GCodeViewer.Title') }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<panel :title="$t('GCodeViewer.Title')" icon="mdi-video-3d" card-class="gcode-viewer-panel">
|
||||
<template v-slot:buttons>
|
||||
<v-btn @click="reloadViewer" color="info" class="ml-3" v-show="reloadRequired" small>{{$t("GCodeViewer.ReloadRequired")}}</v-btn>
|
||||
<v-btn @click="resetCamera" class="px-2 minwidth-0 ml-3" color="grey darken-3" small dense><v-icon small>mdi-camera-retake</v-icon></v-btn>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col>
|
||||
@@ -123,7 +119,7 @@
|
||||
</v-row>
|
||||
<input :accept="'.g,.gcode,.gc,.gco,.nc,.ngc,.tap'" @change="fileSelected" hidden multiple ref="fileInput" type="file" />
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
<v-snackbar v-model="loading" :timeout="-1" :value="true" fixed right bottom dark>
|
||||
<div>
|
||||
{{ $t('GCodeViewer.Rendering') }} - {{ loadingPercent }}%<br />
|
||||
@@ -158,6 +154,7 @@ import BaseMixin from '../mixins/base'
|
||||
import GCodeViewer from '@sindarius/gcodeviewer'
|
||||
import axios from 'axios'
|
||||
import {formatFilesize} from '@/plugins/helpers'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
|
||||
interface downloadSnackbar {
|
||||
status: boolean
|
||||
@@ -173,8 +170,9 @@ interface downloadSnackbar {
|
||||
}
|
||||
|
||||
let viewer: any = null
|
||||
|
||||
@Component
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class Viewer extends Mixins(BaseMixin) {
|
||||
formatFilesize = formatFilesize
|
||||
private isBusy = false
|
||||
|
@@ -21,19 +21,20 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<v-card class="mb-6" v-if="klipperReadyForGui && ['standby', 'paused', 'complete', 'cancelled', 'error'].includes(printer_state)">
|
||||
<v-toolbar flat dense>
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-gamepad</v-icon>{{ $t('Panels.ControlPanel.Headline') }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel
|
||||
v-if="klipperReadyForGui && ['standby', 'paused', 'complete', 'cancelled', 'error'].includes(printer_state)"
|
||||
icon="mdi-gamepad"
|
||||
:title="$t('Panels.ControlPanel.Headline')"
|
||||
:collapsible="true"
|
||||
card-class="control-panel"
|
||||
>
|
||||
<v-container>
|
||||
<control-panel-cross-control v-if="controlStyle === 'cross'"></control-panel-cross-control>
|
||||
<control-panel-circle-control v-else-if="controlStyle === 'circle'"></control-panel-circle-control>
|
||||
<control-panel-bars-control v-else></control-panel-bars-control>
|
||||
<control-panel-extruder v-if="existsExtruder"></control-panel-extruder>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -43,8 +44,11 @@ import ControlPanelExtruder from '@/components/panels/ControlPanelExtruder.vue'
|
||||
import ControlPanelCrossControl from '@/components/panels/ControlPanelCrossControl.vue'
|
||||
import ControlPanelBarsControl from '@/components/panels/ControlPanelBarsControl.vue'
|
||||
import ControlPanelCircleControl from '@/components/panels/ControlPanelCircleControl.vue'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {ControlPanelCircleControl, ControlPanelBarsControl, ControlPanelCrossControl, ControlPanelExtruder}
|
||||
components: {
|
||||
Panel,
|
||||
ControlPanelCircleControl, ControlPanelBarsControl, ControlPanelCrossControl, ControlPanelExtruder}
|
||||
})
|
||||
export default class ControlPanel extends Mixins(BaseMixin) {
|
||||
get controlStyle() {
|
||||
|
@@ -19,19 +19,22 @@
|
||||
.webcamContainer .webcamFpsOutput {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.v-overlay {
|
||||
top: 48px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<v-card
|
||||
:class="(!printer.socket.isConnected && !printer.socket.isConnecting ? 'disabledPrinter' : '')"
|
||||
<panel
|
||||
icon="mdi-printer-3d"
|
||||
:title="printer_name"
|
||||
:card-class="'farmprinter-panel '+(!printer.socket.isConnected && !printer.socket.isConnecting ? 'disabledPrinter' : '')"
|
||||
:loading="printer.socket.isConnecting"
|
||||
:toolbar-color="isCurrentPrinter ? 'primary' : ''"
|
||||
>
|
||||
<v-toolbar flat dense :color="isCurrentPrinter ? 'primary' : ''" style="z-index: 5;">
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-printer-3d</v-icon>{{ printer_name }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-item-group v-if="printer.socket.isConnected && this.printer_webcams.length">
|
||||
<template v-slot:buttons>
|
||||
<v-item-group v-if="printer.socket.isConnected && printer_webcams.length">
|
||||
<v-menu :offset-y="true" title="Webcam">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn small class="px-2 minwidth-0" color="grey darken-3" v-bind="attrs" v-on="on">
|
||||
@@ -48,7 +51,7 @@
|
||||
<v-list-item-title>{{ $t('Panels.FarmPrinterPanel.WebcamOff') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item v-for="webcam of this.printer_webcams" v-bind:key="webcam.index" link @click="currentCamName = webcam.name">
|
||||
<v-list-item v-for="webcam of printer_webcams" v-bind:key="webcam.index" link @click="currentCamName = webcam.name">
|
||||
<v-list-item-icon class="mr-0">
|
||||
<v-icon small>{{ webcam.icon }}</v-icon>
|
||||
</v-list-item-icon>
|
||||
@@ -59,7 +62,7 @@
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-item-group>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
<v-hover>
|
||||
<template v-slot:default="{ hover }">
|
||||
<div>
|
||||
@@ -112,7 +115,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</v-hover>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -122,9 +125,11 @@ import { FarmPrinterState } from '@/store/farm/printer/types'
|
||||
import Mjpegstreamer from '@/components/webcams/Mjpegstreamer.vue'
|
||||
import MjpegstreamerAdaptive from '@/components/webcams/MjpegstreamerAdaptive.vue'
|
||||
import MainsailLogo from '@/components/ui/MainsailLogo.vue'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
Panel,
|
||||
'webcam-mjpegstreamer': Mjpegstreamer,
|
||||
'webcam-mjpegstreamer-adaptive': MjpegstreamerAdaptive,
|
||||
'mainsail-logo': MainsailLogo
|
||||
|
@@ -1,11 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-card>
|
||||
<v-toolbar flat dense>
|
||||
<v-toolbar-title>
|
||||
<span class="subheading align-baseline"><v-icon left>mdi-file-document-multiple-outline</v-icon>{{ $t('History.PrintHistory') }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel
|
||||
icon="mdi-file-document-multiple-outline"
|
||||
:title="$t('History.PrintHistory')"
|
||||
card-class="history-list-panel"
|
||||
>
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col class="col-4 d-flex align-center">
|
||||
@@ -126,7 +125,7 @@
|
||||
</tr>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</v-card>
|
||||
</panel>
|
||||
<v-menu v-model="contextMenu.shown" :position-x="contextMenu.x" :position-y="contextMenu.y" absolute offset-y>
|
||||
<v-list>
|
||||
<v-list-item @click="clickRow(contextMenu.item)">
|
||||
@@ -140,144 +139,142 @@
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<v-dialog v-model="detailsDialog.boolShow" :max-width="600" :max-height="500" scrollable>
|
||||
<v-card dark>
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-update</v-icon>{{ $t('History.JobDetails') }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn small class="minwidth-0" color="grey darken-3" @click="detailsDialog.boolShow = false"><v-icon small>mdi-close-thick</v-icon></v-btn>
|
||||
</v-toolbar>
|
||||
<v-card-text class="pt-5" style="height: 350px;">
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.Filename') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.filename }}</v-col>
|
||||
</v-row>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'size' in detailsDialog.item.metadata">
|
||||
<v-dialog v-model="detailsDialog.boolShow" :max-width="600" persistent>
|
||||
<panel :title="$t('History.JobDetails')" icon="mdi-update" card-class="history-detail-dialog" :margin-bottom="false">
|
||||
<template v-slot:buttons>
|
||||
<v-btn small class="minwidth-0 px-2" color="grey darken-3" @click="detailsDialog.boolShow = false"><v-icon small>mdi-close-thick</v-icon></v-btn>
|
||||
</template>
|
||||
<v-card-text class="px-0">
|
||||
<perfect-scrollbar style="height: 350px;" :options="{ suppressScrollX: true }" class="px-6">
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.Filename') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.filename }}</v-col>
|
||||
</v-row>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'size' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.Filesize') }}</v-col>
|
||||
<v-col class="text-right">{{ formatFilesize(detailsDialog.item.metadata.size) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'modified' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.LastModified') }}</v-col>
|
||||
<v-col class="text-right">{{ formatDate(detailsDialog.item.metadata.modified) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.Filesize') }}</v-col>
|
||||
<v-col class="text-right">{{ formatFilesize(detailsDialog.item.metadata.size) }}</v-col>
|
||||
<v-col>{{ $t('History.Status') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.status }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'modified' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.LastModified') }}</v-col>
|
||||
<v-col class="text-right">{{ formatDate(detailsDialog.item.metadata.modified) }}</v-col>
|
||||
<v-col>{{ $t('History.StartTime') }}</v-col>
|
||||
<v-col class="text-right">{{ formatDate(detailsDialog.item.start_time) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.Status') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.status }}</v-col>
|
||||
</v-row>
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.StartTime') }}</v-col>
|
||||
<v-col class="text-right">{{ formatDate(detailsDialog.item.start_time) }}</v-col>
|
||||
</v-row>
|
||||
<template v-if="'end_time' in detailsDialog.item && detailsDialog.item.end_time > 0">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.EndTime') }}</v-col>
|
||||
<v-col class="text-right">{{ formatDate(detailsDialog.item.end_time) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'estimated_time' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.EstimatedTime') }}</v-col>
|
||||
<v-col class="text-right">{{ formatPrintTime(detailsDialog.item.metadata.estimated_time) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="detailsDialog.item.print_duration > 0">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.PrintDuration') }}</v-col>
|
||||
<v-col class="text-right">{{ formatPrintTime(detailsDialog.item.print_duration) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="detailsDialog.item.total_duration > 0">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.TotalDuration') }}</v-col>
|
||||
<v-col class="text-right">{{ formatPrintTime(detailsDialog.item.total_duration) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'filament_total' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.EstimatedFilamentWeight') }}</v-col>
|
||||
<v-col class="text-right">{{ Math.round(detailsDialog.item.metadata.filament_weight_total*100)/100 }} g</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'filament_total' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.EstimatedFilament') }}</v-col>
|
||||
<v-col class="text-right">{{ Math.round(detailsDialog.item.metadata.filament_total) }} mm</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="detailsDialog.item.filament_used > 0">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.FilamentUsed') }}</v-col>
|
||||
<v-col class="text-right">{{ Math.round(detailsDialog.item.filament_used) }} mm</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'first_layer_extr_temp' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.FirstLayerExtTemp') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.first_layer_extr_temp }} °C</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'first_layer_bed_temp' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.FirstLayerBedTemp') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.first_layer_bed_temp }} °C</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'first_layer_height' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.FirstLayerHeight') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.first_layer_height }} mm</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'layer_height' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.LayerHeight') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.layer_height }} mm</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'object_height' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.ObjectHeight') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.object_height }} mm</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'slicer' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.Slicer') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.slicer }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'slicer_version' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.SlicerVersion') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.slicer_version }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'end_time' in detailsDialog.item && detailsDialog.item.end_time > 0">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.EndTime') }}</v-col>
|
||||
<v-col class="text-right">{{ formatDate(detailsDialog.item.end_time) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'estimated_time' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.EstimatedTime') }}</v-col>
|
||||
<v-col class="text-right">{{ formatPrintTime(detailsDialog.item.metadata.estimated_time) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="detailsDialog.item.print_duration > 0">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.PrintDuration') }}</v-col>
|
||||
<v-col class="text-right">{{ formatPrintTime(detailsDialog.item.print_duration) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="detailsDialog.item.total_duration > 0">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.TotalDuration') }}</v-col>
|
||||
<v-col class="text-right">{{ formatPrintTime(detailsDialog.item.total_duration) }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'filament_total' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.EstimatedFilamentWeight') }}</v-col>
|
||||
<v-col class="text-right">{{ Math.round(detailsDialog.item.metadata.filament_weight_total*100)/100 }} g</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'filament_total' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.EstimatedFilament') }}</v-col>
|
||||
<v-col class="text-right">{{ Math.round(detailsDialog.item.metadata.filament_total) }} mm</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="detailsDialog.item.filament_used > 0">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.FilamentUsed') }}</v-col>
|
||||
<v-col class="text-right">{{ Math.round(detailsDialog.item.filament_used) }} mm</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'first_layer_extr_temp' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.FirstLayerExtTemp') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.first_layer_extr_temp }} °C</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'first_layer_bed_temp' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.FirstLayerBedTemp') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.first_layer_bed_temp }} °C</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'first_layer_height' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.FirstLayerHeight') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.first_layer_height }} mm</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'layer_height' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.LayerHeight') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.layer_height }} mm</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'object_height' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.ObjectHeight') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.object_height }} mm</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'slicer' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.Slicer') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.slicer }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="'metadata' in detailsDialog.item && 'slicer_version' in detailsDialog.item.metadata">
|
||||
<v-divider class="my-3"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ $t('History.SlicerVersion') }}</v-col>
|
||||
<v-col class="text-right">{{ detailsDialog.item.metadata.slicer_version }}</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
</perfect-scrollbar>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -289,8 +286,10 @@ import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
import {ServerHistoryStateJob} from '@/store/server/history/types'
|
||||
import {caseInsensitiveSort, formatFilesize} from '@/plugins/helpers'
|
||||
|
||||
@Component
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class HistoryListPanel extends Mixins(BaseMixin) {
|
||||
formatFilesize = formatFilesize
|
||||
|
||||
|
119
src/components/panels/HistoryStatisticsPanel.vue
Normal file
119
src/components/panels/HistoryStatisticsPanel.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<panel
|
||||
icon="mdi-chart-areaspline"
|
||||
:title="$t('History.Statistics')"
|
||||
card-class="history-statistics-panel"
|
||||
:collapsible="true"
|
||||
>
|
||||
<v-card-text class="pa-0">
|
||||
<v-row align="center">
|
||||
<v-col class="col-12 col-sm-6 col-md-4">
|
||||
<v-simple-table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ $t('History.TotalPrinttime') }}</td>
|
||||
<td class="text-right">{{ formatPrintTime(totalPrintTime) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('History.LongestPrinttime') }}</td>
|
||||
<td class="text-right">{{ formatPrintTime(longestPrintTime) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('History.AvgPrinttime') }}</td>
|
||||
<td class="text-right">{{ formatPrintTime(avgPrintTime) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('History.TotalFilamentUsed') }}</td>
|
||||
<td class="text-right">{{ Math.round(totalFilamentUsed / 100) / 10 }} m</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('History.TotalJobs') }}</td>
|
||||
<td class="text-right">{{ totalJobsCount }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-simple-table>
|
||||
</v-col>
|
||||
<v-col class="col-12 col-sm-6 col-md-4">
|
||||
<history-all-print-status></history-all-print-status>
|
||||
</v-col>
|
||||
<v-col class="col-12 col-sm-12 col-md-4">
|
||||
<history-filament-usage v-if="toggleChart === 'filament_usage'"></history-filament-usage>
|
||||
<history-printtime-avg v-if="toggleChart === 'printtime_avg'"></history-printtime-avg>
|
||||
<div class="text-center mt-3">
|
||||
<v-btn-toggle v-model="toggleChart" small mandatory>
|
||||
<v-btn small value="filament_usage">
|
||||
{{ $t('History.FilamentUsage') }}
|
||||
</v-btn>
|
||||
<v-btn small value="printtime_avg">
|
||||
{{ $t('History.PrinttimeAvg') }}
|
||||
</v-btn>
|
||||
</v-btn-toggle>
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
import HistoryFilamentUsage from '@/components/charts/HistoryFilamentUsage.vue'
|
||||
import HistoryPrinttimeAvg from '@/components/charts/HistoryPrinttimeAvg.vue'
|
||||
import HistoryAllPrintStatus from '@/components/charts/HistoryAllPrintStatus.vue'
|
||||
@Component({
|
||||
components: {Panel,HistoryFilamentUsage, HistoryPrinttimeAvg, HistoryAllPrintStatus}
|
||||
})
|
||||
export default class HistoryStatisticsPanel extends Mixins(BaseMixin) {
|
||||
get totalPrintTime() {
|
||||
return 'total_print_time' in this.$store.state.server.history.job_totals ? this.$store.state.server.history.job_totals.total_print_time : 0
|
||||
}
|
||||
|
||||
get longestPrintTime() {
|
||||
return 'longest_print' in this.$store.state.server.history.job_totals ? this.$store.state.server.history.job_totals.longest_print : 0
|
||||
}
|
||||
|
||||
get avgPrintTime() {
|
||||
if (this.totalJobsCount > 0 && this.totalPrintTime > 0) return Math.round(this.totalPrintTime / this.totalJobsCount)
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
get totalFilamentUsed() {
|
||||
return 'total_filament_used' in this.$store.state.server.history.job_totals ? this.$store.state.server.history.job_totals.total_filament_used : 0
|
||||
}
|
||||
|
||||
get totalJobsCount() {
|
||||
return 'total_jobs' in this.$store.state.server.history.job_totals ? this.$store.state.server.history.job_totals.total_jobs : 0
|
||||
}
|
||||
|
||||
get toggleChart () {
|
||||
return this.$store.state.gui.history.toggleChartCol3
|
||||
}
|
||||
|
||||
set toggleChart(newVal) {
|
||||
this.$store.dispatch('gui/saveSetting', { name: 'history.toggleChartCol3', value: newVal })
|
||||
}
|
||||
|
||||
formatPrintTime(totalSeconds: number) {
|
||||
if (totalSeconds) {
|
||||
let output = ''
|
||||
|
||||
const hours = Math.floor(totalSeconds / 3600)
|
||||
totalSeconds %= 3600
|
||||
if (hours) output += ' '+hours+'h'
|
||||
|
||||
const minutes = Math.floor(totalSeconds / 60)
|
||||
if (minutes) output += ' '+minutes+'m'
|
||||
|
||||
const seconds = totalSeconds % 60
|
||||
if (seconds) output += ' '+seconds.toFixed(0)+'s'
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
</script>
|
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<v-card class="mb-6" v-if="klipperReadyForGui && warnings.length">
|
||||
<v-toolbar flat dense color="orange darken-2">
|
||||
<v-toolbar-title>
|
||||
<span class="subheading">
|
||||
<v-icon class="mdi mdi-alert-circle" left></v-icon>{{ $t("Panels.KlipperWarningsPanel.KlipperWarnings") }} ({{ warnings.length }})
|
||||
</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel
|
||||
v-if="klipperReadyForGui && warnings.length"
|
||||
icon="mdi-alert-circle"
|
||||
:title="$t('Panels.KlipperWarningsPanel.KlipperWarnings')+' ('+warnings.length+')'"
|
||||
:collapsible="true"
|
||||
card-class="klipper-warnings-panel"
|
||||
toolbar-color="orange darken-2"
|
||||
>
|
||||
<v-card-text :class="index > 0 ? 'py-0' : 'pt-3 pb-0'" v-for="(warning, index) in warnings" v-bind:key="index">
|
||||
<v-divider class="my-2" v-if="index"></v-divider>
|
||||
<v-row>
|
||||
@@ -24,7 +24,7 @@
|
||||
<v-card-actions class="px-4 pt-2 pb-4 text-center text-lg-left">
|
||||
<v-btn small :href="apiUrl+'/server/files/klipper.log'" target="_blank" color="primary" class=""><v-icon class="mr-2" small>mdi-download</v-icon>{{ $t("Panels.KlipperWarningsPanel.DownloadLog") }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -32,8 +32,10 @@ import Component from 'vue-class-component'
|
||||
import BaseMixin from '../mixins/base'
|
||||
import {Mixins} from 'vue-property-decorator'
|
||||
import {caseInsensitiveSort} from '@/plugins/helpers'
|
||||
|
||||
@Component
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class KlipperWarningsPanelPanel extends Mixins(BaseMixin) {
|
||||
|
||||
get warnings() {
|
||||
|
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<v-card v-if="klipperState !== 'ready' && socketIsConnected" class="mb-6">
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-alert-circle</v-icon>{{ $t('Panels.KlippyStatePanel.KlippyState')}}: {{ klipperState }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel
|
||||
v-if="klipperState !== 'ready' && socketIsConnected"
|
||||
icon="mdi-alert-circle"
|
||||
:title="$t('Panels.KlippyStatePanel.KlippyState')+': '+klipperState"
|
||||
card-class="klippy-state-panel"
|
||||
>
|
||||
<template v-if="klippyIsConnected">
|
||||
<v-card-text class="py-1">
|
||||
<pre style="white-space: pre-wrap;">{{ klippy_message }}</pre>
|
||||
@@ -23,7 +23,7 @@
|
||||
<p class="mt-2">{{ $t('Panels.KlippyStatePanel.KlipperCheck') }}</p>
|
||||
</v-card-text>
|
||||
</template>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -31,9 +31,10 @@ import Component from 'vue-class-component'
|
||||
import {Mixins, Watch} from 'vue-property-decorator'
|
||||
import BaseMixin from '../mixins/base'
|
||||
import ConnectionStatus from '../ui/ConnectionStatus.vue'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
|
||||
@Component({
|
||||
components: {ConnectionStatus}
|
||||
components: {Panel, ConnectionStatus}
|
||||
})
|
||||
export default class KlippyStatePanel extends Mixins(BaseMixin) {
|
||||
private timer: number | null = null
|
||||
|
@@ -4,12 +4,7 @@
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<v-card>
|
||||
<v-toolbar flat dense>
|
||||
<v-toolbar-title>
|
||||
<span class="subheading align-baseline"><v-icon left>mdi-information</v-icon>{{ $t('Machine.ConfigFilesPanel.ConfigFiles') }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel :title="$t('Machine.ConfigFilesPanel.ConfigFiles')" card-class="machine-configfiles-panel" icon="mdi-information">
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col class="col-12 col-lg pr-lg-0">
|
||||
@@ -134,7 +129,7 @@
|
||||
</tr>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</v-card>
|
||||
</panel>
|
||||
<v-menu v-model="contextMenu.shown" :position-x="contextMenu.x" :position-y="contextMenu.y" absolute offset-y>
|
||||
<v-list>
|
||||
<v-list-item @click="clickRow(contextMenu.item, true)" v-if="!contextMenu.item.isDirectory">
|
||||
@@ -157,32 +152,21 @@
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<!-- <v-dialog v-model="editor.showLoader" hide-overlay persistent width="300">
|
||||
<v-card color="primary" dark >
|
||||
<v-card-text>
|
||||
{{ $t('Machine.ConfigFilesPanel.PleaseStandBy') }}
|
||||
<v-progress-linear indeterminate color="white" class="mb-0" ></v-progress-linear>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>-->
|
||||
<v-dialog v-model="dialogImage.show" hide-overlay fullscreen @keydown.esc="dialogImage.show = false; dialogImage.item.url = null; dialogImage.item.svg = null;" class="fill-height">
|
||||
<v-card style="position: relative;">
|
||||
<v-toolbar dark color="primary">
|
||||
<v-btn icon dark @click="dialogImage.show = false; dialogImage.item.url = null; dialogImage.item.svg = null;">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
<div class="d-flex justify-center" style="max-height: calc(100vh - 64px); overflow: auto;">
|
||||
<img v-if="dialogImage.item.url" :src="dialogImage.item.url" style="max-height: 100%; width: auto;" alt="image" />
|
||||
<div v-else-if="dialogImage.item.svg"
|
||||
class="fill-width"
|
||||
v-html="dialogImage.item.svg"></div>
|
||||
</div>
|
||||
</v-card>
|
||||
<panel :title="dialogImage.item.name" card-class="maschine-configfiles-imageviewer-dialog" toolbar-color="primary" style="position: relative;">
|
||||
<template v-slot:buttons-left>
|
||||
<v-btn icon dark @click="dialogImage.show = false; dialogImage.item.url = null; dialogImage.item.svg = null;">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<div class="d-flex justify-center" style="max-height: calc(100vh - 64px); overflow: auto;">
|
||||
<img v-if="dialogImage.item.url" :src="dialogImage.item.url" style="max-height: 100%; width: auto;" alt="image" />
|
||||
<div v-else-if="dialogImage.item.svg" class="fill-width" v-html="dialogImage.item.svg"></div>
|
||||
</div>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="dialogRenameFile.show" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title class="headline">{{ $t('Machine.ConfigFilesPanel.RenameFile') }}</v-card-title>
|
||||
<panel :title="$t('Machine.ConfigFilesPanel.RenameFile')" card-class="maschine-configfiles-rename-file-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<v-text-field :label="$t('Machine.ConfigFilesPanel.Name')" required v-model="dialogRenameFile.newName"></v-text-field>
|
||||
</v-card-text>
|
||||
@@ -191,11 +175,10 @@
|
||||
<v-btn color="" text @click="dialogRenameFile.show = false">{{ $t('Machine.ConfigFilesPanel.Cancel') }}</v-btn>
|
||||
<v-btn color="primary" text @click="renameFileAction">{{ $t('Machine.ConfigFilesPanel.Rename') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="dialogCreateFile.show" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title class="headline">{{ $t('Machine.ConfigFilesPanel.CreateFile') }}</v-card-title>
|
||||
<panel :title="$t('Machine.ConfigFilesPanel.CreateFile')" card-class="maschine-configfiles-create-file-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<v-text-field :label="$t('Machine.ConfigFilesPanel.Name')" required v-model="dialogCreateFile.name"></v-text-field>
|
||||
</v-card-text>
|
||||
@@ -204,11 +187,10 @@
|
||||
<v-btn color="" text @click="dialogCreateFile.show = false">{{ $t('Machine.ConfigFilesPanel.Cancel') }}</v-btn>
|
||||
<v-btn color="primary" text @click="createFileAction">{{ $t('Machine.ConfigFilesPanel.Create') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="dialogCreateDirectory.show" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title class="headline">{{ $t('Machine.ConfigFilesPanel.CreateDirectory') }}</v-card-title>
|
||||
<panel :title="$t('Machine.ConfigFilesPanel.CreateDirectory')" card-class="maschine-configfiles-create-directory-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<v-text-field :label="$t('Machine.ConfigFilesPanel.Name')" required v-model="dialogCreateDirectory.name"></v-text-field>
|
||||
</v-card-text>
|
||||
@@ -217,11 +199,10 @@
|
||||
<v-btn color="" text @click="dialogCreateDirectory.show = false">{{ $t('Machine.ConfigFilesPanel.Cancel') }}</v-btn>
|
||||
<v-btn color="primary" text @click="createDirectoryAction">{{ $t('Machine.ConfigFilesPanel.Create') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="dialogRenameDirectory.show" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title class="headline">{{ $t('Machine.ConfigFilesPanel.RenameDirectory') }}</v-card-title>
|
||||
<panel :title="$t('Machine.ConfigFilesPanel.RenameDirectory')" card-class="maschine-configfiles-rename-directory-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<v-text-field :label="$t('Machine.ConfigFilesPanel.Name')" required v-model="dialogRenameDirectory.newName"></v-text-field>
|
||||
</v-card-text>
|
||||
@@ -230,11 +211,10 @@
|
||||
<v-btn color="" text @click="dialogRenameDirectory.show = false">{{ $t('Machine.ConfigFilesPanel.Cancel') }}</v-btn>
|
||||
<v-btn color="primary" text @click="renameDirectoryAction">{{ $t('Machine.ConfigFilesPanel.Rename') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="dialogDeleteDirectory.show" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title class="headline">{{ $t('Machine.ConfigFilesPanel.DeleteDirectory') }}</v-card-title>
|
||||
<panel :title="$t('Machine.ConfigFilesPanel.DeleteDirectory')" card-class="maschine-configfiles-delete-directory-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<p class="mb-0">{{ $t('Machine.ConfigFilesPanel.DeleteDirectoryQuestion', { name: dialogDeleteDirectory.item.filename } )}}</p>
|
||||
</v-card-text>
|
||||
@@ -243,7 +223,7 @@
|
||||
<v-btn color="" text @click="dialogDeleteDirectory.show = false">{{ $t('Machine.ConfigFilesPanel.Cancel') }}</v-btn>
|
||||
<v-btn color="error" text @click="deleteDirectoryAction">{{ $t('Machine.ConfigFilesPanel.Delete') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-snackbar v-model="uploadSnackbar.status" :timeout="-1" :value="true" fixed right bottom dark>
|
||||
<span v-if="uploadSnackbar.max > 1" class="mr-1">({{ uploadSnackbar.number }}/{{ uploadSnackbar.max }})</span><strong>{{ $t('Machine.ConfigFilesPanel.Uploading') }} {{ uploadSnackbar.filename }}</strong><br />
|
||||
@@ -272,6 +252,7 @@ import {readOnlyRoots} from '@/store/variables'
|
||||
import {findDirectory, formatDate, formatFilesize, sortFiles} from '@/plugins/helpers'
|
||||
import {FileStateFile} from '@/store/files/types'
|
||||
import axios from 'axios'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
|
||||
interface contextMenu {
|
||||
shown: boolean
|
||||
@@ -286,6 +267,7 @@ interface contextMenu {
|
||||
interface dialogImageObject {
|
||||
show: boolean
|
||||
item: {
|
||||
name: string | null,
|
||||
url: string | null,
|
||||
svg: string | null
|
||||
}
|
||||
@@ -322,7 +304,9 @@ interface draggingFile {
|
||||
item: FileStateFile
|
||||
}
|
||||
|
||||
@Component
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
sortFiles = sortFiles
|
||||
formatFilesize = formatFilesize
|
||||
@@ -353,6 +337,7 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
private dialogImage: dialogImageObject = {
|
||||
show: false,
|
||||
item: {
|
||||
name: null,
|
||||
url: null,
|
||||
svg: null
|
||||
}
|
||||
@@ -551,6 +536,7 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
if (!item.isDirectory) {
|
||||
if (['png', 'jpeg', 'jpg', 'gif', 'bmp', 'tif', 'svg'].includes(item.filename.split('.').pop()?.toLowerCase() ?? '')) {
|
||||
const url = `${this.apiUrl}/server/files${this.absolutePath}/${item.filename}?t=${Date.now()}`
|
||||
this.dialogImage.item.name = item.filename
|
||||
if (['svg'].includes(item.filename.split('.').pop()?.toLowerCase() ?? '')) {
|
||||
fetch(url)
|
||||
.then(res => res.text())
|
||||
|
@@ -1,10 +1,5 @@
|
||||
<template>
|
||||
<v-card>
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-arrow-expand-vertical</v-icon>{{ $t('Machine.EndstopPanel.Endstops')}}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel :title="$t('Machine.EndstopPanel.Endstops')" icon="mdi-arrow-expand-vertical" card-class="machine-endstop-panel" :collapsible="true">
|
||||
<v-card-text class="pb-0">
|
||||
<v-container px-0 py-0>
|
||||
<template v-if="Object.keys(endstops).length">
|
||||
@@ -49,16 +44,18 @@
|
||||
<v-btn icon @click="syncEndstops" :loading="loadings.includes('queryEndstops')">
|
||||
<v-icon>mdi-sync</v-icon>
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-card-actions>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '../../mixins/base'
|
||||
|
||||
@Component
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class EndstopPanel extends Mixins(BaseMixin) {
|
||||
public sortEndstops: any = {}
|
||||
|
||||
|
@@ -1,10 +1,5 @@
|
||||
<template>
|
||||
<v-card class="mb-6" v-if="klipperReadyForGui">
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-speedometer</v-icon>{{ $t('Machine.LimitsPanel.MachineLimits')}}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel :title="$t('Machine.LimitsPanel.MachineLimits')" v-if="klipperReadyForGui" icon="mdi-speedometer" card-class="machine-machinelimits-panel" :collapsible="true">
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col class="col-6">
|
||||
@@ -51,7 +46,7 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -61,8 +56,9 @@ import { Component, Mixins } from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base.ts'
|
||||
import ToolSlider from '@/components/inputs/ToolSlider'
|
||||
import MachineLimitsInput from '@/components/inputs/MachineLimitsInput'
|
||||
import Panel from '@/components/ui/Panel'
|
||||
@Component({
|
||||
components: {MachineLimitsInput, ToolSlider}
|
||||
components: {Panel, MachineLimitsInput, ToolSlider}
|
||||
})
|
||||
export default class LimitsPanel extends Mixins(BaseMixin) {
|
||||
|
||||
|
@@ -1,10 +1,5 @@
|
||||
<template>
|
||||
<v-card>
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-file-document-edit</v-icon>{{ $t("Machine.LogfilesPanel.Logfiles")}}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel :title="$t('Machine.LogfilesPanel.Logfiles')" icon="mdi-file-document-edit" card-class="machine-logfiles-panel" :collapsible="true">
|
||||
<v-card-text :class="'text-center text-lg-left py-0'">
|
||||
<v-container pb-0 px-0>
|
||||
<v-row>
|
||||
@@ -17,15 +12,17 @@
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '../../mixins/base'
|
||||
|
||||
@Component
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class LogfilesPanel extends Mixins(BaseMixin) {
|
||||
downloadLog(event: any) {
|
||||
event.preventDefault()
|
||||
|
@@ -6,12 +6,7 @@
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<v-card class="mb-6">
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-memory</v-icon>{{ $t('Machine.SystemPanel.SystemLoad') }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel :title="$t('Machine.SystemPanel.SystemLoad')" icon="mdi-memory" card-class="machine-systemload-panel" :collapsible="true">
|
||||
<v-card-text class="px-0 py-2">
|
||||
<div v-for="(mcu, index) of mcus" v-bind:key="mcu.name">
|
||||
<v-divider class="my-2" v-if="index" ></v-divider>
|
||||
@@ -101,77 +96,73 @@
|
||||
</v-row>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
<v-dialog v-model="mcuDetailsDialog.bool" :max-width="400" :max-height="500" scrollable>
|
||||
<v-card dark>
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-text-box-search-outline</v-icon>{{ mcuDetailsDialog.headline }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<panel :title="mcuDetailsDialog.headline" icon="mdi-text-box-search-outline" card-class="machine-systemload-mcu-details-dialog" :margin-bottom="false">
|
||||
<template v-slot:buttons>
|
||||
<v-btn small class="minwidth-0 px-2" color="grey darken-3" @click="mcuDetailsDialog.bool = false"><v-icon small>mdi-close-thick</v-icon></v-btn>
|
||||
</v-toolbar>
|
||||
<v-card-text class="pt-5" style="height: 350px;">
|
||||
<template v-if="mcuDetailsDialog.mcu.mcu_constants">
|
||||
<v-row>
|
||||
<v-col><span class="headline">{{ $t('Machine.SystemPanel.Constants') }}</span></v-col>
|
||||
</v-row>
|
||||
<div v-for="(value, key, index) in mcuDetailsDialog.mcu.mcu_constants" :key="key">
|
||||
<v-divider class="my-3" v-if="index"></v-divider>
|
||||
</template>
|
||||
<v-card-text class="pt-5 px-0">
|
||||
<perfect-scrollbar style="height: 350px;" :options="{ suppressScrollX: true }" class="px-6">
|
||||
<template v-if="mcuDetailsDialog.mcu.mcu_constants">
|
||||
<v-row>
|
||||
<v-col>{{ key }}</v-col>
|
||||
<v-col class="text-right">{{ value }}</v-col>
|
||||
<v-col><span class="headline">{{ $t('Machine.SystemPanel.Constants') }}</span></v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="mcuDetailsDialog.mcu.last_stats">
|
||||
<v-row class="mt-5">
|
||||
<v-col><span class="headline">{{ $t('Machine.SystemPanel.LastStats') }}</span></v-col>
|
||||
</v-row>
|
||||
<div v-for="(value, key, index) in mcuDetailsDialog.mcu.last_stats" :key="key">
|
||||
<v-divider class="my-3" v-if="index"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ key }}</v-col>
|
||||
<v-col class="text-right">{{ value }}</v-col>
|
||||
<div v-for="(value, key, index) in mcuDetailsDialog.mcu.mcu_constants" :key="key">
|
||||
<v-divider class="my-3" v-if="index"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ key }}</v-col>
|
||||
<v-col class="text-right">{{ value }}</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="mcuDetailsDialog.mcu.last_stats">
|
||||
<v-row class="mt-5">
|
||||
<v-col><span class="headline">{{ $t('Machine.SystemPanel.LastStats') }}</span></v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="(value, key, index) in mcuDetailsDialog.mcu.last_stats" :key="key">
|
||||
<v-divider class="my-3" v-if="index"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ key }}</v-col>
|
||||
<v-col class="text-right">{{ value }}</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
</perfect-scrollbar>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="hostDetailsDialog.bool" :max-width="600" :max-height="500" scrollable>
|
||||
<v-card dark>
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-text-box-search-outline</v-icon>{{ $t('Machine.SystemPanel.HostDetails') }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<panel :title="$t('Machine.SystemPanel.HostDetails')" icon="mdi-text-box-search-outline" card-class="machine-systemload-host-details-dialog" :margin-bottom="false">
|
||||
<template v-slot:buttons>
|
||||
<v-btn small class="minwidth-0 px-2" color="grey darken-3" @click="hostDetailsDialog.bool = false"><v-icon small>mdi-close-thick</v-icon></v-btn>
|
||||
</v-toolbar>
|
||||
<v-card-text class="pt-5" style="height: 350px;">
|
||||
<template v-if="Object.keys(systemInfo).length">
|
||||
<div v-for="(infoGroup, key, index) of systemInfo" v-bind:key="key">
|
||||
<template v-if="key !== 'available_services'">
|
||||
<v-row :class="index ? 'mt-5' : ''">
|
||||
<v-col><span class="headline">{{ key }}</span></v-col>
|
||||
</v-row>
|
||||
<div v-for="(value, key, index) in infoGroup" :key="key">
|
||||
<v-divider class="my-3" v-if="index"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ key }}</v-col>
|
||||
<v-col class="text-right">{{ value }}</v-col>
|
||||
</template>
|
||||
<v-card-text class="pt-5 px-0">
|
||||
<perfect-scrollbar style="height: 350px;" :options="{ suppressScrollX: true }" class="px-6">
|
||||
<template v-if="Object.keys(systemInfo).length">
|
||||
<div v-for="(infoGroup, key, index) of systemInfo" v-bind:key="key">
|
||||
<template v-if="key !== 'available_services'">
|
||||
<v-row :class="index ? 'mt-5' : ''">
|
||||
<v-col><span class="headline">{{ key }}</span></v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<v-row class="mt-5">
|
||||
<v-col><p>No more Infos</p></v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
<div v-for="(value, key, index) in infoGroup" :key="key">
|
||||
<v-divider class="my-3" v-if="index"></v-divider>
|
||||
<v-row>
|
||||
<v-col>{{ key }}</v-col>
|
||||
<v-col class="text-right">{{ value }}</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<v-row class="mt-5">
|
||||
<v-col><p>No more Infos</p></v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
</perfect-scrollbar>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -180,8 +171,10 @@
|
||||
|
||||
import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '../../mixins/base'
|
||||
|
||||
@Component
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class SystemPanel extends Mixins(BaseMixin) {
|
||||
|
||||
private mcuDetailsDialog: { bool: boolean, headline: string, mcu: any } = {
|
||||
|
@@ -5,23 +5,18 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div v-if="enableUpdateManager">
|
||||
<v-card>
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-update</v-icon>{{ $t('Machine.UpdatePanel.UpdateManager') }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<div>
|
||||
<panel :title="$t('Machine.UpdatePanel.UpdateManager')" v-if="enableUpdateManager" icon="mdi-update" card-class="machine-update-panel" :collapsible="true">
|
||||
<template v-slot:buttons>
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn small class="px-2 minwidth-0" color="primary" :loading="loadings.includes('loadingBtnSyncUpdateManager')" :disabled="['printing', 'paused'].includes(printer_state)" @click="btnSync" v-bind="attrs" v-on="on"><v-icon small>mdi-refresh</v-icon></v-btn>
|
||||
</template>
|
||||
<span>{{ $t('Machine.UpdatePanel.CheckForUpdates') }}</span>
|
||||
</v-tooltip>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
<v-card-text class="px-0 py-0">
|
||||
<v-container py-0 px-0>
|
||||
|
||||
<div v-for="(value, key, index) of updateableSoftwares" v-bind:key="key">
|
||||
<v-divider class="my-0" v-if="index" ></v-divider>
|
||||
<v-row class="py-2">
|
||||
@@ -111,16 +106,12 @@
|
||||
</div>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
<v-dialog v-model="commitsOverlay.bool" persistent max-width="800">
|
||||
<v-card dark>
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-update</v-icon>{{ $t('Machine.UpdatePanel.Commits') }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<panel :title="$t('Machine.UpdatePanel.Commits')" icon="mdi-update" :margin-bottom="false" card-class="machine-update-commits-dialog">
|
||||
<template v-slot:buttons>
|
||||
<v-btn small class="minwidth-0 px-2" color="grey darken-3" @click="commitsOverlay.bool = false"><v-icon small>mdi-close-thick</v-icon></v-btn>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
<v-card-text class="py-0 px-0">
|
||||
<perfect-scrollbar style="max-height: 400px;" :options="{ suppressScrollX: true }">
|
||||
<v-row>
|
||||
@@ -142,7 +133,7 @@
|
||||
</v-row>
|
||||
</perfect-scrollbar>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -153,8 +144,10 @@
|
||||
import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '../../mixins/base'
|
||||
import semver from 'semver'
|
||||
|
||||
@Component
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class UpdatePanel extends Mixins(BaseMixin) {
|
||||
|
||||
private commitsOverlay = {
|
||||
|
@@ -3,12 +3,13 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<v-card class="mb-6" v-if="klipperReadyForGui && macros.length > 0">
|
||||
<v-toolbar flat dense>
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-code-tags</v-icon>{{ $t('Panels.MacrosPanel.Headline') }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel
|
||||
v-if="klipperReadyForGui && macros.length > 0"
|
||||
icon="mdi-code-tags"
|
||||
:title="$t('Panels.MacrosPanel.Headline')"
|
||||
:collapsible="true"
|
||||
card-class="macros-panel"
|
||||
>
|
||||
<v-container>
|
||||
<v-row no-gutters v-if="macros.length">
|
||||
<v-col class="text-center mr-fix-2 mb-fix-2">
|
||||
@@ -22,14 +23,16 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '../mixins/base'
|
||||
|
||||
@Component
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class MacrosPanel extends Mixins(BaseMixin) {
|
||||
|
||||
get macros() {
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<v-card class="mb-6" v-if="klipperState === 'ready' && existsPrinterConfig && missingConfigs.length">
|
||||
<v-toolbar flat dense color="orange darken-2">
|
||||
<v-toolbar-title>
|
||||
<span class="subheading">
|
||||
<v-icon class="mdi mdi-alert-circle" left></v-icon>{{ $t("Panels.MinSettingsPanel.MissingConfiguration") }}
|
||||
</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel
|
||||
v-if="klipperState === 'ready' && existsPrinterConfig && missingConfigs.length"
|
||||
icon="mdi-alert-circle"
|
||||
:title="$t('Panels.MinSettingsPanel.MissingConfiguration')"
|
||||
:collapsible="true"
|
||||
card-class="min-settings-panel"
|
||||
toolbar-color="orange darken-2"
|
||||
>
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col>
|
||||
@@ -32,7 +32,7 @@
|
||||
<v-card-actions class="justify-center pb-3">
|
||||
<v-btn href="https://docs.mainsail.xyz/necessary-configuration" target="_blank" color="white" outlined small><v-icon small class="mr-1">mdi-information</v-icon>{{ $t("Panels.MinSettingsPanel.MoreInformation") }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -40,8 +40,10 @@
|
||||
import Component from 'vue-class-component'
|
||||
import {Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
|
||||
@Component
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class MinSettingsPanel extends Mixins(BaseMixin) {
|
||||
|
||||
get existsPrinterConfig() {
|
||||
|
@@ -6,12 +6,13 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<v-card v-if="socketIsConnected" class="mb-6 d-flex flex-column">
|
||||
<v-toolbar flat dense class="order-0">
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-console-line</v-icon>{{ $t("Panels.MiniconsolePanel.Headline") }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel
|
||||
v-if="socketIsConnected"
|
||||
icon="mdi-console-line"
|
||||
:title="$t('Panels.MiniconsolePanel.Headline')"
|
||||
:collapsible="true"
|
||||
card-class="miniconsole-panel"
|
||||
>
|
||||
<v-card-text :class="consoleDirection === 'table' ? 'order-1' : 'order-2'">
|
||||
<v-row>
|
||||
<v-col>
|
||||
@@ -69,7 +70,7 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -80,9 +81,11 @@ import {CommandHelp, VTextareaType} from '@/store/printer/types'
|
||||
import ConsoleTable from '@/components/console/ConsoleTable.vue'
|
||||
import CommandHelpModal from '@/components/CommandHelpModal.vue'
|
||||
import Vue from 'vue'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
Panel,
|
||||
ConsoleTable,
|
||||
CommandHelpModal
|
||||
}
|
||||
|
@@ -3,12 +3,13 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<v-card class="mb-6" v-if="klipperReadyForGui && (miscellaneous.length || filamentSensors.length)">
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-dip-switch</v-icon>{{ $t("Panels.MiscellaneousPanel.Headline") }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel
|
||||
v-if="klipperReadyForGui && (miscellaneous.length || filamentSensors.length)"
|
||||
icon="mdi-dip-switch"
|
||||
:title="$t('Panels.MiscellaneousPanel.Headline')"
|
||||
:collapsible="true"
|
||||
card-class="miscellaneous-panel"
|
||||
>
|
||||
<div v-for="(object, index) of miscellaneous" v-bind:key="index">
|
||||
<v-divider v-if="index"></v-divider>
|
||||
<miscellaneous-slider
|
||||
@@ -31,7 +32,7 @@
|
||||
:filament_detected="sensor.filament_detected"
|
||||
></filament-sensor>
|
||||
</div>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -40,8 +41,9 @@ import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
import MiscellaneousSlider from '@/components/inputs/MiscellaneousSlider.vue'
|
||||
import FilamentSensor from '@/components/inputs/FilamentSensor.vue'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {FilamentSensor, MiscellaneousSlider}
|
||||
components: {Panel, FilamentSensor, MiscellaneousSlider}
|
||||
})
|
||||
export default class MiscellaneousPanel extends Mixins(BaseMixin) {
|
||||
get miscellaneous() {
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<v-card class="mb-6" v-if="failedComponents.length || warnings.length">
|
||||
<v-toolbar flat dense color="orange darken-2">
|
||||
<v-toolbar-title>
|
||||
<span class="subheading">
|
||||
<v-icon class="mdi mdi-alert-circle" left></v-icon>{{ $t("Panels.MoonrakerStatePanel.MoonrakerWarnings") }}
|
||||
</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel
|
||||
v-if="failedComponents.length || warnings.length"
|
||||
icon="mdi-alert-circle"
|
||||
:title="$t('Panels.MoonrakerStatePanel.MoonrakerWarnings')"
|
||||
:collapsible="true"
|
||||
card-class="moonraker-state-panel"
|
||||
toolbar-color="orange darken-2"
|
||||
>
|
||||
<v-card-text v-if="failedComponents.length">
|
||||
<v-row>
|
||||
<v-col>
|
||||
@@ -27,15 +27,17 @@
|
||||
<v-card-actions class="px-4 pt-2 pb-4 text-center text-lg-left">
|
||||
<v-btn small :href="apiUrl+'/server/files/moonraker.log'" target="_blank" color="primary" class=""><v-icon class="mr-2" small>mdi-download</v-icon>{{ $t("Panels.MoonrakerStatePanel.DownloadLog") }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Component from 'vue-class-component'
|
||||
import BaseMixin from '../mixins/base'
|
||||
import {Mixins} from 'vue-property-decorator'
|
||||
|
||||
@Component
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class MoonrakerStatePanel extends Mixins(BaseMixin) {
|
||||
|
||||
get failedComponents() {
|
||||
|
@@ -3,18 +3,19 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<v-card class="mb-6" v-if="klipperReadyForGui && ['printing', 'paused'].includes(printer_state)">
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon class="mdi mdi-printer-3d" left></v-icon>{{ $t("Panels.PrintsettingsPanel.Headline") }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel
|
||||
v-if="klipperReadyForGui && ['printing', 'paused'].includes(printer_state)"
|
||||
icon="mdi-printer-3d"
|
||||
:title="$t('Panels.PrintsettingsPanel.Headline')"
|
||||
:collapsible="true"
|
||||
card-class="printsettings-panel"
|
||||
>
|
||||
<tool-slider :label="$t('Panels.PrintsettingsPanel.SpeedFactor')" :target="speed_factor" :max="200" :multi="100" :step="5" :dynamic-range="true" command="M220" attribute-name="S" ></tool-slider>
|
||||
<template v-if="existsExtruder">
|
||||
<v-divider></v-divider>
|
||||
<tool-slider :label="$t('Panels.PrintsettingsPanel.ExtrusionFactor')" :target="extrude_factor" :max="200" :multi="100" :step="1" command="M221" attribute-name="S" ></tool-slider>
|
||||
</template>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -22,8 +23,9 @@
|
||||
import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
import ToolSlider from '@/components/inputs/ToolSlider.vue'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {ToolSlider}
|
||||
components: {Panel, ToolSlider}
|
||||
})
|
||||
export default class PrintsettingsPanel extends Mixins(BaseMixin) {
|
||||
|
||||
|
@@ -10,49 +10,43 @@
|
||||
<moonraker-state-panel></moonraker-state-panel>
|
||||
<klippy-state-panel></klippy-state-panel>
|
||||
<klipper-warnings-panel></klipper-warnings-panel>
|
||||
<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>
|
||||
<panel
|
||||
v-if="klipperState === 'ready'"
|
||||
icon="mdi-information"
|
||||
:title="printerStateOutput"
|
||||
:collapsible="true"
|
||||
card-class="status-panel"
|
||||
>
|
||||
<template v-slot:icon>
|
||||
<v-progress-circular
|
||||
:rotate="-90"
|
||||
:size="30"
|
||||
:width="5"
|
||||
:value="printPercent"
|
||||
color="primary"
|
||||
class="mr-3"
|
||||
v-if="['paused', 'printing'].includes(printer_state)"
|
||||
>
|
||||
</v-progress-circular>
|
||||
</template>
|
||||
<template v-slot:buttons >
|
||||
<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-card-text class="px-0 py-0 content">
|
||||
<template v-if="boolBigThumbnail">
|
||||
<v-img
|
||||
@@ -270,7 +264,7 @@
|
||||
</v-container>
|
||||
</template>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -283,9 +277,11 @@ import MoonrakerStatePanel from '@/components/panels/MoonrakerStatePanel.vue'
|
||||
import KlippyStatePanel from '@/components/panels/KlippyStatePanel.vue'
|
||||
import KlipperWarningsPanel from '@/components/panels/KlipperWarningsPanel.vue'
|
||||
import StatusPanelExcludeObject from '@/components/panels/StatusPanelExcludeObject.vue'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
Panel,
|
||||
StatusPanelExcludeObject, KlipperWarningsPanel, KlippyStatePanel, MoonrakerStatePanel, MinSettingsPanel}
|
||||
})
|
||||
export default class StatusPanel extends Mixins(BaseMixin) {
|
||||
|
@@ -23,12 +23,14 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<v-card v-if="klipperReadyForGui" class="mb-6">
|
||||
<v-toolbar flat dense>
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-thermometer-lines</v-icon>{{ $t("Panels.ToolsPanel.Headline") }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<panel
|
||||
v-if="klipperReadyForGui"
|
||||
icon="mdi-thermometer-lines"
|
||||
:title="$t('Panels.ToolsPanel.Headline')"
|
||||
:collapsible="true"
|
||||
card-class="tools-panel"
|
||||
>
|
||||
<template v-slot:buttons>
|
||||
<v-menu :offset-y="true" title="Preheat" v-if="presets.length">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn small class="px-2 minwidth-0" color="primary" v-bind="attrs" v-on="on" :disabled="['printing', 'paused'].includes(printer_state)">{{ $t("Panels.ToolsPanel.Presets") }} <v-icon small>mdi-menu-down</v-icon></v-btn>
|
||||
@@ -69,7 +71,7 @@
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
<v-card-text class="pa-0 content">
|
||||
<v-container class="px-0">
|
||||
<v-row align="center">
|
||||
@@ -243,7 +245,7 @@
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -257,9 +259,10 @@ import TempChart from '@/components/charts/TempChart.vue'
|
||||
import {datasetTypes} from '@/store/variables'
|
||||
import {PrinterStateHeater, PrinterStateSensor, PrinterStateTemperatureFan} from '@/store/printer/types'
|
||||
import {Debounce} from 'vue-debounce-decorator'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
|
||||
@Component({
|
||||
components: {TempChart, ToolInput}
|
||||
components: {Panel, TempChart, ToolInput}
|
||||
})
|
||||
export default class ToolsPanel extends Mixins(BaseMixin) {
|
||||
convertName = convertName
|
||||
|
@@ -3,15 +3,15 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<v-card class="mb-6" v-if="socketIsConnected">
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading">
|
||||
<v-icon left>mdi-webcam</v-icon> {{ $t('Panels.WebcamPanel.Headline')}}
|
||||
</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-item-group v-if="this.webcams.length > 1">
|
||||
<panel
|
||||
v-if="socketIsConnected"
|
||||
icon="mdi-webcam"
|
||||
:title="$t('Panels.WebcamPanel.Headline')"
|
||||
:collapsible="true"
|
||||
card-class="webcam-panel"
|
||||
>
|
||||
<template v-slot:buttons>
|
||||
<v-item-group v-if="webcams.length > 1">
|
||||
<v-menu :offset-y="true" title="Webcam">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn small class="px-2 minwidth-0" color="primary" v-bind="attrs" v-on="on">
|
||||
@@ -29,7 +29,7 @@
|
||||
<v-list-item-title>{{ $t('Panels.WebcamPanel.All') }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item v-for="webcam of this.webcams" v-bind:key="webcam.name" link @click="currentCamName = webcam.name">
|
||||
<v-list-item v-for="webcam of webcams" v-bind:key="webcam.name" link @click="currentCamName = webcam.name">
|
||||
<v-list-item-icon class="mr-0">
|
||||
<v-icon small>{{ webcam.icon }}</v-icon>
|
||||
</v-list-item-icon>
|
||||
@@ -40,7 +40,7 @@
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-item-group>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
<v-card-text class="px-0 py-0 content d-inline-block">
|
||||
<v-row>
|
||||
<v-col class="pb-0" style="position: relative;">
|
||||
@@ -65,7 +65,7 @@
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -78,9 +78,11 @@ import Component from 'vue-class-component'
|
||||
import {Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '../mixins/base'
|
||||
import {GuiStateWebcam} from '@/store/gui/types'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
Panel,
|
||||
'webcam-mjpegstreamer': Mjpegstreamer,
|
||||
'webcam-mjpegstreamer-adaptive': MjpegstreamerAdaptive,
|
||||
'webcam-ipstreamer': Ipstreamer,
|
||||
|
@@ -4,12 +4,14 @@
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<v-card v-if="displayPanel" class="mb-6">
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon class="mdi mdi-arrow-collapse-vertical" left></v-icon>{{ $t("Panels.ZoffsetPanel.Headline") }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<panel
|
||||
v-if="displayPanel"
|
||||
icon="mdi-arrow-collapse-vertical"
|
||||
:title="$t('Panels.ZoffsetPanel.Headline')"
|
||||
:collapsible="true"
|
||||
card-class="zoffset-panel"
|
||||
>
|
||||
<template v-slot:buttons>
|
||||
<template v-if="z_gcode_offset !== 0">
|
||||
<v-btn small class="px-2 minwidth-0" color="grey darken-3" @click="clearZOffset()" :loading="loadings.includes('babySteppingClear')"><v-icon small>mdi-broom</v-icon></v-btn>
|
||||
<v-menu offset-y left v-if="existZOffsetApplyProbe && existZOffsetApplyEndstop">
|
||||
@@ -38,8 +40,7 @@
|
||||
<v-btn small class="px-2 minwidth-0" color="primary ml-3" v-else-if="existZOffsetApplyProbe && !existZOffsetApplyEndstop" @click="saveZOffsetToProbe"><v-icon small class="mr-1">mdi-content-save</v-icon>{{ $t("Panels.ZoffsetPanel.Save") }}</v-btn>
|
||||
<v-btn small class="px-2 minwidth-0" color="primary ml-3" v-else-if="!existZOffsetApplyProbe && existZOffsetApplyEndstop" @click="saveZOffsetToEndstop"><v-icon small class="mr-1">mdi-content-save</v-icon>{{ $t("Panels.ZoffsetPanel.Save") }}</v-btn>
|
||||
</template>
|
||||
</v-toolbar>
|
||||
|
||||
</template>
|
||||
<v-card-text class="px-0 py-0">
|
||||
<v-container>
|
||||
<v-row class="py-0">
|
||||
@@ -61,14 +62,9 @@
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
<v-dialog v-model="saveOffsetDialog" max-width="290">
|
||||
<v-card>
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon class="mdi mdi-information" left></v-icon>{{ $t("Panels.ZoffsetPanel.SaveInfoHeadline") }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel :title="$t('Panels.ZoffsetPanel.SaveInfoHeadline')" icon="mdi-information" card-class="zoffset-saveinfo-dialog" :margin-bottom="false">
|
||||
<v-card-text class="mt-3" v-if="printerIsPrinting">{{ $t("Panels.ZoffsetPanel.SaveInfoDescriptionPrint") }}</v-card-text>
|
||||
<v-card-text class="mt-3" v-else>{{ $t("Panels.ZoffsetPanel.SaveInfoDescription") }}</v-card-text>
|
||||
<v-card-actions v-if="printerIsPrinting">
|
||||
@@ -80,7 +76,7 @@
|
||||
<v-btn color="primary" text @click="saveConfig">{{ $t("Panels.ZoffsetPanel.SAVE_CONFIG") }}</v-btn>
|
||||
<v-btn text @click="saveOffsetDialog = false">{{ $t("Panels.ZoffsetPanel.Later") }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -90,8 +86,10 @@
|
||||
import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '../mixins/base'
|
||||
import {CommandHelp} from '@/store/printer/types'
|
||||
|
||||
@Component
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class ZoffsetPanel extends Mixins(BaseMixin) {
|
||||
private saveOffsetDialog = false
|
||||
|
||||
|
71
src/components/ui/Panel.vue
Normal file
71
src/components/ui/Panel.vue
Normal file
@@ -0,0 +1,71 @@
|
||||
<style lang="scss" scoped>
|
||||
.expanded header.v-toolbar{
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.expand-button:focus:after {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
.icon-rotate-180 {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<v-card :class="cardClass+' '+(marginBottom ? 'mb-6' : '')+' '+(!expand ? 'expanded' : '')" :loading="loading">
|
||||
<v-toolbar flat dense :color="toolbarColor" :class="toolbarClass" >
|
||||
<slot name="buttons-left"></slot>
|
||||
<v-toolbar-title class="d-flex align-center">
|
||||
<slot name="icon" v-if="hasIconSlot"></slot>
|
||||
<v-icon left v-if="icon !== null && !hasIconSlot">{{ icon }}</v-icon>
|
||||
<span class="subheading" v-if="title">{{ title }}</span>
|
||||
</v-toolbar-title>
|
||||
<slot name="buttons-title"></slot>
|
||||
<v-spacer></v-spacer>
|
||||
<slot name="buttons"></slot>
|
||||
<v-icon
|
||||
v-if="collapsible"
|
||||
@click="expand = !expand"
|
||||
:class="'ml-3 expand-button '+(!expand ? 'icon-rotate-180' : '')"
|
||||
>mdi-chevron-down</v-icon>
|
||||
</v-toolbar>
|
||||
<v-expand-transition>
|
||||
<div v-show="expand || !collapsible">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</v-expand-transition>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import Component from 'vue-class-component'
|
||||
import {Mixins, Prop} from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
|
||||
@Component
|
||||
export default class Panel extends Mixins(BaseMixin) {
|
||||
@Prop({ default: null }) readonly icon!: string | null
|
||||
@Prop({ required: true, default: '' }) readonly title!: string
|
||||
@Prop({ default: false }) readonly collapsible!: boolean
|
||||
@Prop({ required: true }) readonly cardClass!: string
|
||||
@Prop({ default: '' }) readonly toolbarColor!: string
|
||||
@Prop({ default: '' }) readonly toolbarClass!: string
|
||||
@Prop({ default: false }) readonly loading!: boolean
|
||||
@Prop({ default: true }) readonly marginBottom!: boolean
|
||||
|
||||
get expand() {
|
||||
return this.$store.getters['gui/getPanelExpand'](this.cardClass)
|
||||
}
|
||||
|
||||
set expand(newVal) {
|
||||
this.$store.dispatch('gui/saveExpandPanel', { name: this.cardClass, value: newVal })
|
||||
}
|
||||
|
||||
get hasIconSlot() {
|
||||
return !! this.$slots.icon
|
||||
}
|
||||
}
|
||||
</script>
|
@@ -178,6 +178,7 @@
|
||||
"Name": "Name",
|
||||
"Abort": "abort",
|
||||
"Rename": "rename",
|
||||
"BedMeshRemove": "Bed Mesh Remove",
|
||||
"BedMeshCalibrate": "Bed Mesh Calibrate",
|
||||
"DoYouReallyWantToCalibrate": "Do you really want to start the bed calibration?",
|
||||
"DeleteBedMeshProfile": "Delete Bed Mesh Profile",
|
||||
|
@@ -45,12 +45,7 @@
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<v-card class="fileupload-card mb-3" @dragover="dragOverUpload" @dragleave="dragLeaveUpload" @drop.prevent.stop="dragDropUpload">
|
||||
<v-toolbar flat dense>
|
||||
<v-toolbar-title>
|
||||
<span class="subheading align-baseline"><v-icon left>mdi-file-document-multiple-outline</v-icon>{{ $t("Files.GCodeFiles")}}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel :title="$t('Files.GCodeFiles')" icon="mdi-file-document-multiple-outline" card-class="gcode-files-panel fileupload-card" @dragover="dragOverUpload" @dragleave="dragLeaveUpload" @drop.prevent.stop="dragDropUpload">
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col class="col-12 d-flex align-center">
|
||||
@@ -218,7 +213,7 @@
|
||||
<div class="dragzone" :style="'visibility: '+dropzone.visibility+'; opacity: '+dropzone.hidden">
|
||||
<div class="textnode">{{ $t('Files.DropFilesToAddGcode')}}</div>
|
||||
</div>
|
||||
</v-card>
|
||||
</panel>
|
||||
<v-snackbar
|
||||
:timeout="-1"
|
||||
:value="true"
|
||||
@@ -300,9 +295,8 @@
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<v-dialog v-model="dialogCreateDirectory.show" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title class="headline">{{ $t('Files.NewDirectory') }}</v-card-title>
|
||||
<v-dialog v-model="dialogCreateDirectory.show" :max-width="400">
|
||||
<panel :title="$t('Files.NewDirectory')" card-class="gcode-files-new-directory-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
{{ $t('Files.PleaseEnterANewDirectoryName') }}
|
||||
<v-text-field label="Name" :rules="input_rules" @keypress.enter="createDirectoryAction" required v-model="dialogCreateDirectory.name" ref="inputFieldCreateDirectory"></v-text-field>
|
||||
@@ -312,11 +306,10 @@
|
||||
<v-btn color="" text @click="dialogCreateDirectory.show = false">{{ $t('Files.Cancel') }}</v-btn>
|
||||
<v-btn color="primary" text @click="createDirectoryAction">{{ $t('Files.Create') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="dialogRenameFile.show" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title class="headline">{{ $t('Files.RenameFile')}}</v-card-title>
|
||||
<v-dialog v-model="dialogRenameFile.show" :max-width="400">
|
||||
<panel :title="$t('Files.RenameFile')" card-class="gcode-files-rename-file-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<v-text-field :label="$t('Files.Name')" required v-model="dialogRenameFile.newName" ref="inputFieldRenameFile"></v-text-field>
|
||||
</v-card-text>
|
||||
@@ -325,11 +318,10 @@
|
||||
<v-btn color="" text @click="dialogRenameFile.show = false">{{ $t('Files.Cancel') }}</v-btn>
|
||||
<v-btn color="primary" text @click="renameFileAction">{{ $t('Files.Rename') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="dialogRenameDirectory.show" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title class="headline">{{ $t('Files.RenameDirectory') }}</v-card-title>
|
||||
<panel :title="$t('Files.RenameDirectory')" card-class="gcode-files-rename-directory-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<v-text-field label="Name" required v-model="dialogRenameDirectory.newName" ref="inputFieldRenameDirectory"></v-text-field>
|
||||
</v-card-text>
|
||||
@@ -338,11 +330,10 @@
|
||||
<v-btn color="" text @click="dialogRenameDirectory.show = false">{{ $t('Files.Cancel') }}</v-btn>
|
||||
<v-btn color="primary" text @click="renameDirectoryAction">{{ $t('Files.Rename') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="dialogDeleteDirectory.show" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title class="headline">{{ $t('Files.DeleteDirectory') }}</v-card-title>
|
||||
<panel :title="$t('Files.DeleteDirectory')" card-class="gcode-files-delete-directory-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<p class="mb-0">{{ $t('Files.DeleteDirectoryQuestion', { name: dialogDeleteDirectory.item.filename } )}}</p>
|
||||
</v-card-text>
|
||||
@@ -351,7 +342,7 @@
|
||||
<v-btn color="" text @click="dialogDeleteDirectory.show = false">{{ $t('Files.Cancel') }}</v-btn>
|
||||
<v-btn color="error" text @click="deleteDirectoryAction">{{ $t('Files.Delete') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -362,6 +353,7 @@ import axios from 'axios'
|
||||
import { validGcodeExtensions } from '@/store/variables'
|
||||
import {findDirectory, formatFilesize, formatDate, sortFiles} from '@/plugins/helpers'
|
||||
import {FileStateFile} from '@/store/files/types'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
|
||||
interface draggingFile {
|
||||
status: boolean
|
||||
@@ -394,7 +386,9 @@ interface dialogRenameObject {
|
||||
item: FileStateFile
|
||||
}
|
||||
|
||||
@Component
|
||||
@Component({
|
||||
components: {Panel}
|
||||
})
|
||||
export default class PageFiles extends Mixins(BaseMixin) {
|
||||
validGcodeExtensions = validGcodeExtensions
|
||||
formatDate = formatDate
|
||||
|
@@ -6,32 +6,16 @@
|
||||
<div>
|
||||
<v-row v-if="klipperReadyForGui">
|
||||
<v-col class="col-12 col-md-8">
|
||||
<v-card>
|
||||
<v-toolbar flat dense>
|
||||
<v-toolbar-title>
|
||||
<span class="subheading">
|
||||
<v-icon left>mdi-grid</v-icon>
|
||||
{{ $t('Heightmap.Heightmap') }}
|
||||
</span>
|
||||
<v-btn
|
||||
text
|
||||
color="primary"
|
||||
class="ml-1 d-none d-sm-inline-flex"
|
||||
v-if="bed_mesh"
|
||||
@click="openRenameProfile()">{{ bed_mesh ? bed_mesh.profile_name : "" }}</v-btn>
|
||||
</v-toolbar-title>
|
||||
<v-spacer class=""></v-spacer>
|
||||
<v-btn
|
||||
text
|
||||
color="primary"
|
||||
class=" d-sm-none"
|
||||
@click="openRenameProfile()">{{ bed_mesh ? bed_mesh.profile_name : "" }}</v-btn>
|
||||
<v-item-group class="v-btn-toggle d-none d-sm-flex" name="controllers">
|
||||
<v-btn small class="px-2 minwidth-0" color="primary" @click="homePrinter" :loading="loadings.includes('homeAll')" :title="$t('Heightmap.TitleHomeAll')"><v-icon small>mdi-home</v-icon></v-btn>
|
||||
<v-btn small class="px-2 minwidth-0" color="primary" @click="clearBedMesh" :loading="loadings.includes('bedMeshClear')" v-if="bed_mesh" :title="$t('Heightmap.TitleClear')">{{ $t('Heightmap.Clear') }}</v-btn>
|
||||
<v-btn small class="px-2 minwidth-0" color="primary" @click="calibrateDialog = true" :loading="loadings.includes('bedMeshCalibrate')" :disabled="printerIsPrinting" :title="$t('Heightmap.TitleCalibrate')">{{ $t('Heightmap.Calibrate') }}</v-btn>
|
||||
</v-item-group>
|
||||
</v-toolbar>
|
||||
<panel card-class="heightmap-map-panel" :title="$t('Heightmap.Heightmap')" icon="mdi-grid">
|
||||
<template v-slot:buttons-title>
|
||||
<v-btn text color="primary" class="ml-1 d-none d-sm-inline-flex" v-if="bed_mesh" @click="openRenameProfile()">{{ bed_mesh ? bed_mesh.profile_name : "" }}</v-btn>
|
||||
</template>
|
||||
<template v-slot:buttons>
|
||||
<v-btn text color="primary" class=" d-sm-none" @click="openRenameProfile()">{{ bed_mesh ? bed_mesh.profile_name : "" }}</v-btn>
|
||||
<v-btn small class="px-2 minwidth-0 ml-3" color="primary" @click="homePrinter" :loading="loadings.includes('homeAll')" :title="$t('Heightmap.TitleHomeAll')"><v-icon small>mdi-home</v-icon></v-btn>
|
||||
<v-btn small class="px-2 minwidth-0 ml-3" color="primary" @click="clearBedMesh" :loading="loadings.includes('bedMeshClear')" v-if="bed_mesh" :title="$t('Heightmap.TitleClear')">{{ $t('Heightmap.Clear') }}</v-btn>
|
||||
<v-btn small class="px-2 minwidth-0 ml-3" color="primary" @click="calibrateDialog = true" :loading="loadings.includes('bedMeshCalibrate')" :disabled="printerIsPrinting" :title="$t('Heightmap.TitleCalibrate')">{{ $t('Heightmap.Calibrate') }}</v-btn>
|
||||
</template>
|
||||
<v-card-text class="d-sm-none text-center pb-0">
|
||||
<v-item-group class="v-btn-toggle" name="controllers">
|
||||
<v-btn small class="px-2 minwidth-0" color="primary" @click="homePrinter" :loading="loadings.includes('homeAll')" :title="$t('Heightmap.TitleHomeAll')"><v-icon small>mdi-home</v-icon></v-btn>
|
||||
@@ -79,15 +63,10 @@
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</template>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-col>
|
||||
<v-col class="col-12 col-md-4">
|
||||
<v-card>
|
||||
<v-toolbar flat dense>
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-stack-overflow</v-icon>{{ $t('Heightmap.Profiles') }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<panel :title="$t('Heightmap.Profiles')" card-class="heightmap-profiles-panel" icon="mdi-stack-overflow">
|
||||
<v-card-text class="py-0 px-0" v-if="profiles.length">
|
||||
<v-simple-table>
|
||||
<template v-slot:default>
|
||||
@@ -116,7 +95,7 @@
|
||||
<v-card-text v-else>
|
||||
<p>{{ $t('Heightmap.NoProfile') }}</p>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row v-else>
|
||||
@@ -130,11 +109,8 @@
|
||||
icon="mdi-lock-outline"
|
||||
>{{ $t('Heightmap.ErrorKlipperNotReady') }}</v-alert>
|
||||
</v-row>
|
||||
<v-dialog v-model="renameDialog" persistent max-width="600px">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<span class="headline">{{ $t('Heightmap.RenameBedMeshProfile') }}</span>
|
||||
</v-card-title>
|
||||
<v-dialog v-model="renameDialog" persistent :max-width="400">
|
||||
<panel :title="$t('Heightmap.RenameBedMeshProfile')" icon="mdi-grid" card-class="heightmap-rename-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
@@ -147,47 +123,31 @@
|
||||
<v-btn text @click="renameDialog = false">{{ $t('Heightmap.Abort') }}</v-btn>
|
||||
<v-btn color="primary" text @click="renameProfile">{{ $t('Heightmap.Rename') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="calibrateDialog" persistent max-width="600px">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<span class="headline">{{ $t('Heightmap.BedMeshCalibrate') }}</span>
|
||||
</v-card-title>
|
||||
<v-dialog v-model="calibrateDialog" persistent :max-width="400">
|
||||
<panel :title="$t('Heightmap.BedMeshCalibrate')" icon="mdi-grid" card-class="heightmap-calibrate-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<p>{{ $t('Heightmap.DoYouReallyWantToCalibrate') }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<p>{{ $t('Heightmap.DoYouReallyWantToCalibrate') }}</p>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn text @click="calibrateDialog = false">{{ $t('Heightmap.Abort') }}</v-btn>
|
||||
<v-btn color="primary" text @click="calibrateMesh">{{ $t('Heightmap.Calibrate') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="removeDialog" persistent max-width="600px">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<span class="headline"></span>
|
||||
</v-card-title>
|
||||
<v-dialog v-model="removeDialog" persistent :max-width="400">
|
||||
<panel :title="$t('Heightmap.BedMeshRemove')" icon="mdi-grid" card-class="heightmap-calibrate-dialog" :margin-bottom="false">
|
||||
<v-card-text>
|
||||
<v-container>
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<p>{{ $t('Heightmap.DoYouReallyWantToDelete', { name: removeDialogProfile }) }}</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
<p>{{ $t('Heightmap.DoYouReallyWantToDelete', { name: removeDialogProfile }) }}</p>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn text @click="removeDialog = false">{{ $t('Heightmap.Abort') }}</v-btn>
|
||||
<v-btn color="error" text @click="removeProfile">{{ $t('Heightmap.Remove') }}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</panel>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -199,6 +159,7 @@ import { createComponent } from 'echarts-for-vue'
|
||||
import * as echarts from 'echarts'
|
||||
import {ECharts} from 'echarts/core'
|
||||
import 'echarts-gl'
|
||||
import Panel from '@/components/ui/Panel.vue'
|
||||
|
||||
interface HeightmapSerie {
|
||||
type: string
|
||||
@@ -216,6 +177,7 @@ interface HeightmapSerie {
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
Panel,
|
||||
ECharts: createComponent({ echarts }),
|
||||
}
|
||||
})
|
||||
|
@@ -6,63 +6,10 @@
|
||||
<div>
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-card>
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-chart-areaspline</v-icon>{{ $t('History.Statistics') }}</span>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<v-card-text class="pa-0">
|
||||
<v-row align="center">
|
||||
<v-col class="col-12 col-sm-6 col-md-4">
|
||||
<v-simple-table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ $t('History.TotalPrinttime') }}</td>
|
||||
<td class="text-right">{{ formatPrintTime(totalPrintTime) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('History.LongestPrinttime') }}</td>
|
||||
<td class="text-right">{{ formatPrintTime(longestPrintTime) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('History.AvgPrinttime') }}</td>
|
||||
<td class="text-right">{{ formatPrintTime(avgPrintTime) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('History.TotalFilamentUsed') }}</td>
|
||||
<td class="text-right">{{ Math.round(totalFilamentUsed / 100) / 10 }} m</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('History.TotalJobs') }}</td>
|
||||
<td class="text-right">{{ totalJobsCount }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-simple-table>
|
||||
</v-col>
|
||||
<v-col class="col-12 col-sm-6 col-md-4">
|
||||
<history-all-print-status></history-all-print-status>
|
||||
</v-col>
|
||||
<v-col class="col-12 col-sm-12 col-md-4">
|
||||
<history-filament-usage v-if="toggleChart === 'filament_usage'"></history-filament-usage>
|
||||
<history-printtime-avg v-if="toggleChart === 'printtime_avg'"></history-printtime-avg>
|
||||
<div class="text-center mt-3">
|
||||
<v-btn-toggle v-model="toggleChart" small mandatory>
|
||||
<v-btn small value="filament_usage">
|
||||
{{ $t('History.FilamentUsage') }}
|
||||
</v-btn>
|
||||
<v-btn small value="printtime_avg">
|
||||
{{ $t('History.PrinttimeAvg') }}
|
||||
</v-btn>
|
||||
</v-btn-toggle>
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<history-statistics-panel></history-statistics-panel>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row class="mt-6">
|
||||
<v-row class="mt-0">
|
||||
<v-col>
|
||||
<history-list-panel></history-list-panel>
|
||||
</v-col>
|
||||
@@ -74,63 +21,15 @@
|
||||
|
||||
import {Component, Mixins} from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
import HistoryAllPrintStatus from '@/components/charts/HistoryAllPrintStatus.vue'
|
||||
import HistoryPrinttimeAvg from '@/components/charts/HistoryPrinttimeAvg.vue'
|
||||
import HistoryFilamentUsage from '@/components/charts/HistoryFilamentUsage.vue'
|
||||
import HistoryListPanel from '@/components/panels/HistoryListPanel.vue'
|
||||
import HistoryStatisticsPanel from '@/components/panels/HistoryStatisticsPanel.vue'
|
||||
@Component({
|
||||
components: {HistoryListPanel, HistoryFilamentUsage, HistoryPrinttimeAvg, HistoryAllPrintStatus}
|
||||
components: {
|
||||
HistoryStatisticsPanel,
|
||||
HistoryListPanel
|
||||
}
|
||||
})
|
||||
export default class PageHistory extends Mixins(BaseMixin) {
|
||||
|
||||
get totalPrintTime() {
|
||||
return 'total_print_time' in this.$store.state.server.history.job_totals ? this.$store.state.server.history.job_totals.total_print_time : 0
|
||||
}
|
||||
|
||||
get longestPrintTime() {
|
||||
return 'longest_print' in this.$store.state.server.history.job_totals ? this.$store.state.server.history.job_totals.longest_print : 0
|
||||
}
|
||||
|
||||
get avgPrintTime() {
|
||||
if (this.totalJobsCount > 0 && this.totalPrintTime > 0) return Math.round(this.totalPrintTime / this.totalJobsCount)
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
get totalFilamentUsed() {
|
||||
return 'total_filament_used' in this.$store.state.server.history.job_totals ? this.$store.state.server.history.job_totals.total_filament_used : 0
|
||||
}
|
||||
|
||||
get totalJobsCount() {
|
||||
return 'total_jobs' in this.$store.state.server.history.job_totals ? this.$store.state.server.history.job_totals.total_jobs : 0
|
||||
}
|
||||
|
||||
get toggleChart () {
|
||||
return this.$store.state.gui.history.toggleChartCol3
|
||||
}
|
||||
|
||||
set toggleChart(newVal) {
|
||||
this.$store.dispatch('gui/saveSetting', { name: 'history.toggleChartCol3', value: newVal })
|
||||
}
|
||||
|
||||
formatPrintTime(totalSeconds: number) {
|
||||
if (totalSeconds) {
|
||||
let output = ''
|
||||
|
||||
const hours = Math.floor(totalSeconds / 3600)
|
||||
totalSeconds %= 3600
|
||||
if (hours) output += ' '+hours+'h'
|
||||
|
||||
const minutes = Math.floor(totalSeconds / 60)
|
||||
if (minutes) output += ' '+minutes+'m'
|
||||
|
||||
const seconds = totalSeconds % 60
|
||||
if (seconds) output += ' '+seconds.toFixed(0)+'s'
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -191,6 +191,16 @@ export const actions: ActionTree<GuiState, RootState> = {
|
||||
}
|
||||
},
|
||||
|
||||
saveExpandPanel({ commit, dispatch, state }, payload) {
|
||||
if (!payload.value) commit('addClosePanel', { name: payload.name })
|
||||
else commit('removeClosePanel', { name: payload.name })
|
||||
|
||||
dispatch('updateSettings', {
|
||||
keyName: 'dashboard.nonExpandPanels',
|
||||
newVal: state.dashboard.nonExpandPanels
|
||||
})
|
||||
},
|
||||
|
||||
showStatusInHistoryList({ commit, dispatch, state }, name) {
|
||||
const array: string[] = [...state.history.hidePrintStatus]
|
||||
|
||||
|
@@ -102,5 +102,9 @@ export const getters: GetterTree<GuiState, any> = {
|
||||
|
||||
return 0
|
||||
})
|
||||
},
|
||||
|
||||
getPanelExpand: (state) => (name: string) => {
|
||||
return !state.dashboard.nonExpandPanels?.includes(name) ?? true
|
||||
}
|
||||
}
|
||||
|
@@ -89,7 +89,8 @@ export const getDefaultState = (): GuiState => {
|
||||
widescreenLayout3: [
|
||||
{ 'name': 'webcam', visable: true },
|
||||
{ 'name': 'miniconsole', visable: true },
|
||||
]
|
||||
],
|
||||
nonExpandPanels: []
|
||||
},
|
||||
webcam: {
|
||||
selectedCam: '',
|
||||
|
@@ -152,5 +152,15 @@ export const mutations: MutationTree<GuiState> = {
|
||||
|
||||
setHistoryHidePrintStatus(state, payload) {
|
||||
Vue.set(state.history, 'hidePrintStatus', payload)
|
||||
},
|
||||
|
||||
addClosePanel(state, payload) {
|
||||
const exist = state.dashboard.nonExpandPanels?.includes(payload.name) ?? false
|
||||
if (!exist) state.dashboard.nonExpandPanels.push(payload.name)
|
||||
},
|
||||
|
||||
removeClosePanel(state, payload) {
|
||||
const index = state.dashboard.nonExpandPanels.indexOf(payload.name)
|
||||
if (index > -1) state.dashboard.nonExpandPanels.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
@@ -62,7 +62,8 @@ export const actions: ActionTree<ServerState, RootState> = {
|
||||
},
|
||||
|
||||
initProcStats({ commit }, payload) {
|
||||
commit('setThrottledState', payload.throttled_state)
|
||||
if (payload.throttled_state !== null)
|
||||
commit('setThrottledState', payload.throttled_state)
|
||||
},
|
||||
|
||||
setKlippyReady({ dispatch }) {
|
||||
|
Reference in New Issue
Block a user