mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-08-11 00:30:12 -04:00
Fix maintenance tasks showing wrong rod type for printer models (#351)
H2/A1 series have linear rails, not carbon rods. X1/P1/P2S have carbon rods, not linear rails. Split rod-specific maintenance into model-aware pairs: "Lubricate/Clean Carbon Rods" for X1/P1/P2S and "Lubricate/Clean Linear Rails" for A1/H2. Added rod type classification to printer_models and startup cleanup for stale/duplicate system maintenance types.
This commit is contained in:
parent
f9b47282a1
commit
cffe7e62bc
11 changed files with 267 additions and 118 deletions
|
|
@ -11,6 +11,7 @@ All notable changes to Bambuddy will be documented in this file.
|
|||
- **Nozzle-Aware AMS Filament Mapping for Dual-Nozzle Printers** ([#318](https://github.com/maziggy/bambuddy/issues/318)) — On dual-nozzle printers (H2D, H2D Pro), each AMS unit is physically connected to either the left or right nozzle. Bambuddy now reads nozzle assignments from the 3MF file (`filament_nozzle_map` + `physical_extruder_map` in `project_settings.config`) and constrains filament matching to only AMS trays connected to the correct nozzle via `ams_extruder_map`. Applies to the print scheduler, reprint modal, queue modal, and multi-printer selection. Falls back gracefully to unfiltered matching when no trays exist on the target nozzle. The filament mapping UI shows L/R nozzle badges for dual-nozzle prints. Translated in all 4 locales (en, de, ja, it).
|
||||
|
||||
### Fixed
|
||||
- **Model-Specific Maintenance Tasks for Carbon Rods vs Linear Rails** ([#351](https://github.com/maziggy/bambuddy/issues/351)) — Maintenance tasks "Clean Carbon Rods" and "Lubricate Linear Rails" were shown for all printers regardless of motion system. H2 and A1 series use linear rails (not carbon rods), and X1/P1/P2S series use carbon rods (not linear rails). Maintenance types are now classified by rod/rail type: "Lubricate Carbon Rods" and "Clean Carbon Rods" for X1/P1/P2S, "Lubricate Linear Rails" and "Clean Linear Rails" for A1/H2. Stale and duplicate system types are automatically cleaned up on startup. Includes model-specific wiki links and i18n keys for all 4 locales.
|
||||
- **AMS Slot Configuration Overwritten on Startup** — Bambuddy was resetting AMS slot filament presets on every startup and reconnection. The `on_ams_change` callback unconditionally unlinked Bambu Lab spool assignments on each MQTT push-all response, then re-assigned them by sending `ams_filament_setting` without a `setting_id`, which cleared the printer's filament preset. Now compares spool RFID identifiers (`tray_uuid` / `tag_uid`) before unlinking — if the same spool is still in the slot, the assignment is preserved and no `ams_filament_setting` command is sent.
|
||||
- **Bambu Lab Spool Detection False Positives** — The `is_bambu_lab_spool()` function (backend) and `isBambuLabSpool()` (frontend) incorrectly identified third-party spools as Bambu Lab spools when they used Bambu generic filament presets (e.g., "Generic PLA"). The `tray_info_idx` field (e.g., "GFA00") identifies the filament *type*, not the spool manufacturer — third-party spools using Bambu presets also have GF-prefixed values. Removed `tray_info_idx` from detection logic; now uses only hardware RFID identifiers (`tray_uuid` and `tag_uid`) which are physically embedded in genuine Bambu Lab spools.
|
||||
- **FTP Disconnect Raises EOFError When Server Dies** — `BambuFTPClient.disconnect()` only caught `OSError` and `ftplib.Error`, but `quit()` raises `EOFError` when the server has closed the connection mid-session. `EOFError` is not a subclass of either, so it propagated to callers. Now caught alongside the other exception types for clean best-effort disconnect.
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ from backend.app.schemas.maintenance import (
|
|||
PrinterMaintenanceUpdate,
|
||||
)
|
||||
from backend.app.services.notification_service import notification_service
|
||||
from backend.app.utils.printer_models import get_rod_type
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -33,12 +34,33 @@ router = APIRouter(prefix="/maintenance", tags=["maintenance"])
|
|||
|
||||
# Default maintenance types
|
||||
DEFAULT_MAINTENANCE_TYPES = [
|
||||
# Carbon rod models only (X1/P1/P2S)
|
||||
{
|
||||
"name": "Lubricate Linear Rails",
|
||||
"description": "Apply lubricant to linear rails and rods for smooth motion",
|
||||
"name": "Lubricate Carbon Rods",
|
||||
"description": "Apply lubricant to carbon rods for smooth motion",
|
||||
"default_interval_hours": 50.0,
|
||||
"icon": "Droplet",
|
||||
},
|
||||
{
|
||||
"name": "Clean Carbon Rods",
|
||||
"description": "Wipe carbon rods with a dry cloth",
|
||||
"default_interval_hours": 100.0,
|
||||
"icon": "Sparkles",
|
||||
},
|
||||
# Linear rail models only (A1/H2)
|
||||
{
|
||||
"name": "Lubricate Linear Rails",
|
||||
"description": "Apply lubricant to linear rails for smooth motion",
|
||||
"default_interval_hours": 50.0,
|
||||
"icon": "Droplet",
|
||||
},
|
||||
{
|
||||
"name": "Clean Linear Rails",
|
||||
"description": "Wipe linear rails with a dry cloth to remove dust and debris",
|
||||
"default_interval_hours": 100.0,
|
||||
"icon": "Sparkles",
|
||||
},
|
||||
# Universal (all models)
|
||||
{
|
||||
"name": "Clean Nozzle/Hotend",
|
||||
"description": "Clean nozzle exterior and perform cold pull if needed",
|
||||
|
|
@ -51,12 +73,6 @@ DEFAULT_MAINTENANCE_TYPES = [
|
|||
"default_interval_hours": 200.0,
|
||||
"icon": "Ruler",
|
||||
},
|
||||
{
|
||||
"name": "Clean Carbon Rods",
|
||||
"description": "Wipe carbon rods with a dry cloth",
|
||||
"default_interval_hours": 100.0,
|
||||
"icon": "Sparkles",
|
||||
},
|
||||
{
|
||||
"name": "Clean Build Plate",
|
||||
"description": "Deep clean build plate with IPA or soap",
|
||||
|
|
@ -71,6 +87,30 @@ DEFAULT_MAINTENANCE_TYPES = [
|
|||
},
|
||||
]
|
||||
|
||||
# System types that only apply to printers with a specific rod/rail type.
|
||||
# "carbon" = X1/P1/P2S series (carbon rods), "linear_rail" = A1/H2 series.
|
||||
# Types not listed here apply to all printers.
|
||||
_ROD_TYPE_REQUIREMENTS: dict[str, str] = {
|
||||
"Lubricate Carbon Rods": "carbon",
|
||||
"Clean Carbon Rods": "carbon",
|
||||
"Lubricate Linear Rails": "linear_rail",
|
||||
"Clean Linear Rails": "linear_rail",
|
||||
}
|
||||
|
||||
|
||||
def _should_apply_to_printer(type_name: str, printer_model: str | None) -> bool:
|
||||
"""Check if a system maintenance type should apply to a given printer model."""
|
||||
rod_requirement = _ROD_TYPE_REQUIREMENTS.get(type_name)
|
||||
if rod_requirement is None:
|
||||
return True # Not model-specific, applies to all
|
||||
|
||||
rod_type = get_rod_type(printer_model)
|
||||
if rod_type is None:
|
||||
# Unknown model — default to carbon rods (legacy behavior)
|
||||
return rod_requirement == "carbon"
|
||||
|
||||
return rod_type == rod_requirement
|
||||
|
||||
|
||||
async def get_printer_total_hours(db: AsyncSession, printer_id: int) -> float:
|
||||
"""Calculate total active hours for a printer from runtime counter plus offset.
|
||||
|
|
@ -94,13 +134,27 @@ async def get_printer_total_hours(db: AsyncSession, printer_id: int) -> float:
|
|||
|
||||
|
||||
async def ensure_default_types(db: AsyncSession) -> None:
|
||||
"""Ensure default maintenance types exist."""
|
||||
result = await db.execute(select(MaintenanceType).where(MaintenanceType.is_system.is_(True)))
|
||||
"""Ensure default maintenance types exist, remove stale/duplicate ones."""
|
||||
result = await db.execute(
|
||||
select(MaintenanceType).where(MaintenanceType.is_system.is_(True)).order_by(MaintenanceType.id)
|
||||
)
|
||||
existing = result.scalars().all()
|
||||
existing_names = {t.name for t in existing}
|
||||
|
||||
default_names = {t["name"] for t in DEFAULT_MAINTENANCE_TYPES}
|
||||
|
||||
# Remove stale system types no longer in defaults (e.g. renamed types)
|
||||
# and deduplicate: if concurrent requests created the same type twice,
|
||||
# keep only the first (lowest id) and delete the rest.
|
||||
seen_names: set[str] = set()
|
||||
for t in existing:
|
||||
if t.name not in default_names or t.name in seen_names:
|
||||
await db.delete(t)
|
||||
else:
|
||||
seen_names.add(t.name)
|
||||
|
||||
# Create any missing default types
|
||||
for type_def in DEFAULT_MAINTENANCE_TYPES:
|
||||
if type_def["name"] not in existing_names:
|
||||
if type_def["name"] not in seen_names:
|
||||
new_type = MaintenanceType(
|
||||
name=type_def["name"],
|
||||
description=type_def["description"],
|
||||
|
|
@ -228,6 +282,11 @@ async def _get_printer_maintenance_internal(
|
|||
now = datetime.utcnow()
|
||||
|
||||
for maint_type in all_types:
|
||||
# Skip system types that don't apply to this printer model
|
||||
# (e.g., "Clean Carbon Rods" for H2D which has steel rods)
|
||||
if maint_type.is_system and not _should_apply_to_printer(maint_type.name, printer.model):
|
||||
continue
|
||||
|
||||
item = existing_items.get(maint_type.id)
|
||||
default_interval_type = getattr(maint_type, "interval_type", "hours") or "hours"
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,69 @@ PRINTER_MODEL_ID_MAP = {
|
|||
}
|
||||
|
||||
|
||||
# Rod/rail type classification for maintenance tasks.
|
||||
# Carbon rods: X1, P1, P2S series (CoreXY with carbon fiber rods)
|
||||
# Linear rails: A1, H2 series (linear rail motion system)
|
||||
# Values must be uppercase with spaces stripped for normalized comparison.
|
||||
CARBON_ROD_MODELS = frozenset(
|
||||
[
|
||||
# Display names (uppercase, no spaces)
|
||||
"X1",
|
||||
"X1C",
|
||||
"X1E",
|
||||
"P1P",
|
||||
"P1S",
|
||||
"P2S",
|
||||
# Internal codes
|
||||
"C11", # X1C
|
||||
"C12", # X1
|
||||
"C13", # X1E
|
||||
"N7", # P2S
|
||||
]
|
||||
)
|
||||
|
||||
LINEAR_RAIL_MODELS = frozenset(
|
||||
[
|
||||
# Display names (uppercase, no spaces)
|
||||
"A1",
|
||||
"A1MINI",
|
||||
"H2D",
|
||||
"H2DPRO",
|
||||
"H2C",
|
||||
"H2S",
|
||||
# Internal codes
|
||||
"N1", # A1
|
||||
"N2S", # A1 Mini
|
||||
"A04", # A1 Mini (alternate)
|
||||
"A11", # A1
|
||||
"A12", # A1 Mini
|
||||
"O1D", # H2D
|
||||
"O1E", # H2D Pro
|
||||
"O2D", # H2D Pro (alternate)
|
||||
"O1C", # H2C
|
||||
"O1S", # H2S
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def get_rod_type(model: str | None) -> str | None:
|
||||
"""Return the rod/rail type for a printer model.
|
||||
|
||||
Returns:
|
||||
"carbon" for X1/P1/P2S series (carbon fiber rods),
|
||||
"linear_rail" for A1/H2 series (linear rails),
|
||||
None for unknown models.
|
||||
"""
|
||||
if not model:
|
||||
return None
|
||||
normalized = model.strip().upper().replace(" ", "").replace("-", "")
|
||||
if normalized in CARBON_ROD_MODELS:
|
||||
return "carbon"
|
||||
if normalized in LINEAR_RAIL_MODELS:
|
||||
return "linear_rail"
|
||||
return None
|
||||
|
||||
|
||||
def normalize_printer_model_id(model_id: str | None) -> str | None:
|
||||
"""Convert printer_model_id (internal code) to normalized short name.
|
||||
|
||||
|
|
|
|||
|
|
@ -980,6 +980,7 @@ export default {
|
|||
removeFromPrinter: 'Von diesem Drucker entfernen',
|
||||
// Types
|
||||
types: {
|
||||
lubricateCarbonRods: 'Karbonstäbe schmieren',
|
||||
lubricateRails: 'Linearschienen schmieren',
|
||||
cleanNozzle: 'Düse/Hotend reinigen',
|
||||
checkBelts: 'Riemenspannung prüfen',
|
||||
|
|
@ -988,6 +989,7 @@ export default {
|
|||
checkCooling: 'Kühlungslüfter prüfen',
|
||||
generalInspection: 'Allgemeine Inspektion',
|
||||
cleanCarbonRods: 'Kohlenstoffstangen reinigen',
|
||||
cleanLinearRails: 'Linearschienen reinigen',
|
||||
checkPtfeTube: 'PTFE-Schlauch prüfen',
|
||||
replaceHepaFilter: 'HEPA-Filter ersetzen',
|
||||
replaceCarbonFilter: 'Aktivkohlefilter ersetzen',
|
||||
|
|
@ -2977,6 +2979,7 @@ export default {
|
|||
|
||||
// Maintenance type descriptions (built-in)
|
||||
maintenanceDescriptions: {
|
||||
lubricateCarbonRods: 'Schmiermittel auf Karbonstäbe für sanfte Bewegung auftragen',
|
||||
lubricateRails: 'Schmiermittel auf Linearschienen für sanfte Bewegung auftragen',
|
||||
cleanNozzle: 'Hotend und Düse reinigen, um Verstopfungen zu verhindern',
|
||||
checkBelts: 'Riemenspannung für präzise Drucke überprüfen',
|
||||
|
|
@ -2985,6 +2988,7 @@ export default {
|
|||
checkCooling: 'Sicherstellen, dass Lüfter ordnungsgemäß funktionieren',
|
||||
generalInspection: 'Allgemeine Druckerinspektion',
|
||||
cleanCarbonRods: 'Karbonstäbe reinigen, um Reibung zu reduzieren',
|
||||
cleanLinearRails: 'Linearschienen abwischen, um Staub und Schmutz zu entfernen',
|
||||
checkPtfeTube: 'PTFE-Schlauch auf Verschleiß oder Beschädigung prüfen',
|
||||
replaceHepaFilter: 'HEPA-Filter für Luftqualität ersetzen',
|
||||
replaceCarbonFilter: 'Aktivkohlefilter ersetzen',
|
||||
|
|
|
|||
|
|
@ -980,6 +980,7 @@ export default {
|
|||
removeFromPrinter: 'Remove from this printer',
|
||||
// Types
|
||||
types: {
|
||||
lubricateCarbonRods: 'Lubricate Carbon Rods',
|
||||
lubricateRails: 'Lubricate Linear Rails',
|
||||
cleanNozzle: 'Clean Nozzle/Hotend',
|
||||
checkBelts: 'Check Belt Tension',
|
||||
|
|
@ -988,6 +989,7 @@ export default {
|
|||
checkCooling: 'Check Cooling Fans',
|
||||
generalInspection: 'General Inspection',
|
||||
cleanCarbonRods: 'Clean Carbon Rods',
|
||||
cleanLinearRails: 'Clean Linear Rails',
|
||||
checkPtfeTube: 'Check PTFE Tube',
|
||||
replaceHepaFilter: 'Replace HEPA Filter',
|
||||
replaceCarbonFilter: 'Replace Carbon Filter',
|
||||
|
|
@ -2982,6 +2984,7 @@ export default {
|
|||
|
||||
// Maintenance type descriptions (built-in)
|
||||
maintenanceDescriptions: {
|
||||
lubricateCarbonRods: 'Apply lubricant to carbon rods for smooth motion',
|
||||
lubricateRails: 'Apply lubricant to linear rails for smooth motion',
|
||||
cleanNozzle: 'Clean hotend and nozzle to prevent clogs',
|
||||
checkBelts: 'Verify belt tension for accurate prints',
|
||||
|
|
@ -2990,6 +2993,7 @@ export default {
|
|||
checkCooling: 'Ensure cooling fans are working properly',
|
||||
generalInspection: 'General printer inspection',
|
||||
cleanCarbonRods: 'Clean carbon rods to reduce friction',
|
||||
cleanLinearRails: 'Wipe linear rails to remove dust and debris',
|
||||
checkPtfeTube: 'Inspect PTFE tube for wear or damage',
|
||||
replaceHepaFilter: 'Replace HEPA filter for air quality',
|
||||
replaceCarbonFilter: 'Replace activated carbon filter',
|
||||
|
|
|
|||
|
|
@ -967,6 +967,7 @@ export default {
|
|||
removeFromPrinter: 'Rimuovi da questa stampante',
|
||||
// Types
|
||||
types: {
|
||||
lubricateCarbonRods: 'Lubrifica aste in carbonio',
|
||||
lubricateRails: 'Lubrifica guide lineari',
|
||||
cleanNozzle: 'Pulisci ugello/Hotend',
|
||||
checkBelts: 'Controlla tensione cinghie',
|
||||
|
|
@ -975,6 +976,7 @@ export default {
|
|||
checkCooling: 'Controlla ventole raffreddamento',
|
||||
generalInspection: 'Ispezione generale',
|
||||
cleanCarbonRods: 'Pulisci aste in carbonio',
|
||||
cleanLinearRails: 'Pulisci guide lineari',
|
||||
checkPtfeTube: 'Controlla tubo PTFE',
|
||||
replaceHepaFilter: 'Sostituisci filtro HEPA',
|
||||
replaceCarbonFilter: 'Sostituisci filtro carbone',
|
||||
|
|
@ -2651,6 +2653,7 @@ export default {
|
|||
|
||||
// Maintenance type descriptions (built-in)
|
||||
maintenanceDescriptions: {
|
||||
lubricateCarbonRods: 'Applica lubrificante alle aste in carbonio per un movimento fluido',
|
||||
lubricateRails: 'Applica lubrificante alle guide lineari per un movimento fluido',
|
||||
cleanNozzle: 'Pulisci hotend e ugello per prevenire intasamenti',
|
||||
checkBelts: 'Verifica tensione cinghie per stampe accurate',
|
||||
|
|
@ -2659,6 +2662,7 @@ export default {
|
|||
checkCooling: 'Assicurati che le ventole di raffreddamento funzionino',
|
||||
generalInspection: 'Ispezione generale stampante',
|
||||
cleanCarbonRods: 'Pulisci le aste in carbonio per ridurre attrito',
|
||||
cleanLinearRails: 'Pulisci le guide lineari per rimuovere polvere e detriti',
|
||||
checkPtfeTube: 'Ispeziona il tubo PTFE per usura o danni',
|
||||
replaceHepaFilter: 'Sostituisci filtro HEPA per qualità aria',
|
||||
replaceCarbonFilter: 'Sostituisci filtro a carbone attivo',
|
||||
|
|
|
|||
|
|
@ -1015,6 +1015,7 @@ export default {
|
|||
noPrintersAssigned: 'プリンター未割り当て',
|
||||
removeFromPrinter: 'このプリンターから削除',
|
||||
types: {
|
||||
lubricateCarbonRods: 'カーボンロッドの潤滑',
|
||||
lubricateRails: 'リニアレールの潤滑',
|
||||
cleanNozzle: 'ノズル/ホットエンドの清掃',
|
||||
checkBelts: 'ベルト張力の確認',
|
||||
|
|
@ -1023,6 +1024,7 @@ export default {
|
|||
checkCooling: '冷却ファンの確認',
|
||||
generalInspection: '総合点検',
|
||||
cleanCarbonRods: 'カーボンロッドの清掃',
|
||||
cleanLinearRails: 'リニアレールの清掃',
|
||||
checkPtfeTube: 'PTFEチューブの確認',
|
||||
replaceHepaFilter: 'HEPAフィルター交換',
|
||||
replaceCarbonFilter: 'カーボンフィルター交換',
|
||||
|
|
@ -2860,6 +2862,7 @@ export default {
|
|||
},
|
||||
},
|
||||
maintenanceDescriptions: {
|
||||
lubricateCarbonRods: 'カーボンロッドに潤滑剤を塗布してスムーズな動きを確保',
|
||||
lubricateRails: 'リニアレールの潤滑',
|
||||
cleanNozzle: 'ノズル/ホットエンドの清掃',
|
||||
checkBelts: 'ベルト張力の確認',
|
||||
|
|
@ -2868,6 +2871,7 @@ export default {
|
|||
checkCooling: '冷却ファンの確認',
|
||||
generalInspection: '総合点検',
|
||||
cleanCarbonRods: 'カーボンロッドの清掃',
|
||||
cleanLinearRails: 'リニアレールを拭いてほこりや汚れを除去',
|
||||
checkPtfeTube: 'PTFEチューブの確認',
|
||||
replaceHepaFilter: 'HEPAフィルター交換',
|
||||
replaceCarbonFilter: 'カーボンフィルター交換',
|
||||
|
|
|
|||
|
|
@ -140,14 +140,19 @@ function getMaintenanceWikiUrl(typeName: string, printerModel: string | null): s
|
|||
const isP2S = model.includes('P2S');
|
||||
|
||||
switch (typeName) {
|
||||
case 'Lubricate Linear Rails':
|
||||
case 'Lubricate Carbon Rods':
|
||||
// X1, P1, P2S series have carbon rods
|
||||
if (isX1) return 'https://wiki.bambulab.com/en/x1/maintenance/basic-maintenance';
|
||||
if (isP1) return 'https://wiki.bambulab.com/en/p1/maintenance/p1p-maintenance';
|
||||
if (isP2S) return 'https://wiki.bambulab.com/en/p2s/maintenance/belt-tension';
|
||||
return null;
|
||||
|
||||
case 'Lubricate Linear Rails':
|
||||
// A1 and H2 series have linear rails
|
||||
if (isA1Mini) return 'https://wiki.bambulab.com/en/a1-mini/maintenance/lubricate-y-axis';
|
||||
if (isA1) return 'https://wiki.bambulab.com/en/a1/maintenance/lubricate-y-axis';
|
||||
if (isH2) return 'https://wiki.bambulab.com/en/h2/maintenance/x-axis-lubrication';
|
||||
if (isP2S) return 'https://wiki.bambulab.com/en/p2s/maintenance/belt-tension'; // P2S maintenance page
|
||||
return 'https://wiki.bambulab.com/en/general/lead-screws-lubrication';
|
||||
return null;
|
||||
|
||||
case 'Clean Nozzle/Hotend':
|
||||
if (isX1 || isP1) return 'https://wiki.bambulab.com/en/x1/troubleshooting/nozzle-clog';
|
||||
|
|
@ -168,11 +173,16 @@ function getMaintenanceWikiUrl(typeName: string, printerModel: string | null): s
|
|||
return 'https://wiki.bambulab.com/en/x1/maintenance/belt-tension';
|
||||
|
||||
case 'Clean Carbon Rods':
|
||||
// Only X1 and P1 series have carbon rods
|
||||
if (isX1 || isP1) return 'https://wiki.bambulab.com/en/general/carbon-rods-clearance';
|
||||
// A1, H2, P2S don't have carbon rods - return null
|
||||
if (isA1Mini || isA1 || isH2 || isP2S) return null;
|
||||
return 'https://wiki.bambulab.com/en/general/carbon-rods-clearance';
|
||||
// X1, P1, P2S series have carbon rods
|
||||
if (isX1 || isP1 || isP2S) return 'https://wiki.bambulab.com/en/general/carbon-rods-clearance';
|
||||
return null;
|
||||
|
||||
case 'Clean Linear Rails':
|
||||
// A1 and H2 series have linear rails
|
||||
if (isA1Mini) return 'https://wiki.bambulab.com/en/a1-mini/maintenance/lubricate-y-axis';
|
||||
if (isA1) return 'https://wiki.bambulab.com/en/a1/maintenance/lubricate-y-axis';
|
||||
if (isH2) return 'https://wiki.bambulab.com/en/h2/maintenance/x-axis-lubrication';
|
||||
return null;
|
||||
|
||||
case 'Clean Build Plate':
|
||||
// Same for all printers
|
||||
|
|
@ -381,7 +391,7 @@ function PrinterSection({
|
|||
hasPermission: (permission: Permission) => boolean;
|
||||
t: TFunction;
|
||||
}) {
|
||||
const [expanded, setExpanded] = useState(true);
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
const [editingHours, setEditingHours] = useState(false);
|
||||
const [hoursInput, setHoursInput] = useState(overview.total_print_hours.toFixed(1));
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
<!-- Splash screens for iOS -->
|
||||
<link rel="apple-touch-startup-image" href="/img/android-chrome-512x512.png" />
|
||||
<script type="module" crossorigin src="/assets/index-C7KLL0cs.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-D1nHfvlC.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DMk3iz3Q.css">
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
cd backend
|
||||
ruff check && ruff format --check
|
||||
|
||||
if [ "$1" = "--full" ]; then
|
||||
../venv/bin/python3 -m pytest tests/ -v -n 14
|
||||
else
|
||||
../venv/bin/python3 -m pytest tests/ -v -n 14 --ignore=tests/unit/services/test_bambu_ftp.py
|
||||
fi
|
||||
cd ..
|
||||
#if [ "$1" = "--full" ]; then
|
||||
# ../venv/bin/python3 -m pytest tests/ -v -n 14
|
||||
#else
|
||||
../venv/bin/python3 -m pytest tests/ -v -n 14 --ignore=tests/unit/services/test_bambu_ftp.py
|
||||
#fi
|
||||
#cd ..
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue