From 4851c3b7ae3f872aeba80e1c026e37d70dc2b669 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Mon, 1 May 2023 21:17:54 +0200 Subject: [PATCH 01/46] refactor: move HistoryListPanelDetailsDialog to a own component Signed-off-by: Stefan Dej --- .../dialogs/HistoryListPanelDetailsDialog.vue | 256 ++++++++++++++++++ src/components/panels/HistoryListPanel.vue | 207 +------------- src/store/server/history/getters.ts | 4 +- src/store/server/history/types.ts | 28 +- 4 files changed, 295 insertions(+), 200 deletions(-) create mode 100644 src/components/dialogs/HistoryListPanelDetailsDialog.vue diff --git a/src/components/dialogs/HistoryListPanelDetailsDialog.vue b/src/components/dialogs/HistoryListPanelDetailsDialog.vue new file mode 100644 index 000000000..3ae016ebd --- /dev/null +++ b/src/components/dialogs/HistoryListPanelDetailsDialog.vue @@ -0,0 +1,256 @@ + + + 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 02/46] 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 04/46] 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 06/46] 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 07/46] 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 11/46] 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 12/46] 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 13/46] 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 14/46] 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 7131f39c2e59d7cff0a9ff69f36f3a0c500f3f0f Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Wed, 14 Feb 2024 19:31:45 +0100 Subject: [PATCH 15/46] locale(de): update german locale (#1772) Co-authored-by: rackrick <45207681+rackrick@users.noreply.github.com> --- src/locales/de.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/locales/de.json b/src/locales/de.json index 885e42c3d..f7e4b544d 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -299,19 +299,15 @@ "InvalidNameAscii": "Name ist ungültig. Nur ASCII Zeichen sind erlaubt.", "InvalidNameEmpty": "Feld darf nicht leer sein!", "InvalidNameReserved": "Das Profil 'default' ist reserviert, bitte wähle einen anderen Profilnamen.", - "Later": "später", "Mesh": "Mesh", "Name": "Name", "NoBedMeshHasBeenLoadedYet": "Es wurde noch kein Bed Mesh geladen.", "NoProfile": "Kein Profil verfügbar", - "Ok": "Ok", "Probed": "Abgetastet", "Profiles": "Profile", "Remove": "löschen", - "RemoveSaveDescription": "Das Löschen des Höhenprofils wurde registriert. Mit einem Klick auf SAVE_CONFIG wird es aus der printer.cfg gelöscht und Klipper neu gestartet.", "Rename": "umbenennen", "RenameBedMeshProfile": "Bed Mesh umbenennen", - "SAVE_CONFIG": "SAVE_CONFIG", "ScaleGradient": "Farbverlauf skalieren", "ScaleZMax": "Skaliere z-max.", "TitleCalibrate": "Neues Bed Mesh kalibrieren", @@ -1088,6 +1084,11 @@ "RetractDistanceDescription": "Die Länge an Filament die der Extruder zurückzieht.", "RetractSpeed": "Rückzuggeschwindigkeit", "RetractSpeedDescription": "Geschwindigkeit mit der der Extruder das Filament zurückzieht.", + "RulesBetweenMinMax": "Der Wert muss zwischen {min} und {max} sein!", + "RulesMin": "Der Wert muss mindestens {min} sein!", + "RulesPositive": "Der Wert muss positiv sein!", + "RulesRequired": "Der Wert ist erforderlich!", + "RulesZeroAndPositive": "Der Wert muss 0 oder größer sein!", "SaveFrames": "Bilder speichern", "SaveFramesDescription": "Speichern der Bilder in einer Zip-Datei für externes Rendern", "StreamDelayCompensation": "Stream-Verzögerungs-Kompensation", From 087d55af7ffc6853314846efebc29c80ceb71548 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Wed, 14 Feb 2024 19:31:57 +0100 Subject: [PATCH 16/46] fix: fix ETA calculation from jobqueue during print preheat (#1773) --- src/components/panels/Status/JobqueueEntrySum.vue | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/panels/Status/JobqueueEntrySum.vue b/src/components/panels/Status/JobqueueEntrySum.vue index d994db3a0..28fcd8526 100644 --- a/src/components/panels/Status/JobqueueEntrySum.vue +++ b/src/components/panels/Status/JobqueueEntrySum.vue @@ -103,10 +103,18 @@ export default class StatusPanelJobqueueEntrySum extends Mixins(BaseMixin) { } get currentPrintEta() { - const eta = this.$store.getters['printer/getEstimatedTimeETA'] - if (eta === 0) return Date.now() + let eta = this.$store.getters['printer/getEstimatedTimeETA'] + if (eta) return eta + + // if no eta and printer is printing, use the estimated time from the current file + now. + // this is a fallback for the case when the printer is in the preheating time, and the + // estimated time is not yet available + if (this.printerIsPrinting && this.$store.state.printer.print_stats?.print_duration === 0) { + return Date.now() + (this.$store.state.printer.current_file?.estimated_time ?? 0) * 1000 + } - return eta + // fallback current time + return Date.now() } get eta() { From 88e98271297fda8e903af1742de9cee4b3a897cd Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Wed, 14 Feb 2024 22:12:20 +0100 Subject: [PATCH 17/46] locale(en): fix typo in DescriptionPreviouslyThrottled (#1776) --- src/locales/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/locales/en.json b/src/locales/en.json index 58639460a..d72f18c2a 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -46,7 +46,7 @@ "DescriptionFrequencyCapped": "rPi ARM max frequency is currently limited to 1.2 GHz.", "DescriptionPreviouslyFrequencyCapped": "rPi ARM max frequency was at least once limited to 1.2 GHz since last power-on.", "DescriptionPreviouslyTemperatureLimited": "rPi uC (3A+/3B+ only) temperature was at least once above the soft limit (default 60C) since last power-on.", - "DescriptionPreviouslyThrottled": "rPI ARM core(s) where throttled down at least once since last power-on.", + "DescriptionPreviouslyThrottled": "rPI ARM core(s) were throttled down at least once since last power-on.", "DescriptionPreviouslyUnderVolted": "rPI supply voltage dropped below 4.65V at least once since the last power-on.", "DescriptionTemperatureLimitActive": "rPi uC (3A+/3B+ only) temperature is currently above the soft limit (default 60C).", "DescriptionUnderVoltageDetected": "rPI supply voltage currently below 4.65V", From b9b793dfae6ca9228605af6778c7f5c226644bd0 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Thu, 15 Feb 2024 19:26:25 +0100 Subject: [PATCH 18/46] feat: add devices dialog in editor (#1765) --- src/components/TheEditor.vue | 13 +- src/components/dialogs/DevicesDialog.vue | 111 ++++++++++++++++++ src/components/dialogs/DevicesDialogCan.vue | 84 +++++++++++++ .../dialogs/DevicesDialogCanDevice.vue | 32 +++++ .../dialogs/DevicesDialogSerial.vue | 72 ++++++++++++ .../dialogs/DevicesDialogSerialDevice.vue | 45 +++++++ src/components/dialogs/DevicesDialogUsb.vue | 74 ++++++++++++ .../dialogs/DevicesDialogUsbDevice.vue | 55 +++++++++ src/components/dialogs/DevicesDialogVideo.vue | 103 ++++++++++++++++ .../DevicesDialogVideoDeviceLibcamera.vue | 61 ++++++++++ .../dialogs/DevicesDialogVideoDeviceV4l2.vue | 84 +++++++++++++ src/components/inputs/TextfieldWithCopy.vue | 52 ++++++++ src/locales/en.json | 18 +++ src/plugins/helpers.ts | 34 ++++++ src/store/variables.ts | 2 +- 15 files changed, 837 insertions(+), 3 deletions(-) create mode 100644 src/components/dialogs/DevicesDialog.vue create mode 100644 src/components/dialogs/DevicesDialogCan.vue create mode 100644 src/components/dialogs/DevicesDialogCanDevice.vue create mode 100644 src/components/dialogs/DevicesDialogSerial.vue create mode 100644 src/components/dialogs/DevicesDialogSerialDevice.vue create mode 100644 src/components/dialogs/DevicesDialogUsb.vue create mode 100644 src/components/dialogs/DevicesDialogUsbDevice.vue create mode 100644 src/components/dialogs/DevicesDialogVideo.vue create mode 100644 src/components/dialogs/DevicesDialogVideoDeviceLibcamera.vue create mode 100644 src/components/dialogs/DevicesDialogVideoDeviceV4l2.vue create mode 100644 src/components/inputs/TextfieldWithCopy.vue diff --git a/src/components/TheEditor.vue b/src/components/TheEditor.vue index 4d0974c67..df97f93ce 100644 --- a/src/components/TheEditor.vue +++ b/src/components/TheEditor.vue @@ -13,6 +13,10 @@ :icon="isWriteable ? mdiFileDocumentEditOutline : mdiFileDocumentOutline" :title="title"> @@ -135,14 +140,17 @@ import { mdiHelp, mdiHelpCircle, mdiRestart, + mdiUsb, } from '@mdi/js' import type Codemirror from '@/components/inputs/Codemirror.vue' +import DevicesDialog from '@/components/dialogs/DevicesDialog.vue' @Component({ - components: { Panel, CodemirrorAsync }, + components: { DevicesDialog, Panel, CodemirrorAsync }, }) export default class TheEditor extends Mixins(BaseMixin) { - private dialogConfirmChange = false + dialogConfirmChange = false + dialogDevices = false formatFilesize = formatFilesize @@ -157,6 +165,7 @@ export default class TheEditor extends Mixins(BaseMixin) { mdiHelpCircle = mdiHelpCircle mdiFileDocumentEditOutline = mdiFileDocumentEditOutline mdiFileDocumentOutline = mdiFileDocumentOutline + mdiUsb = mdiUsb private scrollbarOptions = { scrollbars: { autoHide: 'never' } } diff --git a/src/components/dialogs/DevicesDialog.vue b/src/components/dialogs/DevicesDialog.vue new file mode 100644 index 000000000..10555aaeb --- /dev/null +++ b/src/components/dialogs/DevicesDialog.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/src/components/dialogs/DevicesDialogCan.vue b/src/components/dialogs/DevicesDialogCan.vue new file mode 100644 index 000000000..39a6dc1c4 --- /dev/null +++ b/src/components/dialogs/DevicesDialogCan.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/src/components/dialogs/DevicesDialogCanDevice.vue b/src/components/dialogs/DevicesDialogCanDevice.vue new file mode 100644 index 000000000..163362ce3 --- /dev/null +++ b/src/components/dialogs/DevicesDialogCanDevice.vue @@ -0,0 +1,32 @@ + + + diff --git a/src/components/dialogs/DevicesDialogSerial.vue b/src/components/dialogs/DevicesDialogSerial.vue new file mode 100644 index 000000000..0a0104c86 --- /dev/null +++ b/src/components/dialogs/DevicesDialogSerial.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/src/components/dialogs/DevicesDialogSerialDevice.vue b/src/components/dialogs/DevicesDialogSerialDevice.vue new file mode 100644 index 000000000..b3293ee33 --- /dev/null +++ b/src/components/dialogs/DevicesDialogSerialDevice.vue @@ -0,0 +1,45 @@ + + + diff --git a/src/components/dialogs/DevicesDialogUsb.vue b/src/components/dialogs/DevicesDialogUsb.vue new file mode 100644 index 000000000..229b0e9ff --- /dev/null +++ b/src/components/dialogs/DevicesDialogUsb.vue @@ -0,0 +1,74 @@ + + + + + diff --git a/src/components/dialogs/DevicesDialogUsbDevice.vue b/src/components/dialogs/DevicesDialogUsbDevice.vue new file mode 100644 index 000000000..58458994c --- /dev/null +++ b/src/components/dialogs/DevicesDialogUsbDevice.vue @@ -0,0 +1,55 @@ + + + diff --git a/src/components/dialogs/DevicesDialogVideo.vue b/src/components/dialogs/DevicesDialogVideo.vue new file mode 100644 index 000000000..f6ef97c9e --- /dev/null +++ b/src/components/dialogs/DevicesDialogVideo.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/src/components/dialogs/DevicesDialogVideoDeviceLibcamera.vue b/src/components/dialogs/DevicesDialogVideoDeviceLibcamera.vue new file mode 100644 index 000000000..22091d0dc --- /dev/null +++ b/src/components/dialogs/DevicesDialogVideoDeviceLibcamera.vue @@ -0,0 +1,61 @@ + + + diff --git a/src/components/dialogs/DevicesDialogVideoDeviceV4l2.vue b/src/components/dialogs/DevicesDialogVideoDeviceV4l2.vue new file mode 100644 index 000000000..7909db8fa --- /dev/null +++ b/src/components/dialogs/DevicesDialogVideoDeviceV4l2.vue @@ -0,0 +1,84 @@ + + + diff --git a/src/components/inputs/TextfieldWithCopy.vue b/src/components/inputs/TextfieldWithCopy.vue new file mode 100644 index 000000000..81b3fe969 --- /dev/null +++ b/src/components/inputs/TextfieldWithCopy.vue @@ -0,0 +1,52 @@ + + + diff --git a/src/locales/en.json b/src/locales/en.json index d72f18c2a..504b53644 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -36,6 +36,9 @@ "NoEmptyAllowedError": "Input must not be empty!" }, "Printers": "Printers", + "TextfieldWithCopy": { + "Copied": "Copied" + }, "TheServiceWorker": { "DescriptionNeedUpdate": "The local cache is outdated and needs to be updated. Please click on the button below to update the cache.", "TitleNeedUpdate": "PWA needs update", @@ -146,6 +149,20 @@ "SendCode": "Send code...", "SetupConsole": "Setup Console" }, + "DevicesDialog": { + "CanBusInfo": "Only unassigned nodes can be detected. It’s recommended to have only one unassigned device connected to the can bus to avoid communication issues. For more details, please click on the link:", + "ClickRefresh": "Click on the refresh button to search for devices.", + "DevicePath": "Device path", + "Formats": "Formats", + "Headline": "Devices", + "HideSystemEntries": "Hide system entries", + "LibcameraId": "Libcamera ID", + "NoDeviceFound": "No device found. Please check the connection and click on the refresh button.", + "PathByHardware": "Path by hardware", + "PathById": "Path by ID", + "Refresh": "refresh", + "Resolutions": "Resolutions" + }, "Dialogs": { "StartPrint": { "Cancel": "Cancel", @@ -158,6 +175,7 @@ }, "Editor": { "ConfigReference": "Config Reference", + "DeviceDialog": "Devices", "DontSave": "Don't save", "Downloading": "Downloading", "FailedSave": "{filename} could not be uploaded!", diff --git a/src/plugins/helpers.ts b/src/plugins/helpers.ts index 0641ec209..8cbd54a94 100644 --- a/src/plugins/helpers.ts +++ b/src/plugins/helpers.ts @@ -248,3 +248,37 @@ export function windowBeforeUnloadFunction(e: BeforeUnloadEvent) { e.preventDefault() e.returnValue = '' } + +export function copyToClipboard(text: string) { + if (navigator.clipboard) { + navigator.clipboard.writeText(text) + return + } + + const textArea = document.createElement('textarea') + let element = document.getElementById('devices-dialog') + if (!element) element = document.body + + textArea.value = text + textArea.style.position = 'absolute' + textArea.style.top = '0' + textArea.style.left = '0' + textArea.style.zIndex = '100000' + textArea.style.opacity = '0' + element.appendChild(textArea) + textArea.focus() + textArea.select() + try { + document.execCommand('copy') + } catch (err) { + console.error('Unable to copy to clipboard', err) + } + textArea.remove() +} + +export function sortResolutions(a: string, b: string) { + const aSplit = parseInt(a.split('x')[0]) + const bSplit = parseInt(b.split('x')[0]) + + return aSplit - bSplit +} diff --git a/src/store/variables.ts b/src/store/variables.ts index 8afa67f6f..f3676d781 100644 --- a/src/store/variables.ts +++ b/src/store/variables.ts @@ -4,7 +4,7 @@ export const defaultPrimaryColor = '#2196f3' export const defaultBigThumbnailBackground = '#1e1e1e' export const minKlipperVersion = 'v0.11.0-257' -export const minMoonrakerVersion = 'v0.8.0-137' +export const minMoonrakerVersion = 'v0.8.0-306' export const minBrowserVersions = [{ name: 'safari', version: '16.5.2' }] export const colorArray = ['#F44336', '#8e379d', '#03DAC5', '#3F51B5', '#ffde03', '#009688', '#E91E63'] From 3b78c3bf2bba979959e80c664f64376eb53d96f8 Mon Sep 17 00:00:00 2001 From: "Michal Dziekonski (mdz)" Date: Thu, 15 Feb 2024 20:20:14 +0100 Subject: [PATCH 19/46] fix: file upload rate displays `NaN` instead of an actual value (#1777) --- src/components/TheTopbar.vue | 28 ++++-------------- src/components/gcodeviewer/Viewer.vue | 29 ++++--------------- .../panels/Machine/ConfigFilesPanel.vue | 8 ----- src/store/files/actions.ts | 27 ++++------------- 4 files changed, 15 insertions(+), 77 deletions(-) diff --git a/src/components/TheTopbar.vue b/src/components/TheTopbar.vue index ee9225313..c74ab0980 100644 --- a/src/components/TheTopbar.vue +++ b/src/components/TheTopbar.vue @@ -110,7 +110,7 @@ import { Mixins } from 'vue-property-decorator' import BaseMixin from '@/components/mixins/base' import { validGcodeExtensions } from '@/store/variables' import Component from 'vue-class-component' -import axios from 'axios' +import axios, { AxiosProgressEvent } from 'axios' import { formatFilesize } from '@/plugins/helpers' import TheTopCornerMenu from '@/components/TheTopCornerMenu.vue' import TheSettingsMenu from '@/components/TheSettingsMenu.vue' @@ -128,10 +128,6 @@ type uploadSnackbar = { speed: number total: number cancelTokenSource: any - lastProgress: { - time: number - loaded: number - } } @Component({ @@ -162,10 +158,6 @@ export default class TheTopbar extends Mixins(BaseMixin) { speed: 0, total: 0, cancelTokenSource: null, - lastProgress: { - time: 0, - loaded: 0, - }, } formatFilesize = formatFilesize @@ -317,8 +309,6 @@ export default class TheTopbar extends Mixins(BaseMixin) { this.uploadSnackbar.status = true this.uploadSnackbar.percent = 0 this.uploadSnackbar.speed = 0 - this.uploadSnackbar.lastProgress.loaded = 0 - this.uploadSnackbar.lastProgress.time = 0 formData.append('file', file, filename) formData.append('print', 'true') @@ -329,18 +319,10 @@ export default class TheTopbar extends Mixins(BaseMixin) { .post(this.apiUrl + '/server/files/upload', formData, { cancelToken: this.uploadSnackbar.cancelTokenSource.token, headers: { 'Content-Type': 'multipart/form-data' }, - onUploadProgress: (progressEvent: ProgressEvent) => { - this.uploadSnackbar.percent = (progressEvent.loaded * 100) / progressEvent.total - if (this.uploadSnackbar.lastProgress.time) { - const time = progressEvent.timeStamp - this.uploadSnackbar.lastProgress.time - const data = progressEvent.loaded - this.uploadSnackbar.lastProgress.loaded - - if (time) this.uploadSnackbar.speed = data / (time / 1000) - } - - this.uploadSnackbar.lastProgress.time = progressEvent.timeStamp - this.uploadSnackbar.lastProgress.loaded = progressEvent.loaded - this.uploadSnackbar.total = progressEvent.total + onUploadProgress: (progressEvent: AxiosProgressEvent) => { + this.uploadSnackbar.percent = (progressEvent.progress ?? 0) * 100 + this.uploadSnackbar.speed = progressEvent.rate ?? 0 + this.uploadSnackbar.total = progressEvent.total ?? 0 }, }) .then((result) => { diff --git a/src/components/gcodeviewer/Viewer.vue b/src/components/gcodeviewer/Viewer.vue index 778415ec5..6e195f752 100644 --- a/src/components/gcodeviewer/Viewer.vue +++ b/src/components/gcodeviewer/Viewer.vue @@ -277,7 +277,7 @@ import { Component, Mixins, Prop, Ref, Watch } from 'vue-property-decorator' import BaseMixin from '../mixins/base' import GCodeViewer from '@sindarius/gcodeviewer' -import axios from 'axios' +import axios, { AxiosProgressEvent } from 'axios' import { formatFilesize } from '@/plugins/helpers' import Panel from '@/components/ui/Panel.vue' import CodeStream from '@/components/gcodeviewer/CodeStream.vue' @@ -304,10 +304,6 @@ interface downloadSnackbar { speed: number total: number cancelTokenSource: any - lastProgress: { - time: number - loaded: number - } } let viewer: any = null @@ -357,10 +353,6 @@ export default class Viewer extends Mixins(BaseMixin) { speed: 0, total: 0, cancelTokenSource: {}, - lastProgress: { - time: 0, - loaded: 0, - }, } private excludeObject = { @@ -634,7 +626,6 @@ export default class Viewer extends Mixins(BaseMixin) { async loadFile(filename: string) { this.downloadSnackbar.status = true this.downloadSnackbar.speed = 0 - this.downloadSnackbar.lastProgress.time = 0 this.downloadSnackbar.filename = filename.startsWith('gcodes/') ? filename.slice(7) : filename const CancelToken = axios.CancelToken this.downloadSnackbar.cancelTokenSource = CancelToken.source() @@ -642,20 +633,10 @@ export default class Viewer extends Mixins(BaseMixin) { .get(this.apiUrl + '/server/files/' + encodeURI(filename), { cancelToken: this.downloadSnackbar.cancelTokenSource.token, responseType: 'blob', - onDownloadProgress: (progressEvent) => { - this.downloadSnackbar.percent = (progressEvent.loaded * 100) / progressEvent.total - if (this.downloadSnackbar.lastProgress.time) { - const time = progressEvent.timeStamp - this.downloadSnackbar.lastProgress.time - const data = progressEvent.loaded - this.downloadSnackbar.lastProgress.loaded - - if (time > 1000 || this.downloadSnackbar.speed === 0) { - this.downloadSnackbar.speed = data / (time / 1000) - this.downloadSnackbar.lastProgress.time = progressEvent.timeStamp - this.downloadSnackbar.lastProgress.loaded = progressEvent.loaded - } - } else this.downloadSnackbar.lastProgress.time = progressEvent.timeStamp - - this.downloadSnackbar.total = progressEvent.total + onDownloadProgress: (progressEvent: AxiosProgressEvent) => { + this.downloadSnackbar.percent = (progressEvent.progress ?? 0) * 100 + this.downloadSnackbar.speed = progressEvent.rate ?? 0 + this.downloadSnackbar.total = progressEvent.total ?? 0 }, }) .then((res) => res.data.text()) diff --git a/src/components/panels/Machine/ConfigFilesPanel.vue b/src/components/panels/Machine/ConfigFilesPanel.vue index b289778ad..293738e96 100644 --- a/src/components/panels/Machine/ConfigFilesPanel.vue +++ b/src/components/panels/Machine/ConfigFilesPanel.vue @@ -601,10 +601,6 @@ interface uploadSnackbar { number: number max: number cancelTokenSource: any - lastProgress: { - time: number - loaded: number - } } interface draggingFile { @@ -719,10 +715,6 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin, ThemeMixin) { number: 0, max: 0, cancelTokenSource: {}, - lastProgress: { - time: 0, - loaded: 0, - }, } private draggingFile: draggingFile = { item: { diff --git a/src/store/files/actions.ts b/src/store/files/actions.ts index ca0af88cf..032e98e22 100644 --- a/src/store/files/actions.ts +++ b/src/store/files/actions.ts @@ -10,7 +10,7 @@ import { import { RootState } from '@/store/types' import i18n from '@/plugins/i18n' import { hiddenDirectories, validGcodeExtensions } from '@/store/variables' -import axios from 'axios' +import axios, { AxiosProgressEvent } from 'axios' import { BatchMessage } from '@/plugins/webSocketClient' export const actions: ActionTree = { @@ -316,34 +316,17 @@ export const actions: ActionTree = { await commit('uploadSetFilename', payload.file.name) await commit('uploadSetShow', true) - let lastTime = 0 - let lastLoaded = 0 - return new Promise((resolve) => { axios .post(apiUrl + '/server/files/upload', formData, { cancelToken: cancelTokenSource.token, headers: { 'Content-Type': 'multipart/form-data' }, - onUploadProgress: (progressEvent: any) => { - const percent = (progressEvent.loaded * 100) / progressEvent.total + onUploadProgress: (progressEvent: AxiosProgressEvent) => { + const percent = (progressEvent.progress ?? 0) * 100 commit('uploadSetPercent', percent) - if (lastTime === 0) { - lastTime = progressEvent.timeStamp - lastLoaded = progressEvent.loaded - - return - } - - const time = progressEvent.timeStamp - lastTime - if (time < 1000) return - - const data = progressEvent.loaded - lastLoaded - const speed = data / (time / 1000) - commit('uploadSetSpeed', speed) - - lastTime = progressEvent.timeStamp - lastLoaded = progressEvent.loaded + const rate = progressEvent.rate ?? 0 + commit('uploadSetSpeed', rate) }, }) .then((result: any) => { From 8e7db0da04915f734fa8802ae76d5f283621f4de Mon Sep 17 00:00:00 2001 From: "Michal Dziekonski (mdz)" Date: Thu, 15 Feb 2024 22:28:56 +0100 Subject: [PATCH 20/46] feat: add ability to add history items to job queue (#1778) Co-authored-by: Stefan Dej --- .../dialogs/AddBatchToQueueDialog.vue | 120 ++++++++++++++++++ src/components/panels/GcodefilesPanel.vue | 100 +++------------ src/components/panels/HistoryListPanel.vue | 47 ++++++- src/components/panels/Status/Gcodefiles.vue | 96 ++------------ src/components/panels/Status/Jobqueue.vue | 4 +- src/locales/en.json | 1 + 6 files changed, 198 insertions(+), 170 deletions(-) create mode 100644 src/components/dialogs/AddBatchToQueueDialog.vue diff --git a/src/components/dialogs/AddBatchToQueueDialog.vue b/src/components/dialogs/AddBatchToQueueDialog.vue new file mode 100644 index 000000000..f98c958c9 --- /dev/null +++ b/src/components/dialogs/AddBatchToQueueDialog.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/src/components/panels/GcodefilesPanel.vue b/src/components/panels/GcodefilesPanel.vue index 052a61bde..712ba6136 100644 --- a/src/components/panels/GcodefilesPanel.vue +++ b/src/components/panels/GcodefilesPanel.vue @@ -568,53 +568,10 @@ - - - - - - - - - - - - {{ $t('Files.Cancel') }} - {{ $t('Files.AddToQueue') }} - - - + @@ -628,8 +585,6 @@ import Panel from '@/components/ui/Panel.vue' import SettingsRow from '@/components/settings/SettingsRow.vue' import draggable from 'vuedraggable' import { - mdiChevronDown, - mdiChevronUp, mdiDragVertical, mdiCheckboxBlankOutline, mdiCheckboxMarked, @@ -654,6 +609,7 @@ import { mdiContentCopy, } from '@mdi/js' import StartPrintDialog from '@/components/dialogs/StartPrintDialog.vue' +import AddBatchToQueueDialog from '@/components/dialogs/AddBatchToQueueDialog.vue' import ControlMixin from '@/components/mixins/control' import PathNavigation from '@/components/ui/PathNavigation.vue' @@ -675,12 +631,6 @@ interface dialogPrintFile { item: FileStateGcodefile } -interface dialogAddBatchToQueue { - show: boolean - count: number - item: FileStateGcodefile -} - interface dialogRenameObject { show: boolean newName: string @@ -698,11 +648,9 @@ interface tableColumnSetting { } @Component({ - components: { StartPrintDialog, Panel, SettingsRow, PathNavigation, draggable }, + components: { StartPrintDialog, AddBatchToQueueDialog, Panel, SettingsRow, PathNavigation, draggable }, }) export default class GcodefilesPanel extends Mixins(BaseMixin, ControlMixin) { - mdiChevronDown = mdiChevronDown - mdiChevronUp = mdiChevronUp mdiContentCopy = mdiContentCopy mdiFile = mdiFile mdiFileDocumentMultipleOutline = mdiFileDocumentMultipleOutline @@ -779,10 +727,9 @@ export default class GcodefilesPanel extends Mixins(BaseMixin, ControlMixin) { item: { ...this.contextMenu.item }, } - private dialogAddBatchToQueue: dialogAddBatchToQueue = { - show: false, - count: 1, - item: { ...this.contextMenu.item }, + dialogAddBatchToQueue: { isVisible: boolean; filename: string } = { + isVisible: false, + filename: '', } private dialogRenameFile: dialogRenameObject = { @@ -1272,23 +1219,15 @@ export default class GcodefilesPanel extends Mixins(BaseMixin, ControlMixin) { } openAddBatchToQueueDialog(item: FileStateGcodefile) { - this.dialogAddBatchToQueue.show = true - this.dialogAddBatchToQueue.count = 1 - this.dialogAddBatchToQueue.item = item - } - - async addBatchToQueueAction() { - let filename = [this.currentPath, this.dialogAddBatchToQueue.item.filename].join('/') + let filename = [this.currentPath, item.filename].join('/') if (filename.startsWith('/')) filename = filename.slice(1) - const array: string[] = [] - for (let i = 0; i < this.dialogAddBatchToQueue.count; i++) { - array.push(filename) - } - - await this.$store.dispatch('server/jobQueue/addToQueue', array) + this.dialogAddBatchToQueue.isVisible = true + this.dialogAddBatchToQueue.filename = filename + } - this.dialogAddBatchToQueue.show = false + closeAddBatchToQueueDialog() { + this.dialogAddBatchToQueue.isVisible = false } changeMetadataVisible(name: string, value: boolean) { @@ -1549,15 +1488,6 @@ export default class GcodefilesPanel extends Mixins(BaseMixin, ControlMixin) { } - - diff --git a/src/components/panels/Status/Jobqueue.vue b/src/components/panels/Status/Jobqueue.vue index 85ca50dd9..e9ee73c94 100644 --- a/src/components/panels/Status/Jobqueue.vue +++ b/src/components/panels/Status/Jobqueue.vue @@ -13,7 +13,9 @@ -
{{ $t('Panels.StatusPanel.EmptyJobqueue') }}
+
+

{{ $t('Panels.StatusPanel.EmptyJobqueue') }}

+
diff --git a/src/locales/en.json b/src/locales/en.json index 504b53644..1006432eb 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -339,6 +339,7 @@ }, "History": { "AddNote": "Add note", + "AddToQueueSuccessful": "File {filename} added to Queue.", "AllJobs": "All", "AvgPrinttime": "Print Time - Ø", "Cancel": "Cancel", From 021cb61f61485b61017153d0401d9e101330ffd3 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 21:40:03 +0000 Subject: [PATCH 21/46] chore: push version number to v2.10.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 011e9f425..f03b16774 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mainsail", - "version": "2.9.1", + "version": "2.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mainsail", - "version": "2.9.1", + "version": "2.10.0", "dependencies": { "@codemirror/commands": "^6.0.1", "@codemirror/lang-css": "^6.0.0", diff --git a/package.json b/package.json index c2c31dfc2..f077bb3ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mainsail", - "version": "2.9.1", + "version": "2.10.0", "private": true, "decription": "a klipper web interface", "author": { From 9c4eade646a957a40e4af91218cac49f4f716293 Mon Sep 17 00:00:00 2001 From: meteyou Date: Thu, 15 Feb 2024 21:42:51 +0000 Subject: [PATCH 22/46] docs(changelog): update changelog --- CHANGELOG.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca2208e0d..e6175037c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,47 @@ # Changelog All notable changes to Mainsail will be documented in this file. +## [2.10.0](https://github.com/mainsail-crew/mainsail/releases/tag/v2.10.0) - 2024-02-15 +### Features + +- **history**: Add interrupted state to history job ([#1738](https://github.com/mainsail-crew/mainsail/pull/1738)) +- Add ability to re-arrange job queue's items ([#1692](https://github.com/mainsail-crew/mainsail/pull/1692)) +- Add sum + eta in jobqueue panel ([#1770](https://github.com/mainsail-crew/mainsail/pull/1770)) +- Add devices dialog in editor ([#1765](https://github.com/mainsail-crew/mainsail/pull/1765)) +- Add ability to add history items to job queue ([#1778](https://github.com/mainsail-crew/mainsail/pull/1778)) + +### Bug Fixes and Improvements + +- **console**: Fix color of autocomplete and command list ([#1733](https://github.com/mainsail-crew/mainsail/pull/1733)) +- **timelapse**: Fix issue with changing timelapse settings ([#1745](https://github.com/mainsail-crew/mainsail/pull/1745)) +- Incorrect scaling of images in dialogImage ([#1746](https://github.com/mainsail-crew/mainsail/pull/1746)) +- Show extruder extra menu without load/unload macros ([#1747](https://github.com/mainsail-crew/mainsail/pull/1747)) +- Fix ETA calculation from jobqueue during print preheat ([#1773](https://github.com/mainsail-crew/mainsail/pull/1773)) +- File upload rate displays `NaN` instead of an actual value ([#1777](https://github.com/mainsail-crew/mainsail/pull/1777)) + +### Performance + +- Batch gcode file metadata requests ([#1737](https://github.com/mainsail-crew/mainsail/pull/1737)) + +### Refactor + +- Refactor spoolman integration to support v2 response ([#1749](https://github.com/mainsail-crew/mainsail/pull/1749)) +- Refactor heightmap page ([#1759](https://github.com/mainsail-crew/mainsail/pull/1759)) + +### Localization + +- **da**: Update danish translation ([#1757](https://github.com/mainsail-crew/mainsail/pull/1757)) +- **de**: Update german locale ([#1772](https://github.com/mainsail-crew/mainsail/pull/1772)) +- **en**: Fix typo in DescriptionPreviouslyThrottled ([#1776](https://github.com/mainsail-crew/mainsail/pull/1776)) +- **it**: Update italian translation ([#1763](https://github.com/mainsail-crew/mainsail/pull/1763)) +- **zh**: Update chinese locale ([#1767](https://github.com/mainsail-crew/mainsail/pull/1767)) + +### Other + +- **deps**: Update @sindarius/gcodeviewer ([#1755](https://github.com/mainsail-crew/mainsail/pull/1755)) +- Update github issue bot text ([#1743](https://github.com/mainsail-crew/mainsail/pull/1743)) +- Fix typo in bot text ([#1748](https://github.com/mainsail-crew/mainsail/pull/1748)) + ## [2.9.1](https://github.com/mainsail-crew/mainsail/releases/tag/v2.9.1) - 2023-12-31 ### Bug Fixes and Improvements From 4f46d40071347b764452b42625082b1b3254b004 Mon Sep 17 00:00:00 2001 From: Paolo Paterna Date: Sat, 17 Feb 2024 15:23:26 +0100 Subject: [PATCH 23/46] chore(deps): Update @sindarius/gcodeviewer (#1755) (#1783) --- package-lock.json | 148 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/package-lock.json b/package-lock.json index f03b16774..aa968f738 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "@codemirror/view": "^6.0.3", "@jaames/iro": "^5.5.2", "@lezer/highlight": "^1.0.0", - "@sindarius/gcodeviewer": "^3.7.6", + "@sindarius/gcodeviewer": "^3.7.8", "@uiw/codemirror-theme-vscode": "^4.19.11", "axios": "^1.6.0", "codemirror": "^6.0.1", @@ -2136,76 +2136,76 @@ } }, "node_modules/@babylonjs/core": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-5.57.1.tgz", - "integrity": "sha512-k8U+SFPVGvHgeNr651nxZL26iVCmTzjmRrdbQa0BGas+lg8PIV/tfhN4uTeWWQeRFLvjbkcHA5qD8x/Xk3EpMQ==" + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-6.43.0.tgz", + "integrity": "sha512-pLFvvtC26TeICUcF0YjuuQqvCahJwPlATXnJkvBzMWXXxUE0Y5rI8L28iScu2WKy975605KdccJI5VL2NG7sUQ==" }, "node_modules/@babylonjs/gui": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-5.57.1.tgz", - "integrity": "sha512-NUOYKF5iAA0UmFFHUBkb12K9Zvqw8BnOVAbM27CZ7WpnHFQ+4/CJuy9nFoCGkBjv2A5W7M1ML/7cjmce0CbdRA==", + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-6.43.0.tgz", + "integrity": "sha512-iYsB7uyC40w0QkFGcPw8jAzE26jsgTFvWHTVKPSZxjQ5cG2RQEeK3aD8l+GvWauSc2qPB0wMOsvkAtusdy1g7g==", "peer": true, "peerDependencies": { - "@babylonjs/core": "^5.22.0" + "@babylonjs/core": "^6.0.0" } }, "node_modules/@babylonjs/gui-editor": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@babylonjs/gui-editor/-/gui-editor-5.57.1.tgz", - "integrity": "sha512-FY4py7CzLiW0NAd0atBb5oCI/bS6kLsfszliZFvgrWl+eJ6z54aD1m23dZ+zvy8IqxcbSUkFYKqSfRinZttnkA==", + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@babylonjs/gui-editor/-/gui-editor-6.43.0.tgz", + "integrity": "sha512-OtahbC04Mklj2i2WdGlYXc9oN/ntpp2DuNZhqc1l95ioPIZWtlhSzMQKzh6/VmJQZBwwRi8HZwPPjQ1arIkRHA==", "peer": true, "peerDependencies": { - "@babylonjs/core": "^5.22.0", - "@babylonjs/gui": "^5.22.0", + "@babylonjs/core": "^6.0.0", + "@babylonjs/gui": "^6.0.0", "@types/react": ">=16.7.3", "@types/react-dom": ">=16.0.9" } }, "node_modules/@babylonjs/inspector": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-5.57.1.tgz", - "integrity": "sha512-F40V91R4h+vhlmBs7FHA4qQkFKjJwWF78cUhUgTVwGdwHDRwZ3Pweu26xEfTtw71am26tgHgBZedBTNCokgqtQ==", + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-6.43.0.tgz", + "integrity": "sha512-Cjw/Xk8v5/84IFi6rhLS363XgDkQzPrfQG7nFKHF6k8OWwz8Ze/cb8O8IeXKEc2QFImCdRnZoDv7BkJnZ03Caw==", "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.1.0", "@fortawesome/free-regular-svg-icons": "^6.0.0", "@fortawesome/free-solid-svg-icons": "^6.0.0" }, "peerDependencies": { - "@babylonjs/core": "^5.22.0", - "@babylonjs/gui": "^5.22.0", - "@babylonjs/gui-editor": "^5.22.0", - "@babylonjs/loaders": "^5.22.0", - "@babylonjs/materials": "^5.22.0", - "@babylonjs/serializers": "^5.22.0", + "@babylonjs/core": "^6.0.0", + "@babylonjs/gui": "^6.0.0", + "@babylonjs/gui-editor": "^6.0.0", + "@babylonjs/loaders": "^6.0.0", + "@babylonjs/materials": "^6.0.0", + "@babylonjs/serializers": "^6.0.0", "@types/react": ">=16.7.3", "@types/react-dom": ">=16.0.9" } }, "node_modules/@babylonjs/loaders": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-5.57.1.tgz", - "integrity": "sha512-DHk0iOwJgnTcj8vI+cQVzpiUvWGJvYqWyZxsf7nzhbeND+ZwNWSG0AelaGbGHpWTaDSd/DjUcoWVZuT4Cg6/Xg==", + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-6.43.0.tgz", + "integrity": "sha512-+cgw4NDchjc/5dZYGzOEhJU+9++ygYlA+ChybE5yvF+yUDWZ7fGXnEXMFImXeFELjk5RRK1NS3H3YvPe7A+Rug==", "peerDependencies": { - "@babylonjs/core": "^5.22.0", - "babylonjs-gltf2interface": "^5.22.0" + "@babylonjs/core": "^6.0.0", + "babylonjs-gltf2interface": "^6.0.0" } }, "node_modules/@babylonjs/materials": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@babylonjs/materials/-/materials-5.57.1.tgz", - "integrity": "sha512-NLdR6eGUr+wFqie937HRWsnaWPeECpjOrYDGvjjYDg08VAcIC3YyctAuQxv8rId7BoDttkUd8Ey/IZ5d/9H7GA==", + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@babylonjs/materials/-/materials-6.43.0.tgz", + "integrity": "sha512-x4pKz2d0IRFZ9pmWIJ4FR/X5mak8Ycl2tAQtOf1ihsanNyDgXnB3Jfgl9z9TaoQSoU2y+HpjvenDF4oaLkXzUw==", "peerDependencies": { - "@babylonjs/core": "^5.22.0" + "@babylonjs/core": "^6.0.0" } }, "node_modules/@babylonjs/serializers": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-5.57.1.tgz", - "integrity": "sha512-wV7pMhvEP9lf3zjYo2YmQDl2D8V617wONkMuNRj+lpJsD2I2PT7B2wxUqtKVoCY+TyCEM5ns9vn722V7bHZiHg==", + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-6.43.0.tgz", + "integrity": "sha512-cVFGO98SapRf/QJRQx7+hZkbFnDhXuHK9obDJKKpv/76vSpLWDoLoZk1v1Nu8pm30n75Ukffcco77Za14ZZhFA==", "peer": true, "peerDependencies": { - "@babylonjs/core": "^5.22.0", - "babylonjs-gltf2interface": "^5.22.0" + "@babylonjs/core": "^6.0.0", + "babylonjs-gltf2interface": "^6.0.0" } }, "node_modules/@codemirror/autocomplete": { @@ -2825,45 +2825,45 @@ } }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.2.tgz", - "integrity": "sha512-1DgP7f+XQIJbLFCTX1V2QnxVmpLdKdzzo2k8EmvDOePfchaIGQ9eCHj2up3/jNEbZuBqel5OxiaOJf37TWauRA==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz", + "integrity": "sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==", "hasInstallScript": true, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.2.tgz", - "integrity": "sha512-gjYDSKv3TrM2sLTOKBc5rH9ckje8Wrwgx1CxAPbN5N3Fm4prfi7NsJVWd1jklp7i5uSCVwhZS5qlhMXqLrpAIg==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz", + "integrity": "sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.2" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.2.tgz", - "integrity": "sha512-0+sIUWnkgTVVXVAPQmW4vxb9ZTHv0WstOa3rBx9iPxrrrDH6bNLsDYuwXF9b6fGm+iR7DKQvQshUH/FJm3ed9Q==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.1.tgz", + "integrity": "sha512-m6ShXn+wvqEU69wSP84coxLbNl7sGVZb+Ca+XZq6k30SzuP3X4TfPqtycgUh9ASwlNh5OfQCd8pDIWxl+O+LlQ==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.2" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.2.tgz", - "integrity": "sha512-sYwXurXUEQS32fZz9hVCUUv/xu49PEJEyUOsA51l6PU/qVgfbTb2glsTEaJngVVT8VqBATRIdh7XVgV1JF1LkA==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz", + "integrity": "sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.4.2" + "@fortawesome/fontawesome-common-types": "6.5.1" }, "engines": { "node": ">=6" @@ -3197,14 +3197,14 @@ "dev": true }, "node_modules/@sindarius/gcodeviewer": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/@sindarius/gcodeviewer/-/gcodeviewer-3.7.6.tgz", - "integrity": "sha512-6L8znazyJgAJ8IiDTSF1o4DB+iQxszM3WfsQBFcKaSIwUYJVWQIpuccHrXvsvFQB6xQ7WAwrac5grkGfzIrNpA==", - "dependencies": { - "@babylonjs/core": "^5.53.0", - "@babylonjs/inspector": "^5.53.0", - "@babylonjs/loaders": "^5.53.0", - "@babylonjs/materials": "^5.53.0", + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/@sindarius/gcodeviewer/-/gcodeviewer-3.7.8.tgz", + "integrity": "sha512-/Z9YE/GaVBV4dydju9kJ1uv8/GlffUzjoIGYxlj+kvZnBhP7OZ0ZWviL7zs4d7npSwSw7J+LNYWaIpVW13KQrA==", + "dependencies": { + "@babylonjs/core": "^6.43.0", + "@babylonjs/inspector": "^6.43.0", + "@babylonjs/loaders": "^6.43.0", + "@babylonjs/materials": "^6.43.0", "d3": "^7.4.4" } }, @@ -3293,15 +3293,15 @@ "dev": true }, "node_modules/@types/prop-types": { - "version": "15.7.8", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.8.tgz", - "integrity": "sha512-kMpQpfZKSCBqltAJwskgePRaYRFukDkm1oItcAbC3gNELR20XIBcN9VRgg4+m8DKsTfkWeA4m4Imp4DDuWy7FQ==", + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", "peer": true }, "node_modules/@types/react": { - "version": "18.2.24", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.24.tgz", - "integrity": "sha512-Ee0Jt4sbJxMu1iDcetZEIKQr99J1Zfb6D4F3qfUWoR1JpInkY1Wdg4WwCyBjL257D0+jGqSl1twBjV8iCaC0Aw==", + "version": "18.2.56", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.56.tgz", + "integrity": "sha512-NpwHDMkS/EFZF2dONFQHgkPRwhvgq/OAvIaGQzxGSBmaeR++kTg6njr15Vatz0/2VcCEwJQFi6Jf4Q0qBu0rLA==", "peer": true, "dependencies": { "@types/prop-types": "*", @@ -3310,9 +3310,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.8", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.8.tgz", - "integrity": "sha512-bAIvO5lN/U8sPGvs1Xm61rlRHHaq5rp5N3kp9C+NJ/Q41P8iqjkXSu0+/qu8POsjH9pNWb0OYabFez7taP7omw==", + "version": "18.2.19", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz", + "integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==", "peer": true, "dependencies": { "@types/react": "*" @@ -3328,9 +3328,9 @@ } }, "node_modules/@types/scheduler": { - "version": "0.16.4", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.4.tgz", - "integrity": "sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==", + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", "peer": true }, "node_modules/@types/semver": { @@ -4225,9 +4225,9 @@ } }, "node_modules/babylonjs-gltf2interface": { - "version": "5.57.1", - "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-5.57.1.tgz", - "integrity": "sha512-RZnaKfJ6Q/AYLdIjBYMRxCW/HPEC8jabAL1U8wJ0KVziw6NSbSV6S80S22fUCPTyaZ7nCekn1TYg1IPmJ/eA6w==", + "version": "6.43.0", + "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-6.43.0.tgz", + "integrity": "sha512-+orCb4giE41Ysl8d2ZOeYCRBsT6FnmDwkW9+sHcEACUEpdtFeTShZ+ckucDAB/Ia2e3ah9F2hADbGA/8TfFngg==", "peer": true }, "node_modules/balanced-match": { diff --git a/package.json b/package.json index f077bb3ac..74cbd5c73 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@codemirror/view": "^6.0.3", "@jaames/iro": "^5.5.2", "@lezer/highlight": "^1.0.0", - "@sindarius/gcodeviewer": "^3.7.6", + "@sindarius/gcodeviewer": "^3.7.8", "@uiw/codemirror-theme-vscode": "^4.19.11", "axios": "^1.6.0", "codemirror": "^6.0.1", From 20de6be9074db740dd871b9ba34644b002f604a1 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Sat, 17 Feb 2024 20:55:29 +0100 Subject: [PATCH 24/46] fix: fix commit list view on desktop and mobile devices (#1785) --- .../Machine/UpdatePanel/GitCommitsList.vue | 88 ++++++++++++------- .../UpdatePanel/GitCommitsListDayCommit.vue | 4 +- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/src/components/panels/Machine/UpdatePanel/GitCommitsList.vue b/src/components/panels/Machine/UpdatePanel/GitCommitsList.vue index 688ff0e4d..cc11e51d5 100644 --- a/src/components/panels/Machine/UpdatePanel/GitCommitsList.vue +++ b/src/components/panels/Machine/UpdatePanel/GitCommitsList.vue @@ -1,5 +1,5 @@ - - - - - - - - - -

{{ $t('Machine.UpdatePanel.MoreCommitsInfo') }}

-
- - {{ $t('Machine.UpdatePanel.LinkToGithub') }} - -
-
-
-
-
-
-
-
+ + + + + + + +

{{ $t('Machine.UpdatePanel.MoreCommitsInfo') }}

+
+ + {{ $t('Machine.UpdatePanel.LinkToGithub') }} + +
+
+
+
+
+
@@ -110,6 +106,24 @@ export default class GitCommitsList extends Mixins(BaseMixin) { return `https://github.com/${this.repo?.owner}/${this.repo?.name}/commits/${this.repo?.branch}/?after=${this.lastCommit?.sha}+0` } + get overlayScrollbarsStyle() { + if (this.isMobile) { + return { + height: 'calc(100vh - 48px)', + } + } + + return { + height: '400px', + } + } + + get timelineClassName() { + if (this.isMobile) return ['groupedCommits', 'mobile'] + + return ['groupedCommits'] + } + closeDialog() { this.$emit('close-dialog') } @@ -161,4 +175,18 @@ export default class GitCommitsList extends Mixins(BaseMixin) { } } } + +::v-deep .groupedCommits.mobile { + &:before { + left: 20px; + } + + .v-timeline-item__body { + max-width: calc(100% - 41px); + } + + .v-timeline-item__divider { + min-width: 41px; + } +} diff --git a/src/components/panels/Machine/UpdatePanel/GitCommitsListDayCommit.vue b/src/components/panels/Machine/UpdatePanel/GitCommitsListDayCommit.vue index 68854fbc9..44c2a3160 100644 --- a/src/components/panels/Machine/UpdatePanel/GitCommitsListDayCommit.vue +++ b/src/components/panels/Machine/UpdatePanel/GitCommitsListDayCommit.vue @@ -1,6 +1,6 @@ @@ -131,4 +131,9 @@ export default class SpoolmanChangeSpoolDialogRow extends Mixins(BaseMixin) { .no--padding { padding: 0; } + +.comment { + white-space: pre-wrap; + overflow-wrap: anywhere; +} From e0bcd7464c89856e0d0c5f35984d198f1eeb830e Mon Sep 17 00:00:00 2001 From: evgarthub Date: Sun, 18 Feb 2024 19:09:12 +0200 Subject: [PATCH 26/46] locale(uk): update ukrainian translation (#1788) --- src/locales/uk.json | 469 +++++++++++++++++++++++++++++++++----------- 1 file changed, 359 insertions(+), 110 deletions(-) diff --git a/src/locales/uk.json b/src/locales/uk.json index 02e6b68ca..684818cc9 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -1,12 +1,16 @@ { "App": { "Notifications": { + "BrowserWarnings": { + "Description": "{name} більше не підтримується. Поточна версія {version}, але Mainsail потребує версію {minVersion} або вище.", + "Headline": "Застарілий браузер" + }, "DependencyDescription": "Поточна версія {name} не підтримує всі функції Mainsail. Оновіть {Ім'я} принаймні до {needversion}.", "DependencyName": "Залежність: {Ім'я}", "DismissAll": "Відкинути всі", "KlipperWarnings": { "DeprecatedOption": "Опція '{option}' у розділі '{section}' застаріла і буде видалена у майбутньому випуску.", - "DeprecatedOptionHeadline": "Застаріла опція кліппера", + "DeprecatedOptionHeadline": "Застаріла опція Klipper", "DeprecatedValue": "Значення '{value}' опції '{option}' у секції '{section}' застаріла і буде видалена у майбутньому випуску.", "DeprecatedValueHeadline": "Застаріле значення Klipper", "KlipperWarning": "Попередження Klipper" @@ -14,6 +18,8 @@ "MoonrakerWarnings": { "MoonrakerComponent": "Moonraker: {component}", "MoonrakerFailedComponentDescription": "Помилка була виявлена під час завантаження компонента Moonraker '{component}'. Будь ласка, перевірте файл журналу та виправте проблему.", + "MoonrakerFailedInitComponentDescription": "Було виявлено помилку під час ініціалізації компонента moonraker '{component}'. Перевірте файл журналу та виправте проблему.", + "MoonrakerInitComponent": "Поч. компонент Moonraker: {component}", "MoonrakerWarning": "Попередження Moonraker", "UnparsedConfigOption": "Непарний параметр конфігурації '{option}: {value}' виявлено в розділі [{section}]. Це може бути варіантом, який більше не доступний, або може бути результатом модуля, який не зміг завантажитися.", "UnparsedConfigSection": "Непарний розділ конфігурації [{section}] виявлений. Це може бути результатом компонента, який не вдалося завантажити.." @@ -30,8 +36,16 @@ "NoEmptyAllowedError": "Поле не повинно бути порожнім!" }, "Printers": "Принтери", + "TextfieldWithCopy": { + "Copied": "Скопійовано" + }, + "TheServiceWorker": { + "DescriptionNeedUpdate": "Локальний кеш застарів і потребує оновлення. Щоб оновити кеш, натисніть кнопку нижче.", + "TitleNeedUpdate": "Веб додаток потребує оновлення", + "Update": "оновити" + }, "ThrottledStates": { - "DescriptionCurrentlyThrottled": "Ядро (и) RPI ARM в даний час зменьшуються.", + "DescriptionCurrentlyThrottled": "Ядро (и) RPI ARM в даний час зменшується.", "DescriptionFrequencyCapped": "Частота Max ARM RPI наразі обмежена 1,2 ГГц.", "DescriptionPreviouslyFrequencyCapped": "Частота Max ARM RPI принаймні раз була обмежена 1,2 ГГц з останнього ввімкнення.", "DescriptionPreviouslyTemperatureLimited": "Температура RPI UC (3a+/3b+) була принаймні раз вище за легке обмеження (за замовчуванням 60°) з останнього ввімкнення.", @@ -52,16 +66,17 @@ "Complete": "Завершено - {filename}", "Error": "Помилка", "Pause": "Призупинення друку", + "PrinterOff": "Принтер вимкнений", "Printing": "{percent}% Друк - {filename}", "PrintingETA": "{percent}% Друк - Очікуваний час: {eta} - {filename}" }, "TopBar": { "CannotUploadTheFile": "Не вдається завантажити файл!", "EmergencyStop": "АВАРІЙНА ЗУПИНКА", - "SAVE_CONFIG": "ЗБЕРЕЖЕННЯ КОНФІГУРАЦІЇ", + "SAVE_CONFIG": "ЗБЕРЕГТИ КОНФІГУРАЦІЮ", "Uploading": "Завантаження", "UploadOfFileSuccessful": "Завантаження {file} успішно!", - "UploadPrint": "Завантажити та Друканутити" + "UploadPrint": "Завантажити та надрукувати" }, "TopCornerMenu": { "Cancel": "Скасувати", @@ -71,10 +86,10 @@ "HostShutdown": "Вимкнення хоста призведе до зупинки поточного друку!", "KlipperFirmwareRestart": "Перезапуск прошивки Klipper призведе до зупинки поточного друку!", "KlipperRestart": "Перезапуск Klipper призведе до зупинки поточного друку!", - "KlipperStop": "Зупинення Кліппера призведе до зупинки поточного друку! ", + "KlipperStop": "Зупинення Klipper призведе до зупинки поточного друку! ", "ServiceRestart": "Перезапуск цього сервісу може призвести до виходу з ладу поточного друку!", - "ServiceStart": "Запуск цього сервіса може призвести до виходу з ладу поточного друку!", - "ServiceStop": "Зупинення цього сервіса може призвести до виходу з ладу поточного друку!" + "ServiceStart": "Запуск цього сервісу може призвести до виходу з ладу поточного друку!", + "ServiceStop": "Зупинення цього сервісу може призвести до виходу з ладу поточного друку!" }, "Title": { "HostReboot": "Перезавантаження хоста", @@ -107,6 +122,17 @@ "UpdatingDone": "Оновлення {software} виконано!" } }, + "BedScrews": { + "Abort": "перервати", + "Accept": "прийняти", + "Adjusted": "відрегульований", + "Description": "Натисніть ADJUSTED, якщо поточний гвинт було відрегульовано. Натисніть ACCEPT, щоб продовжити без коригування.", + "Headline": "Гвинти столу", + "ScrewAccepted": "Готові гвинти", + "ScrewIndex": "Індекс гвинта", + "ScrewName": "Ім'я гвинта", + "ScrewOutput": "{current} з {max}" + }, "ConnectionDialog": { "CannotConnectTo": "Не вдається підключитися до Moonraker ({host}).", "CheckMoonrakerLog": "Якщо це повідомлення з’являється неодноразово, будь ласка, подивіться у файл журналу, розташований за адресою:", @@ -123,10 +149,25 @@ "SendCode": "Надіслати код...", "SetupConsole": "Консоль налаштування" }, + "DevicesDialog": { + "CanBusInfo": "Можна виявити лише непризначені вузли. Рекомендується мати лише один непризначений пристрій, підключений до шини can, щоб уникнути проблем зі зв’язком. Щоб отримати детальнішу інформацію, натисніть на посилання:", + "ClickRefresh": "Натисніть кнопку оновити, щоб знайти пристрої.", + "DevicePath": "Шлях пристрою", + "Formats": "Формати", + "Headline": "Пристрої", + "HideSystemEntries": "Приховати системні записи", + "LibcameraId": "Libcamera ID", + "NoDeviceFound": "Пристрій не знайдено. Перевірте підключення та натисніть кнопку оновити.", + "PathByHardware": "Фізичний шлях", + "PathById": "Шлях за ID", + "Refresh": "оновити", + "Resolutions": "Резолюції" + }, "Dialogs": { "StartPrint": { "Cancel": "Скасувати", "DoYouWantToStartFilename": "Ви хочете роздрукувати {filename}?", + "DoYouWantToStartFilenameFilament": "Хочете почати друк {filename} з наявного філаменту?", "Headline": "Почати друк", "Print": "друк", "Timelapse": "Таймлапс" @@ -134,6 +175,7 @@ }, "Editor": { "ConfigReference": "Довідка Конфігурації", + "DeviceDialog": "Пристрої", "DontSave": "Не зберігати", "Downloading": "Завантаження", "FailedSave": "{filename} не вдалося завантажити!", @@ -149,15 +191,17 @@ "EmergencyStopDialog": { "AreYouSure": "Ви впевнені?", "EmergencyStop": "АВАРІЙНА ЗУПИНКА", - "No": "НІТ", + "No": "НІ", "Yes": "ТАК" }, "Files": { + "AddBatchToQueue": "Додати партію в чергу", "AddToQueue": "Додати в чергу", "AllFiles": "ВСІ", "BedTemp": "t° Столу.", "Cancel": "Скасувати", "ChamberTemp": "t° Камери.", + "Count": "Кількість", "Create": "Створити", "CreateNewDirectory": "Створити нову теку", "CurrentPath": "Директорія", @@ -165,11 +209,13 @@ "DeleteDirectory": "Видалити теку", "DeleteDirectoryQuestion": "Ви дійсно хочете видалити \"{name}\" теку із усім її вмістом?", "DeleteSelectedQuestion": "Ви дійсно хочете видалити {count} обрані файли?", + "DeleteSingleFileQuestion": "Ви дійсно хочете видалити файл \"{name}\"?", "Download": "Завантажити", + "Duplicate": "Дублікат", + "DuplicateFile": "Дублікат файлу", "EditFile": "Редагувати Файл", "Empty": "Порожньо", "ExtruderTemp": "t° Екструдеру.", - "Filament": "Пруток", "FilamentName": "Назва Прутка", "FilamentType": "Тип Прутка", "FilamentUsage": "Використано Прутка", @@ -181,6 +227,8 @@ "GCodeFiles": "Файли G-Code", "GcodesRootDirectoryDoesntExists": "Жодного каталогу G-коду не знайдено. Будь ласка, перевірте опцію \"path\" in the [virtual_sdcard] розділі конфігурації Klipper.", "HiddenFiles": "Приховані файли", + "InvalidNameAlreadyExists": "Ім'я вже існує, виберіть інше ім'я.", + "InvalidNameEmpty": "Поле не повинне бути порожнім!", "LastEndTime": "Закінчено", "LastFilamentUsed": "Використано прутку", "LastModified": "Завантажено", @@ -196,10 +244,12 @@ "PrintedFiles": "Надруковані Файли", "PrintStart": "Почати Друк", "PrintTime": "Час Друку", - "RefreshCurrentDirectory": "Оновити поточну дирикторію", + "RefreshCurrentDirectory": "Оновити поточну директорію", "Rename": "Перейменувати", "RenameDirectory": "Перейменувати директорію", "RenameFile": "Перейменувати Файл", + "ScanMeta": "Сканувати метадані", + "ScanMetaSuccess": "Успішно проскановано метадані з: {filename}", "Search": "Пошук", "SetupCurrentList": "Поточний список налаштування", "Slicer": "Слайсер", @@ -219,6 +269,7 @@ }, "GCodeViewer": { "ClearLoadedFile": "Очистити", + "CNCMode": "Режим ЧПД", "ColorMode": "Кольоровий Режим", "Downloading": "Завантаження", "ForceLineRendering": "Примусова лінійна Візуалізація", @@ -229,9 +280,10 @@ "Low": "Низько", "Max": "Максимум", "Medium": "Середньо", - "ReloadRequired": "Потрібно перезавантаження", + "ReloadRequired": "Потрібне перезавантаження", "Rendering": "Візуалізація", "RenderQuality": "Якість Візуалізації", + "ShowGCode": "Показати G-Code", "ShowObjectSelection": "Показати Вибір Об'єктів", "ShowToolhead": "Показати Інструмент", "ShowTravelMoves": "Показати Вільні Переміщення", @@ -253,8 +305,8 @@ "Max": "Max", "Min": "Min", "Name": "Ім'я", - "Size": "Розмір", - "Variance": "Розбіжність" + "Range": "Діапазон", + "Size": "Розмір" }, "DeleteBedMeshProfile": "Видалити профіль сітки для столу", "DoYouReallyWantToDelete": "Ви дійсно хочете видалити профіль \"{name}\"?", @@ -262,36 +314,36 @@ "Flat": "Плоский", "Heightmap": "Карта", "InvalidNameAlreadyExists": "Ім'я профілю вже існує, будь ласка, виберіть інше ім'я профілю.", + "InvalidNameAscii": "Ім'я недійсне. Дозволяється лише символи ascii.", "InvalidNameEmpty": "Введення не повинно бути порожнім!", "InvalidNameReserved": "Profile 'default' зарезервовано, будь ласка, виберіть інше ім'я профілю.", - "Later": "Згодом", "Mesh": "Сітка", "Name": "Ім'я", "NoBedMeshHasBeenLoadedYet": "Жодна сітка для ліжка ще не була завантажена.", "NoProfile": "Немає профілю", - "Ok": "OK", "Probed": "Зондований", "Profiles": "Профілі", "Remove": "видалити", - "RemoveSaveDescription": "Профіль BED_MESH зареєстрований як видалений. Клацніть на SAVE_CONFIG, щоб видалити його з printer.cfg та перезапустіть Klipper.", "Rename": "перейменувати", "RenameBedMeshProfile": "Перейменуйте профіль сітки для столу", - "SAVE_CONFIG": "SAVE_CONFIG", "ScaleGradient": "Градієнт Масштабу", "ScaleZMax": "Масштаб Z-Max.", "TitleCalibrate": "Калібрування нової сітки столу", - "TitleClear": "Очистити сітку калібровки", + "TitleClear": "Очистити сітку калібрування", "TitleHomeAll": "Всі до Дому", "Wireframe": "Каркас" }, "History": { "AddNote": "Додати коментар", + "AddToQueueSuccessful": "Файл {filename} додано до черги.", "AllJobs": "ВСІ", "AvgPrinttime": "Час Друку - Ø", "Cancel": "Скасувати", + "Chart": "Графік", "CreateNote": "Створити Примітку", "Delete": "Видалити", - "DeleteSelectedQuestion": "Ви дійсно хочете видалити {count} вибрану роботу?", + "DeleteSelectedQuestion": "Ви дійсно хочете видалити {count} вибране завдання?", + "DeleteSingleJobQuestion": "Ви справді хочете видалити завдання?", "Details": "Деталі", "EditNote": "Редагувати Примітку", "Empty": "порожньо", @@ -300,7 +352,7 @@ "EstimatedFilamentWeight": "Орієнтовна вага прутка", "EstimatedTime": "Орієнтовний Час", "FilamentCalc": "Калькулятор Прутка", - "FilamentUsage": "Використаня Прутка", + "FilamentUsage": "Використання Прутка", "FilamentUsed": "Використано Прутка", "Filename": "Ім'я", "Filesize": "Розмір", @@ -309,22 +361,23 @@ "FirstLayerHeight": "Висота першого шару", "HistoryFilamentUsage": "Пруток", "HistoryPrinttimeAVG": "Друк", - "JobDetails": "Деталі Роботи", - "Jobs": "Робота", + "JobDetails": "Деталі Завдань", + "Jobs": "Завдання", "LastModified": "Дата Створення", "LayerHeight": "Висота Шару", + "LoadCompleteHistory": "Завантажити повну історію", "LongestPrinttime": "Найдовший Час Друку", "Note": "Примітка", "ObjectHeight": "Висота Об'єкта", "PrintDuration": "Час Друку", - "PrintHistory": "Історія Роздруківок", + "PrintHistory": "Історія друку", "PrintTime": "Час Друку", "PrinttimeAvg": "Час Друку - Ø", "Reprint": "Передрукувати", - "Save": "зберігти", + "Save": "зберегти", "Search": "пошук", - "SelectedFilamentUsed": "Вибран використовуваний пруток", - "SelectedJobs": "Вибрані Роботи", + "SelectedFilamentUsed": "Використано філаменту", + "SelectedJobs": "Вибрані завдання", "SelectedPrinttime": "Вибраний Час Друку", "Slicer": "Слайсер", "SlicerVersion": "Версія Слайсера", @@ -336,28 +389,32 @@ "completed": "Закінчені", "error": "Помилкові", "in_progress": "Триває", + "interrupted": "Перерваний", "klippy_disconnect": "Klippy відключився", - "klippy_shutdown": "Помилка Кліпперу", + "klippy_shutdown": "Помилка Klipper", "Others": "Інші", "server_exit": "Вихід сервера" }, + "Table": "Таблиця", "TitleExportHistory": "Історія Експорту", - "TitleRefreshHistory": "Оновити Історію", - "TitleSettings": "Налаштування", "TotalDuration": "Загальний Час", - "TotalFilamentUsed": "Використано Прутка", - "TotalJobs": "Всі Роботи", + "TotalFilamentUsed": "Використано філаменту", + "TotalJobs": "Всі завдання", "TotalPrinttime": "Загальний Час Друку", "TotalTime": "Загальний Час" }, "JobQueue": { - "AllJobs": "Всі Роботи", + "Cancel": "Скасувати", + "ChangeCount": "Змінити кількість", + "Count": "Кількість", "Empty": "Порожньо", - "JobQueue": "Черга Робіт", - "Jobs": "Роботи", + "InvalidCountEmpty": "Поле не повинне бути порожнім!", + "InvalidCountGreaterZero": "Значення має бути більше 0!", + "JobQueue": "Черга завдань", "Pause": "Пауза", "RemoveFromQueue": "Видаліть з Черги", - "Start": "Почати" + "Start": "Почати", + "StartPrint": "Почати завдання" }, "Machine": { "ConfigFilesPanel": { @@ -373,7 +430,10 @@ "DeleteDirectory": "Видалити директорію", "DeleteDirectoryQuestion": "Видалити директорію \"{name}\" і весь її вміст?", "DeleteSelectedQuestion": "Видалити {count} вибрані елементи?", + "DeleteSingleFileQuestion": "Ви дійсно хочете видалити файл \"{name}\"?", "Download": "Завантажити", + "Duplicate": "Дублікат", + "DuplicateFile": "Дублікат файлу", "EditFile": "Редагувати файл", "Empty": "Порожньо", "Files": "Файл", @@ -404,15 +464,21 @@ "TRIGGERED": "ЗАМКНЕНО" }, "LogfilesPanel": { - "Logfiles": "Журнали" + "Accept": "прийняти", + "Cancel": "скасувати", + "Logfiles": "Журнали", + "Rollover": "Журнали переходів", + "RolloverDescription": "Виберіть, які журнали потрібно скинути:", + "RolloverToastFailed": "Перехідний журнал для \"{name}\": {message}", + "RolloverToastSuccessful": "Журнал для \"{name}\" успішно скинуто." }, "SystemPanel": { "Constants": "Константи", - "Cpu": "ЦПК", + "Cpu": "CPU", "HostDetails": "Деталі хоста", "LastStats": "Остання статистика", "Load": "Навантаження", - "Memory": "ОЗУ", + "Memory": "RAM", "NoMoreInfos": "Більше немає Infos", "SystemLoad": "Навантаження системи", "Values": { @@ -421,8 +487,8 @@ "Distro": "Дистрибутив: {name} {version_id}", "Frequency": "Частота: {frequency}", "Load": "Навантаження: {load}", - "Memory": "ОЗУ: {memory}", - "Os": "Операційка: {os}", + "Memory": "RAM: {memory}", + "Os": "Операційна Система: {os}", "Received": "Отримано: {received}", "Temp": "t° проц.: {temp}°C", "TempMax": "макс: {temp}°C", @@ -432,38 +498,68 @@ } }, "UpdatePanel": { + "Abort": "Перервати", + "AreYouSure": "Ти впевнений?", "CheckForUpdates": "Перевірити оновлення", - "Commits": "Коментар", - "CommitsAvailable": "Немає коментарів | {count} доступний коментар | {count} Доступні", - "CommitsOnDate": "Коментар від {date}", - "CommittedDaysAgo": "Прокоментовано {days} днів тому", - "CommittedHoursAgo": "Прокоментовано {hours} годин тому", - "CommittedOnDate": "Прокоментовано {date}", - "CommittedYesterday": "Сьогоднішній комент", + "Close": "Закрити", + "CommitHistory": "Історія комітів", + "Commits": "Коміт", + "CommitsAvailable": "Немає комітів | {count} доступний коміт | {count} доступних комітів", + "CommitsOnDate": "Коміт від {date}", + "CommittedDaysAgo": "Коміт {days} днів тому", + "CommittedHoursAgo": "Коміт {hours} годин тому", + "CommittedOnDate": "Коміт {date}", + "CommittedYesterday": "Коміт вчорашній", + "ConfigChanges": "Зміни конфігурації", + "Corrupt": "пошкоджений", + "CountPackagesCanBeUpgraded": "{count} пакетів можна оновити", "Detached": "відокремлений", "Dirty": "брудний", - "ERROR": "ПОМИЛКА", + "GenericUpdateQuestion": "Перевірте історію комітів (якщо доступна) і сторінку GitHub для цього пакету, щоб дізнатися, чи потрібні якісь ручні налаштування для цього оновлення.", + "GitHubPage": "Сторінка GitHub", + "HardRecovery": "Повне скидання", + "InitUpdateManager": "Менеджер оновлень ще не ініціалізовано. Це нормально, коли ви запускаєте систему вперше. Натисніть кнопку оновити, щоб ініціалізувати всі компоненти.", "Invalid": "недійсний", + "IUnderstandTheRisks": "Я розумію ризики", + "KlipperUpdateQuestionConfig": "Це оновлення також може містити зміни в параметрах конфігурації, які потрібно буде змінити у файлі printer.cfg, подробиці дивіться в журналі змін.", + "KlipperUpdateQuestionFirmware": "Це призведе до оновлення програмного забезпечення Klipper хоста. Плати керування (MCU), на яких працює мікропрограмне забезпечення Klipper, можливо, потребуватиме перепрошивки за допомогою перекомпільованого мікропрограмного забезпечення, перш ніж принтер можна буде знову ввести в експлуатацію.", + "LinkToGithub": "Посилання на GitHub", + "MoonrakerUpdateQuestion": "Це оновить Moonraker API. Для продовження використання принтера можуть знадобитися зміни у файлі moonraker.conf.", + "MoreCommitsInfo": "Тут відображено максимум 30 комітів. Щоб переглянути всі коміти, перейдіть за посиланням:", "OSPackages": "ОС-Пакети", - "PackagesCanBeUpgraded": "пакети можна оновити", + "SoftRecovery": "Часткове відновлення", + "StartUpdate": "Почати оновлення", "System": "Система", + "ThesePackagesCanBeUpgrade": "Ці системні пакети можна оновити:", "Unknown": "невідомо", "Update": "оновити", - "UpdateAll": "Оновіть усі компоненти", + "UpdateAll": "Оновити всі", "UpdateManager": "Менеджер Оновлень", + "UpdateWarning": "Попередження про оновлення: {name}", "Upgrade": "оновити", - "UpToDate": "актуальний" + "UpgradeableSystemPackages": "Системні пакети що можна оновити", + "UpToDate": "актуальний", + "WebClientUpdateQuestion": "У деяких випадках оновлення веб-клієнт має зміни, які можуть спричинити несумісність. Для отримання додаткової інформації див. примітки до релізу." } }, + "ManualProbe": { + "Abort": "перервати", + "Accept": "прийняти", + "Advanced": "Просунутий", + "Headline": "Проба вручну" + }, "Panels": { "ExtruderControlPanel": { "Allowed": "Допущений", + "CleanNozzle": "Очистити сопло", "EstimatedExtrusion": "Розрахункова екструзія:", "Extrude": "Видавити", + "ExtruderControl": "Керування екструдером", "ExtruderTempTooLow": " t° екструдера. <", "ExtrusionFactor": "Коефіцієнт ЕКСТРУЗІЇ", "ExtrusionFeedrate": "Екструзійна подача", - "FilamentLength": "Продавити на", + "FilamentLength": "Довжина філаменту", + "FirmwareRetraction": "Програмний ретракт", "FirmwareRetractionSettings": { "RetractLength": "Довжина Ретракту", "RetractSpeed": "Швидкість Ретракту", @@ -472,41 +568,50 @@ }, "Headline": "Екструдер", "LoadFilament": "Завантажити Пруток", + "PressureAdvance": "Pressure Advance", "PressureAdvanceSettings": { "Advance": "Pressure Advance", "Extruder": "Екструдер", "SmoothTime": "Плавний Час" }, - "Requested": "Запитуваний", + "PurgeFilament": "Purge філаменту", + "Requested": "Заданий", "Retract": "Ретракт", "TooLargeExtrusion": "Екструзія занадто велика!", - "UnloadFilament": "Вигрузка Прутка" + "Tools": "Інструменти", + "UnloadFilament": "Вивантаження філаменту" }, "FarmPrinterPanel": { - "ReconnectToPrinter": "Переподключення", + "ReconnectToPrinter": "Перепідключення", "SwitchToPrinter": "Перемкнутися на Принтер", "WebcamOff": "ВИМК" }, "KlippyStatePanel": { + "CheckKlippyAndUdsAddress": "Будь ласка, перевірте, чи працює служба Klipper і чи правильно налаштовано klippy_uds_address у файлі moonraker.conf.", "FirmwareRestart": "Перезапуск Прошивки", - "KlipperCheck": "Будь ласка, перевірте, чи працює служба Klipper та налаштована UDS (UNIX домен).", "MoonrakerCannotConnect": "Moonraker не може підключитися до Klipper!", - "Restart": "Перезапустити" + "PowerOn": "Увімкнено", + "PrinterSwitchedOff": "Принтер вимкнений", + "PrinterSwitchedOffDescription": "Принтер наразі вимкнено, і Klipper не може підключитися. Щоб увімкнути принтер, натисніть кнопку нижче:", + "Restart": "Перезапустити", + "ServiceReports": "{service} повідомляє" }, "MachineSettingsPanel": { "Headline": "Машина", "MotionSettings": { "Acceleration": "Прискорення", - "MaxAccelToDecel": "Max Accel. to Decel.", + "MaxAccelToDecel": "Макс. прискорення до сповільнення.", + "MinimumCruiseRatio": "Мін. коефіцієнт руху", "SquareCornerVelocity": "Квадратна кутова швидкість", "Velocity": "Швидкість" } }, "MacrosPanel": { "Headline": "Макрос", - "Send": "надсилати" + "Send": "відправити" }, "MiniconsolePanel": { + "Autoscroll": "Автопрокручування", "Headline": "Консоль", "HideTemperatures": "Сховати температуру", "HideTimelapse": "Сховати таймлапс", @@ -521,26 +626,57 @@ }, "MiscellaneousPanel": { "Headline": "Різне", + "Light": { + "Blue": "блакитний", + "Green": "зелений", + "Red": "червоний", + "White": "білий" + }, "RunoutSensor": { "Detected": "виявлено", - "Disabled": "Не активно", "Empty": "Порожньо" } }, "PowerControlPanel": { "Error": "Помилка", "Off": "ВИМК", - "On": "ВВІМК", + "On": "УВІМК", "PowerControl": "Управління Живленням" }, + "SpoolmanPanel": { + "Cancel": "Скасувати", + "ChangeSpool": "Зміна шпулі", + "DaysAgo": "{days} днів тому", + "EjectSpool": "Прибрати шпулю", + "EjectSpoolQuestion": "Ви впевнені, що хочете прибрати шпулю з філаментом?", + "Filament": "Філамент", + "FilamentTypeMismatch": "Матеріал активної шпулі ({spoolType}) не збігається з матеріалом G-коду ({fileType}).", + "Headline": "Spoolman", + "LastUsed": "Останнє використання", + "Location": "Місцезнаходження", + "Material": "Матеріал", + "Never": "Ніколи", + "NoActiveSpool": "Відстеження філаменту неактивне. Щоб почати, будь ласка, виберіть котушку.", + "NoResults": "За поточними критеріями пошуку шпулю не знайдено.", + "NoSpools": "Немає шпуль", + "NoSpoolSelected": "Шпулю не вибрано. Виберіть шпулю, інакше цей друк не відстежуватиметься.", + "OpenSpoolManager": "відкрити менеджер шпуль", + "Refresh": "оновити", + "Search": "Пошук", + "SelectSpool": "Виберіть шпулю", + "Today": "Сьогодні", + "TooLessFilament": "У поточній котушці може бути недостатньо філаменту для цього друку. ({spoolWeight}г з {fileWeight}г)", + "Weight": "Вага", + "Yesterday": "Вчора" + }, "StatusPanel": { "CancelPrint": "Скасувати друк", "ClearPrintStats": "Чітка статистика друку", "Difference": "Різниця", "EmptyGcodes": "Немає G-коду, що доступний.", - "EmptyJobqueue": "Наразі в черзі роботи немає файлу.", + "EmptyJobqueue": "Наразі в черзі завдань немає файлу.", "Estimate": "Оцінка", - "ETA": "Час Закінченя", + "ETA": "Час закінчення", "ExcludeObject": { "Cancel": "скасувати", "Excluded": "Виключений", @@ -548,21 +684,33 @@ "ExcludeObjectHeadline": "Виключіть Об'єкт", "ExcludeObjectText": "Ви дійсно хочете виключити \"{name}\"?" }, - "Filament": "Пруток", + "Filament": "Філамент", "File": "Файл", "Files": "Файли", "Flow": "Потік", "Headline": "Статус", - "Jobqueue": "Черга робіт", - "JobqueueMoreFiles": "більше нема робіт | ще одна робота | {count} більше робіт", + "Jobqueue": "Черга завдань", + "JobqueueMoreFiles": "більше нема робіт | ще одне завдання | {count} більше завдань", "Layer": "Шар", "Max": "макс", "ObjectHeight": "Висота Об'кта", + "PauseAtLayer": { + "Abort": "перервати", + "Accept": "прийняти", + "AtLayer": "на Шарі", + "Call": "Виклик", + "DescriptionPauseAtLayerActive": "Ця функція вже активна та викличе \"{call}\" на шарі {layer}. Якщо ви знову викличете команду, ці параметри буде перезаписано.", + "DescriptionPauseNextLayerActive": "Ця функція вже активна та викличе \"{call}\" на наступному шарі.", + "Layer": "Шар", + "NextLayer": "наступний шар", + "PauseAtLayer": "Пауза на шарі", + "Type": "Тип" + }, "PausePrint": "Призупинення друку", "Print": "Друк", "PrintTime": "Час Друку", "ReprintJob": "Роздруковано", - "Requested": "Запитуваний", + "Requested": "Встановлено", "ResumePrint": "Відновити друк", "Slicer": "Слайсер", "Speed": "Швидкість", @@ -581,7 +729,9 @@ "Target": "цільова температура", "Temperature": "поточна температура" }, - "Headline": "Температури", + "Headline": "Температура", + "HideMcuHostSensors": "Приховати датчики хоста/MCU", + "HideMonitors": "Приховати монітори", "Max": "макс", "Min": "мін", "Name": "Ім'я", @@ -599,18 +749,22 @@ "ToolheadControlPanel": { "Absolute": "абсолютні", "ALL": "ВСІ", + "ControlButtons": "Кнопки управління", + "CoordinateFields": "Поля координат", "Headline": "Інструмент", "PleaseConfigureSteps": "Будь ласка, налаштуйте кроки", "Position": "Положення", + "PositionOutput": "Розташування", "QGL": "QGL", "Relative": "відносні", "SettingsInterfaceControl": "Налаштування > Інтерфейс > Контроль", - "SpeedFactor": "Коефіцієнт ШВИДКОСТІі", + "SpeedFactor": "Коефіцієнт ШВИДКОСТІ", + "ZOffset": "Z-Offset", "ZTilt": "Z-Нахил" }, "WebcamPanel": { "All": "ВСІ", - "FPS": "ФПС", + "FPS": "FPS", "Headline": "Веб-камера", "NoWebcam": "Немає веб-камери. Додайте веб -камеру \"Налаштування Інтерфейсу\" -> \"Веб-камери\".", "UnknownWebcamService": "Невідома служба веб-камери" @@ -618,22 +772,20 @@ "ZoffsetPanel": { "Clear": "Очистити", "Headline": "Z-Offset", - "Later": "Згодом", + "Later": "Пізніше", "Ok": "OK", "Save": "Зберегти", - "SaveConfig": "SAVE CONFIG", - "SaveInfoDescription": "Новий Z-Offset був обчислений та зареєстрований. Натисніть на \"SAVE CONFIG\" Щоб зберегти його на printer.cfg та перезапустити Klipper.", - "SaveInfoDescriptionPrint": "Новий Z-Offset був обчислений та зареєстрований. Після друку натисніть на \"SAVE CONFIG\" у верхній панелі, щоб зберегти його у printer.cfg та перезапустити Klipper.", - "SaveInfoHeadline": "Інформація", - "ToEndstop": "до Кінцевика", - "ToProbe": "Зондувати" + "SaveConfig": "ЗБЕРЕГТИ КОНФІГУРАЦІЮ", + "SaveInfoDescription": "Новий Z-Offset був обчислений та зареєстрований. Натисніть на \"ЗБЕРЕГТИ КОНФІГУРАЦІЮ\" Щоб зберегти його на printer.cfg та перезапустити Klipper.", + "SaveInfoDescriptionPrint": "Новий Z-Offset був обчислений та зареєстрований. Після друку натисніть на \"ЗБЕРЕГТИ КОНФІГУРАЦІЮ\" у верхній панелі, щоб зберегти його у printer.cfg та перезапустити Klipper.", + "SaveInfoHeadline": "Інформація" } }, "PowerDeviceChangeDialog": { "AreYouSure": "Ви впевнені?", - "No": "НІТ", + "No": "НІ", "TurnDeviceOff": "Поворот {device} ВИМК", - "TurnDeviceOn": "Поворот {device} ВВІМК", + "TurnDeviceOn": "Поворот {device} УВІМК", "Yes": "ТАК" }, "Router": { @@ -648,6 +800,13 @@ "Timelapse": "Таймлапс", "Webcam": "Веб-камера" }, + "ScrewsTiltAdjust": { + "Accept": "прийняти", + "Base": "Основа", + "ErrorText": "Щось пішло не так під час процесу взяття проби.", + "Headline": "Гвинти регулювання нахилу", + "Retry": "повторити спробу" + }, "SelectPrinterDialog": { "AddPrinter": "Додати Принтер", "AddPrintersToJson": "Будь ласка, додайте принтери до config.json.", @@ -659,7 +818,7 @@ "Hello": "Привіт і ласкаво просимо до віддаленого режиму Mainsail!", "HostnameInvalid": "Недійсне ім'я хоста/IP", "HostnameIp": "Ім'я хоста/IP", - "HostnameRequired": "Ім'я хоста потрібно", + "HostnameRequired": "Необхідне ім'я хоста", "Port": "Порт", "PortRequired": "Потрібен порт", "RememberToAdd": "Будь ласка, не забудьте додати '{cors}' у moonraker.conf всередині 'cors_domains'.", @@ -676,10 +835,10 @@ "Console": "Консоль", "CreateHeadline": "Створити фільтр", "Direction": "Напрямок", - "DirectionShell": "Останній запис унизу", - "DirectionTable": "Останній запис у верхній частині", + "DirectionShell": "Останній запис внизу", + "DirectionTable": "Останній запис звурху", "EditHeadline": "Редагувати фільтр", - "EntryStyle": "Entry-Дизайн", + "EntryStyle": "Початковий дизайн", "EntryStyleCompact": "компактний", "EntryStyleDefault": "за замовчуванням", "Filters": "Фільтри", @@ -692,13 +851,14 @@ "UpdateButton": "Оновити фільтр" }, "ControlTab": { - "Bars": "Брус", - "Circle": "Кола", + "Bars": "Вкладка", + "Circle": "Коло", "Control": "Контроль", "Cross": "Перехрестя", "EnableXYHoming": "Увімкнути комбіноване наведення вісь X і Y до дому", "EstimatedExtrusionInfo": "Показати орієнтовну інформацію про екструзію", "EstimatedExtrusionInfoDescription": "Показати / приховати інформацію про орієнтовні екструзії на основі кількості екструзії та подачі", + "HideDuringPrint": "Приховати елементи керування віссю під час друку", "InvertXMovement": "Інвертуйте напрямок руху осі X", "InvertYMovement": "Інвертувати напрямок руху осі Y", "InvertZMovement": "Інвертувати напрямок руху осі Z", @@ -713,11 +873,13 @@ "MoveDistancesZInMm": "Дистанція переміщення вісі Z у мм", "QuadGantryLevel": "Quad Gantry Вирівнювання{isDefault}", "SpeedEInMms": "Швидкість екструзії (у мм/с)", - "SpeedXY": "Швидкість руху вісєй X та Y", + "SpeedXY": "Швидкість руху вісі X та Y", "SpeedZ": "Швидкість руху вісі Z", "Style": "Стиль", "ValueGreaterThan": "Значення повинно бути більшим, ніж {value}", "ZOffsetIncrements": "Збільшення Z-Offset (в мм)", + "ZOffsetSaveOption": "Опція збереження Z-Offset", + "ZOffsetSaveOptionDescription": "Змініть параметр, щоб зберегти Z-Offset", "ZTiltAdjust": "Налаштування Z-нахилу{isDefault}" }, "DashboardTab": { @@ -730,13 +892,16 @@ }, "Edit": "Редагувати", "EditorTab": { - "ConfirmUnsavedChanges": "Підказувати зберігати чи ніт не збережені зміни", + "ConfirmUnsavedChanges": "Підказувати зберігати чи ні не збережені зміни", "ConfirmUnsavedChangesDescription": "Якщо ввімкнено, редактор вимагає підтвердження, щоб зберегти, або відкинути внесені зміни. Якщо відключено, зміни не зберігаються.", "Editor": "Редактор", "KlipperRestartMethod": "Метод перезапуску Klipper", "KlipperRestartMethodDescription": "Виберіть, який метод перезавантаження буде використовуватися на 'Зберегти та перезапустити' під час редагування файлів конфігурації Klipper..", - "UseEscToClose": "Використовуйте ESC для закриття редактора", - "UseEscToCloseDescription": "Дозволяє клавішу ESC закрити редактор" + "Spaces": "Пробіли: {count}", + "TabSize": "Розмір відступів", + "TabSizeDescription": "Регулює кількість пробілів для табуляції", + "UseEscToClose": "ESC закриває редактор", + "UseEscToCloseDescription": "Дозволити клавішу ESC для закриття редактора" }, "GCodeViewerTab": { "BackgroundColor": "Колір фону", @@ -746,9 +911,11 @@ "MaxFeed": "Максимальна швидкість подачі", "MinFeed": "Мінімальна швидкість подачі", "ProgressColor": "Колір прогресу", - "ShowAxes": "Показати осі" + "ShowAxes": "Показати вісі" }, "GeneralTab": { + "12hours": "12 годин ({time})", + "24hours": "24 години ({time})", "Backup": "Резервна копія", "BackupDialog": "Виберіть усі розділи, які ви хочете створити резервну копію:", "CalcEstimateTime": "Оцінка розрахунку часу", @@ -763,27 +930,42 @@ "FileRelative": "Позиція файлу (відносна)", "Slicer": "Слайсер (M73)" }, - "CannotReadJson": "Не вдається читати/розбирати резервний файл.", + "CannotReadJson": "Не вдається читати/розібрати резервний файл.", + "DateFormat": "Формат дати", "DbConsoleHistory": "Історія Консолі", - "DbHistoryJobs": "Історія роботи", + "DbHistoryJobs": "Історія завдань", "DbHistoryTotals": "Загальна Історія", + "DBNavigation": "Навігація", "DbTimelapseSettings": "Налаштування Таймлапсу", "DbView": "Налаштування перегляду", - "DbWebcams": "Веб -камери", "EstimateValues": { "Filament": "Пруток", "File": "Файл", "Slicer": "Слайсер" }, + "Everything": "Все", "FactoryDialog": "Будь ласка, виберіть усі розділи, які ви хочете скинути:", "FactoryReset": "Заводські налаштування", "General": "Загальний", "Language": "Мова", - "MoonrakerDb": "Moonraker DB", + "MainsailSettingsMoonrakerDb": "Параметри Mainsail в БД Moonraker", "PrinterName": "Ім'я принтера", "Reset": "скинути", "Restore": "Відновити", - "RestoreDialog": "Будь ласка, виберіть усі розділи, які ви хочете відновити:" + "RestoreDialog": "Будь ласка, виберіть усі розділи, які ви хочете відновити:", + "TimeFormat": "Формат часу" + }, + "HeightmapTab": { + "ColorSchemes": "Палітри кольорів", + "Heightmap": "Карта висот", + "IsDefault": "(за замовчуванням)", + "Schemes": { + "GrayScale": "Відтінки сірого", + "Hot": "Теплота", + "Hsv": "Hsv", + "Portland": "Портленд", + "Spring": "Весна" + } }, "InterfaceSettings": "Налаштування інтерфейсу", "MacrosTab": { @@ -792,7 +974,7 @@ "AvailableMacros": "Доступні Макроси", "ChangeMacroColor": "Змініть колір кнопки.", "Color": "Колір", - "CountMacros": "Жодних макросів не додано | {count} Макрос | {count} Макроси", + "CountMacros": "Жодних макросів не додано | {count} Макрос | {count} Макросів", "Custom": "свій", "CustomColor": "Свій Колір", "DeletedMacro": "Видалений макрос", @@ -813,20 +995,46 @@ "NoMacrosInGroup": "У цій групі немає макросів.", "Primary": "основний", "Secondary": "вторинний", - "ShowInStatePaused": "Показати/приховати, якщо принтер призупинений.", - "ShowInStatePrinting": "Показати/приховати, якщо принтер друкує.", - "ShowInStateStandby": "Показати/приховати, якщо принтер буде в режимі очікування.", + "ShowInStatePaused": "Показати/приховати, коли принтер призупинений.", + "ShowInStatePrinting": "Показати/приховати, коли принтер друкує.", + "ShowInStateStandby": "Показати/приховати, коли принтер в режимі очікування.", "Simple": "Простий", "Status": "Статус", "Success": "успіх", "UnknownGroup": "Невідома Група", "Warning": "УВАГА" }, + "MiscellaneousTab": { + "AddGroup": "додати групу", + "AddPreset": "додати предустановку", + "Color": "Колір", + "CreateGroup": "Створити групу", + "CreatePreset": "Створити предустановку", + "End": "Кінець", + "EndDescription": "Останній світлодіод цієї групи.", + "Groups": "Групи", + "GroupSubTitle": "Початок: {start}, кінець: {end}", + "LightGroups": "{name} - Групи", + "LightPresets": "{name} - Предустановки", + "Miscellaneous": "Різне", + "Name": "Ім'я", + "NoDevicesFound": "Пристроїв не знайдено", + "NoGroupFound": "Групи не знайдено", + "NoPresetFound": "Предустановки не знайдено", + "Presets": "Предустановки", + "Start": "Cтарт", + "StartDescription": "Перший світлодіод цієї групи.", + "UnableToLoadLight": "Не вдалося завантажити світло", + "UnableToLoadPreset": "Неможливо завантажити предналаштування" + }, + "NavigationTab": { + "Navigation": "Навігація" + }, "PresetsTab": { "AddPreset": "додати пресет", "Cooldown": "ОХОЛОДЖЕННЯ Нагрівачів", "CreateHeadline": "Створити пресет", - "CustomGCode": "Свій Г-код", + "CustomGCode": "Свій G-код", "EditCooldown": "Редагувати ОХОЛОДЖЕННЯ", "EditHeadline": "Редагувати пресет", "ErrorInvalidValue": "Недійсне значення", @@ -849,6 +1057,7 @@ "UpdatePrinter": "Оновити принтер", "UseConfigJson": "InstanceDB = JSON виявлений. Будь ласка, використовуйте config.json щоб змінити список принтерів." }, + "Store": "зберегти", "TimelapseTab": { "Autorender": "Автовізуалізація", "AutorenderDescription": "Якщо ввімкнено, відео Таймлапс автоматично відображатиметься в кінці друку", @@ -894,6 +1103,11 @@ "RetractDistanceDescription": "Довжина прутка, яку екструдер втягує.", "RetractSpeed": "Швидкість втягування", "RetractSpeedDescription": "Швидкість, з якою екструдер відтягує пруток.", + "RulesBetweenMinMax": "Значення має бути від {min} до {max}!", + "RulesMin": "Значення має бути не менше {min}!", + "RulesPositive": "Значення не має бути від'ємним!", + "RulesRequired": "Необхідно вказати значення!", + "RulesZeroAndPositive": "Значення має бути 0 або більше!", "SaveFrames": "Зберегти зображення", "SaveFramesDescription": "Збережіть кадри у zip-файлі для зовнішнього відображення", "StreamDelayCompensation": "Компенсація затримки потоку", @@ -911,12 +1125,15 @@ "UnretractSpeedDescription": "Швидкість, з якою екструдер подає пруток після втягування.", "VariableFps": "Змінна FPS", "VariableFpsDescription": "Якщо ввімкнено, кадри вихідного відео буде обчислено на основі довжини відео", - "VariableFpsMax": "Змінна FPS макс", - "VariableFpsMaxDescription": "", - "VariableFpsMin": "Змінна FPS мін", - "VariableFpsMinDescription": "" + "VariableFpsMax": "Динамічний FPS макс", + "VariableFpsMaxDescription": "Максимальне значення при динамічному FPS", + "VariableFpsMin": "Динамічний FPS мін", + "VariableFpsMinDescription": "Мінімальне значення при динамічному FPS" }, "UiSettingsTab": { + "BedScrewsDialog": "Вікно гвинтів стола", + "BedScrewsDialogDescription": "Відобразити допоміжне діалогове вікно для BED_SCREWS_ADJUST.", + "BigThumbnailBackground": "Колір тла великої мініатюри", "BoolBigThumbnail": "Велика мініатюра", "BoolBigThumbnailDescription": "Відобразити велику мініатюру на панелі статусу під час друку.", "BoolHideUploadAndPrintButton": "Приховати кнопку завантаження та друк", @@ -925,40 +1142,67 @@ "ConfirmOnEmergencyStopDescription": "Показати діалогове вікно підтвердження АВАРІЙНОЇ ЗУПИНКИ", "ConfirmOnPowerDeviceChange": "Вимагати підтвердження змін живлення пристрою", "ConfirmOnPowerDeviceChangeDescription": "Показати діалогове вікно підтвердження щодо змін живлення пристрою", + "DefaultNavigationState": "Стандартний стан навігації", + "DefaultNavigationStateAlwaysClosed": "завжди закрита", + "DefaultNavigationStateAlwaysOpen": "завжди відкрита", + "DefaultNavigationStateDescription": "У якому стані має бути навігація за умовчанням.", + "DefaultNavigationStateLastState": "останній стан", + "DisableFanAnimation": "Вимкнути анімацію кулера", + "DisableFanAnimationDescription": "Це може зменшити навантаження на ваш браузер.", "DisplayCANCEL_PRINT": "Відображати кнопку Скасування Друку", "DisplayCANCEL_PRINTDescription": "Показує кнопку CANCEL_PRINT постійно - не потрібно підтвердження другого рівня.", "GcodeThumbnails": "Ескіз G-Code", "GcodeThumbnailsDescription": "Клацніть на кнопку, щоб дістатися до інструкцій.", "Guide": "Інструкція", + "HideSaveConfigButtonForBedMesh": "Приховати кнопку SAVE_CONFIG для змін bed_mesh", + "HideSaveConfigButtonForBedMeshDescription": "Приховати SAVE_CONFIG, якщо тільки зміни bed_mesh очікують на збереження в Klipper.", + "HideUpdateWarnings": "Приховати попередження про оновлення", + "HideUpdateWarningsDescription": "Ця опція приховає всі попередження про оновлення в менеджері оновлень.", "LockSliders": "Заблокуйте повзунки на пристроях сенсорного екрану", "LockSlidersDelay": "Затримка блокування повзунка", "LockSlidersDelayDescription": "Слайдери заблокуються після заданої затримки. Якщо встановлено на 0 або залишився порожнім, повзунки лише заблокують зміну/перезавантаження сторінки.", "LockSlidersDescription": "Слайдери на сенсорному екрані потрібно розблокувати, перш ніж зміни будуть дозволені.", "Logo": "Колір Логотипу", + "ManualProbeDialog": "Вікно помічника ручної проби", + "ManualProbeDialogDescription": "Відобразити допоміжне діалогове вікно для PROBE_CALIBRATE або Z_ENDSTOP_CALIBRATE.", "NavigationStyle": "Стиль навігації", "NavigationStyleDescription": "Змінити зовнішній вигляд навігації", "NavigationStyleIconsAndText": "Піктограми + текст", "NavigationStyleIconsOnly": "Тільки іконки", + "PowerDeviceName": "Пристрій живлення принтера", + "PowerDeviceNameDescription": "Виберіть, який пристрій живлення Moonraker слід використовувати для живлення принтера.", "Primary": "Основний Колір", - "ShowWebcamInNavigation": "Показати веб -камеру в навігації", + "ScrewsTiltAdjustDialog": "Вікно налаштування гвинтів нахилу стола", + "ScrewsTiltAdjustDialogDescription": "Відобразити допоміжне вікно для SCREWS_TILT_CALCULATE.", + "TempchartHeight": "Висота графіку температур", + "TempchartHeightDescription": "Змініть висоту графіка температури на інформаційній панелі.", + "Theme": "Тема", + "ThemeDark": "Темна", + "ThemeDescription": "Змініть загальний вигляд програми", + "ThemeLight": "Світла", "UiSettings": "Налаштування в інтерфейсі" }, + "Update": "оновлення", "WebcamsTab": { "AddWebcam": "Додати веб-камеру", "CreateWebcam": "Створити веб-камеру", "EditCrowsnestConf": "Редагувати crowsnest.conf", "EditWebcam": "Редагувати веб-камеру", + "EnableAudio": "Увімкнути аудіо", "FlipWebcam": "Повернути веб-камеру:", + "HideFps": "Приховати лічильник FPS", + "Hlsstream": "Потік HLS", "Horizontally": "горизонтально", "IconBed": "Ліжко", "IconCam": "Cam", "IconDoor": "Двері", "IconFilament": "Пруток", "IconHot": "Гарячий", - "IconMcu": "ЦПК", + "IconMcu": "MCU", "IconNozzle": "Сопло", "IconPrinter": "Прінтер", - "Ipstream": "IP -камера", + "Ipstream": "IP-камера", + "JMuxerStream": "Необроблений потік h264 (jmuxer)", "Mjpegstreamer": "MJPEG-Стример", "MjpegstreamerAdaptive": "Adaptive MJPEG-Streamer (експериментальний)", "Name": "Ім'я", @@ -973,7 +1217,11 @@ "UrlStream": "URL-адреса Потоку", "Uv4lMjpeg": "UV4L-MJPEG", "Vertically": "вертикально", - "Webcams": "Веб-камери" + "Webcams": "Веб-камери", + "WebrtcCameraStreamer": "WebRTC (camera-streamer)", + "WebrtcGo2rtc": "WebRTC (go2rtc)", + "WebrtcJanus": "WebRTC (janus-gateway)", + "WebrtcMediaMTX": "WebRTC (MediaMTX)" } }, "Timelapse": { @@ -987,6 +1235,7 @@ "DeleteDirectory": "Видалити директорію", "DeleteDirectoryQuestion": "Ви дійсно хочете видалити \"{name}\" директоріб із усім її вмістом?", "DeleteSelectedQuestion": "Ви дійсно хочете видалити {count} вибрані файли?", + "DeleteSingleFileQuestion": "Ви дійсно хочете видалити файл \"{name}\"?", "Download": "Завантажити", "DuplicateLastframe": "Дублікат останнього кадру", "Empty": "Не знайдено закінченого Таймлапсу.", @@ -998,8 +1247,8 @@ "Framerate": "Частота кадрів", "Frames": "Кадри", "Free": "Вільно", - "FreeDisk": "Вільний диск", - "LastModified": "Датат Створення", + "FreeDisk": "Вільнр на диску", + "LastModified": "Дата Створення", "MaxFramerate": "Макс. частота кадрів", "MinFramerate": "Мін. частота кадрів", "Name": "Ім'я", From 5c6556cfd987954b79486c8586793256f2cfe38d Mon Sep 17 00:00:00 2001 From: Samuel Wang Date: Sun, 3 Mar 2024 05:18:17 -0800 Subject: [PATCH 27/46] locale(zh): update chinese locale (#1791) Co-authored-by: Stefan Dej --- src/locales/zh.json | 67 +++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/src/locales/zh.json b/src/locales/zh.json index a7d862a11..f33d907d1 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -6,7 +6,7 @@ "Headline": "浏览器已过时" }, "DependencyDescription": "当前版本的{name}并不支持Mainsail的全部功能。{name}需要至少更新到{neededVersion}版本。", - "DependencyName": "{name}依赖", + "DependencyName": "依赖:{name}", "DismissAll": "忽略全部", "KlipperWarnings": { "DeprecatedOption": "在'{section}'标签中的'{option}'选项已被弃用,将在未来的版本中删除。", @@ -16,17 +16,17 @@ "KlipperWarning": "Klipper警告" }, "MoonrakerWarnings": { - "MoonrakerComponent": "Moonraker: {component}", + "MoonrakerComponent": "Moonraker:{component}", "MoonrakerFailedComponentDescription": "加载moonraker组件'{component}'时发生错误。请检查日志文件并修复此问题。", "MoonrakerFailedInitComponentDescription": "初始化moonraker组件'{component}'时发生错误。请检查日志文件并修复此问题。", - "MoonrakerInitComponent": "初始化 Moonraker: {component}", + "MoonrakerInitComponent": "初始化 Moonraker:{component}", "MoonrakerWarning": "Moonraker警告", "UnparsedConfigOption": "在[{section}]标签中检测到无法解析的配置'{option}: {value}'。这可能是一个不再可用的选项,也可能是组件加载失败的结果。在将来,这将导致启动错误。", "UnparsedConfigSection": "检测到无法解析的标签[{section}]。这可能是一个不再可用的标签,也可能是组件加载失败的结果。在未来,这将导致启动错误。" }, "Never": "永不", "NextReboot": "下次重启", - "NoNotification": "没有通知", + "NoNotification": "没有可用的通知", "Notifications": "通知", "Remind": "提醒:" }, @@ -36,6 +36,9 @@ "NoEmptyAllowedError": "输入值不能为空!" }, "Printers": "打印机列表", + "TextfieldWithCopy": { + "Copied": "复制" + }, "TheServiceWorker": { "DescriptionNeedUpdate": "本地缓存已过时,需要进行更新。请点击下面的按钮来更新缓存。", "TitleNeedUpdate": "PWA需要更新", @@ -63,7 +66,7 @@ "Complete": "已完成 - {filename}", "Error": "错误", "Pause": "暂停打印", - "PrinterOff": "打印机已关闭", + "PrinterOff": "打印机关闭", "Printing": "已打印 {percent}% - {filename}", "PrintingETA": "已打印 {percent}% - 预估: {eta} - {filename}" }, @@ -120,13 +123,13 @@ } }, "BedScrews": { - "Abort": "取消", + "Abort": "中止", "Accept": "接受", "Adjusted": "已调整", - "Description": "如果当前螺丝已调整,请点击已调整。未调整下继续请点击认可。", + "Description": "如果当前螺丝已调整,请点击已调整。如果不需要调整,请点击接受继续。", "Headline": "热床调平螺丝", "ScrewAccepted": "已接受的调平螺丝", - "ScrewIndex": "螺丝索引", + "ScrewIndex": "螺丝编号", "ScrewName": "螺丝名称", "ScrewOutput": "{current}/{max}" }, @@ -146,6 +149,20 @@ "SendCode": "输入要执行的代码...", "SetupConsole": "设置控制台" }, + "DevicesDialog": { + "CanBusInfo": "只有未分配的节点才能被检测到。建议仅连接一个未分配的设备到CAN总线,以避免通信问题。更多详情,请点击链接:", + "ClickRefresh": "点击刷新按钮以搜索设备。", + "DevicePath": "设备路径", + "Formats": "格式", + "Headline": "设备", + "HideSystemEntries": "隐藏系统条目", + "LibcameraId": "Libcamera标识符", + "NoDeviceFound": "未发现设备。请检查连接并点击刷新按钮。", + "PathByHardware": "硬件路径", + "PathById": "标识符路径", + "Refresh": "刷新", + "Resolutions": "分辨率" + }, "Dialogs": { "StartPrint": { "Cancel": "取消", @@ -153,11 +170,12 @@ "DoYouWantToStartFilenameFilament": "是否使用以下耗材开始打印文件{filename}?", "Headline": "开始任务", "Print": "打印", - "Timelapse": "延时摄像" + "Timelapse": "延时摄影" } }, "Editor": { "ConfigReference": "配置参考", + "DeviceDialog": "设备", "DontSave": "不保存", "Downloading": "正在下载", "FailedSave": "上传{filename}失败!", @@ -274,10 +292,10 @@ "Tracking": "正在追踪", "Transparency": "透明度", "Ultra": "极致", - "VoxelMode": "体素模式(ASMBL)" + "VoxelMode": "三维像素模式(ASMBL)" }, "Heightmap": { - "Abort": "取消", + "Abort": "中止", "BedMeshCalibrate": "校准床网", "BedMeshRemove": "移除床网", "Calibrate": "测量", @@ -298,20 +316,16 @@ "InvalidNameAlreadyExists": "预设名称已经存在,请换一个名称。", "InvalidNameAscii": "错误的名称,请删除所有非ascii字符后重试。", "InvalidNameEmpty": "输入值不能为空!", - "InvalidNameReserved": "预设 'default' 已保留,请选择其他预设名称。", - "Later": "以后", + "InvalidNameReserved": "预设'default'已保留,请选择其他预设名称。", "Mesh": "网格", "Name": "名称", "NoBedMeshHasBeenLoadedYet": "没有加载床网。", "NoProfile": "没有预设可用", - "Ok": "好的", "Probed": "测量结果", "Profiles": "预设", "Remove": "删除", - "RemoveSaveDescription": "预设床网已标记需删除。点击\"保存配置\"将会从printer.cfg中移除并重启Klipper。", "Rename": "重命名", "RenameBedMeshProfile": "重命名预设床网", - "SAVE_CONFIG": "保存配置", "ScaleGradient": "尺度梯度", "ScaleZMax": "Z最大标度", "TitleCalibrate": "校准新床网", @@ -321,6 +335,7 @@ }, "History": { "AddNote": "添加便条", + "AddToQueueSuccessful": "文件{filename}已添加到队列。", "AllJobs": "全部", "AvgPrinttime": "平均打印时长", "Cancel": "取消", @@ -483,7 +498,7 @@ } }, "UpdatePanel": { - "Abort": "放弃", + "Abort": "中止", "AreYouSure": "你确定吗?", "CheckForUpdates": "检查更新", "Close": "关闭", @@ -528,7 +543,7 @@ } }, "ManualProbe": { - "Abort": "取消", + "Abort": "中止", "Accept": "接受", "Advanced": "高级", "Headline": "手动Probe" @@ -680,7 +695,7 @@ "Max": "最高", "ObjectHeight": "物体高度", "PauseAtLayer": { - "Abort": "取消", + "Abort": "中止", "Accept": "接受", "AtLayer": "所在层", "Call": "调用", @@ -776,8 +791,8 @@ "Router": { "Console": "控制台", "Dashboard": "控制面板", - "G-Code Files": "G-Code 文件", - "G-Code Viewer": "G-Code 预览", + "G-Code Files": "G-Code文件", + "G-Code Viewer": "G-Code预览", "Heightmap": "高度图", "History": "历史记录", "Machine": "机器", @@ -794,8 +809,8 @@ }, "SelectPrinterDialog": { "AddPrinter": "添加打印机", - "AddPrintersToJson": "请将打印机添加到 config.json 。", - "CannotConnectTo": "无法连接到{host} 。", + "AddPrintersToJson": "请将打印机添加到config.json。", + "CannotConnectTo": "无法连接到{host}。", "ChangePrinter": "切换打印机", "Connecting": "正在连接到{host}", "ConnectionFailed": "连接失败", @@ -891,7 +906,7 @@ "GCodeViewerTab": { "BackgroundColor": "背景颜色", "ExtruderColor": "喷嘴颜色", - "GCodeViewer": "G-Code 预览", + "GCodeViewer": "G-Code预览", "GridColor": "网格颜色", "MaxFeed": "最大挤出速度", "MinFeed": "最小挤出速度", @@ -1040,7 +1055,7 @@ "Port": "Moonraker服务端口", "RemotePrinters": "打印机", "UpdatePrinter": "更新打印机", - "UseConfigJson": "检测到InstanceDB参数为JSON。请使用 config.json 来修改打印机列表。" + "UseConfigJson": "检测到InstanceDB参数为JSON。请使用config.json来修改打印机列表。" }, "Store": "存储", "TimelapseTab": { @@ -1064,7 +1079,7 @@ "HyperlapseCycle": "Hyperlapse周期时间", "HyperlapseCycleDescription": "每隔X秒获取一张快照", "Mode": "模式", - "ModeDescription": "选择Layermacro(基于层变化)或者Hyperlapse(基于时间)模式", + "ModeDescription": "选择Layermacro模式(基于层变化)或者Hyperlapse模式(基于时间)", "OutputFramerate": "输出帧率", "OutputFramerateDescription": "设置视频帧率。注意:如果可变FPS设置开启,此设置会被忽略", "Parkhead": "放置打印头到停靠位置", From 5071f61a1e2be946f555b8dedea4307a6534c5f0 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Sun, 3 Mar 2024 20:00:45 +0100 Subject: [PATCH 28/46] refactor: update branch and add "add to queue" function from develop Signed-off-by: Stefan Dej --- .../HistoryList/HistoryListEntryJob.vue | 42 +++++++++++++++---- src/components/panels/HistoryListPanel.vue | 27 +++--------- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/components/panels/HistoryList/HistoryListEntryJob.vue b/src/components/panels/HistoryList/HistoryListEntryJob.vue index 2af687651..44b098716 100644 --- a/src/components/panels/HistoryList/HistoryListEntryJob.vue +++ b/src/components/panels/HistoryList/HistoryListEntryJob.vue @@ -96,6 +96,14 @@ {{ mdiPrinter }} {{ $t('History.Reprint') }} + + {{ mdiPlaylistPlus }} + {{ $t('Files.AddToQueue') }} + + + {{ mdiPlaylistPlus }} + {{ $t('Files.AddBatchToQueue') }} + {{ mdiDelete }} {{ $t('History.Delete') }} @@ -113,6 +121,12 @@ :type="noteDialogType" :job="item" @close-dialog="noteDialogBool = false" /> + + From d5953d6e5d0b72dedccd0fe41439e3674586b3c5 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Mon, 4 Mar 2024 21:07:13 +0100 Subject: [PATCH 30/46] refactor: refactor addMaintenance dialog Signed-off-by: Stefan Dej --- .../HistoryListPanelAddMaintenance.vue | 219 +++++++++--------- src/components/panels/HistoryListPanel.vue | 10 +- 2 files changed, 114 insertions(+), 115 deletions(-) diff --git a/src/components/dialogs/HistoryListPanelAddMaintenance.vue b/src/components/dialogs/HistoryListPanelAddMaintenance.vue index 3ceb15d5f..481f71875 100644 --- a/src/components/dialogs/HistoryListPanelAddMaintenance.vue +++ b/src/components/dialogs/HistoryListPanelAddMaintenance.vue @@ -1,116 +1,111 @@ diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index a94efbf75..dc1789f99 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -27,7 +27,9 @@ {{ mdiDelete }} - + + {{ 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 31/46] 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 32/46] 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 33/46] 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 @@