mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 03:54:17 +02:00
Add auto-print G-code injection for queue items (#422)
Per-model start/end G-code snippets configurable in Settings (Workflow tab). Queue items get "Inject G-code" toggle — scheduler injects snippets into a temp 3MF copy before FTP upload. Supports Farmloop, SwapMod, AutoClear, Printflow 3D and similar bed-clearing systems. Original files are never modified.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Calendar, Clock, Hand, Power, Layers } from 'lucide-react';
|
||||
import { Calendar, Clock, Hand, Power, Layers, Code } from 'lucide-react';
|
||||
import type { ScheduleOptionsProps, ScheduleType } from './types';
|
||||
import {
|
||||
formatDateInput,
|
||||
@@ -27,6 +27,7 @@ export function ScheduleOptionsPanel({
|
||||
canControlPrinter = true,
|
||||
showStagger = false,
|
||||
printerCount = 0,
|
||||
hasGcodeSnippets = false,
|
||||
}: ScheduleOptionsProps) {
|
||||
const { t } = useTranslation();
|
||||
const [dateValue, setDateValue] = useState('');
|
||||
@@ -251,6 +252,23 @@ export function ScheduleOptionsPanel({
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* G-code injection */}
|
||||
{hasGcodeSnippets && (
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="gcodeInjection"
|
||||
checked={options.gcodeInjection}
|
||||
onChange={(e) => onChange({ ...options, gcodeInjection: e.target.checked })}
|
||||
className="rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"
|
||||
/>
|
||||
<label htmlFor="gcodeInjection" className="text-sm flex items-center gap-1 text-bambu-gray">
|
||||
<Code className="w-3.5 h-3.5" />
|
||||
{t('printModal.gcodeInjection', 'Inject auto-print G-code')}
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Stagger start */}
|
||||
{showStagger && options.scheduleType !== 'manual' && (
|
||||
<div className="space-y-3">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { AlertCircle, AlertTriangle, Calendar, Layers, Loader2, Pencil, Printer, X } from 'lucide-react';
|
||||
import { AlertCircle, AlertTriangle, Calendar, Code, Layers, Loader2, Pencil, Printer, X } from 'lucide-react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import type { PrintQueueItemCreate, PrintQueueItemUpdate, SpoolAssignment } from '../../api/client';
|
||||
@@ -124,6 +124,7 @@ export function PrintModal({
|
||||
scheduledTime,
|
||||
requirePreviousSuccess: queueItem.require_previous_success,
|
||||
autoOffAfter: queueItem.auto_off_after,
|
||||
gcodeInjection: queueItem.gcode_injection ?? false,
|
||||
staggerEnabled: false,
|
||||
staggerGroupSize: DEFAULT_SCHEDULE_OPTIONS.staggerGroupSize,
|
||||
staggerIntervalMinutes: DEFAULT_SCHEDULE_OPTIONS.staggerIntervalMinutes,
|
||||
@@ -645,6 +646,7 @@ export function PrintModal({
|
||||
library_file_id: isLibraryFile ? libraryFileId : undefined,
|
||||
require_previous_success: scheduleOptions.requirePreviousSuccess,
|
||||
auto_off_after: scheduleOptions.autoOffAfter,
|
||||
gcode_injection: scheduleOptions.gcodeInjection,
|
||||
manual_start: scheduleOptions.scheduleType === 'manual',
|
||||
ams_mapping: printerId ? getMappingForPrinter(printerId) : undefined,
|
||||
plate_id: plateOverride !== undefined ? plateOverride : selectedPlate,
|
||||
@@ -678,6 +680,7 @@ export function PrintModal({
|
||||
filament_overrides: filamentOverridesArray || null,
|
||||
require_previous_success: scheduleOptions.requirePreviousSuccess,
|
||||
auto_off_after: scheduleOptions.autoOffAfter,
|
||||
gcode_injection: scheduleOptions.gcodeInjection,
|
||||
manual_start: scheduleOptions.scheduleType === 'manual',
|
||||
ams_mapping: undefined,
|
||||
plate_id: plateId,
|
||||
@@ -755,6 +758,7 @@ export function PrintModal({
|
||||
target_location: null,
|
||||
require_previous_success: scheduleOptions.requirePreviousSuccess,
|
||||
auto_off_after: scheduleOptions.autoOffAfter,
|
||||
gcode_injection: scheduleOptions.gcodeInjection,
|
||||
manual_start: scheduleOptions.scheduleType === 'manual',
|
||||
ams_mapping: printerMapping,
|
||||
plate_id: plateId,
|
||||
@@ -1130,9 +1134,27 @@ export function PrintModal({
|
||||
canControlPrinter={hasPermission('printers:control')}
|
||||
showStagger={mode === 'add-to-queue' && assignmentMode === 'printer' && selectedPrinters.length > 1}
|
||||
printerCount={selectedPrinters.length}
|
||||
hasGcodeSnippets={!!settings?.gcode_snippets}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* G-code injection for reprint mode (only shown when quantity > 1 — applies to queued copies) */}
|
||||
{mode === 'reprint' && !!settings?.gcode_snippets && effectiveQuantity > 1 && (
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="gcodeInjectionReprint"
|
||||
checked={scheduleOptions.gcodeInjection}
|
||||
onChange={(e) => setScheduleOptions({ ...scheduleOptions, gcodeInjection: e.target.checked })}
|
||||
className="rounded border-bambu-dark-tertiary bg-bambu-dark text-bambu-green focus:ring-bambu-green"
|
||||
/>
|
||||
<label htmlFor="gcodeInjectionReprint" className="text-sm flex items-center gap-1 text-bambu-gray">
|
||||
<Code className="w-3.5 h-3.5" />
|
||||
{t('printModal.gcodeInjection', 'Inject auto-print G-code')}
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Error message */}
|
||||
{updateQueueMutation.isError && (
|
||||
<div className="mb-4 p-3 bg-red-500/20 border border-red-500/50 rounded-lg text-sm text-red-400">
|
||||
|
||||
@@ -69,6 +69,7 @@ export interface ScheduleOptions {
|
||||
scheduledTime: string;
|
||||
requirePreviousSuccess: boolean;
|
||||
autoOffAfter: boolean;
|
||||
gcodeInjection: boolean;
|
||||
staggerEnabled: boolean;
|
||||
staggerGroupSize: number;
|
||||
staggerIntervalMinutes: number;
|
||||
@@ -82,6 +83,7 @@ export const DEFAULT_SCHEDULE_OPTIONS: ScheduleOptions = {
|
||||
scheduledTime: '',
|
||||
requirePreviousSuccess: false,
|
||||
autoOffAfter: false,
|
||||
gcodeInjection: false,
|
||||
staggerEnabled: false,
|
||||
staggerGroupSize: 2,
|
||||
staggerIntervalMinutes: 5,
|
||||
@@ -214,4 +216,6 @@ export interface ScheduleOptionsProps {
|
||||
showStagger?: boolean;
|
||||
/** Number of selected printers (for stagger preview) */
|
||||
printerCount?: number;
|
||||
/** Whether G-code snippets are configured in settings */
|
||||
hasGcodeSnippets?: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user