From 159663c8c04b3ed55df93e0960f6f2f98b80536d Mon Sep 17 00:00:00 2001 From: Jeremiah Pratt Date: Fri, 17 Feb 2023 20:34:56 -0500 Subject: [PATCH 01/71] Store for reminders --- src/store/gui/reminders/actions.ts | 48 ++++++++++++++++++++++++++++ src/store/gui/reminders/getters.ts | 21 ++++++++++++ src/store/gui/reminders/index.ts | 23 +++++++++++++ src/store/gui/reminders/mutations.ts | 33 +++++++++++++++++++ src/store/gui/reminders/types.ts | 13 ++++++++ src/store/server/actions.ts | 4 +++ src/store/server/index.ts | 2 ++ 7 files changed, 144 insertions(+) create mode 100644 src/store/gui/reminders/actions.ts create mode 100644 src/store/gui/reminders/getters.ts create mode 100644 src/store/gui/reminders/index.ts create mode 100644 src/store/gui/reminders/mutations.ts create mode 100644 src/store/gui/reminders/types.ts diff --git a/src/store/gui/reminders/actions.ts b/src/store/gui/reminders/actions.ts new file mode 100644 index 000000000..eda44f9af --- /dev/null +++ b/src/store/gui/reminders/actions.ts @@ -0,0 +1,48 @@ +import Vue from 'vue' +import { ActionTree } from 'vuex' +import { GuiRemindersState } from '@/store/gui/reminders/types' +import { RootState } from '@/store/types' +import { v4 as uuidv4 } from 'uuid' + +export const actions: ActionTree = { + reset({ commit }) { + commit('reset') + }, + + init() { + Vue.$socket.emit('server.database.get_item', { namespace: 'reminders' }, { action: 'gui/reminders/initStore' }) + }, + + async initStore({ commit, dispatch }, payload) { + await commit('reset') + await commit('initStore', payload) + await dispatch('socket/removeInitModule', 'gui/reminders/init', { root: true }) + }, + + upload(_, payload) { + Vue.$socket.emit('server.database.post_item', { namespace: 'reminders', key: payload.id, value: payload.value }) + }, + + store({ commit, dispatch, state }, payload) { + const id = uuidv4() + + commit('store', { id, values: payload.values }) + dispatch('upload', { + id, + value: state.reminders[id], + }) + }, + + update({ commit, dispatch, state }, payload) { + commit('update', payload) + dispatch('upload', { + id: payload.id, + value: state.reminders[payload.id], + }) + }, + + delete({ commit }, payload) { + commit('delete', payload) + Vue.$socket.emit('server.database.delete_item', { namespace: 'reminders', key: payload }) + }, +} diff --git a/src/store/gui/reminders/getters.ts b/src/store/gui/reminders/getters.ts new file mode 100644 index 000000000..d4a4f7a2a --- /dev/null +++ b/src/store/gui/reminders/getters.ts @@ -0,0 +1,21 @@ +import { GetterTree } from 'vuex' +import { GuiRemindersState, GuiRemindersStateReminder } from '@/store/gui/reminders/types' + +// eslint-disable-next-line +export const getters: GetterTree = { + getReminders: (state) => { + const reminders: GuiRemindersStateReminder[] = [] + + Object.keys(state.reminders).forEach((id: string) => { + reminders.push({ ...state.reminders[id], id }) + }) + + return reminders + }, + + getReminder: (state, getters) => (id: string) => { + const reminders = getters['getReminders'] ?? [] + + return reminders.find((reminder: GuiRemindersStateReminder) => reminder.id === id) + }, +} diff --git a/src/store/gui/reminders/index.ts b/src/store/gui/reminders/index.ts new file mode 100644 index 000000000..227263eba --- /dev/null +++ b/src/store/gui/reminders/index.ts @@ -0,0 +1,23 @@ +import { Module } from 'vuex' +import { GuiRemindersState } from '@/store/gui/reminders/types' +import { actions } from '@/store/gui/reminders/actions' +import { mutations } from '@/store/gui/reminders/mutations' +import { getters } from '@/store/gui/reminders/getters' + +export const getDefaultState = (): GuiRemindersState => { + return { + reminders: {}, + } +} + +// initial state +const state = getDefaultState() + +// eslint-disable-next-line +export const reminders: Module = { + namespaced: true, + state, + getters, + actions, + mutations, +} diff --git a/src/store/gui/reminders/mutations.ts b/src/store/gui/reminders/mutations.ts new file mode 100644 index 000000000..67b56bffe --- /dev/null +++ b/src/store/gui/reminders/mutations.ts @@ -0,0 +1,33 @@ +import Vue from 'vue' +import { MutationTree } from 'vuex' +import { GuiRemindersState } from '@/store/gui/reminders/types' +import { getDefaultState } from './index' + +export const mutations: MutationTree = { + reset(state) { + Object.assign(state, getDefaultState()) + }, + + initStore(state, payload) { + Vue.set(state, 'reminders', payload.value) + }, + + store(state, payload) { + Vue.set(state.reminders, payload.id, payload.value) + }, + + update(state, payload) { + if (payload.id in state.reminders) { + const reminder = { ...state.reminders[payload.id] } + Object.assign(reminder, payload.values) + + Vue.set(state.reminders, payload.id, reminder) + } + }, + + delete(state, payload) { + if (payload in state.reminders) { + Vue.delete(state.reminders, payload) + } + }, +} diff --git a/src/store/gui/reminders/types.ts b/src/store/gui/reminders/types.ts new file mode 100644 index 000000000..2b70d4496 --- /dev/null +++ b/src/store/gui/reminders/types.ts @@ -0,0 +1,13 @@ +export interface GuiRemindersState { + reminders: { + [key: string]: GuiRemindersStateReminder + } +} + +export interface GuiRemindersStateReminder { + id: string + name: string + start_total_print_time: number + time_delta: number + time_remaining?: number +} diff --git a/src/store/server/actions.ts b/src/store/server/actions.ts index c48195bcf..208790fba 100644 --- a/src/store/server/actions.ts +++ b/src/store/server/actions.ts @@ -63,6 +63,10 @@ export const actions: ActionTree = { dispatch('socket/addInitModule', 'gui/webcam/init', { root: true }) dispatch('gui/webcams/init', null, { root: true }) } + if (payload.namespaces?.includes('reminders')) { + dispatch('socket/addInitModule', 'gui/reminders/init', { root: true }) + dispatch('gui/reminders/init', null, { root: true }) + } commit('saveDbNamespaces', payload.namespaces) diff --git a/src/store/server/index.ts b/src/store/server/index.ts index 95717ac7c..410432668 100644 --- a/src/store/server/index.ts +++ b/src/store/server/index.ts @@ -11,6 +11,7 @@ import { history } from '@/store/server/history' import { timelapse } from '@/store/server/timelapse' import { jobQueue } from '@/store/server/jobQueue' import { announcements } from '@/store/server/announcements' +import { reminders } from '@/store/gui/reminders' // create getDefaultState export const getDefaultState = (): ServerState => { @@ -59,5 +60,6 @@ export const server: Module = { timelapse, jobQueue, announcements, + reminders, }, } From 45b02f40b29044480cc923b599c4d0bf86c59b03 Mon Sep 17 00:00:00 2001 From: Jeremiah Pratt Date: Fri, 17 Feb 2023 23:21:12 -0500 Subject: [PATCH 02/71] Add reminders panel --- .../panels/HistoryRemindersPanel.vue | 378 ++++++++++++++++++ src/pages/History.vue | 7 + src/store/gui/reminders/types.ts | 2 +- 3 files changed, 386 insertions(+), 1 deletion(-) create mode 100644 src/components/panels/HistoryRemindersPanel.vue diff --git a/src/components/panels/HistoryRemindersPanel.vue b/src/components/panels/HistoryRemindersPanel.vue new file mode 100644 index 000000000..f100daa15 --- /dev/null +++ b/src/components/panels/HistoryRemindersPanel.vue @@ -0,0 +1,378 @@ + + + diff --git a/src/pages/History.vue b/src/pages/History.vue index 372b780d3..35ca1fe70 100644 --- a/src/pages/History.vue +++ b/src/pages/History.vue @@ -7,6 +7,11 @@ + + + + + @@ -19,10 +24,12 @@ import { Component, Mixins } from 'vue-property-decorator' import BaseMixin from '@/components/mixins/base' import HistoryListPanel from '@/components/panels/HistoryListPanel.vue' import HistoryStatisticsPanel from '@/components/panels/HistoryStatisticsPanel.vue' +import HistoryRemindersPanel from '@/components/panels/HistoryRemindersPanel.vue' @Component({ components: { HistoryStatisticsPanel, HistoryListPanel, + HistoryRemindersPanel, }, }) export default class PageHistory extends Mixins(BaseMixin) {} diff --git a/src/store/gui/reminders/types.ts b/src/store/gui/reminders/types.ts index 2b70d4496..373aa73f5 100644 --- a/src/store/gui/reminders/types.ts +++ b/src/store/gui/reminders/types.ts @@ -9,5 +9,5 @@ export interface GuiRemindersStateReminder { name: string start_total_print_time: number time_delta: number - time_remaining?: number + remaining_print_time?: number } From e1083afcb1fca1a87c4f4def17e33b74c1062514 Mon Sep 17 00:00:00 2001 From: Jeremiah Pratt Date: Sat, 18 Feb 2023 14:46:05 -0500 Subject: [PATCH 03/71] Fix store and visual errors --- .../panels/HistoryRemindersPanel.vue | 60 ++++++++++++------- src/store/gui/index.ts | 2 + src/store/gui/reminders/mutations.ts | 7 ++- src/store/server/index.ts | 2 - 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/components/panels/HistoryRemindersPanel.vue b/src/components/panels/HistoryRemindersPanel.vue index f100daa15..024964e9f 100644 --- a/src/components/panels/HistoryRemindersPanel.vue +++ b/src/components/panels/HistoryRemindersPanel.vue @@ -3,7 +3,7 @@ - + - + {{ mdiPlus }} @@ -38,7 +38,7 @@ + + {{ item.name }} + +

Do you really want to delete {{ selectedReminders.length }} reminders?

@@ -111,6 +118,7 @@
+ + - + + - + - Confirm + + + Confirm + @@ -139,21 +165,34 @@ + - + + + dense + @update:error="isInvalidHours = !isInvalidHours"> - Confirm + + + Confirm + @@ -195,6 +234,13 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { editingReminder: GuiRemindersStateReminder | null = null creatingReminder: GuiRemindersStateReminder | null = null + nameInputRules = [(value: string) => !!value || this.$t('Files.InvalidNameEmpty')] + isInvalidName = false + + // TODO: translate + hoursInputRules = [(value: number) => value > 0 || 'Must be a postitive number'] + isInvalidHours = false + sortBy = 'remaining_print_time' sortDesc = false @@ -206,6 +252,7 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { item: {}, } + // TODO: translate headers = [ { text: 'Name', @@ -298,6 +345,7 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { return remainingPrintTime >= 0 ? 'orange' : 'red' } + // TODO: translate getStatusText(remainingPrintTime: number) { return remainingPrintTime >= 0 ? 'Active' : 'Overdue' } From 29e583873e007b8c0db7e1ca6a853d73a0c044c6 Mon Sep 17 00:00:00 2001 From: Jeremiah Pratt Date: Sat, 18 Feb 2023 15:43:46 -0500 Subject: [PATCH 05/71] Notifications, and fix validation --- .../panels/HistoryRemindersPanel.vue | 40 ++++++++++++++----- src/store/gui/notifications/getters.ts | 40 +++++++++++++++++++ src/store/gui/reminders/getters.ts | 7 ++++ 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/src/components/panels/HistoryRemindersPanel.vue b/src/components/panels/HistoryRemindersPanel.vue index 1e060b327..ef0b7db20 100644 --- a/src/components/panels/HistoryRemindersPanel.vue +++ b/src/components/panels/HistoryRemindersPanel.vue @@ -133,8 +133,7 @@ :rules="nameInputRules" hide-details outlined - dense - @update:error="isInvalidName = !isInvalidName"> + dense> @@ -144,8 +143,7 @@ :rules="hoursInputRules" hide-details outlined - dense - @update:error="isInvalidHours = !isInvalidHours"> + dense> @@ -172,8 +170,7 @@ :rules="nameInputRules" hide-details outlined - dense - @update:error="isInvalidName = !isInvalidName"> + dense> @@ -183,8 +180,7 @@ :rules="hoursInputRules" hide-details outlined - dense - @update:error="isInvalidHours = !isInvalidHours"> + dense> @@ -210,7 +206,7 @@ import { mdiCloseThick, mdiRepeatOnce, } from '@mdi/js' -import { Component, Mixins } from 'vue-property-decorator' +import { Component, Mixins, Watch } from 'vue-property-decorator' import { GuiRemindersStateReminder } from '@/store/gui/reminders/types' import BaseMixin from '@/components/mixins/base' import Panel from '@/components/ui/Panel.vue' @@ -238,7 +234,7 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { isInvalidName = false // TODO: translate - hoursInputRules = [(value: number) => value > 0 || 'Must be a postitive number'] + hoursInputRules = [(value: number) => value > 0 || 'Must be a positive number'] isInvalidHours = false sortBy = 'remaining_print_time' @@ -416,6 +412,8 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { start_total_print_time: 0, time_delta: 0, } + this.isInvalidHours = true + this.isInvalidName = true } createReminder() { @@ -431,6 +429,8 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { openEditReminderDialog(reminder: GuiRemindersStateReminder) { this.editingReminder = { ...reminder } this.editingReminder.time_delta = Math.round(this.editingReminder.time_delta / 3600) + this.isInvalidHours = false + this.isInvalidName = false this.editReminderDialog = true } @@ -442,5 +442,25 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { this.editReminderDialog = false this.editingReminder = null } + + @Watch('editingDisplayName') + onEditingDisplayname(val: string) { + this.isInvalidName = !val + } + + @Watch('editingPrintHours') + onEditingPrintHours(val: string) { + this.isInvalidHours = parseFloat(val) <= 0 + } + + @Watch('creatingDisplayName') + onCreatingDisplayName(val: string) { + this.isInvalidName = !val + } + + @Watch('creatingPrintHours') + onCreatingPrintHours(val: string) { + this.isInvalidHours = parseFloat(val) <= 0 + } } diff --git a/src/store/gui/notifications/getters.ts b/src/store/gui/notifications/getters.ts index de456430d..500319054 100644 --- a/src/store/gui/notifications/getters.ts +++ b/src/store/gui/notifications/getters.ts @@ -5,6 +5,7 @@ import i18n from '@/plugins/i18n.js' import { RootStateDependency } from '@/store/types' import { sha256 } from 'js-sha256' import { PrinterStateKlipperConfigWarning } from '@/store/printer/types' +import { GuiRemindersStateReminder } from '../reminders/types' export const getters: GetterTree = { getNotifications: (state, getters) => { @@ -28,6 +29,9 @@ export const getters: GetterTree = { // klipper warnings notifications = notifications.concat(getters['getNotificationsKlipperWarnings']) + // user-created reminders + notifications = notifications.concat(getters['getNotificationsOverdueReminders']) + const mapType = { normal: 2, high: 1, @@ -270,6 +274,42 @@ export const getters: GetterTree = { return notifications }, + getNotificationsOverdueReminders: (state, getters, rootState, rootGetters) => { + const notifications: GuiNotificationStateEntry[] = [] + let reminders: GuiRemindersStateReminder[] = rootGetters['gui/reminders/getOverdueReminders'] + + const date = rootState.server.system_boot_at ?? new Date() + + if (reminders.length) { + // get all dismissed reminders and convert it to a string[] + const remindersDismisses = rootGetters['gui/notifications/getDismissByCategory']('reminder').map( + (dismiss: GuiNotificationStateDismissEntry) => { + return dismiss.id + } + ) + + // filter all dismissed reminders + reminders = reminders.filter((reminder) => !remindersDismisses.includes(reminder.id)) + + reminders.forEach((reminder) => { + // TODO: translate + const title = 'User Created Reminder' + const description = reminder.name + + notifications.push({ + id: `reminder/${reminder.id}`, + priority: 'normal', + title: title, + description: description, + date, + dismissed: false, + }) + }) + } + + return notifications + }, + getDismiss: (state, getters, rootState) => { const currentTime = new Date() const systemBootAt = rootState.server.system_boot_at ?? new Date() diff --git a/src/store/gui/reminders/getters.ts b/src/store/gui/reminders/getters.ts index d4a4f7a2a..31595b6e2 100644 --- a/src/store/gui/reminders/getters.ts +++ b/src/store/gui/reminders/getters.ts @@ -18,4 +18,11 @@ export const getters: GetterTree = { return reminders.find((reminder: GuiRemindersStateReminder) => reminder.id === id) }, + + getOverdueReminders: (state, getters, rootState) => { + const currentTotalPrintTime = rootState.server.history.job_totals.total_print_time + return Object.values(state.reminders).filter( + (reminder) => reminder.time_delta - (currentTotalPrintTime - reminder.start_total_print_time) < 0 + ) + }, } From 76efd431074cbea48ce5a4d80fdd5af7dd968d62 Mon Sep 17 00:00:00 2001 From: Jeremiah Pratt Date: Mon, 20 Feb 2023 17:47:42 -0500 Subject: [PATCH 06/71] Add repeating to reminder - notifications TBD --- .../panels/HistoryRemindersPanel.vue | 45 +++++++++++++++++-- src/store/gui/reminders/types.ts | 2 + 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/components/panels/HistoryRemindersPanel.vue b/src/components/panels/HistoryRemindersPanel.vue index ef0b7db20..457146e5f 100644 --- a/src/components/panels/HistoryRemindersPanel.vue +++ b/src/components/panels/HistoryRemindersPanel.vue @@ -145,6 +145,12 @@ outlined dense> + + + + @@ -182,6 +188,11 @@ outlined dense> + + + @@ -287,8 +298,14 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { if (!baseReminders) return [] return baseReminders.map((reminder: GuiRemindersStateReminder) => { let tempReminder = { ...reminder } - tempReminder.remaining_print_time = - reminder.time_delta - (this.totalPrintTime - reminder.start_total_print_time) + if (reminder.snooze_timestamps.length > 0) { + tempReminder.remaining_print_time = + reminder.time_delta - + (this.totalPrintTime - reminder.snooze_timestamps[reminder.snooze_timestamps.length - 1]) + } else { + tempReminder.remaining_print_time = + reminder.time_delta - (this.totalPrintTime - reminder.start_total_print_time) + } return tempReminder }) } @@ -313,6 +330,16 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { this.editingReminder.time_delta = parseFloat(value) || 0 } + get editingRepeating() { + if (!this.editingReminder) return false + return this.editingReminder.repeating + } + + set editingRepeating(value: boolean) { + if (!this.editingReminder) return + this.editingReminder.repeating = value + } + get creatingDisplayName() { if (!this.creatingReminder) return '' return this.creatingReminder.name @@ -333,6 +360,16 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { this.creatingReminder.time_delta = parseFloat(value) || 0 } + get creatingRepeating() { + if (!this.creatingReminder) return false + return this.creatingReminder.repeating + } + + set creatingRepeating(value: boolean) { + if (!this.creatingReminder) return + this.creatingReminder.repeating = value + } + getStatusIcon(remainingPrintTime: number) { return remainingPrintTime >= 0 ? mdiClockOutline : mdiClockAlertOutline } @@ -387,7 +424,7 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { } repeatReminder(reminder: GuiRemindersStateReminder) { - reminder.start_total_print_time = this.totalPrintTime + reminder.snooze_timestamps = [...reminder.snooze_timestamps, this.totalPrintTime] this.$store.dispatch('gui/reminders/update', reminder) } @@ -410,6 +447,8 @@ export default class HistoryRemindersPanel extends Mixins(BaseMixin) { id: '', name: '', start_total_print_time: 0, + snooze_timestamps: [], + repeating: true, time_delta: 0, } this.isInvalidHours = true diff --git a/src/store/gui/reminders/types.ts b/src/store/gui/reminders/types.ts index 373aa73f5..7105c019b 100644 --- a/src/store/gui/reminders/types.ts +++ b/src/store/gui/reminders/types.ts @@ -9,5 +9,7 @@ export interface GuiRemindersStateReminder { name: string start_total_print_time: number time_delta: number + repeating: boolean + snooze_timestamps: number[] remaining_print_time?: number } From e1a46f1f0dde906699b495bc31fba4c43fc9fc1a Mon Sep 17 00:00:00 2001 From: Jeremiah Pratt Date: Sat, 4 Mar 2023 12:20:09 -0500 Subject: [PATCH 07/71] Add print time and epoch timestamp recording --- .../notifications/NotificationMenuEntry.vue | 25 ++++++++++++++++++- .../panels/HistoryRemindersPanel.vue | 11 ++++---- src/store/gui/reminders/actions.ts | 12 +++++++++ src/store/gui/reminders/mutations.ts | 1 - src/store/gui/reminders/types.ts | 3 ++- 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/components/notifications/NotificationMenuEntry.vue b/src/components/notifications/NotificationMenuEntry.vue index 55cdc2e6d..e6d01af0c 100644 --- a/src/components/notifications/NotificationMenuEntry.vue +++ b/src/components/notifications/NotificationMenuEntry.vue @@ -29,6 +29,15 @@ {{ mdiClose }} + + {{ mdiCalendarRefreshOutline }} + {{ mdiBellOffOutline }} @@ -99,7 +108,7 @@ diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index ab51972d4..d2fdee2a8 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -240,196 +240,10 @@ - - - - - - - {{ $t('History.Filename') }} - {{ detailsDialog.item.filename }} - - - - - - {{ $t('History.Status') }} - - {{ - $te(`History.StatusValues.${detailsDialog.item.status}`, 'en') - ? $t(`History.StatusValues.${detailsDialog.item.status}`) - : detailsDialog.item.status - }} - - - - - {{ $t('History.StartTime') }} - {{ formatDateTime(detailsDialog.item.start_time * 1000) }} - - - - - - - - - - - - - - - - - - - + = { // find jobs via metadata const jobs = state.jobs.filter((job) => { - return job.metadata?.size === filesize && Math.round(job.metadata?.modified * 1000) === modified + return job.metadata?.size === filesize && Math.round((job.metadata?.modified ?? 0) * 1000) === modified }) if (jobs.length) return jobs if (job_id) return jobs.filter((job) => job.job_id === job_id) @@ -312,7 +312,7 @@ export const getters: GetterTree = { getPrintStatusByFilename: (state) => (filename: string, modified: number) => { if (state.jobs.length) { const job = state.jobs.find((job) => { - return job.filename === filename && Math.round(job.metadata?.modified * 1000) === modified + return job.filename === filename && Math.round((job.metadata?.modified ?? 0) * 1000) === modified }) return job?.status ?? '' diff --git a/src/store/server/history/types.ts b/src/store/server/history/types.ts index ada84d13b..25e6bd000 100644 --- a/src/store/server/history/types.ts +++ b/src/store/server/history/types.ts @@ -1,3 +1,5 @@ +import { FileStateFileThumbnail } from '@/store/files/types' + export interface ServerHistoryState { jobs: ServerHistoryStateJob[] job_totals: { @@ -17,7 +19,31 @@ export interface ServerHistoryStateJob { filament_used: number filename: string // eslint-disable-next-line - metadata: any + metadata: { + print_start_time?: number + job_id?: number + size?: number + slicer?: string + slicer_version?: string + layer_count?: number + layer_height?: number + first_layer_height?: number + object_height?: number + filament_total?: number + filament_weight_total?: number + estimated_time?: number + thumbnails?: FileStateFileThumbnail[] + first_layer_bed_temp?: number + first_layer_extr_temp?: number + gcode_start_byte?: number + gcode_end_byte?: number + filename?: string + filesize?: number + modified?: number + uuid?: string + nozzle_diameter?: number + [key: string]: any + } note?: string print_duration: number status: string From 6cf542bcebb91c3dca9ff2ee32f1fcf1756bb0dd Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Fri, 5 May 2023 23:45:36 +0200 Subject: [PATCH 11/71] refactor: finish history details dialog Signed-off-by: Stefan Dej --- .../dialogs/HistoryListPanelDetailsDialog.vue | 173 +++--------------- src/components/panels/HistoryListPanel.vue | 2 +- 2 files changed, 24 insertions(+), 151 deletions(-) diff --git a/src/components/dialogs/HistoryListPanelDetailsDialog.vue b/src/components/dialogs/HistoryListPanelDetailsDialog.vue index 3ae016ebd..67b9eb3c0 100644 --- a/src/components/dialogs/HistoryListPanelDetailsDialog.vue +++ b/src/components/dialogs/HistoryListPanelDetailsDialog.vue @@ -10,150 +10,13 @@ {{ mdiCloseThick }} - + - - {{ $t('History.Filename') }} - {{ job.filename }} - - - - - - {{ $t('History.Status') }} - - {{ - $te(`History.StatusValues.${job.status}`, 'en') - ? $t(`History.StatusValues.${job.status}`) - : job.status - }} - - - - - {{ $t('History.StartTime') }} - {{ formatDateTime(job.start_time * 1000) }} - - - - - - - - - - - - - - - - + - + {{ outputValue(col, item) }} - + {{ 'slicer' in item.metadata && item.metadata.slicer ? item.metadata.slicer : '--' }}
@@ -266,7 +266,11 @@
@@ -661,7 +665,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { } getSmallThumbnail(item: ServerHistoryStateJob) { - if ('metadata' in item && 'thumbnails' in item.metadata && item.metadata.thumbnails.length) { + if (item.metadata?.thumbnails?.length) { const thumbnail = item.metadata.thumbnails.find( (thumb: any) => thumb.width >= thumbnailSmallMin && @@ -686,8 +690,8 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { } getBigThumbnail(item: ServerHistoryStateJob) { - if ('metadata' in item && 'thumbnails' in item.metadata && item.metadata.thumbnails.length) { - const thumbnail = item.metadata.thumbnails.find((thumb: any) => thumb.width >= thumbnailBigMin) + if (item.metadata?.thumbnails?.length) { + const thumbnail = item.metadata?.thumbnails?.find((thumb: any) => thumb.width >= thumbnailBigMin) let relative_url = '' if (item.filename.lastIndexOf('/') !== -1) { @@ -705,7 +709,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { getThumbnailWidth(item: ServerHistoryStateJob) { if (this.getBigThumbnail(item)) { - const thumbnail = item.metadata.thumbnails.find((thumb: any) => thumb.width >= thumbnailBigMin) + const thumbnail = item.metadata?.thumbnails?.find((thumb: any) => thumb.width >= thumbnailBigMin) if (thumbnail) return thumbnail.width } From beb346ae74cc3ff4a76f1125c4a1724b6e21e937 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Sat, 6 May 2023 22:56:13 +0200 Subject: [PATCH 13/71] refactor: move style at the end of the file Signed-off-by: Stefan Dej --- src/components/panels/HistoryListPanel.vue | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index b1530f1af..c9e0da5a4 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -1,13 +1,3 @@ - - @@ -272,11 +181,7 @@ - + @@ -296,7 +201,6 @@ import BaseMixin from '@/components/mixins/base' import { ServerHistoryStateJob } from '@/store/server/history/types' import { caseInsensitiveSort, formatFilesize } from '@/plugins/helpers' import Panel from '@/components/ui/Panel.vue' -import { thumbnailBigMin, thumbnailSmallMax, thumbnailSmallMin } from '@/store/variables' import { mdiDatabaseExportOutline, mdiDelete, @@ -304,17 +208,27 @@ import { mdiCog, mdiPrinter, mdiTextBoxSearch, - mdiFile, mdiFileDocumentMultipleOutline, mdiMagnify, mdiCloseThick, mdiNotebookEdit, mdiNotebookPlus, - mdiNotebook, } from '@mdi/js' import HistoryListPanelDetailsDialog from '@/components/dialogs/HistoryListPanelDetailsDialog.vue' +import HistoryListEntryJob from '@/components/panels/HistoryList/HistoryListEntryJob.vue' + +export interface HistoryListPanelRow { + text: string + value: string + align: string + configable: boolean + visible: boolean + filterable?: boolean + outputType?: string +} + @Component({ - components: { HistoryListPanelDetailsDialog, Panel }, + components: { HistoryListEntryJob, HistoryListPanelDetailsDialog, Panel }, }) export default class HistoryListPanel extends Mixins(BaseMixin) { mdiDatabaseExportOutline = mdiDatabaseExportOutline @@ -324,12 +238,10 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { mdiPrinter = mdiPrinter mdiFileDocumentMultipleOutline = mdiFileDocumentMultipleOutline mdiTextBoxSearch = mdiTextBoxSearch - mdiFile = mdiFile mdiMagnify = mdiMagnify mdiCloseThick = mdiCloseThick mdiNotebookPlus = mdiNotebookPlus mdiNotebookEdit = mdiNotebookEdit - mdiNotebook = mdiNotebook formatFilesize = formatFilesize @@ -377,7 +289,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { } get headers() { - const headers = [ + const headers: HistoryListPanelRow[] = [ { text: '', value: '', @@ -387,7 +299,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { filterable: false, }, { - text: this.$t('History.Filename'), + text: this.$t('History.Filename').toString() as string, value: 'filename', align: 'left', configable: false, @@ -402,7 +314,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { filterable: false, }, { - text: this.$t('History.Filesize'), + text: this.$t('History.Filesize').toString() as string, value: 'size', align: 'left', configable: true, @@ -410,7 +322,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'filesize', }, { - text: this.$t('History.LastModified'), + text: this.$t('History.LastModified').toString() as string, value: 'modified', align: 'left', configable: true, @@ -418,7 +330,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'date', }, { - text: this.$t('History.StartTime'), + text: this.$t('History.StartTime').toString() as string, value: 'start_time', align: 'left', configable: true, @@ -426,7 +338,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'date', }, { - text: this.$t('History.EndTime'), + text: this.$t('History.EndTime').toString() as string, value: 'end_time', align: 'left', configable: true, @@ -434,7 +346,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'date', }, { - text: this.$t('History.EstimatedTime'), + text: this.$t('History.EstimatedTime').toString() as string, value: 'estimated_time', align: 'left', configable: true, @@ -442,7 +354,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'time', }, { - text: this.$t('History.PrintTime'), + text: this.$t('History.PrintTime').toString() as string, value: 'print_duration', align: 'left', configable: true, @@ -450,7 +362,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'time', }, { - text: this.$t('History.TotalTime'), + text: this.$t('History.TotalTime').toString() as string, value: 'total_duration', align: 'left', configable: true, @@ -458,7 +370,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'time', }, { - text: this.$t('History.FilamentCalc'), + text: this.$t('History.FilamentCalc').toString() as string, value: 'filament_total', align: 'left', configable: true, @@ -466,7 +378,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'length', }, { - text: this.$t('History.FilamentUsed'), + text: this.$t('History.FilamentUsed').toString() as string, value: 'filament_used', align: 'left', configable: true, @@ -474,7 +386,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'length', }, { - text: this.$t('History.FirstLayerExtTemp'), + text: this.$t('History.FirstLayerExtTemp').toString() as string, value: 'first_layer_extr_temp', align: 'left', configable: true, @@ -482,7 +394,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'temp', }, { - text: this.$t('History.FirstLayerBedTemp'), + text: this.$t('History.FirstLayerBedTemp').toString() as string, value: 'first_layer_bed_temp', align: 'left', configable: true, @@ -490,7 +402,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'temp', }, { - text: this.$t('History.FirstLayerHeight'), + text: this.$t('History.FirstLayerHeight').toString() as string, value: 'first_layer_height', align: 'left', configable: true, @@ -498,7 +410,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'length', }, { - text: this.$t('History.LayerHeight'), + text: this.$t('History.LayerHeight').toString() as string, value: 'layer_height', align: 'left', configable: true, @@ -506,7 +418,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'length', }, { - text: this.$t('History.ObjectHeight'), + text: this.$t('History.ObjectHeight').toString() as string, value: 'object_height', align: 'left', configable: true, @@ -514,7 +426,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { outputType: 'length', }, { - text: this.$t('History.Slicer'), + text: this.$t('History.Slicer').toString() as string, value: 'slicer', align: 'left', configable: true, @@ -535,7 +447,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { get tableFields() { return this.filteredHeaders.filter( - (col: any) => !['filename', 'status', 'slicer'].includes(col.value) && col.value !== '' + (col: any) => !['filename', 'status'].includes(col.value) && col.value !== '' ) } @@ -654,59 +566,6 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { return value != null && search != null && value.toString().toLowerCase().indexOf(search.toLowerCase()) !== -1 } - getSmallThumbnail(item: ServerHistoryStateJob) { - if (item.metadata?.thumbnails?.length) { - const thumbnail = item.metadata.thumbnails.find( - (thumb: any) => - thumb.width >= thumbnailSmallMin && - thumb.width <= thumbnailSmallMax && - thumb.height >= thumbnailSmallMin && - thumb.height <= thumbnailSmallMax - ) - - let relative_url = '' - if (item.filename.lastIndexOf('/') !== -1) { - relative_url = item.filename.substr(0, item.filename.lastIndexOf('/') + 1) - } - - if (thumbnail && 'relative_path' in thumbnail) { - return `${this.apiUrl}/server/files/gcodes/${encodeURI( - relative_url + thumbnail.relative_path - )}?timestamp=${item.metadata.modified}` - } - } - - return false - } - - getBigThumbnail(item: ServerHistoryStateJob) { - if (item.metadata?.thumbnails?.length) { - const thumbnail = item.metadata?.thumbnails?.find((thumb: any) => thumb.width >= thumbnailBigMin) - - let relative_url = '' - if (item.filename.lastIndexOf('/') !== -1) { - relative_url = item.filename.substr(0, item.filename.lastIndexOf('/') + 1) - } - - if (thumbnail && 'relative_path' in thumbnail) - return `${this.apiUrl}/server/files/gcodes/${encodeURI( - relative_url + thumbnail.relative_path - )}?timestamp=${item.metadata.modified}` - } - - return false - } - - getThumbnailWidth(item: ServerHistoryStateJob) { - if (this.getBigThumbnail(item)) { - const thumbnail = item.metadata?.thumbnails?.find((thumb: any) => thumb.width >= thumbnailBigMin) - - if (thumbnail) return thumbnail.width - } - - return 400 - } - changeColumnVisible(name: string) { if (this.headers.filter((header) => header.value === name).length) { let value = this.headers.filter((header) => header.value === name)[0].visible @@ -806,15 +665,13 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { link.remove() } - getStatusIcon(status: string) { - return this.$store.getters['server/history/getPrintStatusIcon'](status) - } - - getStatusColor(status: string) { - return this.$store.getters['server/history/getPrintStatusIconColor'](status) - } - - outputValue(col: any, item: any, format: boolean = true, escapeChar: string | null = null) { + outputValue( + col: HistoryListPanelRow, + item: ServerHistoryStateJob, + format: boolean = true, + escapeChar: string | null = null + ) { + //@ts-ignore let value = col.value in item ? item[col.value] : null if (value === null) value = col.value in item.metadata ? item.metadata[col.value] : null @@ -840,7 +697,9 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { return value } } - } else if (value > 0) { + } + + if (value > 0) { switch (col.outputType) { case 'filesize': return formatFilesize(value) @@ -862,7 +721,9 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { default: return value } - } else return '--' + } + + return '--' } createNote(item: ServerHistoryStateJob) { From c394713aa1ebfd55275bdd82c9518c2065a7acd6 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Thu, 18 May 2023 21:00:52 +0200 Subject: [PATCH 15/71] style: order imports after update branch Signed-off-by: Stefan Dej --- src/store/gui/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/store/gui/index.ts b/src/store/gui/index.ts index a826fcd61..8cacbf9d7 100644 --- a/src/store/gui/index.ts +++ b/src/store/gui/index.ts @@ -14,9 +14,8 @@ import { navigation } from '@/store/gui/navigation' import { notifications } from '@/store/gui/notifications' import { presets } from '@/store/gui/presets' import { remoteprinters } from '@/store/gui/remoteprinters' -import { webcams } from '@/store/gui/webcams' -import { notifications } from '@/store/gui/notifications' import { reminders } from '@/store/gui/reminders' +import { webcams } from '@/store/gui/webcams' export const getDefaultState = (): GuiState => { return { From fca24a8fcbe53427ce43ead3c7ef3e5643aa33aa Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Fri, 19 May 2023 00:20:03 +0200 Subject: [PATCH 16/71] refactor: split and cleanup HistoryListPanel Signed-off-by: Stefan Dej --- .../dialogs/HistoryListPanelDetailsDialog.vue | 7 +- .../dialogs/HistoryListPanelNoteDialog.vue | 88 +++++ .../HistoryList/HistoryListEntryJob.vue | 312 +++++++++++++----- src/components/panels/HistoryListPanel.vue | 252 +++----------- 4 files changed, 366 insertions(+), 293 deletions(-) create mode 100644 src/components/dialogs/HistoryListPanelNoteDialog.vue diff --git a/src/components/dialogs/HistoryListPanelDetailsDialog.vue b/src/components/dialogs/HistoryListPanelDetailsDialog.vue index 67b9eb3c0..16f7f33f8 100644 --- a/src/components/dialogs/HistoryListPanelDetailsDialog.vue +++ b/src/components/dialogs/HistoryListPanelDetailsDialog.vue @@ -47,11 +47,8 @@ export default class HistoryListPanelDetailsDialog extends Mixins(BaseMixin) { formatFilesize = formatFilesize formatPrintTime = formatPrintTime - @Prop({ required: true, default: false }) - declare readonly show: boolean - - @Prop({ required: true }) - declare job: ServerHistoryStateJob + @Prop({ type: Boolean, required: true }) readonly show!: boolean + @Prop({ type: Object, required: true }) readonly job!: ServerHistoryStateJob get entries() { let entries: { name: string; value: string | null; exists: boolean }[] = [ diff --git a/src/components/dialogs/HistoryListPanelNoteDialog.vue b/src/components/dialogs/HistoryListPanelNoteDialog.vue new file mode 100644 index 000000000..63c2c163d --- /dev/null +++ b/src/components/dialogs/HistoryListPanelNoteDialog.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/src/components/panels/HistoryList/HistoryListEntryJob.vue b/src/components/panels/HistoryList/HistoryListEntryJob.vue index d392dde1e..2af687651 100644 --- a/src/components/panels/HistoryList/HistoryListEntryJob.vue +++ b/src/components/panels/HistoryList/HistoryListEntryJob.vue @@ -1,41 +1,56 @@ + - + Date: Mon, 22 May 2023 22:30:45 +0200 Subject: [PATCH 20/71] feat: add Maintenance store Signed-off-by: Stefan Dej --- src/store/gui/index.ts | 4 ++-- src/store/gui/maintenance/actions.ts | 16 ++++++++++------ src/store/gui/maintenance/getters.ts | 12 ++++++------ src/store/gui/maintenance/index.ts | 2 +- src/store/gui/maintenance/mutations.ts | 14 +++++++------- src/store/gui/maintenance/types.ts | 18 ++++++++++++++---- src/store/gui/notifications/getters.ts | 4 ++-- src/store/server/actions.ts | 6 +++--- 8 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/store/gui/index.ts b/src/store/gui/index.ts index 8cacbf9d7..60a7794bd 100644 --- a/src/store/gui/index.ts +++ b/src/store/gui/index.ts @@ -14,7 +14,7 @@ import { navigation } from '@/store/gui/navigation' import { notifications } from '@/store/gui/notifications' import { presets } from '@/store/gui/presets' import { remoteprinters } from '@/store/gui/remoteprinters' -import { reminders } from '@/store/gui/reminders' +import { maintenance } from '@/store/gui/maintenance' import { webcams } from '@/store/gui/webcams' export const getDefaultState = (): GuiState => { @@ -271,12 +271,12 @@ export const gui: Module = { console, gcodehistory, macros, + maintenance, miscellaneous, navigation, notifications, presets, remoteprinters, webcams, - reminders, }, } diff --git a/src/store/gui/maintenance/actions.ts b/src/store/gui/maintenance/actions.ts index ac2cfa106..b03e2c088 100644 --- a/src/store/gui/maintenance/actions.ts +++ b/src/store/gui/maintenance/actions.ts @@ -23,17 +23,21 @@ export const actions: ActionTree = { await dispatch('socket/removeInitModule', 'gui/maintenance/init', { root: true }) }, - /*upload(_, payload) { - Vue.$socket.emit('server.database.post_item', { namespace: 'reminders', key: payload.id, value: payload.value }) + upload(_, payload) { + Vue.$socket.emit('server.database.post_item', { + namespace: 'maintenance', + key: payload.id, + value: payload.value, + }) }, store({ commit, dispatch, state }, payload) { const id = uuidv4() - commit('store', { id, values: payload.values }) + commit('store', { id, values: payload.entry }) dispatch('upload', { id, - value: state.reminders[id], + value: state.entries[id], }) }, @@ -41,11 +45,11 @@ export const actions: ActionTree = { commit('update', payload) dispatch('upload', { id: payload.id, - value: state.reminders[payload.id], + value: state.entries[payload.id], }) }, - delete({ commit }, payload) { + /*delete({ commit }, payload) { commit('delete', payload) Vue.$socket.emit('server.database.delete_item', { namespace: 'reminders', key: payload }) }, diff --git a/src/store/gui/maintenance/getters.ts b/src/store/gui/maintenance/getters.ts index bf45083af..03f966239 100644 --- a/src/store/gui/maintenance/getters.ts +++ b/src/store/gui/maintenance/getters.ts @@ -3,17 +3,17 @@ import { GuiMaintenanceState, GuiMaintenanceStateEntry } from '@/store/gui/maint // eslint-disable-next-line export const getters: GetterTree = { - /*getReminders: (state) => { - const reminders: GuiRemindersStateReminder[] = [] + getEntries: (state) => { + const entries: GuiMaintenanceStateEntry[] = [] - Object.keys(state.reminders).forEach((id: string) => { - reminders.push({ ...state.reminders[id], id }) + Object.keys(state.entries).forEach((id: string) => { + entries.push({ ...state.entries[id], id }) }) - return reminders + return entries }, - getReminder: (state, getters) => (id: string) => { + /*getReminder: (state, getters) => (id: string) => { const reminders = getters['getReminders'] ?? [] return reminders.find((reminder: GuiRemindersStateReminder) => reminder.id === id) diff --git a/src/store/gui/maintenance/index.ts b/src/store/gui/maintenance/index.ts index dfc35d272..fdfcc39b3 100644 --- a/src/store/gui/maintenance/index.ts +++ b/src/store/gui/maintenance/index.ts @@ -14,7 +14,7 @@ export const getDefaultState = (): GuiMaintenanceState => { const state = getDefaultState() // eslint-disable-next-line -export const reminders: Module = { +export const maintenance: Module = { namespaced: true, state, getters, diff --git a/src/store/gui/maintenance/mutations.ts b/src/store/gui/maintenance/mutations.ts index ccfad5d2d..9d88fa90d 100644 --- a/src/store/gui/maintenance/mutations.ts +++ b/src/store/gui/maintenance/mutations.ts @@ -12,19 +12,19 @@ export const mutations: MutationTree = { Vue.set(state, 'entries', payload.value) }, - /*store(state, payload) { - Vue.set(state.reminders, payload.id, payload.values) + store(state, payload) { + Vue.set(state.entries, payload.id, payload.values) }, update(state, payload) { - if (payload.id in state.reminders) { - const reminder = { ...state.reminders[payload.id] } - Object.assign(reminder, payload) - Vue.set(state.reminders, payload.id, reminder) + if (payload.id in state.entries) { + const entry = { ...state.entries[payload.id] } + Object.assign(entry, payload) + Vue.set(state.entries, payload.id, entry) } }, - delete(state, payload) { + /*delete(state, payload) { if (payload in state.reminders) { Vue.delete(state.reminders, payload) } diff --git a/src/store/gui/maintenance/types.ts b/src/store/gui/maintenance/types.ts index cf57a7050..ca77aae3f 100644 --- a/src/store/gui/maintenance/types.ts +++ b/src/store/gui/maintenance/types.ts @@ -5,15 +5,25 @@ export interface GuiMaintenanceState { } export interface GuiMaintenanceStateEntry { - id: string + id?: string name: string note: string + start_time: number + end_time: number | null + reminder: boolean reminderRepeat: boolean + reminderFilament: boolean - reminderFilamentValue: number | null + reminderFilamentStart: number + reminderFilamentTrigger: number | null + reminderFilamentEnd: number | null + reminderPrinttime: boolean - reminderPrinttimeValue: number | null + reminderPrinttimeStart: number | null + reminderPrinttimeTrigger: number | null + reminderPrinttimeEnd: number | null + reminderDate: boolean - reminderDateValue: number | null + reminderDateTrigger: number | null } diff --git a/src/store/gui/notifications/getters.ts b/src/store/gui/notifications/getters.ts index da2a165ca..a62de622a 100644 --- a/src/store/gui/notifications/getters.ts +++ b/src/store/gui/notifications/getters.ts @@ -276,7 +276,7 @@ export const getters: GetterTree = { getNotificationsOverdueReminders: (state, getters, rootState, rootGetters) => { const notifications: GuiNotificationStateEntry[] = [] - let reminders: GuiRemindersStateReminder[] = rootGetters['gui/reminders/getOverdueReminders'] + /*let reminders: GuiRemindersStateReminder[] = rootGetters['gui/reminders/getOverdueReminders'] const date = rootState.server.system_boot_at ?? new Date() @@ -304,7 +304,7 @@ export const getters: GetterTree = { dismissed: false, }) }) - } + }*/ return notifications }, diff --git a/src/store/server/actions.ts b/src/store/server/actions.ts index 208790fba..b7abf509f 100644 --- a/src/store/server/actions.ts +++ b/src/store/server/actions.ts @@ -63,9 +63,9 @@ export const actions: ActionTree = { dispatch('socket/addInitModule', 'gui/webcam/init', { root: true }) dispatch('gui/webcams/init', null, { root: true }) } - if (payload.namespaces?.includes('reminders')) { - dispatch('socket/addInitModule', 'gui/reminders/init', { root: true }) - dispatch('gui/reminders/init', null, { root: true }) + if (payload.namespaces?.includes('maintenance')) { + dispatch('socket/addInitModule', 'gui/maintenance/init', { root: true }) + dispatch('gui/maintenance/init', null, { root: true }) } commit('saveDbNamespaces', payload.namespaces) From 28633fa378fbb55d151e9a8f530e1a46e0bf54c1 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Mon, 22 May 2023 22:31:05 +0200 Subject: [PATCH 21/71] feat: add Maintenance entry in history list panel Signed-off-by: Stefan Dej --- ...vue => HistoryListPanelAddMaintenance.vue} | 2 +- .../HistoryListEntryMaintenance.vue | 70 +++++++++++++++++++ src/components/panels/HistoryListPanel.vue | 51 ++++++++++++-- 3 files changed, 118 insertions(+), 5 deletions(-) rename src/components/dialogs/{HistoryListPanelAddMaintenace.vue => HistoryListPanelAddMaintenance.vue} (99%) create mode 100644 src/components/panels/HistoryList/HistoryListEntryMaintenance.vue diff --git a/src/components/dialogs/HistoryListPanelAddMaintenace.vue b/src/components/dialogs/HistoryListPanelAddMaintenance.vue similarity index 99% rename from src/components/dialogs/HistoryListPanelAddMaintenace.vue rename to src/components/dialogs/HistoryListPanelAddMaintenance.vue index 28f24c989..3ceb15d5f 100644 --- a/src/components/dialogs/HistoryListPanelAddMaintenace.vue +++ b/src/components/dialogs/HistoryListPanelAddMaintenance.vue @@ -122,7 +122,7 @@ import { mdiCloseThick, mdiNotebookPlus } from '@mdi/js' SettingsRow, }, }) -export default class HistoryListPanelAddMaintenace extends Mixins(BaseMixin) { +export default class HistoryListPanelAddMaintenance extends Mixins(BaseMixin) { mdiCloseThick = mdiCloseThick mdiNotebookPlus = mdiNotebookPlus diff --git a/src/components/panels/HistoryList/HistoryListEntryMaintenance.vue b/src/components/panels/HistoryList/HistoryListEntryMaintenance.vue new file mode 100644 index 000000000..ab05782be --- /dev/null +++ b/src/components/panels/HistoryList/HistoryListEntryMaintenance.vue @@ -0,0 +1,70 @@ + + diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index de3da35b7..e95610336 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -27,7 +27,7 @@ {{ mdiDelete }} - + + @@ -156,7 +164,9 @@ import { } from '@mdi/js' import HistoryListPanelDetailsDialog from '@/components/dialogs/HistoryListPanelDetailsDialog.vue' import HistoryListEntryJob from '@/components/panels/HistoryList/HistoryListEntryJob.vue' -import HistoryListPanelAddMaintenace from '@/components/dialogs/HistoryListPanelAddMaintenace.vue' +import HistoryListPanelAddMaintenance from '@/components/dialogs/HistoryListPanelAddMaintenace.vue' +import { GuiMaintenanceStateEntry } from '@/store/gui/maintenance/types' +import HistoryListEntryMaintenance from '@/components/panels/HistoryList/HistoryListEntryMaintenance.vue' export interface HistoryListPanelRow { text: string @@ -169,7 +179,13 @@ export interface HistoryListPanelRow { } @Component({ - components: { HistoryListPanelAddMaintenace, HistoryListEntryJob, HistoryListPanelDetailsDialog, Panel }, + components: { + HistoryListEntryMaintenance, + HistoryListPanelAddMaintenance, + HistoryListEntryJob, + HistoryListPanelDetailsDialog, + Panel, + }, }) export default class HistoryListPanel extends Mixins(BaseMixin) { mdiCloseThick = mdiCloseThick @@ -189,10 +205,37 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { private deleteSelectedDialog = false + mounted() { + window.console.log(this.maintenanceEntries) + } + get jobs() { return this.$store.getters['server/history/getFilterdJobList'] ?? [] } + get maintenanceEntries() { + const entries = this.$store.getters['gui/maintenance/getEntries'] ?? [] + + window.console.log('mEntries', entries) + + return entries + } + + get entries() { + let entries = [...this.jobs].map((job) => { + return { ...job, type: 'job' } + }) + + entries = [ + ...entries, + ...this.maintenanceEntries.map((entry: GuiMaintenanceStateEntry) => { + return { ...entry, type: 'maintenance' } + }), + ] + + return entries + } + get selectedJobs() { return this.$store.state.gui.view.history.selectedJobs ?? [] } From 66e409a7673724d92598e7c1d749042e7585bfb1 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Mon, 22 May 2023 22:31:20 +0200 Subject: [PATCH 22/71] refactor: remove unused icon Signed-off-by: Stefan Dej --- .../panels/HistoryList/HistoryListEntryMaintenance.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/panels/HistoryList/HistoryListEntryMaintenance.vue b/src/components/panels/HistoryList/HistoryListEntryMaintenance.vue index ab05782be..1ec645e82 100644 --- a/src/components/panels/HistoryList/HistoryListEntryMaintenance.vue +++ b/src/components/panels/HistoryList/HistoryListEntryMaintenance.vue @@ -21,7 +21,7 @@ import { Component, Mixins, Prop } from 'vue-property-decorator' import HistoryListPanelDetailsDialog from '@/components/dialogs/HistoryListPanelDetailsDialog.vue' import Panel from '@/components/ui/Panel.vue' import BaseMixin from '@/components/mixins/base' -import { mdiCloseThick, mdiDelete, mdiFile, mdiFileCancel } from '@mdi/js' +import { mdiCloseThick, mdiDelete, mdiFile } from '@mdi/js' import { HistoryListPanelRow } from '@/components/panels/HistoryListPanel.vue' import HistoryListPanelNoteDialog from '@/components/dialogs/HistoryListPanelNoteDialog.vue' import { GuiMaintenanceStateEntry } from '@/store/gui/maintenance/types' From 1c5d738601b2f492e3373183d1dfe6eaf398ead9 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Sun, 1 Oct 2023 18:18:46 +0200 Subject: [PATCH 23/71] refactor: fix merging issue Signed-off-by: Stefan Dej --- src/components/panels/HistoryListPanel.vue | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index f4d3c87ab..a9f4a0334 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -166,7 +166,7 @@ import { } from '@mdi/js' import HistoryListPanelDetailsDialog from '@/components/dialogs/HistoryListPanelDetailsDialog.vue' import HistoryListEntryJob from '@/components/panels/HistoryList/HistoryListEntryJob.vue' -import HistoryListPanelAddMaintenance from '@/components/dialogs/HistoryListPanelAddMaintenace.vue' +import HistoryListPanelAddMaintenance from '@/components/dialogs/HistoryListPanelAddMaintenance.vue' import { GuiMaintenanceStateEntry } from '@/store/gui/maintenance/types' import HistoryListEntryMaintenance from '@/components/panels/HistoryList/HistoryListEntryMaintenance.vue' @@ -201,15 +201,11 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { formatFilesize = formatFilesize - private search = '' - private sortBy = 'start_time' - private sortDesc = true + search = '' + sortBy = 'start_time' + sortDesc = true - private deleteSelectedDialog = false - - mounted() { - window.console.log(this.maintenanceEntries) - } + deleteSelectedDialog = false get jobs() { return this.$store.getters['server/history/getFilterdJobList'] ?? [] From 494e42513354ef5c1650595b99def5018a84c741 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Tue, 13 Feb 2024 00:11:13 +0100 Subject: [PATCH 24/71] refactor: refactor history list panel Signed-off-by: Stefan Dej --- .../dialogs/HistoryDeleteJobDialog.vue | 49 + .../HistoryDeleteSelectedJobsDialog.vue | 58 ++ .../dialogs/HistoryDetailsDialog.vue | 170 ++++ .../dialogs/HistoryDetailsDialogEntry.vue | 41 + src/components/dialogs/HistoryNoteDialog.vue | 67 ++ src/components/panels/GcodefilesPanel.vue | 39 +- .../History/HistoryListPanelExportCsv.vue | 143 +++ .../panels/History/HistoryListRow.vue | 226 +++++ .../panels/History/HistoryListRowCell.vue | 61 ++ src/components/panels/HistoryListPanel.vue | 954 +++--------------- .../panels/HistoryStatisticsPanel.vue | 23 +- src/plugins/helpers.ts | 32 +- src/store/server/history/getters.ts | 4 +- src/store/server/history/types.ts | 11 +- 14 files changed, 997 insertions(+), 881 deletions(-) create mode 100644 src/components/dialogs/HistoryDeleteJobDialog.vue create mode 100644 src/components/dialogs/HistoryDeleteSelectedJobsDialog.vue create mode 100644 src/components/dialogs/HistoryDetailsDialog.vue create mode 100644 src/components/dialogs/HistoryDetailsDialogEntry.vue create mode 100644 src/components/dialogs/HistoryNoteDialog.vue create mode 100644 src/components/panels/History/HistoryListPanelExportCsv.vue create mode 100644 src/components/panels/History/HistoryListRow.vue create mode 100644 src/components/panels/History/HistoryListRowCell.vue diff --git a/src/components/dialogs/HistoryDeleteJobDialog.vue b/src/components/dialogs/HistoryDeleteJobDialog.vue new file mode 100644 index 000000000..e41c5d20d --- /dev/null +++ b/src/components/dialogs/HistoryDeleteJobDialog.vue @@ -0,0 +1,49 @@ + + diff --git a/src/components/dialogs/HistoryDeleteSelectedJobsDialog.vue b/src/components/dialogs/HistoryDeleteSelectedJobsDialog.vue new file mode 100644 index 000000000..1db91ae57 --- /dev/null +++ b/src/components/dialogs/HistoryDeleteSelectedJobsDialog.vue @@ -0,0 +1,58 @@ + + diff --git a/src/components/dialogs/HistoryDetailsDialog.vue b/src/components/dialogs/HistoryDetailsDialog.vue new file mode 100644 index 000000000..dfa3c2c34 --- /dev/null +++ b/src/components/dialogs/HistoryDetailsDialog.vue @@ -0,0 +1,170 @@ + + + diff --git a/src/components/dialogs/HistoryDetailsDialogEntry.vue b/src/components/dialogs/HistoryDetailsDialogEntry.vue new file mode 100644 index 000000000..5bc3cc735 --- /dev/null +++ b/src/components/dialogs/HistoryDetailsDialogEntry.vue @@ -0,0 +1,41 @@ + + diff --git a/src/components/dialogs/HistoryNoteDialog.vue b/src/components/dialogs/HistoryNoteDialog.vue new file mode 100644 index 000000000..ee8f75735 --- /dev/null +++ b/src/components/dialogs/HistoryNoteDialog.vue @@ -0,0 +1,67 @@ + + diff --git a/src/components/panels/GcodefilesPanel.vue b/src/components/panels/GcodefilesPanel.vue index 052a61bde..966c19f3b 100644 --- a/src/components/panels/GcodefilesPanel.vue +++ b/src/components/panels/GcodefilesPanel.vue @@ -727,7 +727,6 @@ export default class GcodefilesPanel extends Mixins(BaseMixin, ControlMixin) { mdiDragVertical = mdiDragVertical formatFilesize = formatFilesize - formatPrintTime = formatPrintTime sortFiles = sortFiles declare $refs: { @@ -1519,32 +1518,32 @@ export default class GcodefilesPanel extends Mixins(BaseMixin, ControlMixin) { outputValue(col: any, item: FileStateGcodefile) { const value = col.value in item ? item[col.value] : null - if (value !== null) { - switch (col.outputType) { - case 'filesize': - return formatFilesize(value) + if (value === null) return '--' - case 'date': - return this.formatDateTime(value) + switch (col.outputType) { + case 'filesize': + return formatFilesize(value) - case 'time': - return this.formatPrintTime(value) + case 'date': + return this.formatDateTime(value) - case 'temp': - return value.toFixed() + ' °C' + case 'time': + return formatPrintTime(value) - case 'length': - if (value > 1000) return (value / 1000).toFixed(2) + ' m' + case 'temp': + return value.toFixed() + ' °C' - return value.toFixed(2) + ' mm' + case 'length': + if (value > 1000) return (value / 1000).toFixed(2) + ' m' - case 'weight': - return value.toFixed(2) + ' g' + return value.toFixed(2) + ' mm' - default: - return value - } - } else return '--' + case 'weight': + return value.toFixed(2) + ' g' + + default: + return value + } } } diff --git a/src/components/panels/History/HistoryListPanelExportCsv.vue b/src/components/panels/History/HistoryListPanelExportCsv.vue new file mode 100644 index 000000000..5e7177497 --- /dev/null +++ b/src/components/panels/History/HistoryListPanelExportCsv.vue @@ -0,0 +1,143 @@ + + + diff --git a/src/components/panels/History/HistoryListRow.vue b/src/components/panels/History/HistoryListRow.vue new file mode 100644 index 000000000..eb1c98cfa --- /dev/null +++ b/src/components/panels/History/HistoryListRow.vue @@ -0,0 +1,226 @@ + + diff --git a/src/components/panels/History/HistoryListRowCell.vue b/src/components/panels/History/HistoryListRowCell.vue new file mode 100644 index 000000000..c651b08a0 --- /dev/null +++ b/src/components/panels/History/HistoryListRowCell.vue @@ -0,0 +1,61 @@ + + diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index 3ef8af0b9..fb68d47bf 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -1,585 +1,173 @@ - + + {{ mdiNotebookPlus }} + @@ -167,6 +170,7 @@ import { mdiDelete, mdiFileDocumentMultipleOutline, mdiMagnify, + mdiNotebookPlus, } from '@mdi/js' import HistoryListPanelDetailsDialog from '@/components/dialogs/HistoryListPanelDetailsDialog.vue' import HistoryListEntryJob from '@/components/panels/HistoryList/HistoryListEntryJob.vue' @@ -196,11 +200,12 @@ export interface HistoryListPanelRow { export default class HistoryListPanel extends Mixins(BaseMixin) { mdiCloseThick = mdiCloseThick mdiCog = mdiCog + mdiDatabaseArrowDownOutline = mdiDatabaseArrowDownOutline mdiDatabaseExportOutline = mdiDatabaseExportOutline mdiDelete = mdiDelete mdiFileDocumentMultipleOutline = mdiFileDocumentMultipleOutline mdiMagnify = mdiMagnify - mdiDatabaseArrowDownOutline = mdiDatabaseArrowDownOutline + mdiNotebookPlus = mdiNotebookPlus formatFilesize = formatFilesize @@ -208,6 +213,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { sortBy = 'start_time' sortDesc = true + addMaintenanceDialog = false deleteSelectedDialog = false get allLoaded() { From 48bf08db296058d2f99d5339d3dd2f5fce4bf249 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Mon, 4 Mar 2024 21:07:29 +0100 Subject: [PATCH 34/71] refactor: rename getFilteredJobList getter Signed-off-by: Stefan Dej --- src/components/panels/HistoryListPanel.vue | 2 +- src/store/server/history/getters.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index dc1789f99..712327d6a 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -221,7 +221,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { } get jobs() { - return this.$store.getters['server/history/getFilterdJobList'] ?? [] + return this.$store.getters['server/history/getFilteredJobList'] ?? [] } get maintenanceEntries() { diff --git a/src/store/server/history/getters.ts b/src/store/server/history/getters.ts index b9841ca47..836f6bc76 100644 --- a/src/store/server/history/getters.ts +++ b/src/store/server/history/getters.ts @@ -354,7 +354,7 @@ export const getters: GetterTree = { } }, - getFilterdJobList: (state, getters, rootState) => { + getFilteredJobList: (state, getters, rootState) => { const hideStatus = rootState.gui.view.history.hidePrintStatus return state.jobs.filter((job: ServerHistoryStateJob) => { From 78f481b971c135777fd790fc86196a8ed3996dea Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Mon, 4 Mar 2024 21:07:40 +0100 Subject: [PATCH 35/71] refactor: remove HistoryRemindersPanel.vue Signed-off-by: Stefan Dej --- .../panels/HistoryRemindersPanel.vue | 506 ------------------ 1 file changed, 506 deletions(-) delete mode 100644 src/components/panels/HistoryRemindersPanel.vue diff --git a/src/components/panels/HistoryRemindersPanel.vue b/src/components/panels/HistoryRemindersPanel.vue deleted file mode 100644 index a6547f417..000000000 --- a/src/components/panels/HistoryRemindersPanel.vue +++ /dev/null @@ -1,506 +0,0 @@ - - - From b6c42f096b532a0cf73315bda1aa4f4f140fab7d Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Mon, 4 Mar 2024 21:21:03 +0100 Subject: [PATCH 36/71] refactor: separate HistoryListPanelDeleteSelectedDialog.vue from HistoryListPanel.vue Signed-off-by: Stefan Dej --- .../HistoryListPanelDeleteSelectedDialog.vue | 66 ++++ src/components/panels/HistoryListPanel.vue | 303 +++++++----------- 2 files changed, 186 insertions(+), 183 deletions(-) create mode 100644 src/components/dialogs/HistoryListPanelDeleteSelectedDialog.vue diff --git a/src/components/dialogs/HistoryListPanelDeleteSelectedDialog.vue b/src/components/dialogs/HistoryListPanelDeleteSelectedDialog.vue new file mode 100644 index 000000000..281c6d75d --- /dev/null +++ b/src/components/dialogs/HistoryListPanelDeleteSelectedDialog.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index 712327d6a..ad5fec6d2 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -1,159 +1,133 @@ diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index ad5fec6d2..d4eb7e4a3 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -201,11 +201,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { } get maintenanceEntries() { - const entries = this.$store.getters['gui/maintenance/getEntries'] ?? [] - - window.console.log('mEntries', entries) - - return entries + return this.$store.getters['gui/maintenance/getEntries'] ?? [] } get entries() { @@ -213,6 +209,8 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { return { ...job, type: 'job' } }) + if (this.sortBy !== 'start_time') return entries + entries = [ ...entries, ...this.maintenanceEntries.map((entry: GuiMaintenanceStateEntry) => { diff --git a/src/components/panels/HistoryStatisticsPanel.vue b/src/components/panels/HistoryStatisticsPanel.vue index ae6b25126..20b31c4c9 100644 --- a/src/components/panels/HistoryStatisticsPanel.vue +++ b/src/components/panels/HistoryStatisticsPanel.vue @@ -12,15 +12,15 @@