From 4224553710d4131844d63c12356391dbd33fa9fa Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Tue, 16 Mar 2021 00:10:52 +0100 Subject: [PATCH 01/32] first implementation of print history Signed-off-by: Stefan Dej --- .../charts/HistoryAllPrintStatus.vue | 87 +++++ .../charts/HistoryFilamentUsage.vue | 160 ++++++++ src/components/charts/HistoryPrinttimeAvg.vue | 136 +++++++ src/components/panels/HistoryListPanel.vue | 348 ++++++++++++++++++ src/components/panels/index.js | 2 + src/pages/History.vue | 156 ++++++++ src/plugins/vuetify.js | 31 +- src/routes/index.js | 8 + src/store/files/mutations.js | 1 + src/store/gui/actions.js | 10 +- src/store/gui/index.js | 5 + src/store/gui/mutations.js | 10 +- src/store/server/actions.js | 3 + src/store/server/history/actions.js | 17 + src/store/server/history/getters.js | 135 +++++++ src/store/server/history/index.js | 20 + src/store/server/history/mutations.js | 11 + src/store/server/index.js | 2 + 18 files changed, 1126 insertions(+), 16 deletions(-) create mode 100644 src/components/charts/HistoryAllPrintStatus.vue create mode 100644 src/components/charts/HistoryFilamentUsage.vue create mode 100644 src/components/charts/HistoryPrinttimeAvg.vue create mode 100644 src/components/panels/HistoryListPanel.vue create mode 100644 src/pages/History.vue create mode 100644 src/store/server/history/actions.js create mode 100644 src/store/server/history/getters.js create mode 100644 src/store/server/history/index.js create mode 100644 src/store/server/history/mutations.js diff --git a/src/components/charts/HistoryAllPrintStatus.vue b/src/components/charts/HistoryAllPrintStatus.vue new file mode 100644 index 00000000..9ddb5fed --- /dev/null +++ b/src/components/charts/HistoryAllPrintStatus.vue @@ -0,0 +1,87 @@ + + + \ No newline at end of file diff --git a/src/components/charts/HistoryFilamentUsage.vue b/src/components/charts/HistoryFilamentUsage.vue new file mode 100644 index 00000000..6a9bf143 --- /dev/null +++ b/src/components/charts/HistoryFilamentUsage.vue @@ -0,0 +1,160 @@ + + + \ No newline at end of file diff --git a/src/components/charts/HistoryPrinttimeAvg.vue b/src/components/charts/HistoryPrinttimeAvg.vue new file mode 100644 index 00000000..3d046c88 --- /dev/null +++ b/src/components/charts/HistoryPrinttimeAvg.vue @@ -0,0 +1,136 @@ + + + \ No newline at end of file diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue new file mode 100644 index 00000000..e68d6a60 --- /dev/null +++ b/src/components/panels/HistoryListPanel.vue @@ -0,0 +1,348 @@ + + + \ No newline at end of file diff --git a/src/components/panels/index.js b/src/components/panels/index.js index 3206ecbe..4f68c0b9 100644 --- a/src/components/panels/index.js +++ b/src/components/panels/index.js @@ -12,6 +12,7 @@ import WebcamPanel from "./WebcamPanel"; import MiniconsolePanel from "./MiniconsolePanel"; import Settings from "./Settings/"; import PowerControlPanel from "./PowerControlPanel.vue"; +import HistoryListPanel from "./HistoryListPanel.vue"; Vue.component('status-panel', StatusPanel); Vue.component('klippy-state-panel', KlippyStatePanel); @@ -24,6 +25,7 @@ Vue.component('miscellaneous-panel', Miscellaneous); Vue.component('webcam-panel', WebcamPanel); Vue.component('miniconsole-panel', MiniconsolePanel); Vue.component('power-control-panel', PowerControlPanel); +Vue.component('history-list-panel', HistoryListPanel); export default { Settings diff --git a/src/pages/History.vue b/src/pages/History.vue new file mode 100644 index 00000000..de70dacc --- /dev/null +++ b/src/pages/History.vue @@ -0,0 +1,156 @@ + + + + diff --git a/src/plugins/vuetify.js b/src/plugins/vuetify.js index 4d27f5a5..282bbf60 100644 --- a/src/plugins/vuetify.js +++ b/src/plugins/vuetify.js @@ -11,22 +11,25 @@ Vue.use(VueToast, { }) Vue.use(Vuetify,{ - components: { - VSnackbar, - VBtn, - VIcon, - } + options: { + customProperties: true + }, + components: { + VSnackbar, + VBtn, + VIcon, + } }) export default new Vuetify({ - theme: { - themes: { - dark: { + theme: { + themes: { + dark: { - } - } - }, - icons: { - iconfont: 'mdi', - }, + } + } + }, + icons: { + iconfont: 'mdi', + }, }) diff --git a/src/routes/index.js b/src/routes/index.js index 64361a58..3b4e0802 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -4,6 +4,7 @@ import Farm from '../pages/Farm.vue' import Console from '../pages/Console.vue' import Heightmap from '../pages/Heightmap.vue' import Files from '../pages/Files.vue' +import History from '../pages/History.vue' import Settings from '../pages/Settings.vue' import SettingsInterface from '../pages/settings/interface.vue' import SettingsMachine from '../pages/settings/machine.vue' @@ -56,6 +57,13 @@ const routes = [ component: Files, alwaysShow: false, }, + { + title: "History", + path: '/history', + icon: 'history', + component: History, + alwaysShow: false, + }, { title: "Settings", path: '/settings', diff --git a/src/store/files/mutations.js b/src/store/files/mutations.js index 39efb346..e5daaedd 100644 --- a/src/store/files/mutations.js +++ b/src/store/files/mutations.js @@ -22,6 +22,7 @@ export default { item.isDirectory && 'filename' in item && 'dirs' in payload && + payload.dirs !== undefined && payload.dirs.length > 0 && payload.dirs.findIndex(element => element.dirname === item.filename) < 0 ) parent.splice(key, 1) diff --git a/src/store/gui/actions.js b/src/store/gui/actions.js index 47b98ce8..2d5be061 100644 --- a/src/store/gui/actions.js +++ b/src/store/gui/actions.js @@ -144,5 +144,13 @@ export default { dispatch('farm/readStoredPrinters', {}, { root: true }) } dispatch('printer/init', null, { root: true }) - } + }, + + setHistoryColumns({ commit, dispatch, state }, data) { + commit('setHistoryColumns', data) + dispatch('updateSettings', { + keyName: 'history', + newVal: state.history + }) + }, } \ No newline at end of file diff --git a/src/store/gui/index.js b/src/store/gui/index.js index 2c09ab6b..950cab74 100644 --- a/src/store/gui/index.js +++ b/src/store/gui/index.js @@ -59,6 +59,11 @@ export function getDefaultState() { showHiddenFiles: false, hideMetadataColums: [] }, + history: { + countPerPage: 10, + toggleChartCol3: 'filament_usage', + hideColums: [] + }, settings: { configfiles: { countPerPage: 10, diff --git a/src/store/gui/mutations.js b/src/store/gui/mutations.js index a1036e6c..0e2e6fb4 100644 --- a/src/store/gui/mutations.js +++ b/src/store/gui/mutations.js @@ -88,5 +88,13 @@ export default { Vue.set(state.tempchart.datasetSettings[payload.name]['additionalSensors'], payload.sensor, {}) Vue.set(state.tempchart.datasetSettings[payload.name]['additionalSensors'][payload.sensor], 'boolList', payload.value) - } + }, + + setHistoryColumns(state, data) { + if (data.value && state.history.hideColums.includes(data.name)) { + state.history.hideColums.splice(state.history.hideColums.indexOf(data.name), 1) + } else if (!data.value && !state.history.hideColums.includes(data.name)) { + state.history.hideColums.push(data.name) + } + }, } \ No newline at end of file diff --git a/src/store/server/actions.js b/src/store/server/actions.js index 9a6b7442..bf358f0b 100644 --- a/src/store/server/actions.js +++ b/src/store/server/actions.js @@ -53,6 +53,9 @@ export default { if (payload.plugins.includes("update_manager") !== false) Vue.prototype.$socket.sendObj('machine.update.status', {}, 'server/updateManager/getStatus') + + if (payload.plugins.includes("history") !== false) + Vue.prototype.$socket.sendObj('server.history.list', {}, 'server/history/getHistory') } if (state.registered_directories.length === 0 && 'registered_directories' in payload) { diff --git a/src/store/server/history/actions.js b/src/store/server/history/actions.js new file mode 100644 index 00000000..c236e79e --- /dev/null +++ b/src/store/server/history/actions.js @@ -0,0 +1,17 @@ +export default { + reset({ commit }) { + commit('reset') + }, + + getHistory({ commit, state }, payload) { + commit('reset') + + payload.jobs.forEach(job => { + const index = state.jobs.findIndex(tmpJob => tmpJob.job_id === job.job_id) + if (index === -1) { + commit('addJob', job) + } + }) + } + +} \ No newline at end of file diff --git a/src/store/server/history/getters.js b/src/store/server/history/getters.js new file mode 100644 index 00000000..0a6fdd06 --- /dev/null +++ b/src/store/server/history/getters.js @@ -0,0 +1,135 @@ +export default { + + getTotalPrintTime(state) { + let output = 0 + + state.jobs.forEach(current => { + output += current.print_duration + }) + + return output + }, + + getTotalCompletedPrintTime(state) { + let output = 0 + + state.jobs.forEach(current => { + if (current.status === "completed") output += current.print_duration + }) + + return output + }, + + getLongestPrintTime(state) { + let output = 0 + + state.jobs.forEach(current => { + if (current.print_duration > output) output = current.print_duration + }) + + return output + }, + + getTotalFilamentUsed(state) { + let output = 0 + + state.jobs.forEach(current => { + output += current.filament_used + }) + + return output + }, + + getTotalJobsCount(state) { + return state.jobs.length + }, + + getTotalCompletedJobsCount(state) { + return state.jobs.filter(job => job.status === "completed").length + }, + + getAvgPrintTime(state, getters) { + const totalCompletedPrintTime = getters.getTotalCompletedPrintTime + const totalCompletedJobsCount = getters.getTotalCompletedJobsCount + + return totalCompletedPrintTime > 0 && totalCompletedJobsCount > 0 ? Math.round(totalCompletedPrintTime / totalCompletedJobsCount) : 0 + }, + + getAllPrintStatusArray(state) { + let output = [] + + state.jobs.forEach(current => { + const index = output.findIndex(element => element.name === current.status) + if (index !== -1) output[index].value +=1 + else { + let itemStyle = { + opacity: 0.9, + color: '#212121' + } + + switch (current.status) { + case 'completed': + itemStyle['color'] = '#BDBDBD' + break + + case 'in_progress': + itemStyle['color'] = '#EEEEEE' + break + + case 'cancelled': + itemStyle['color'] = '#424242' + break + } + + output.push({ + name: current.status, + value: 1, + itemStyle: itemStyle + }) + } + }) + + return output + }, + + getFilamentUsageArray(state) { + let output = [] + const startDate = new Date(new Date().getDate() - 14) + const jobsFiltered = state.jobs.filter(job => job.start_time * 1000 >= startDate && job.filament_used > 0) + + if (jobsFiltered.length) { + jobsFiltered.forEach(current => { + const currentStartDate = new Date(current.start_time * 1000).setHours(0,0,0,0) + const index = output.findIndex(element => element[0] === currentStartDate) + if (index !== -1) output[index][1] += Math.round(current.filament_used) / 1000 + else + output.push([ + currentStartDate, + Math.round(current.filament_used) / 1000 + ]) + }) + } + + return output.sort((a,b) => { + return b[0] - a[0] + }) + }, + + getPrinttimeAvgArray(state) { + let output = [0,0,0,0,0] + const startDate = new Date(new Date().getDate() - 14) + const jobsFiltered = state.jobs.filter(job => job.start_time * 1000 >= startDate && job.status === 'completed') + + if (jobsFiltered.length) { + jobsFiltered.forEach(current => { + if (current.print_duration > 0 && current.print_duration <= 60*60*2) output[0]++ + else if (current.print_duration > 60*60*2 && current.print_duration <= 60*60*6) output[1]++ + else if (current.print_duration > 60*60*6 && current.print_duration <= 60*60*12) output[2]++ + else if (current.print_duration > 60*60*12 && current.print_duration <= 60*60*24) output[3]++ + else if (current.print_duration > 60*60*24) output[4]++ + }) + } + + return output + } +} \ No newline at end of file diff --git a/src/store/server/history/index.js b/src/store/server/history/index.js new file mode 100644 index 00000000..6e724dc4 --- /dev/null +++ b/src/store/server/history/index.js @@ -0,0 +1,20 @@ +import actions from './actions' +import mutations from './mutations' +import getters from './getters' + +export function getDefaultState() { + return { + jobs: [] + } +} + +// initial state +const state = getDefaultState() + +export default { + namespaced: true, + state, + getters, + actions, + mutations +} \ No newline at end of file diff --git a/src/store/server/history/mutations.js b/src/store/server/history/mutations.js new file mode 100644 index 00000000..2af3c4d5 --- /dev/null +++ b/src/store/server/history/mutations.js @@ -0,0 +1,11 @@ +import { getDefaultState } from './index' + +export default { + reset(state) { + Object.assign(state, getDefaultState()) + }, + + addJob(state, payload) { + state.jobs.push(payload) + } +} \ No newline at end of file diff --git a/src/store/server/index.js b/src/store/server/index.js index d3ce878e..4cd8de4d 100644 --- a/src/store/server/index.js +++ b/src/store/server/index.js @@ -5,6 +5,7 @@ import getters from './getters' // import modules import power from './power' import updateManager from './updateManager' +import history from './history' // create getDefaultState export function getDefaultState() { @@ -32,5 +33,6 @@ export default { modules: { power, updateManager, + history, } } \ No newline at end of file From 8e77e84a6ecf2fd7927c89c2b43b45e191b4d429 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Tue, 16 Mar 2021 00:59:36 +0100 Subject: [PATCH 02/32] fix allPrintStatusChart in history Signed-off-by: Stefan Dej --- src/components/charts/HistoryAllPrintStatus.vue | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/charts/HistoryAllPrintStatus.vue b/src/components/charts/HistoryAllPrintStatus.vue index 9ddb5fed..5e6e0826 100644 --- a/src/components/charts/HistoryAllPrintStatus.vue +++ b/src/components/charts/HistoryAllPrintStatus.vue @@ -17,10 +17,10 @@ export default { darkMode: true, animation: false, grid: { - top: 0, + top: 10, right: 0, bottom: 0, - left: 0, + left: 10, }, tooltip: { trigger: 'item' @@ -36,9 +36,7 @@ export default { }, computed: { ...mapState({ - intervalChartUpdate: state => state.gui.tempchart.intervalChartUpdate, - intervalDatasetUpdate: state => state.gui.tempchart.intervalDatasetUpdate, - boolTempchart: state => state.gui.dashboard.boolTempchart, + }), getAllPrintStatusArray: { get: function() { @@ -51,7 +49,6 @@ export default { if (document.getElementById("historyAllPrintStatus") && this.chart === null) { this.chart = echarts.init(document.getElementById("historyAllPrintStatus"), null, { renderer: 'svg' }) this.updateChart() - window.console.log("create AllPrintStatus") } else setTimeout(() => { this.createChart() @@ -60,10 +57,9 @@ export default { updateChart() { if (this.chart) { const chartOptions = { series: this.chartOptions.series } - chartOptions.series[0].data = this.filamentUsageArray + chartOptions.series[0].data = this.getAllPrintStatusArray this.chart.setOption(chartOptions) this.chart.resize() - window.console.log("update AllPrintStatus") } }, }, From 38fa2bd75b46b75ce51691a05a110230a165a3fb Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Tue, 16 Mar 2021 20:34:53 +0100 Subject: [PATCH 03/32] add notify_history_changed Signed-off-by: Stefan Dej --- src/components/panels/HistoryListPanel.vue | 2 +- src/store/server/history/actions.js | 5 +++++ src/store/server/history/mutations.js | 7 +++++++ src/store/socket/actions.js | 6 +++++- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index e68d6a60..5511bf05 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -199,7 +199,7 @@ }, getIconColor(status) { switch(status) { - case 'in_progress': return 'white' + case 'in_progress': return 'blue-grey darken-1' case 'completed': return 'green' case 'cancelled': return 'red' diff --git a/src/store/server/history/actions.js b/src/store/server/history/actions.js index c236e79e..aac7bd0e 100644 --- a/src/store/server/history/actions.js +++ b/src/store/server/history/actions.js @@ -12,6 +12,11 @@ export default { commit('addJob', job) } }) + }, + + getChanged({ commit }, payload) { + if (payload.action === 'added') commit('addJob', payload.job) + else if (payload.action === 'finished') commit('updateJob', payload.job) } } \ No newline at end of file diff --git a/src/store/server/history/mutations.js b/src/store/server/history/mutations.js index 2af3c4d5..54e83d4e 100644 --- a/src/store/server/history/mutations.js +++ b/src/store/server/history/mutations.js @@ -7,5 +7,12 @@ export default { addJob(state, payload) { state.jobs.push(payload) + }, + + updateJob(state, payload) { + const index = state.jobs.findIndex(job => job.job_id === payload.job_id) + if (index !== -1) { + state.jobs[index] = payload + } } } \ No newline at end of file diff --git a/src/store/socket/actions.js b/src/store/socket/actions.js index a8f9b7e8..12ca2ce0 100644 --- a/src/store/socket/actions.js +++ b/src/store/socket/actions.js @@ -31,7 +31,7 @@ export default { if (event.wasClean) window.console.log('Socket closed clear') }, - onMessage ({ commit, state }, payload) { + onMessage ({ commit, state, dispatch }, payload) { if (!state.isConnected) commit('setConnected') switch(payload.method) { @@ -99,6 +99,10 @@ export default { commit('server/updateManager/setStatus', payload.params[0], { root: true }) break + case 'notify_history_changed': + dispatch('server/history/getChanged', payload.params[0], { root: true }) + break + default: if (payload.result !== "ok") { if ( From 62f4a602d99a5c1dded3a86d2bbc0683abdb70d5 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Tue, 16 Mar 2021 20:46:38 +0100 Subject: [PATCH 04/32] change history filament usage chart from line to bar Signed-off-by: Stefan Dej --- src/components/charts/HistoryFilamentUsage.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/charts/HistoryFilamentUsage.vue b/src/components/charts/HistoryFilamentUsage.vue index 6a9bf143..b8df0835 100644 --- a/src/components/charts/HistoryFilamentUsage.vue +++ b/src/components/charts/HistoryFilamentUsage.vue @@ -37,6 +37,8 @@ export default { if (datasets.length) { let outputTime = datasets[0]['axisValueLabel'] outputTime = outputTime.substr(0, outputTime.indexOf(" ")+1) + let outputTimeDate = new Date(outputTime) + outputTime = outputTimeDate.toLocaleDateString() let outputValue = Math.round(datasets[0]['data'][1] * 10) / 10 output += outputTime+": "+outputValue+"m" @@ -92,12 +94,10 @@ export default { }, } }, + color: ['#000'], series: [{ - type: 'line', + type: 'bar', data: [], - lineStyle: { - color: '#000', - }, showSymbol: false }], }, @@ -127,7 +127,7 @@ export default { if (this.chart) { const chartOptions = { series: this.chartOptions.series } chartOptions.series[0].data = this.filamentUsageArray - chartOptions.series[0].lineStyle.color = this.getPrimaryColor() + chartOptions.color = [this.getPrimaryColor()] this.chart.setOption(chartOptions) this.chart.resize() } From 286523a9970634d45a80e87775f282a44e35a232 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Tue, 16 Mar 2021 23:32:35 +0100 Subject: [PATCH 05/32] add detail dialog to history list Signed-off-by: Stefan Dej --- src/components/panels/HistoryListPanel.vue | 112 ++++++++++++++++++++- src/store/server/history/getters.js | 5 +- 2 files changed, 115 insertions(+), 2 deletions(-) diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index 5511bf05..6c923f87 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -102,6 +102,100 @@ + + + + + mdi-updateJob Details + + + mdi-close-thick + + + + + + Filename + {{ detailsDialog.item.filename }} + + + Filesize + {{ formatFilesize(detailsDialog.item.metadata.size) }} + + + Last Modified + {{ formatDate(detailsDialog.item.metadata.modified) }} + + + Status + {{ detailsDialog.item.status }} + + + Start Time + {{ formatDate(detailsDialog.item.start_time) }} + + + End Time + {{ formatDate(detailsDialog.item.end_time) }} + + + Estimated Time + {{ formatPrintTime(detailsDialog.item.metadata.estimated_time) }} + + + Print Duration + {{ formatPrintTime(detailsDialog.item.print_duration) }} + + + Total Duration + {{ formatPrintTime(detailsDialog.item.total_duration) }} + + + Estimated Filament + {{ Math.round(detailsDialog.item.metadata.filament_total) }} mm + + + Filament Used + {{ Math.round(detailsDialog.item.filament_used) }} mm + + + First Layer Ext. Temp. + {{ detailsDialog.item.metadata.first_layer_extr_temp }} °C + + + First Layer Bed Temp. + {{ detailsDialog.item.metadata.first_layer_bed_temp }} °C + + + First Layer Height + {{ detailsDialog.item.metadata.first_layer_height }} mm + + + Layer Height + {{ detailsDialog.item.metadata.layer_height }} mm + + + Object Height + {{ detailsDialog.item.metadata.object_height }} mm + + + Slicer + {{ detailsDialog.item.metadata.slicer }} + + + Slicer Version + {{ detailsDialog.item.metadata.slicer_version }} + + + + + + @@ -141,12 +235,15 @@ }, contextMenu: { shown: false, - isDirectory: false, touchTimer: undefined, x: 0, y: 0, item: {} }, + detailsDialog: { + item: {}, + boolShow: false, + } } }, computed: { @@ -249,6 +346,10 @@ return '--' }, + clickRow(item) { + this.detailsDialog.item = item + this.detailsDialog.boolShow = true + }, showContextMenu (e, item) { if (!this.contextMenu.shown) { e?.preventDefault(); @@ -334,6 +435,15 @@ } return false + }, + getThumbnailWidth(item) { + if (this.getBigThumbnail(item)) { + const thumbnail = item.metadata.thumbnails.find(thumb => thumb.width >= 300 && thumb.width <= 400) + + if (thumbnail) return thumbnail.width + } + + return 400 } }, watch: { diff --git a/src/store/server/history/getters.js b/src/store/server/history/getters.js index 0a6fdd06..95671cc9 100644 --- a/src/store/server/history/getters.js +++ b/src/store/server/history/getters.js @@ -84,7 +84,10 @@ export default { output.push({ name: current.status, value: 1, - itemStyle: itemStyle + itemStyle: itemStyle, + label: { + color: '#fff' + } }) } }) From 88d1debd7379785ebcd24c4de53e0901ad7596c9 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Wed, 17 Mar 2021 22:16:40 +0100 Subject: [PATCH 06/32] add context menu of history jobs (details, reprint, delete) Signed-off-by: Stefan Dej --- src/components/panels/HistoryListPanel.vue | 21 ++++++++++++++++++--- src/pages/History.vue | 6 +++--- src/store/server/history/actions.js | 15 ++++++++++----- src/store/server/history/mutations.js | 10 +++++++++- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index 6c923f87..54ee6404 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -97,8 +97,14 @@ - - mdi-play Print start + + mdi-text-box-search Details + + + mdi-printer Reprint + + + mdi-delete Delete @@ -200,7 +206,7 @@