-
+
+
{{ $t('App.Notifications.Remind') }}
-
-
- 1H
-
-
- 1D
-
-
- 7D
-
-
-
-
- {{ $t('App.Notifications.NextReboot') }}
-
-
- {{ $t('App.Notifications.Never') }}
-
-
+
+ {{ reminder.text }}
+
+
-
-
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 @@
-
-
-
-
-
-
-
-
-
- {{ mdiDelete }}
-
-
-
-
- {{ mdiPlus }}
-
-
-
-
-
-
-
-
- No Reminders
-
-
-
- showContextMenu($event, item)">
-
-
- |
-
- {{ item.name }}
- |
-
-
-
-
-
- {{ getStatusIcon(item.remaining_print_time) }}
-
-
-
-
- {{ getStatusText(item.remaining_print_time) }}
-
-
- |
-
- {{ formatPrintTime(item.remaining_print_time) }}
- |
-
- {{ formatPrintTime(item.time_delta) }}
- |
-
-
-
-
-
-
-
- {{ mdiPencil }}
-
- Edit
-
-
- {{ mdiRepeatOnce }}
-
- Repeat
-
-
- {{ mdiDelete }}
-
- Delete
-
-
-
-
-
-
-
- {{ mdiCloseThick }}
-
-
-
-
- Do you really want to delete {{ selectedReminders.length }} reminders?
-
-
-
- {{ $t('History.Cancel') }}
- {{ $t('History.Delete') }}
-
-
-
-
-
-
-
-
- {{ mdiCloseThick }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Confirm
-
-
-
-
-
-
-
-
- {{ mdiCloseThick }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Confirm
-
-
-
-
-
-
-
-
diff --git a/src/components/panels/HistoryStatisticsPanel.vue b/src/components/panels/HistoryStatisticsPanel.vue
index 5ded56f68..4ef4ecdf1 100644
--- a/src/components/panels/HistoryStatisticsPanel.vue
+++ b/src/components/panels/HistoryStatisticsPanel.vue
@@ -12,15 +12,15 @@
{{ $t('History.SelectedPrinttime') }} |
- {{ formatPrintTime(selectedPrintTime) }} |
+ {{ formatPrintTime(selectedPrintTime, false) }} |
{{ $t('History.LongestPrinttime') }} |
- {{ formatPrintTime(selectedLongestPrintTime) }} |
+ {{ formatPrintTime(selectedLongestPrintTime, false) }} |
{{ $t('History.AvgPrinttime') }} |
- {{ formatPrintTime(selectedAvgPrintTime) }} |
+ {{ formatPrintTime(selectedAvgPrintTime, false) }} |
{{ $t('History.SelectedFilamentUsed') }} |
@@ -34,15 +34,15 @@
{{ $t('History.TotalPrinttime') }} |
- {{ formatPrintTime(totalPrintTime) }} |
+ {{ formatPrintTime(totalPrintTime, false) }} |
{{ $t('History.LongestPrinttime') }} |
- {{ formatPrintTime(longestPrintTime) }} |
+ {{ formatPrintTime(longestPrintTime, false) }} |
{{ $t('History.AvgPrinttime') }} |
- {{ formatPrintTime(avgPrintTime) }} |
+ {{ formatPrintTime(avgPrintTime, false) }} |
{{ $t('History.TotalFilamentUsed') }} |
@@ -57,17 +57,12 @@
-
-
+
+
-
- {{ $t('History.Chart') }}
-
-
- {{ $t('History.Table') }}
-
+ {{ $t('History.Chart') }}
+ {{ $t('History.Table') }}
@@ -88,16 +83,12 @@
-
-
+
+
-
- {{ $t('History.FilamentUsage') }}
-
-
- {{ $t('History.PrinttimeAvg') }}
-
+ {{ $t('History.FilamentUsage') }}
+ {{ $t('History.PrinttimeAvg') }}
@@ -122,6 +113,7 @@ import { formatPrintTime } from '@/plugins/helpers'
export default class HistoryStatisticsPanel extends Mixins(BaseMixin) {
mdiChartAreaspline = mdiChartAreaspline
mdiDatabaseArrowDownOutline = mdiDatabaseArrowDownOutline
+ formatPrintTime = formatPrintTime
formatPrintTime = formatPrintTime
@@ -134,9 +126,7 @@ export default class HistoryStatisticsPanel extends Mixins(BaseMixin) {
}
get totalPrintTime() {
- return 'total_print_time' in this.$store.state.server.history.job_totals
- ? this.$store.state.server.history.job_totals.total_print_time
- : 0
+ return this.$store.state.server.history.job_totals?.total_print_time ?? 0
}
get selectedPrintTime() {
@@ -150,9 +140,7 @@ export default class HistoryStatisticsPanel extends Mixins(BaseMixin) {
}
get longestPrintTime() {
- return 'longest_print' in this.$store.state.server.history.job_totals
- ? this.$store.state.server.history.job_totals.longest_print
- : 0
+ return this.$store.state.server.history.job_totals?.longest_print ?? 0
}
get selectedLongestPrintTime() {
@@ -180,9 +168,7 @@ export default class HistoryStatisticsPanel extends Mixins(BaseMixin) {
}
get totalFilamentUsed() {
- return 'total_filament_used' in this.$store.state.server.history.job_totals
- ? this.$store.state.server.history.job_totals.total_filament_used
- : 0
+ return this.$store.state.server.history.job_totals?.total_filament_used ?? 0
}
get selectedFilamentUsed() {
@@ -196,9 +182,7 @@ export default class HistoryStatisticsPanel extends Mixins(BaseMixin) {
}
get totalJobsCount() {
- return 'total_jobs' in this.$store.state.server.history.job_totals
- ? this.$store.state.server.history.job_totals.total_jobs
- : 0
+ return this.$store.state.server.history.job_totals?.total_jobs ?? 0
}
get toggleChart() {
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/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 @@
-
+
{{ title }}
@@ -20,7 +20,7 @@
{{ commitFormatDate }}
-
+
{{ commitShortSha }}
diff --git a/src/components/panels/Status/Gcodefiles.vue b/src/components/panels/Status/Gcodefiles.vue
index 6ddcb7a66..d2a38e6fa 100644
--- a/src/components/panels/Status/Gcodefiles.vue
+++ b/src/components/panels/Status/Gcodefiles.vue
@@ -173,53 +173,10 @@
-
-
-
-
- {{ mdiCloseThick }}
-
-
-
-
-
-
-
-
- {{ mdiChevronUp }}
-
-
- {{ mdiChevronDown }}
-
-
-
-
-
-
-
- {{ $t('Files.Cancel') }}
- {{ $t('Files.AddToQueue') }}
-
-
-
+
@@ -231,8 +188,6 @@ import ControlMixin from '@/components/mixins/control'
import { FileStateGcodefile } from '@/store/files/types'
import StartPrintDialog from '@/components/dialogs/StartPrintDialog.vue'
import {
- mdiChevronDown,
- mdiChevronUp,
mdiFile,
mdiPlay,
mdiPlaylistPlus,
@@ -246,6 +201,7 @@ import {
} from '@mdi/js'
import Panel from '@/components/ui/Panel.vue'
import { defaultBigThumbnailBackground } from '@/store/variables'
+import AddBatchToQueueDialog from '@/components/dialogs/AddBatchToQueueDialog.vue'
interface dialogRenameObject {
show: boolean
@@ -253,21 +209,14 @@ interface dialogRenameObject {
item: FileStateGcodefile
}
-interface dialogAddBatchToQueue {
- show: boolean
- count: number
- item: FileStateGcodefile
-}
-
@Component({
components: {
Panel,
StartPrintDialog,
+ AddBatchToQueueDialog,
},
})
export default class StatusPanelGcodefiles extends Mixins(BaseMixin, ControlMixin) {
- mdiChevronDown = mdiChevronDown
- mdiChevronUp = mdiChevronUp
mdiFile = mdiFile
mdiPlay = mdiPlay
mdiPlaylistPlus = mdiPlaylistPlus
@@ -320,10 +269,9 @@ export default class StatusPanelGcodefiles extends Mixins(BaseMixin, ControlMixi
item: { ...this.dialogFile },
}
- private dialogAddBatchToQueue: dialogAddBatchToQueue = {
- show: false,
- count: 1,
- item: { ...this.contextMenu.item },
+ dialogAddBatchToQueue: { isVisible: boolean; filename: string } = {
+ isVisible: false,
+ filename: '',
}
private countInputRules = [
@@ -470,23 +418,12 @@ export default class StatusPanelGcodefiles extends Mixins(BaseMixin, ControlMixi
}
openAddBatchToQueueDialog(item: FileStateGcodefile) {
- this.dialogAddBatchToQueue.show = true
- this.dialogAddBatchToQueue.count = 1
- this.dialogAddBatchToQueue.item = item
+ this.dialogAddBatchToQueue.isVisible = true
+ this.dialogAddBatchToQueue.filename = item.filename
}
- async addBatchToQueueAction() {
- let filename = [this.currentPath, this.dialogAddBatchToQueue.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.show = false
+ closeAddBatchToQueueDialog() {
+ this.dialogAddBatchToQueue.isVisible = false
}
view3D(item: FileStateGcodefile) {
@@ -571,11 +508,4 @@ export default class StatusPanelGcodefiles extends Mixins(BaseMixin, ControlMixi
.filesGcodeCard {
position: relative;
}
-
-._spin_button_group {
- width: 24px;
- margin-top: -6px;
- margin-left: -6px;
- margin-bottom: -6px;
-}
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/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() {
diff --git a/src/components/panels/StatusPanel.vue b/src/components/panels/StatusPanel.vue
index 1c68082ea..ec8612bec 100644
--- a/src/components/panels/StatusPanel.vue
+++ b/src/components/panels/StatusPanel.vue
@@ -59,8 +59,10 @@
-
- {{ mdiAlertOutline }}
+
+
+ {{ mdiAlertOutline }}
+
{{ print_stats_message }}
@@ -70,10 +72,10 @@
-
-
-
- {{ mdiMessageProcessingOutline }}
+
+
+
+ {{ mdiMessageProcessingOutline }}
{{ display_message }}
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",
diff --git a/src/locales/en.json b/src/locales/en.json
index 58639460a..f707f594b 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -15,6 +15,8 @@
"DeprecatedValueHeadline": "Deprecated Klipper Value",
"KlipperWarning": "Klipper warning"
},
+ "MaintenanceReminder": "Maintenance Reminder",
+ "MaintenanceReminderText": "Maintenance \"{name}\" is due.",
"MoonrakerWarnings": {
"MoonrakerComponent": "Moonraker: {component}",
"MoonrakerFailedComponentDescription": "An error was detected while loading the moonraker component '{component}'. Please check the log file and fix the issue.",
@@ -28,6 +30,9 @@
"NextReboot": "next reboot",
"NoNotification": "No Notification available",
"Notifications": "Notifications",
+ "OneHourShort": "1H",
+ "OneDayShort": "1D",
+ "OneWeekShort": "1W",
"Remind": "Remind:"
},
"NumberInput": {
@@ -36,6 +41,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",
@@ -46,7 +54,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",
@@ -146,6 +154,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 +180,7 @@
},
"Editor": {
"ConfigReference": "Config Reference",
+ "DeviceDialog": "Devices",
"DontSave": "Don't save",
"Downloading": "Downloading",
"FailedSave": "{filename} could not be uploaded!",
@@ -320,22 +343,30 @@
"Wireframe": "Wireframe"
},
"History": {
+ "AddMaintenance": "Add Maintenance",
"AddNote": "Add note",
+ "AddToQueueSuccessful": "File {filename} added to Queue.",
+ "AddReminder": "Add Reminder",
"AllJobs": "All",
"AvgPrinttime": "Print Time - Ø",
"Cancel": "Cancel",
"Chart": "Chart",
"CreateNote": "Create Note",
+ "DateBasedReminder": "Date",
+ "DateBasedReminderDescription": "This reminder is based on the date.",
"Delete": "Delete",
"DeleteSelectedQuestion": "Do you really want to delete {count} selected jobs?",
"DeleteSingleJobQuestion": "Do you really want to delete the job?",
"Details": "Details",
+ "Days": "days",
"EditNote": "Edit Note",
"Empty": "empty",
"EndTime": "End Time",
"EstimatedFilament": "Estimated Filament",
"EstimatedFilamentWeight": "Estimated Filament Weight",
"EstimatedTime": "Estimated Time",
+ "FilamentBasedReminder": "Filament",
+ "FilamentBasedReminderDescription": "This reminder is based on the filament usage.",
"FilamentCalc": "Filament Calc",
"FilamentUsage": "Filament usage",
"FilamentUsed": "Filament Used",
@@ -344,20 +375,31 @@
"FirstLayerBedTemp": "First Layer Bed Temp.",
"FirstLayerExtTemp": "First Layer Ext. Temp.",
"FirstLayerHeight": "First Layer Height",
+ "Hours": "hours",
"HistoryFilamentUsage": "Filament",
"HistoryPrinttimeAVG": "Prints",
+ "InvalidNameEmpty": "Invalid name. Name must not be empty!",
"JobDetails": "Job Details",
"Jobs": "Jobs",
"LastModified": "Last Modified",
"LayerHeight": "Layer Height",
"LoadCompleteHistory": "Load complete history",
"LongestPrinttime": "Longest Print Time",
+ "Maintenance": "Maintenance",
+ "Meter": "meter",
+ "Name": "Name",
+ "NoReminder": "No reminder",
"Note": "Note",
"ObjectHeight": "Object Height",
+ "OneTime": "One-Time",
"PrintDuration": "Print Time",
"PrintHistory": "Print History",
"PrintTime": "Print Time",
"PrinttimeAvg": "Print Time - Ø",
+ "PrinttimeBasedReminder": "Print Time",
+ "PrinttimeBasedReminderDescription": "This reminder is based on the print time.",
+ "Reminder": "Reminder",
+ "Repeat": "Repeat",
"Reprint": "Reprint",
"Save": "save",
"Search": "search",
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": "Ім'я",
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": "放置打印头到停靠位置",
diff --git a/src/pages/History.vue b/src/pages/History.vue
index 08a751978..4a304f4c4 100644
--- a/src/pages/History.vue
+++ b/src/pages/History.vue
@@ -5,11 +5,6 @@
-
-
-
-
-
@@ -22,13 +17,9 @@ import { Component, Mixins } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import HistoryListPanel from '@/components/panels/HistoryListPanel.vue'
import HistoryStatisticsPanel from '@/components/panels/HistoryStatisticsPanel.vue'
-import HistoryRemindersPanel from '@/components/panels/HistoryRemindersPanel.vue'
+
@Component({
- components: {
- HistoryStatisticsPanel,
- HistoryListPanel,
- HistoryRemindersPanel,
- },
+ components: { HistoryListPanel, HistoryStatisticsPanel },
})
export default class PageHistory extends Mixins(BaseMixin) {}
diff --git a/src/plugins/helpers.ts b/src/plugins/helpers.ts
index 28554d2c5..719408ce8 100644
--- a/src/plugins/helpers.ts
+++ b/src/plugins/helpers.ts
@@ -112,15 +112,17 @@ export const formatFrequency = (frequency: number): string => {
return Math.max(frequency, 0.1).toFixed() + units[i]
}
-export const formatPrintTime = (totalSeconds: number): string => {
- if (totalSeconds === 0) return '--'
+export const formatPrintTime = (totalSeconds: number, boolDays = true): string => {
+ if (!totalSeconds) return '--'
const output: string[] = []
- const days = Math.floor(totalSeconds / (3600 * 24))
- if (days) {
- totalSeconds %= 3600 * 24
- output.push(`${days}d`)
+ if (boolDays) {
+ const days = Math.floor(totalSeconds / (3600 * 24))
+ if (days) {
+ totalSeconds %= 3600 * 24
+ output.push(`${days}d`)
+ }
}
const hours = Math.floor(totalSeconds / 3600)
@@ -246,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/routes/index.ts b/src/routes/index.ts
index 6964df89b..94117ff3c 100644
--- a/src/routes/index.ts
+++ b/src/routes/index.ts
@@ -22,6 +22,7 @@ import {
const routes: AppRoute[] = [
{
+ name: 'dashboard',
title: 'Dashboard',
path: '/',
icon: mdiMonitorDashboard,
@@ -31,6 +32,7 @@ const routes: AppRoute[] = [
position: 10,
},
{
+ name: 'farm',
title: 'Printers',
path: '/allPrinters',
component: Farm,
@@ -38,6 +40,7 @@ const routes: AppRoute[] = [
showInNavi: false,
},
{
+ name: 'webcam',
title: 'Webcam',
path: '/cam',
icon: mdiWebcam,
@@ -45,8 +48,10 @@ const routes: AppRoute[] = [
alwaysShow: true,
showInNavi: true,
position: 20,
+ fullscreen: true,
},
{
+ name: 'console',
title: 'Console',
path: '/console',
icon: mdiConsoleLine,
@@ -57,6 +62,7 @@ const routes: AppRoute[] = [
position: 30,
},
{
+ name: 'heightmap',
title: 'Heightmap',
path: '/heightmap',
icon: mdiGrid,
@@ -67,6 +73,7 @@ const routes: AppRoute[] = [
position: 40,
},
{
+ name: 'gcodefiles',
title: 'G-Code Files',
path: '/files',
icon: mdiFileDocumentMultipleOutline,
@@ -75,8 +82,10 @@ const routes: AppRoute[] = [
showInNavi: true,
registeredDirectory: 'gcodes',
position: 50,
+ fullscreen: true,
},
{
+ name: 'gcodeviewer',
title: 'G-Code Viewer',
path: '/viewer',
icon: mdiVideo3d,
@@ -84,8 +93,10 @@ const routes: AppRoute[] = [
alwaysShow: true,
showInNavi: true,
position: 60,
+ fullscreen: true,
},
{
+ name: 'history',
title: 'History',
path: '/history',
icon: mdiHistory,
@@ -96,6 +107,7 @@ const routes: AppRoute[] = [
position: 70,
},
{
+ name: 'timelapse',
title: 'Timelapse',
path: '/timelapse',
icon: mdiTimelapse,
@@ -106,6 +118,7 @@ const routes: AppRoute[] = [
position: 80,
},
{
+ name: 'machine',
title: 'Machine',
path: '/config',
icon: mdiWrench,
@@ -127,6 +140,7 @@ const routes: AppRoute[] = [
export default routes
export interface AppRoute {
+ name?: string
title: string | null
path: string
redirect?: string
@@ -140,4 +154,5 @@ export interface AppRoute {
klipperIsConnected?: boolean
children?: AppRoute[]
position?: number
+ fullscreen?: boolean
}
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) => {
diff --git a/src/store/gui/index.ts b/src/store/gui/index.ts
index be52a2656..827491c7f 100644
--- a/src/store/gui/index.ts
+++ b/src/store/gui/index.ts
@@ -14,9 +14,9 @@ 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 { maintenance } from '@/store/gui/maintenance'
import { webcams } from '@/store/gui/webcams'
import { heightmap } from '@/store/gui/heightmap'
-import { reminders } from '@/store/gui/reminders'
export const getDefaultState = (): GuiState => {
return {
@@ -293,6 +293,7 @@ export const gui: Module = {
console,
gcodehistory,
macros,
+ maintenance,
miscellaneous,
navigation,
notifications,
@@ -300,6 +301,5 @@ export const gui: Module = {
remoteprinters,
webcams,
heightmap,
- reminders,
},
}
diff --git a/src/store/gui/maintenance/actions.ts b/src/store/gui/maintenance/actions.ts
new file mode 100644
index 000000000..f0e9c318e
--- /dev/null
+++ b/src/store/gui/maintenance/actions.ts
@@ -0,0 +1,68 @@
+import Vue from 'vue'
+import { ActionTree } from 'vuex'
+import { GuiMaintenanceState } from '@/store/gui/maintenance/types'
+import { RootState } from '@/store/types'
+import { v4 as uuidv4 } from 'uuid'
+
+export const actions: ActionTree = {
+ reset({ commit }) {
+ commit('reset')
+ },
+
+ init() {
+ Vue.$socket.emit(
+ 'server.database.get_item',
+ { namespace: 'maintenance' },
+ { action: 'gui/maintenance/initStore' }
+ )
+ },
+
+ async initStore({ commit, dispatch }, payload) {
+ await commit('reset')
+ await commit('initStore', payload)
+ await dispatch('socket/removeInitModule', 'gui/maintenance/init', { root: true })
+ },
+
+ 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.entry })
+ dispatch('upload', {
+ id,
+ value: state.entries[id],
+ })
+ },
+
+ update({ commit, dispatch, state }, payload) {
+ commit('update', payload)
+ dispatch('upload', {
+ id: payload.id,
+ value: state.entries[payload.id],
+ })
+ },
+
+ delete({ commit }, payload) {
+ commit('delete', payload)
+ Vue.$socket.emit('server.database.delete_item', { namespace: 'maintenance', key: payload })
+ },
+
+ /*repeat({ dispatch, getters, state, rootState }, payload) {
+ if (!(payload.id in state.reminders)) return
+ const reminder = getters['getReminder'](payload.id)
+ const new_start_time = rootState.server?.history?.job_totals.total_print_time || 0
+ const snooze_epoch_time = Date.now()
+ dispatch('update', {
+ id: reminder.id,
+ snooze_print_hours_timestamps: [...reminder.snooze_print_hours_timestamps, new_start_time],
+ snooze_epoch_timestamps: [...reminder.snooze_epoch_timestamps, snooze_epoch_time],
+ })
+ },*/
+}
diff --git a/src/store/gui/maintenance/getters.ts b/src/store/gui/maintenance/getters.ts
new file mode 100644
index 000000000..a1b359507
--- /dev/null
+++ b/src/store/gui/maintenance/getters.ts
@@ -0,0 +1,47 @@
+import { GetterTree } from 'vuex'
+import { GuiMaintenanceState, GuiMaintenanceStateEntry } from '@/store/gui/maintenance/types'
+
+// eslint-disable-next-line
+export const getters: GetterTree = {
+ getEntries: (state) => {
+ const entries: GuiMaintenanceStateEntry[] = []
+
+ Object.keys(state.entries).forEach((id: string) => {
+ entries.push({ ...state.entries[id], id })
+ })
+
+ return entries
+ },
+
+ getOverdueEntries: (state, getters, rootState) => {
+ const currentTotalPrintTime = rootState.server.history.job_totals.total_print_time ?? 0
+ const currentTotalFilamentUsed = rootState.server.history.job_totals.total_filament_used ?? 0
+ const currentDate = new Date().getTime() / 1000
+
+ const entries: GuiMaintenanceStateEntry[] = getters['getEntries'] ?? []
+
+ return entries.filter((entry) => {
+ if (entry.reminder.type === null && entry.end_time !== null) return false
+
+ if (entry.reminder.filament.bool) {
+ const end = entry.start_filament + (entry.reminder.filament.value ?? 0)
+
+ if (end <= currentTotalFilamentUsed) return true
+ }
+
+ if (entry.reminder.printtime.bool) {
+ const end = entry.start_printtime + (entry.reminder.printtime.value ?? 0)
+
+ if (end <= currentTotalPrintTime) return true
+ }
+
+ if (entry.reminder.date.bool) {
+ const end = entry.start_time + (entry.reminder.date.value ?? 0)
+
+ if (end <= currentDate) return true
+ }
+
+ return false
+ })
+ },
+}
diff --git a/src/store/gui/maintenance/index.ts b/src/store/gui/maintenance/index.ts
new file mode 100644
index 000000000..fdfcc39b3
--- /dev/null
+++ b/src/store/gui/maintenance/index.ts
@@ -0,0 +1,23 @@
+import { Module } from 'vuex'
+import { GuiMaintenanceState } from '@/store/gui/maintenance/types'
+import { actions } from '@/store/gui/maintenance/actions'
+import { mutations } from '@/store/gui/maintenance/mutations'
+import { getters } from '@/store/gui/maintenance/getters'
+
+export const getDefaultState = (): GuiMaintenanceState => {
+ return {
+ entries: {},
+ }
+}
+
+// initial state
+const state = getDefaultState()
+
+// eslint-disable-next-line
+export const maintenance: Module = {
+ namespaced: true,
+ state,
+ getters,
+ actions,
+ mutations,
+}
diff --git a/src/store/gui/maintenance/mutations.ts b/src/store/gui/maintenance/mutations.ts
new file mode 100644
index 000000000..9ec013b59
--- /dev/null
+++ b/src/store/gui/maintenance/mutations.ts
@@ -0,0 +1,32 @@
+import Vue from 'vue'
+import { MutationTree } from 'vuex'
+import { GuiMaintenanceState } from '@/store/gui/maintenance/types'
+import { getDefaultState } from './index'
+
+export const mutations: MutationTree = {
+ reset(state) {
+ Object.assign(state, getDefaultState())
+ },
+
+ initStore(state, payload) {
+ Vue.set(state, 'entries', payload.value)
+ },
+
+ store(state, payload) {
+ Vue.set(state.entries, payload.id, payload.values)
+ },
+
+ update(state, payload) {
+ 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) {
+ if (payload in state.entries) {
+ Vue.delete(state.entries, payload)
+ }
+ },
+}
diff --git a/src/store/gui/maintenance/types.ts b/src/store/gui/maintenance/types.ts
new file mode 100644
index 000000000..0497f208c
--- /dev/null
+++ b/src/store/gui/maintenance/types.ts
@@ -0,0 +1,38 @@
+export interface GuiMaintenanceState {
+ entries: {
+ [key: string]: GuiMaintenanceStateEntry
+ }
+}
+
+export interface GuiMaintenanceStateEntry {
+ id?: string
+ name: string
+ note: string
+ start_time: number
+ end_time: number | null
+ start_filament: number
+ end_filament: number | null
+ start_printtime: number
+ end_printtime: number | null
+
+ reminder: {
+ type: null | 'one-time' | 'repeat'
+
+ filament: {
+ bool: boolean
+ value: number | null
+ end: number | null
+ }
+
+ printtime: {
+ bool: boolean
+ value: number | null
+ end: number | null
+ }
+
+ date: {
+ bool: boolean
+ value: number | null
+ }
+ }
+}
diff --git a/src/store/gui/notifications/getters.ts b/src/store/gui/notifications/getters.ts
index 3c35cd117..79bf5187d 100644
--- a/src/store/gui/notifications/getters.ts
+++ b/src/store/gui/notifications/getters.ts
@@ -5,10 +5,11 @@ import i18n from '@/plugins/i18n.js'
import { RootStateDependency } from '@/store/types'
import { sha256 } from 'js-sha256'
import { PrinterStateKlipperConfigWarning } from '@/store/printer/types'
+import { GuiRemindersStateReminder } from '../reminders/types'
import { detect } from 'detect-browser'
import semver from 'semver'
import { minBrowserVersions } from '@/store/variables'
-import { GuiRemindersStateReminder } from '../reminders/types'
+import { GuiMaintenanceStateEntry } from '@/store/gui/maintenance/types'
export const getters: GetterTree = {
getNotifications: (state, getters) => {
@@ -35,12 +36,12 @@ export const getters: GetterTree = {
// klipper warnings
notifications = notifications.concat(getters['getNotificationsKlipperWarnings'])
+ // user-created reminders
+ notifications = notifications.concat(getters['getNotificationsOverdueMaintenance'])
+
// browser warnings
notifications = notifications.concat(getters['getNotificationsBrowserWarnings'])
- // user-created reminders
- notifications = notifications.concat(getters['getNotificationsOverdueReminders'])
-
const mapType = {
normal: 2,
high: 1,
@@ -365,37 +366,33 @@ export const getters: GetterTree = {
return notifications
},
- getNotificationsOverdueReminders: (state, getters, rootState, rootGetters) => {
+ getNotificationsOverdueMaintenance: (state, getters, rootState, rootGetters) => {
const notifications: GuiNotificationStateEntry[] = []
- let reminders: GuiRemindersStateReminder[] = rootGetters['gui/reminders/getOverdueReminders']
+ let entries: GuiMaintenanceStateEntry[] = rootGetters['gui/maintenance/getOverdueEntries']
+ if (entries.length == 0) return []
const date = rootState.server.system_boot_at ?? new Date()
- if (reminders.length) {
- // get all dismissed reminders and convert it to a string[]
- const remindersDismisses = rootGetters['gui/notifications/getDismissByCategory']('reminder').map(
- (dismiss: GuiNotificationStateDismissEntry) => {
- return dismiss.id
- }
- )
+ // get all dismissed reminders and convert it to a string[]
+ const remindersDismisses = rootGetters['gui/notifications/getDismissByCategory']('maintenance').map(
+ (dismiss: GuiNotificationStateDismissEntry) => {
+ return dismiss.id
+ }
+ )
- // filter all dismissed reminders
- reminders = reminders.filter((reminder) => !remindersDismisses.includes(reminder.id))
+ // filter all dismissed reminders
+ entries = entries.filter((entry) => !remindersDismisses.includes(entry.id))
- reminders.forEach((reminder) => {
- // TODO: translate
- const title = 'User Created Reminder'
- const description = reminder.name
- notifications.push({
- id: `reminder/${reminder.id}`,
- priority: 'normal',
- title: title,
- description: description,
- date,
- dismissed: false,
- })
+ entries.forEach((entry) => {
+ notifications.push({
+ id: `maintenance/${entry.id}`,
+ priority: 'high',
+ title: i18n.t('App.Notifications.MaintenanceReminder').toString(),
+ description: i18n.t('App.Notifications.MaintenanceReminderText', { name: entry.name }).toString(),
+ date,
+ dismissed: false,
})
- }
+ })
return notifications
},
diff --git a/src/store/printer/getters.ts b/src/store/printer/getters.ts
index 24d5d71d8..225b06bee 100644
--- a/src/store/printer/getters.ts
+++ b/src/store/printer/getters.ts
@@ -289,7 +289,15 @@ export const getters: GetterTree = {
getMiscellaneous: (state) => {
const output: PrinterStateMiscellaneous[] = []
- const supportedObjects = ['controller_fan', 'heater_fan', 'fan_generic', 'fan', 'output_pin']
+ const supportedObjects = [
+ 'controller_fan',
+ 'heater_fan',
+ 'fan_generic',
+ 'fan',
+ 'output_pin',
+ 'pwm_tool',
+ 'pwm_cycle_time',
+ ]
const controllableFans = ['fan_generic', 'fan']
@@ -308,10 +316,11 @@ export const getters: GetterTree = {
if (nameSplit[0].toLowerCase() === 'fan') scale = 255
- if (nameSplit[0].toLowerCase() === 'output_pin') {
+ if (['output_pin', 'pwm_tool', 'pwm_cycle_time'].includes(nameSplit[0])) {
controllable = true
pwm = false
if ('pwm' in settings) pwm = settings?.pwm ?? false
+ if (['pwm_tool', 'pwm_cycle_time'].includes(nameSplit[0])) pwm = true
if ('scale' in settings) scale = settings?.scale ?? 1
}
diff --git a/src/store/server/actions.ts b/src/store/server/actions.ts
index 83d0021f3..6aa39ce15 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)
diff --git a/src/store/server/history/getters.ts b/src/store/server/history/getters.ts
index 3a75c2217..836f6bc76 100644
--- a/src/store/server/history/getters.ts
+++ b/src/store/server/history/getters.ts
@@ -292,7 +292,7 @@ export const getters: GetterTree = {
// 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)
diff --git a/src/store/server/history/types.ts b/src/store/server/history/types.ts
index 28ec9ab83..d28e23a22 100644
--- a/src/store/server/history/types.ts
+++ b/src/store/server/history/types.ts
@@ -19,10 +19,30 @@ export interface ServerHistoryStateJob {
end_time: number
filament_used: number
filename: string
- // @ts-ignore
- metadata?: {
- modified: number
- thumbnails: FileStateFileThumbnail[]
+ // eslint-disable-next-line
+ 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
@@ -30,7 +50,6 @@ export interface ServerHistoryStateJob {
status: string
start_time: number
total_duration: number
- [key: string]: any
}
export interface ServerHistoryStateAllPrintStatusEntry {
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']