فهرست منبع

Add Cloud Profiles template visibility and preset diff view

  Cloud Profiles (ProfilesPage.tsx):
  - Add template visibility control (showInModal flag)
    - Eye/EyeOff toggle in templates modal to show/hide templates
    - Only templates with showInModal=true appear in preset modals
    - Default new templates to showInModal=true in save dialog
  - Add preset diff/compare view with two modes:
    - Compare button in edit modal (preset vs base)
    - Compare mode on main page (two-preset comparison)
    - Side-by-side diff with added/removed/changed highlighting
    - Stats showing added/removed/changed/same counts
    - Search filter and Changes/All toggle
    - Type restriction (only compare same preset types)
  - Fix array value display (show "value" instead of ["value"])
  - Fix printer preset G-code display (format escaped \n as real newlines)
  - Fix modal overflow issues with proper flex patterns
  - Fix light theme colors for compare selection text
maziggy 5 ماه پیش
والد
کامیت
2867401116

+ 11 - 0
README.md

@@ -102,6 +102,16 @@ v∆v
   - Tracks filament usage during prints
   - Tracks filament usage during prints
   - Third-party spools (SpoolEase, etc.) gracefully skipped
   - Third-party spools (SpoolEase, etc.) gracefully skipped
 - **Cloud Profiles Sync** - Access your Bambu Cloud slicer presets
 - **Cloud Profiles Sync** - Access your Bambu Cloud slicer presets
+  - View and manage filament, printer, and process presets
+  - **Template system** for quick preset creation:
+    - Save any preset as a reusable template
+    - Visibility control to choose which templates appear in modals
+    - Apply templates when creating or editing presets
+  - **Preset comparison/diff view**:
+    - Compare any preset against its base preset
+    - Compare any two presets of the same type side-by-side
+    - Highlights added, removed, and changed settings
+    - Searchable diff with change statistics
 - **File Manager** - Browse and manage files on your printer's SD card
 - **File Manager** - Browse and manage files on your printer's SD card
 - **Re-print** - Send archived prints back to any connected printer
 - **Re-print** - Send archived prints back to any connected printer
 - **Dark/Light Theme** - Easy on the eyes, day or night
 - **Dark/Light Theme** - Easy on the eyes, day or night
@@ -892,6 +902,7 @@ To fix the printer's clock:
 - [x] Maintenance tracker
 - [x] Maintenance tracker
 - [x] Multi-language support (English, German)
 - [x] Multi-language support (English, German)
 - [x] Auto updates from GitHub releases
 - [x] Auto updates from GitHub releases
+- [x] Cloud Profiles template system and diff view
 - [ ] Full printer control
 - [ ] Full printer control
 - [ ] Mobile-optimized UI
 - [ ] Mobile-optimized UI
 - [ ] docs: readme -> wiki
 - [ ] docs: readme -> wiki

+ 73 - 1
backend/app/api/routes/cloud.py

@@ -4,6 +4,10 @@ Bambu Lab Cloud API Routes
 Handles authentication and profile management with Bambu Cloud.
 Handles authentication and profile management with Bambu Cloud.
 """
 """
 
 
+import json
+from pathlib import Path
+from typing import Literal
+
 from fastapi import APIRouter, HTTPException, Depends
 from fastapi import APIRouter, HTTPException, Depends
 from sqlalchemy.ext.asyncio import AsyncSession
 from sqlalchemy.ext.asyncio import AsyncSession
 from sqlalchemy import select
 from sqlalchemy import select
@@ -172,7 +176,7 @@ async def logout(db: AsyncSession = Depends(get_db)):
 
 
 @router.get("/settings", response_model=SlicerSettingsResponse)
 @router.get("/settings", response_model=SlicerSettingsResponse)
 async def get_slicer_settings(
 async def get_slicer_settings(
-    version: str = "01.09.00.00",
+    version: str = "02.04.00.70",
     db: AsyncSession = Depends(get_db),
     db: AsyncSession = Depends(get_db),
 ):
 ):
     """
     """
@@ -391,3 +395,71 @@ async def delete_setting(setting_id: str, db: AsyncSession = Depends(get_db)):
         raise HTTPException(status_code=401, detail="Authentication expired")
         raise HTTPException(status_code=401, detail="Authentication expired")
     except BambuCloudError as e:
     except BambuCloudError as e:
         raise HTTPException(status_code=500, detail=str(e))
         raise HTTPException(status_code=500, detail=str(e))
+
+
+# Path to field definition files
+FIELDS_DATA_DIR = Path(__file__).parent.parent.parent / "data"
+
+# Cache for field definitions (loaded once)
+_fields_cache: dict[str, dict] = {}
+
+
+def _load_fields(preset_type: str) -> dict:
+    """Load field definitions from JSON file."""
+    if preset_type in _fields_cache:
+        return _fields_cache[preset_type]
+
+    # Map API type names to file names
+    file_map = {
+        "filament": "filament_fields.json",
+        "print": "process_fields.json",
+        "process": "process_fields.json",
+        "printer": "printer_fields.json",
+    }
+
+    filename = file_map.get(preset_type)
+    if not filename:
+        raise HTTPException(status_code=400, detail=f"Unknown preset type: {preset_type}")
+
+    file_path = FIELDS_DATA_DIR / filename
+    if not file_path.exists():
+        raise HTTPException(status_code=404, detail=f"Field definitions not found for: {preset_type}")
+
+    with open(file_path, "r") as f:
+        data = json.load(f)
+
+    _fields_cache[preset_type] = data
+    return data
+
+
+@router.get("/fields/{preset_type}")
+async def get_preset_fields(preset_type: Literal["filament", "print", "process", "printer"]):
+    """
+    Get field definitions for a preset type.
+
+    Returns a list of field definitions including:
+    - key: The setting key name
+    - label: Human-readable label
+    - type: Field type (text, number, boolean, select)
+    - category: Grouping category
+    - description: Field description
+    - options: For select fields, available options
+    - unit: Unit of measurement (if applicable)
+    - min/max/step: For number fields, validation constraints
+    """
+    data = _load_fields(preset_type)
+    return data
+
+
+@router.get("/fields")
+async def get_all_preset_fields():
+    """
+    Get all field definitions for all preset types.
+
+    Returns field definitions organized by type.
+    """
+    return {
+        "filament": _load_fields("filament"),
+        "process": _load_fields("process"),
+        "printer": _load_fields("printer"),
+    }

+ 1 - 1
backend/app/core/config.py

@@ -2,7 +2,7 @@ from pathlib import Path
 from pydantic_settings import BaseSettings
 from pydantic_settings import BaseSettings
 
 
 # Application version - single source of truth
 # Application version - single source of truth
-APP_VERSION = "0.1.4"
+APP_VERSION = "0.1.5b"
 GITHUB_REPO = "maziggy/bambusy"
 GITHUB_REPO = "maziggy/bambusy"
 
 
 
 

+ 625 - 0
backend/app/data/filament_fields.json

@@ -0,0 +1,625 @@
+{
+  "version": "1.0.0",
+  "description": "Filament preset field definitions for Bambu Lab printers",
+  "fields": [
+    {
+      "key": "filament_vendor",
+      "label": "Vendor",
+      "type": "text",
+      "category": "basic",
+      "description": "Filament manufacturer name"
+    },
+    {
+      "key": "filament_type",
+      "label": "Filament Type",
+      "type": "select",
+      "category": "basic",
+      "description": "Material type",
+      "options": [
+        {"value": "PLA", "label": "PLA"},
+        {"value": "ABS", "label": "ABS"},
+        {"value": "PETG", "label": "PETG"},
+        {"value": "TPU", "label": "TPU"},
+        {"value": "PA", "label": "PA (Nylon)"},
+        {"value": "PA-CF", "label": "PA-CF"},
+        {"value": "PET-CF", "label": "PET-CF"},
+        {"value": "PC", "label": "PC"},
+        {"value": "ASA", "label": "ASA"},
+        {"value": "PVA", "label": "PVA"},
+        {"value": "HIPS", "label": "HIPS"}
+      ]
+    },
+    {
+      "key": "filament_cost",
+      "label": "Filament Cost",
+      "type": "number",
+      "category": "basic",
+      "description": "Cost per kg",
+      "unit": "$/kg"
+    },
+    {
+      "key": "filament_density",
+      "label": "Density",
+      "type": "number",
+      "category": "basic",
+      "description": "Material density",
+      "unit": "g/cm³",
+      "step": 0.01
+    },
+    {
+      "key": "filament_diameter",
+      "label": "Filament Diameter",
+      "type": "number",
+      "category": "basic",
+      "description": "Filament diameter",
+      "unit": "mm",
+      "step": 0.01,
+      "min": 1.5,
+      "max": 3.0
+    },
+    {
+      "key": "nozzle_temperature",
+      "label": "Nozzle Temperature",
+      "type": "text",
+      "category": "temperature",
+      "description": "Printing temperature (comma-separated: normal,first layer)",
+      "unit": "°C"
+    },
+    {
+      "key": "nozzle_temperature_initial_layer",
+      "label": "Initial Layer Nozzle Temp",
+      "type": "text",
+      "category": "temperature",
+      "description": "First layer nozzle temperature",
+      "unit": "°C"
+    },
+    {
+      "key": "nozzle_temperature_range_low",
+      "label": "Min Nozzle Temp",
+      "type": "number",
+      "category": "temperature",
+      "description": "Minimum recommended nozzle temperature",
+      "unit": "°C",
+      "min": 150,
+      "max": 350
+    },
+    {
+      "key": "nozzle_temperature_range_high",
+      "label": "Max Nozzle Temp",
+      "type": "number",
+      "category": "temperature",
+      "description": "Maximum recommended nozzle temperature",
+      "unit": "°C",
+      "min": 150,
+      "max": 350
+    },
+    {
+      "key": "hot_plate_temp",
+      "label": "Bed Temperature (Hot Plate)",
+      "type": "number",
+      "category": "temperature",
+      "description": "Bed temperature for standard plate",
+      "unit": "°C",
+      "min": 0,
+      "max": 120
+    },
+    {
+      "key": "hot_plate_temp_initial_layer",
+      "label": "Initial Layer Bed Temp (Hot Plate)",
+      "type": "number",
+      "category": "temperature",
+      "description": "First layer bed temperature for standard plate",
+      "unit": "°C",
+      "min": 0,
+      "max": 120
+    },
+    {
+      "key": "cool_plate_temp",
+      "label": "Bed Temperature (Cool Plate)",
+      "type": "number",
+      "category": "temperature",
+      "description": "Bed temperature for cool plate",
+      "unit": "°C",
+      "min": 0,
+      "max": 120
+    },
+    {
+      "key": "cool_plate_temp_initial_layer",
+      "label": "Initial Layer Bed Temp (Cool Plate)",
+      "type": "number",
+      "category": "temperature",
+      "description": "First layer bed temperature for cool plate",
+      "unit": "°C",
+      "min": 0,
+      "max": 120
+    },
+    {
+      "key": "eng_plate_temp",
+      "label": "Bed Temperature (Engineering Plate)",
+      "type": "number",
+      "category": "temperature",
+      "description": "Bed temperature for engineering plate",
+      "unit": "°C",
+      "min": 0,
+      "max": 120
+    },
+    {
+      "key": "eng_plate_temp_initial_layer",
+      "label": "Initial Layer Bed Temp (Eng Plate)",
+      "type": "number",
+      "category": "temperature",
+      "description": "First layer bed temperature for engineering plate",
+      "unit": "°C",
+      "min": 0,
+      "max": 120
+    },
+    {
+      "key": "textured_plate_temp",
+      "label": "Bed Temperature (Textured Plate)",
+      "type": "number",
+      "category": "temperature",
+      "description": "Bed temperature for textured plate",
+      "unit": "°C",
+      "min": 0,
+      "max": 120
+    },
+    {
+      "key": "textured_plate_temp_initial_layer",
+      "label": "Initial Layer Bed Temp (Textured)",
+      "type": "number",
+      "category": "temperature",
+      "description": "First layer bed temperature for textured plate",
+      "unit": "°C",
+      "min": 0,
+      "max": 120
+    },
+    {
+      "key": "temperature_vitrification",
+      "label": "Glass Transition Temperature",
+      "type": "number",
+      "category": "temperature",
+      "description": "Glass transition temperature of material",
+      "unit": "°C"
+    },
+    {
+      "key": "pressure_advance",
+      "label": "Pressure Advance",
+      "type": "number",
+      "category": "flow",
+      "description": "Pressure advance value for linear advance",
+      "step": 0.001,
+      "min": 0,
+      "max": 0.2
+    },
+    {
+      "key": "enable_pressure_advance",
+      "label": "Enable Pressure Advance",
+      "type": "boolean",
+      "category": "flow",
+      "description": "Enable pressure advance compensation"
+    },
+    {
+      "key": "filament_flow_ratio",
+      "label": "Flow Ratio",
+      "type": "number",
+      "category": "flow",
+      "description": "Flow rate multiplier",
+      "step": 0.01,
+      "min": 0.8,
+      "max": 1.2
+    },
+    {
+      "key": "filament_max_volumetric_speed",
+      "label": "Max Volumetric Speed",
+      "type": "text",
+      "category": "flow",
+      "description": "Maximum volumetric flow rate (comma-separated values)",
+      "unit": "mm³/s"
+    },
+    {
+      "key": "fan_min_speed",
+      "label": "Min Fan Speed",
+      "type": "number",
+      "category": "cooling",
+      "description": "Minimum part cooling fan speed",
+      "unit": "%",
+      "min": 0,
+      "max": 100
+    },
+    {
+      "key": "fan_max_speed",
+      "label": "Max Fan Speed",
+      "type": "number",
+      "category": "cooling",
+      "description": "Maximum part cooling fan speed",
+      "unit": "%",
+      "min": 0,
+      "max": 100
+    },
+    {
+      "key": "fan_cooling_layer_time",
+      "label": "Fan Cooling Layer Time",
+      "type": "number",
+      "category": "cooling",
+      "description": "Layer time threshold for max fan",
+      "unit": "s",
+      "min": 0,
+      "max": 120
+    },
+    {
+      "key": "slow_down_layer_time",
+      "label": "Slow Down Layer Time",
+      "type": "number",
+      "category": "cooling",
+      "description": "Minimum layer time before slowing down",
+      "unit": "s",
+      "min": 0,
+      "max": 60
+    },
+    {
+      "key": "slow_down_min_speed",
+      "label": "Slow Down Min Speed",
+      "type": "number",
+      "category": "cooling",
+      "description": "Minimum speed when slowing down for cooling",
+      "unit": "mm/s",
+      "min": 5,
+      "max": 100
+    },
+    {
+      "key": "close_fan_the_first_x_layers",
+      "label": "Disable Fan First Layers",
+      "type": "number",
+      "category": "cooling",
+      "description": "Number of initial layers without fan",
+      "min": 0,
+      "max": 10
+    },
+    {
+      "key": "overhang_fan_threshold",
+      "label": "Overhang Fan Threshold",
+      "type": "text",
+      "category": "cooling",
+      "description": "Overhang angle to trigger fan boost"
+    },
+    {
+      "key": "overhang_fan_speed",
+      "label": "Overhang Fan Speed",
+      "type": "number",
+      "category": "cooling",
+      "description": "Fan speed for overhangs",
+      "unit": "%",
+      "min": 0,
+      "max": 100
+    },
+    {
+      "key": "reduce_fan_stop_start_freq",
+      "label": "Reduce Fan Stop/Start Frequency",
+      "type": "boolean",
+      "category": "cooling",
+      "description": "Prevent frequent fan speed changes"
+    },
+    {
+      "key": "activate_air_filtration",
+      "label": "Activate Air Filtration",
+      "type": "boolean",
+      "category": "chamber",
+      "description": "Enable chamber air filtration during print"
+    },
+    {
+      "key": "during_print_exhaust_fan_speed",
+      "label": "Exhaust Fan Speed (During Print)",
+      "type": "number",
+      "category": "chamber",
+      "description": "Exhaust fan speed during printing",
+      "unit": "%",
+      "min": 0,
+      "max": 100
+    },
+    {
+      "key": "complete_print_exhaust_fan_speed",
+      "label": "Exhaust Fan Speed (After Print)",
+      "type": "number",
+      "category": "chamber",
+      "description": "Exhaust fan speed after print completes",
+      "unit": "%",
+      "min": 0,
+      "max": 100
+    },
+    {
+      "key": "activate_chamber_temp_control",
+      "label": "Chamber Temp Control",
+      "type": "boolean",
+      "category": "chamber",
+      "description": "Enable active chamber temperature control"
+    },
+    {
+      "key": "chamber_temperature",
+      "label": "Chamber Temperature",
+      "type": "number",
+      "category": "chamber",
+      "description": "Target chamber temperature",
+      "unit": "°C",
+      "min": 0,
+      "max": 60
+    },
+    {
+      "key": "filament_retraction_length",
+      "label": "Retraction Length",
+      "type": "number",
+      "category": "retraction",
+      "description": "Length of filament to retract",
+      "unit": "mm",
+      "step": 0.1,
+      "min": 0,
+      "max": 10
+    },
+    {
+      "key": "filament_retract_before_wipe",
+      "label": "Retract Before Wipe",
+      "type": "number",
+      "category": "retraction",
+      "description": "Percentage of retraction before wipe",
+      "unit": "%",
+      "min": 0,
+      "max": 100
+    },
+    {
+      "key": "filament_retraction_speed",
+      "label": "Retraction Speed",
+      "type": "number",
+      "category": "retraction",
+      "description": "Speed for retraction moves",
+      "unit": "mm/s",
+      "min": 10,
+      "max": 120
+    },
+    {
+      "key": "filament_deretraction_speed",
+      "label": "Deretraction Speed",
+      "type": "number",
+      "category": "retraction",
+      "description": "Speed for priming after retraction",
+      "unit": "mm/s",
+      "min": 10,
+      "max": 120
+    },
+    {
+      "key": "filament_retract_restart_extra",
+      "label": "Extra Length on Restart",
+      "type": "number",
+      "category": "retraction",
+      "description": "Extra filament to prime after retraction",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "filament_retract_when_changing_layer",
+      "label": "Retract on Layer Change",
+      "type": "boolean",
+      "category": "retraction",
+      "description": "Force retraction when changing layers"
+    },
+    {
+      "key": "filament_wipe",
+      "label": "Enable Wipe",
+      "type": "boolean",
+      "category": "retraction",
+      "description": "Enable nozzle wipe during retraction"
+    },
+    {
+      "key": "filament_wipe_distance",
+      "label": "Wipe Distance",
+      "type": "number",
+      "category": "retraction",
+      "description": "Distance to wipe while retracting",
+      "unit": "mm",
+      "step": 0.1
+    },
+    {
+      "key": "filament_z_hop",
+      "label": "Z Hop Height",
+      "type": "number",
+      "category": "retraction",
+      "description": "Lift height during travel moves",
+      "unit": "mm",
+      "step": 0.1,
+      "min": 0,
+      "max": 2
+    },
+    {
+      "key": "filament_z_hop_types",
+      "label": "Z Hop Type",
+      "type": "select",
+      "category": "retraction",
+      "description": "Type of Z hop motion",
+      "options": [
+        {"value": "Normal Lift", "label": "Normal Lift"},
+        {"value": "Slope Lift", "label": "Slope Lift"},
+        {"value": "Spiral Lift", "label": "Spiral Lift"}
+      ]
+    },
+    {
+      "key": "filament_retraction_minimum_travel",
+      "label": "Min Travel After Retraction",
+      "type": "number",
+      "category": "retraction",
+      "description": "Minimum travel distance to trigger retraction",
+      "unit": "mm",
+      "step": 0.1
+    },
+    {
+      "key": "filament_retract_layer_change",
+      "label": "Retract on Layer Change",
+      "type": "boolean",
+      "category": "retraction",
+      "description": "Retract when layer changes"
+    },
+    {
+      "key": "filament_colour",
+      "label": "Filament Color",
+      "type": "text",
+      "category": "appearance",
+      "description": "Filament color (hex format #RRGGBB)"
+    },
+    {
+      "key": "default_filament_colour",
+      "label": "Default Filament Color",
+      "type": "text",
+      "category": "appearance",
+      "description": "Default color for this filament type"
+    },
+    {
+      "key": "filament_is_support",
+      "label": "Is Support Material",
+      "type": "boolean",
+      "category": "advanced",
+      "description": "Mark as support material filament"
+    },
+    {
+      "key": "filament_soluble",
+      "label": "Soluble Material",
+      "type": "boolean",
+      "category": "advanced",
+      "description": "Material dissolves in liquid"
+    },
+    {
+      "key": "required_nozzle_HRC",
+      "label": "Required Nozzle HRC",
+      "type": "number",
+      "category": "advanced",
+      "description": "Minimum nozzle hardness required",
+      "min": 0,
+      "max": 100
+    },
+    {
+      "key": "filament_start_gcode",
+      "label": "Filament Start G-code",
+      "type": "text",
+      "category": "gcode",
+      "description": "G-code executed when switching to this filament"
+    },
+    {
+      "key": "filament_end_gcode",
+      "label": "Filament End G-code",
+      "type": "text",
+      "category": "gcode",
+      "description": "G-code executed when switching from this filament"
+    },
+    {
+      "key": "filament_loading_speed",
+      "label": "Loading Speed",
+      "type": "number",
+      "category": "ams",
+      "description": "Speed for loading filament",
+      "unit": "mm/s"
+    },
+    {
+      "key": "filament_loading_speed_start",
+      "label": "Loading Start Speed",
+      "type": "number",
+      "category": "ams",
+      "description": "Initial speed when loading filament",
+      "unit": "mm/s"
+    },
+    {
+      "key": "filament_unloading_speed",
+      "label": "Unloading Speed",
+      "type": "number",
+      "category": "ams",
+      "description": "Speed for unloading filament",
+      "unit": "mm/s"
+    },
+    {
+      "key": "filament_unloading_speed_start",
+      "label": "Unloading Start Speed",
+      "type": "number",
+      "category": "ams",
+      "description": "Initial speed when unloading filament",
+      "unit": "mm/s"
+    },
+    {
+      "key": "filament_toolchange_delay",
+      "label": "Toolchange Delay",
+      "type": "number",
+      "category": "ams",
+      "description": "Delay after tool change",
+      "unit": "s"
+    },
+    {
+      "key": "filament_cooling_moves",
+      "label": "Cooling Moves",
+      "type": "number",
+      "category": "ams",
+      "description": "Number of cooling moves during unload"
+    },
+    {
+      "key": "filament_cooling_initial_speed",
+      "label": "Cooling Initial Speed",
+      "type": "number",
+      "category": "ams",
+      "description": "Initial speed for tip shaping cooling moves",
+      "unit": "mm/s"
+    },
+    {
+      "key": "filament_cooling_final_speed",
+      "label": "Cooling Final Speed",
+      "type": "number",
+      "category": "ams",
+      "description": "Final speed for tip shaping cooling moves",
+      "unit": "mm/s"
+    },
+    {
+      "key": "filament_ramming_parameters",
+      "label": "Ramming Parameters",
+      "type": "text",
+      "category": "ams",
+      "description": "Ramming sequence parameters"
+    },
+    {
+      "key": "filament_minimal_purge_on_wipe_tower",
+      "label": "Min Purge on Wipe Tower",
+      "type": "number",
+      "category": "ams",
+      "description": "Minimum purge volume on wipe tower",
+      "unit": "mm³"
+    },
+    {
+      "key": "filament_multitool_ramming",
+      "label": "Multitool Ramming",
+      "type": "boolean",
+      "category": "ams",
+      "description": "Enable ramming for multi-tool"
+    },
+    {
+      "key": "filament_multitool_ramming_volume",
+      "label": "Multitool Ramming Volume",
+      "type": "number",
+      "category": "ams",
+      "description": "Volume to ram during multi-tool change",
+      "unit": "mm³"
+    },
+    {
+      "key": "filament_multitool_ramming_flow",
+      "label": "Multitool Ramming Flow",
+      "type": "number",
+      "category": "ams",
+      "description": "Flow rate during multi-tool ramming",
+      "unit": "mm³/s"
+    },
+    {
+      "key": "filament_long_retractions_when_cut",
+      "label": "Long Retractions When Cut",
+      "type": "boolean",
+      "category": "ams",
+      "description": "Use long retraction when cutting filament"
+    },
+    {
+      "key": "filament_retraction_distances_when_cut",
+      "label": "Retraction Distance When Cut",
+      "type": "text",
+      "category": "ams",
+      "description": "Retraction distance during filament cut"
+    }
+  ]
+}

+ 574 - 0
backend/app/data/printer_fields.json

@@ -0,0 +1,574 @@
+{
+  "version": "1.0.0",
+  "description": "Printer/machine preset field definitions for Bambu Lab printers",
+  "fields": [
+    {
+      "key": "printer_model",
+      "label": "Printer Model",
+      "type": "text",
+      "category": "basic",
+      "description": "Printer model identifier"
+    },
+    {
+      "key": "printer_variant",
+      "label": "Printer Variant",
+      "type": "text",
+      "category": "basic",
+      "description": "Nozzle variant (e.g., 0.4 nozzle)"
+    },
+    {
+      "key": "printer_notes",
+      "label": "Printer Notes",
+      "type": "text",
+      "category": "basic",
+      "description": "Notes about this printer profile"
+    },
+    {
+      "key": "printable_area",
+      "label": "Printable Area",
+      "type": "text",
+      "category": "dimensions",
+      "description": "Bed shape coordinates"
+    },
+    {
+      "key": "printable_height",
+      "label": "Printable Height",
+      "type": "number",
+      "category": "dimensions",
+      "description": "Maximum print height",
+      "unit": "mm"
+    },
+    {
+      "key": "bed_exclude_area",
+      "label": "Bed Exclude Area",
+      "type": "text",
+      "category": "dimensions",
+      "description": "Coordinates of excluded bed areas"
+    },
+    {
+      "key": "nozzle_diameter",
+      "label": "Nozzle Diameter",
+      "type": "number",
+      "category": "extruder",
+      "description": "Diameter of the nozzle",
+      "unit": "mm",
+      "step": 0.1,
+      "min": 0.1,
+      "max": 1.2
+    },
+    {
+      "key": "nozzle_type",
+      "label": "Nozzle Type",
+      "type": "select",
+      "category": "extruder",
+      "description": "Type of nozzle installed",
+      "options": [
+        {"value": "brass", "label": "Brass"},
+        {"value": "stainless_steel", "label": "Stainless Steel"},
+        {"value": "hardened_steel", "label": "Hardened Steel"}
+      ]
+    },
+    {
+      "key": "nozzle_hrc",
+      "label": "Nozzle HRC",
+      "type": "number",
+      "category": "extruder",
+      "description": "Hardness rating of nozzle"
+    },
+    {
+      "key": "nozzle_volume",
+      "label": "Nozzle Volume",
+      "type": "number",
+      "category": "extruder",
+      "description": "Melt zone volume",
+      "unit": "mm³"
+    },
+    {
+      "key": "extruder_type",
+      "label": "Extruder Type",
+      "type": "select",
+      "category": "extruder",
+      "description": "Type of extruder",
+      "options": [
+        {"value": "DirectDrive", "label": "Direct Drive"},
+        {"value": "Bowden", "label": "Bowden"}
+      ]
+    },
+    {
+      "key": "retraction_length",
+      "label": "Retraction Length",
+      "type": "number",
+      "category": "retraction",
+      "description": "Default retraction length",
+      "unit": "mm",
+      "step": 0.1,
+      "min": 0,
+      "max": 10
+    },
+    {
+      "key": "retraction_speed",
+      "label": "Retraction Speed",
+      "type": "number",
+      "category": "retraction",
+      "description": "Speed for retraction",
+      "unit": "mm/s"
+    },
+    {
+      "key": "deretraction_speed",
+      "label": "Deretraction Speed",
+      "type": "number",
+      "category": "retraction",
+      "description": "Speed for deretraction",
+      "unit": "mm/s"
+    },
+    {
+      "key": "retract_before_wipe",
+      "label": "Retract Before Wipe",
+      "type": "number",
+      "category": "retraction",
+      "description": "Percentage to retract before wipe",
+      "unit": "%"
+    },
+    {
+      "key": "retract_when_changing_layer",
+      "label": "Retract on Layer Change",
+      "type": "boolean",
+      "category": "retraction",
+      "description": "Retract when changing layers"
+    },
+    {
+      "key": "wipe",
+      "label": "Enable Wipe",
+      "type": "boolean",
+      "category": "retraction",
+      "description": "Enable wipe during retraction"
+    },
+    {
+      "key": "wipe_distance",
+      "label": "Wipe Distance",
+      "type": "number",
+      "category": "retraction",
+      "description": "Distance to wipe",
+      "unit": "mm"
+    },
+    {
+      "key": "z_hop",
+      "label": "Z Hop Height",
+      "type": "number",
+      "category": "retraction",
+      "description": "Height to lift during travel",
+      "unit": "mm",
+      "step": 0.1,
+      "min": 0,
+      "max": 2
+    },
+    {
+      "key": "z_hop_types",
+      "label": "Z Hop Type",
+      "type": "select",
+      "category": "retraction",
+      "description": "Type of Z hop motion",
+      "options": [
+        {"value": "Normal Lift", "label": "Normal Lift"},
+        {"value": "Slope Lift", "label": "Slope Lift"},
+        {"value": "Spiral Lift", "label": "Spiral Lift"}
+      ]
+    },
+    {
+      "key": "retraction_minimum_travel",
+      "label": "Min Travel for Retraction",
+      "type": "number",
+      "category": "retraction",
+      "description": "Minimum travel to trigger retraction",
+      "unit": "mm"
+    },
+    {
+      "key": "retract_lift_above",
+      "label": "Retract Lift Above",
+      "type": "number",
+      "category": "retraction",
+      "description": "Only lift Z above this height",
+      "unit": "mm"
+    },
+    {
+      "key": "retract_lift_below",
+      "label": "Retract Lift Below",
+      "type": "number",
+      "category": "retraction",
+      "description": "Only lift Z below this height",
+      "unit": "mm"
+    },
+    {
+      "key": "machine_max_speed_x",
+      "label": "Max Speed X",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum X axis speed",
+      "unit": "mm/s"
+    },
+    {
+      "key": "machine_max_speed_y",
+      "label": "Max Speed Y",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum Y axis speed",
+      "unit": "mm/s"
+    },
+    {
+      "key": "machine_max_speed_z",
+      "label": "Max Speed Z",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum Z axis speed",
+      "unit": "mm/s"
+    },
+    {
+      "key": "machine_max_speed_e",
+      "label": "Max Speed E",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum extruder speed",
+      "unit": "mm/s"
+    },
+    {
+      "key": "machine_max_acceleration_x",
+      "label": "Max Acceleration X",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum X axis acceleration",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "machine_max_acceleration_y",
+      "label": "Max Acceleration Y",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum Y axis acceleration",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "machine_max_acceleration_z",
+      "label": "Max Acceleration Z",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum Z axis acceleration",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "machine_max_acceleration_e",
+      "label": "Max Acceleration E",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum extruder acceleration",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "machine_max_acceleration_extruding",
+      "label": "Max Print Acceleration",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum acceleration while printing",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "machine_max_acceleration_retracting",
+      "label": "Max Retract Acceleration",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum acceleration during retraction",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "machine_max_acceleration_travel",
+      "label": "Max Travel Acceleration",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum acceleration during travel",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "machine_max_jerk_x",
+      "label": "Max Jerk X",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum X axis jerk",
+      "unit": "mm/s"
+    },
+    {
+      "key": "machine_max_jerk_y",
+      "label": "Max Jerk Y",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum Y axis jerk",
+      "unit": "mm/s"
+    },
+    {
+      "key": "machine_max_jerk_z",
+      "label": "Max Jerk Z",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum Z axis jerk",
+      "unit": "mm/s"
+    },
+    {
+      "key": "machine_max_jerk_e",
+      "label": "Max Jerk E",
+      "type": "number",
+      "category": "limits",
+      "description": "Maximum extruder jerk",
+      "unit": "mm/s"
+    },
+    {
+      "key": "machine_min_extruding_rate",
+      "label": "Min Extruding Rate",
+      "type": "number",
+      "category": "limits",
+      "description": "Minimum extrusion flow rate",
+      "unit": "mm/s"
+    },
+    {
+      "key": "machine_min_travel_rate",
+      "label": "Min Travel Rate",
+      "type": "number",
+      "category": "limits",
+      "description": "Minimum travel speed",
+      "unit": "mm/s"
+    },
+    {
+      "key": "machine_start_gcode",
+      "label": "Start G-code",
+      "type": "text",
+      "category": "gcode",
+      "description": "G-code executed at print start"
+    },
+    {
+      "key": "machine_end_gcode",
+      "label": "End G-code",
+      "type": "text",
+      "category": "gcode",
+      "description": "G-code executed at print end"
+    },
+    {
+      "key": "before_layer_change_gcode",
+      "label": "Before Layer Change G-code",
+      "type": "text",
+      "category": "gcode",
+      "description": "G-code before each layer change"
+    },
+    {
+      "key": "layer_change_gcode",
+      "label": "Layer Change G-code",
+      "type": "text",
+      "category": "gcode",
+      "description": "G-code after each layer change"
+    },
+    {
+      "key": "change_filament_gcode",
+      "label": "Filament Change G-code",
+      "type": "text",
+      "category": "gcode",
+      "description": "G-code for filament changes"
+    },
+    {
+      "key": "machine_pause_gcode",
+      "label": "Pause G-code",
+      "type": "text",
+      "category": "gcode",
+      "description": "G-code for pause command"
+    },
+    {
+      "key": "template_custom_gcode",
+      "label": "Template Custom G-code",
+      "type": "text",
+      "category": "gcode",
+      "description": "Custom G-code template"
+    },
+    {
+      "key": "gcode_flavor",
+      "label": "G-code Flavor",
+      "type": "select",
+      "category": "gcode",
+      "description": "G-code dialect",
+      "options": [
+        {"value": "marlin", "label": "Marlin"},
+        {"value": "marlin2", "label": "Marlin 2"},
+        {"value": "reprap", "label": "RepRap"},
+        {"value": "klipper", "label": "Klipper"},
+        {"value": "smoothie", "label": "Smoothieware"}
+      ]
+    },
+    {
+      "key": "thumbnails",
+      "label": "Thumbnail Sizes",
+      "type": "text",
+      "category": "output",
+      "description": "Sizes for embedded thumbnails"
+    },
+    {
+      "key": "thumbnails_format",
+      "label": "Thumbnail Format",
+      "type": "select",
+      "category": "output",
+      "description": "Format for thumbnails",
+      "options": [
+        {"value": "PNG", "label": "PNG"},
+        {"value": "JPG", "label": "JPG"},
+        {"value": "QOI", "label": "QOI"}
+      ]
+    },
+    {
+      "key": "use_relative_e_distances",
+      "label": "Use Relative E Distances",
+      "type": "boolean",
+      "category": "output",
+      "description": "Use relative extrusion"
+    },
+    {
+      "key": "use_firmware_retraction",
+      "label": "Use Firmware Retraction",
+      "type": "boolean",
+      "category": "output",
+      "description": "Use G10/G11 for retraction"
+    },
+    {
+      "key": "silent_mode",
+      "label": "Silent Mode",
+      "type": "boolean",
+      "category": "output",
+      "description": "Enable silent mode profile"
+    },
+    {
+      "key": "fan_kickstart",
+      "label": "Fan Kickstart",
+      "type": "number",
+      "category": "cooling",
+      "description": "Time to kickstart fan",
+      "unit": "s"
+    },
+    {
+      "key": "auxiliary_fan",
+      "label": "Auxiliary Fan",
+      "type": "boolean",
+      "category": "cooling",
+      "description": "Printer has auxiliary fan"
+    },
+    {
+      "key": "support_air_filtration",
+      "label": "Support Air Filtration",
+      "type": "boolean",
+      "category": "features",
+      "description": "Printer has air filtration"
+    },
+    {
+      "key": "support_chamber_temp_control",
+      "label": "Support Chamber Temp Control",
+      "type": "boolean",
+      "category": "features",
+      "description": "Printer has chamber heating"
+    },
+    {
+      "key": "support_multi_bed_types",
+      "label": "Support Multiple Bed Types",
+      "type": "boolean",
+      "category": "features",
+      "description": "Printer supports multiple bed plates"
+    },
+    {
+      "key": "upward_compatible_machine",
+      "label": "Upward Compatible Machines",
+      "type": "text",
+      "category": "compatibility",
+      "description": "List of compatible machine models"
+    },
+    {
+      "key": "single_extruder_multi_material",
+      "label": "Single Extruder Multi-Material",
+      "type": "boolean",
+      "category": "multimaterial",
+      "description": "Single extruder with MMU/AMS"
+    },
+    {
+      "key": "cooling_tube_length",
+      "label": "Cooling Tube Length",
+      "type": "number",
+      "category": "multimaterial",
+      "description": "Length of cooling tube",
+      "unit": "mm"
+    },
+    {
+      "key": "cooling_tube_retraction",
+      "label": "Cooling Tube Retraction",
+      "type": "number",
+      "category": "multimaterial",
+      "description": "Retraction into cooling tube",
+      "unit": "mm"
+    },
+    {
+      "key": "extra_loading_move",
+      "label": "Extra Loading Move",
+      "type": "number",
+      "category": "multimaterial",
+      "description": "Extra move after loading",
+      "unit": "mm"
+    },
+    {
+      "key": "high_current_on_filament_swap",
+      "label": "High Current on Swap",
+      "type": "boolean",
+      "category": "multimaterial",
+      "description": "Use high current during swap"
+    },
+    {
+      "key": "parking_pos_retraction",
+      "label": "Parking Position Retraction",
+      "type": "number",
+      "category": "multimaterial",
+      "description": "Retraction for parking",
+      "unit": "mm"
+    },
+    {
+      "key": "bed_custom_model",
+      "label": "Custom Bed Model",
+      "type": "text",
+      "category": "dimensions",
+      "description": "Path to custom bed STL model"
+    },
+    {
+      "key": "bed_custom_texture",
+      "label": "Custom Bed Texture",
+      "type": "text",
+      "category": "dimensions",
+      "description": "Path to custom bed texture"
+    },
+    {
+      "key": "scan_first_layer",
+      "label": "Scan First Layer",
+      "type": "boolean",
+      "category": "features",
+      "description": "Enable first layer scanning"
+    },
+    {
+      "key": "time_cost",
+      "label": "Time Cost Factor",
+      "type": "number",
+      "category": "advanced",
+      "description": "Cost per hour of operation"
+    },
+    {
+      "key": "machine_load_filament_time",
+      "label": "Filament Load Time",
+      "type": "number",
+      "category": "multimaterial",
+      "description": "Time to load filament",
+      "unit": "s"
+    },
+    {
+      "key": "machine_unload_filament_time",
+      "label": "Filament Unload Time",
+      "type": "number",
+      "category": "multimaterial",
+      "description": "Time to unload filament",
+      "unit": "s"
+    }
+  ]
+}

+ 923 - 0
backend/app/data/process_fields.json

@@ -0,0 +1,923 @@
+{
+  "version": "1.0.0",
+  "description": "Print process preset field definitions for Bambu Lab printers",
+  "fields": [
+    {
+      "key": "layer_height",
+      "label": "Layer Height",
+      "type": "number",
+      "category": "quality",
+      "description": "Height of each printed layer",
+      "unit": "mm",
+      "step": 0.01,
+      "min": 0.04,
+      "max": 0.6
+    },
+    {
+      "key": "initial_layer_height",
+      "label": "Initial Layer Height",
+      "type": "number",
+      "category": "quality",
+      "description": "Height of the first layer",
+      "unit": "mm",
+      "step": 0.01,
+      "min": 0.1,
+      "max": 0.5
+    },
+    {
+      "key": "line_width",
+      "label": "Line Width",
+      "type": "number",
+      "category": "quality",
+      "description": "Default extrusion width",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "initial_layer_line_width",
+      "label": "Initial Layer Line Width",
+      "type": "number",
+      "category": "quality",
+      "description": "First layer extrusion width",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "outer_wall_line_width",
+      "label": "Outer Wall Line Width",
+      "type": "number",
+      "category": "quality",
+      "description": "Outer perimeter extrusion width",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "inner_wall_line_width",
+      "label": "Inner Wall Line Width",
+      "type": "number",
+      "category": "quality",
+      "description": "Inner perimeter extrusion width",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "sparse_infill_line_width",
+      "label": "Infill Line Width",
+      "type": "number",
+      "category": "quality",
+      "description": "Sparse infill extrusion width",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "top_surface_line_width",
+      "label": "Top Surface Line Width",
+      "type": "number",
+      "category": "quality",
+      "description": "Top surface extrusion width",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "support_line_width",
+      "label": "Support Line Width",
+      "type": "number",
+      "category": "quality",
+      "description": "Support structure extrusion width",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "wall_loops",
+      "label": "Wall Loops",
+      "type": "number",
+      "category": "strength",
+      "description": "Number of perimeter walls",
+      "min": 1,
+      "max": 10
+    },
+    {
+      "key": "top_shell_layers",
+      "label": "Top Layers",
+      "type": "number",
+      "category": "strength",
+      "description": "Number of solid top layers",
+      "min": 1,
+      "max": 20
+    },
+    {
+      "key": "bottom_shell_layers",
+      "label": "Bottom Layers",
+      "type": "number",
+      "category": "strength",
+      "description": "Number of solid bottom layers",
+      "min": 1,
+      "max": 20
+    },
+    {
+      "key": "top_shell_thickness",
+      "label": "Top Shell Thickness",
+      "type": "number",
+      "category": "strength",
+      "description": "Minimum top shell thickness",
+      "unit": "mm",
+      "step": 0.1
+    },
+    {
+      "key": "bottom_shell_thickness",
+      "label": "Bottom Shell Thickness",
+      "type": "number",
+      "category": "strength",
+      "description": "Minimum bottom shell thickness",
+      "unit": "mm",
+      "step": 0.1
+    },
+    {
+      "key": "sparse_infill_density",
+      "label": "Infill Density",
+      "type": "number",
+      "category": "infill",
+      "description": "Percentage of infill",
+      "unit": "%",
+      "min": 0,
+      "max": 100
+    },
+    {
+      "key": "sparse_infill_pattern",
+      "label": "Infill Pattern",
+      "type": "select",
+      "category": "infill",
+      "description": "Pattern for sparse infill",
+      "options": [
+        {"value": "grid", "label": "Grid"},
+        {"value": "triangles", "label": "Triangles"},
+        {"value": "tri-hexagon", "label": "Tri-Hexagon"},
+        {"value": "cubic", "label": "Cubic"},
+        {"value": "gyroid", "label": "Gyroid"},
+        {"value": "honeycomb", "label": "Honeycomb"},
+        {"value": "3dhoneycomb", "label": "3D Honeycomb"},
+        {"value": "line", "label": "Line"},
+        {"value": "rectilinear", "label": "Rectilinear"},
+        {"value": "concentric", "label": "Concentric"},
+        {"value": "zig-zag", "label": "Zig-Zag"},
+        {"value": "crosshatch", "label": "Cross Hatch"},
+        {"value": "lightning", "label": "Lightning"},
+        {"value": "supportcubic", "label": "Support Cubic"},
+        {"value": "adaptivecubic", "label": "Adaptive Cubic"}
+      ]
+    },
+    {
+      "key": "top_surface_pattern",
+      "label": "Top Surface Pattern",
+      "type": "select",
+      "category": "infill",
+      "description": "Pattern for top solid layers",
+      "options": [
+        {"value": "monotonic", "label": "Monotonic"},
+        {"value": "monotoniclines", "label": "Monotonic Lines"},
+        {"value": "alignedrectilinear", "label": "Aligned Rectilinear"},
+        {"value": "rectilinear", "label": "Rectilinear"},
+        {"value": "concentric", "label": "Concentric"},
+        {"value": "hilbertcurve", "label": "Hilbert Curve"},
+        {"value": "archimedeanchords", "label": "Archimedean Chords"},
+        {"value": "octagramspiral", "label": "Octagram Spiral"}
+      ]
+    },
+    {
+      "key": "bottom_surface_pattern",
+      "label": "Bottom Surface Pattern",
+      "type": "select",
+      "category": "infill",
+      "description": "Pattern for bottom solid layers",
+      "options": [
+        {"value": "monotonic", "label": "Monotonic"},
+        {"value": "monotoniclines", "label": "Monotonic Lines"},
+        {"value": "rectilinear", "label": "Rectilinear"},
+        {"value": "concentric", "label": "Concentric"}
+      ]
+    },
+    {
+      "key": "infill_direction",
+      "label": "Infill Direction",
+      "type": "number",
+      "category": "infill",
+      "description": "Angle of infill pattern",
+      "unit": "°",
+      "min": 0,
+      "max": 360
+    },
+    {
+      "key": "infill_anchor",
+      "label": "Infill Anchor Length",
+      "type": "number",
+      "category": "infill",
+      "description": "Connect infill to walls",
+      "unit": "mm"
+    },
+    {
+      "key": "infill_anchor_max",
+      "label": "Max Infill Anchor Length",
+      "type": "number",
+      "category": "infill",
+      "description": "Maximum anchor length",
+      "unit": "mm"
+    },
+    {
+      "key": "infill_combination",
+      "label": "Combine Infill Layers",
+      "type": "boolean",
+      "category": "infill",
+      "description": "Print infill at higher layer heights"
+    },
+    {
+      "key": "outer_wall_speed",
+      "label": "Outer Wall Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for outer perimeters",
+      "unit": "mm/s",
+      "min": 10,
+      "max": 500
+    },
+    {
+      "key": "inner_wall_speed",
+      "label": "Inner Wall Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for inner perimeters",
+      "unit": "mm/s",
+      "min": 10,
+      "max": 500
+    },
+    {
+      "key": "sparse_infill_speed",
+      "label": "Infill Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for sparse infill",
+      "unit": "mm/s",
+      "min": 10,
+      "max": 500
+    },
+    {
+      "key": "internal_solid_infill_speed",
+      "label": "Internal Solid Infill Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for internal solid layers",
+      "unit": "mm/s"
+    },
+    {
+      "key": "top_surface_speed",
+      "label": "Top Surface Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for top surface",
+      "unit": "mm/s"
+    },
+    {
+      "key": "bridge_speed",
+      "label": "Bridge Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for bridging",
+      "unit": "mm/s"
+    },
+    {
+      "key": "gap_infill_speed",
+      "label": "Gap Fill Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for gap filling",
+      "unit": "mm/s"
+    },
+    {
+      "key": "travel_speed",
+      "label": "Travel Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for non-printing moves",
+      "unit": "mm/s",
+      "min": 50,
+      "max": 1000
+    },
+    {
+      "key": "initial_layer_speed",
+      "label": "Initial Layer Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for first layer",
+      "unit": "mm/s"
+    },
+    {
+      "key": "initial_layer_infill_speed",
+      "label": "Initial Layer Infill Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for first layer infill",
+      "unit": "mm/s"
+    },
+    {
+      "key": "support_speed",
+      "label": "Support Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for support structures",
+      "unit": "mm/s"
+    },
+    {
+      "key": "support_interface_speed",
+      "label": "Support Interface Speed",
+      "type": "number",
+      "category": "speed",
+      "description": "Speed for support interface",
+      "unit": "mm/s"
+    },
+    {
+      "key": "outer_wall_acceleration",
+      "label": "Outer Wall Acceleration",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Acceleration for outer perimeters",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "inner_wall_acceleration",
+      "label": "Inner Wall Acceleration",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Acceleration for inner perimeters",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "default_acceleration",
+      "label": "Default Acceleration",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Default print acceleration",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "travel_acceleration",
+      "label": "Travel Acceleration",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Acceleration for travel moves",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "initial_layer_acceleration",
+      "label": "Initial Layer Acceleration",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Acceleration for first layer",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "top_surface_acceleration",
+      "label": "Top Surface Acceleration",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Acceleration for top surface",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "bridge_acceleration",
+      "label": "Bridge Acceleration",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Acceleration for bridging",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "sparse_infill_acceleration",
+      "label": "Infill Acceleration",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Acceleration for infill",
+      "unit": "mm/s²"
+    },
+    {
+      "key": "outer_wall_jerk",
+      "label": "Outer Wall Jerk",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Jerk for outer perimeters",
+      "unit": "mm/s"
+    },
+    {
+      "key": "inner_wall_jerk",
+      "label": "Inner Wall Jerk",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Jerk for inner perimeters",
+      "unit": "mm/s"
+    },
+    {
+      "key": "default_jerk",
+      "label": "Default Jerk",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Default jerk value",
+      "unit": "mm/s"
+    },
+    {
+      "key": "travel_jerk",
+      "label": "Travel Jerk",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Jerk for travel moves",
+      "unit": "mm/s"
+    },
+    {
+      "key": "initial_layer_jerk",
+      "label": "Initial Layer Jerk",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Jerk for first layer",
+      "unit": "mm/s"
+    },
+    {
+      "key": "top_surface_jerk",
+      "label": "Top Surface Jerk",
+      "type": "number",
+      "category": "acceleration",
+      "description": "Jerk for top surface",
+      "unit": "mm/s"
+    },
+    {
+      "key": "enable_support",
+      "label": "Enable Support",
+      "type": "boolean",
+      "category": "support",
+      "description": "Generate support structures"
+    },
+    {
+      "key": "support_type",
+      "label": "Support Type",
+      "type": "select",
+      "category": "support",
+      "description": "Type of support generation",
+      "options": [
+        {"value": "normal(auto)", "label": "Normal (Auto)"},
+        {"value": "tree(auto)", "label": "Tree (Auto)"},
+        {"value": "hybrid(auto)", "label": "Hybrid (Auto)"}
+      ]
+    },
+    {
+      "key": "support_style",
+      "label": "Support Style",
+      "type": "select",
+      "category": "support",
+      "description": "Style of support structure",
+      "options": [
+        {"value": "default", "label": "Default"},
+        {"value": "grid", "label": "Grid"},
+        {"value": "snug", "label": "Snug"},
+        {"value": "organic", "label": "Organic"}
+      ]
+    },
+    {
+      "key": "support_threshold_angle",
+      "label": "Support Overhang Angle",
+      "type": "number",
+      "category": "support",
+      "description": "Minimum angle for support generation",
+      "unit": "°",
+      "min": 0,
+      "max": 90
+    },
+    {
+      "key": "support_base_pattern",
+      "label": "Support Pattern",
+      "type": "select",
+      "category": "support",
+      "description": "Pattern for support base",
+      "options": [
+        {"value": "rectilinear", "label": "Rectilinear"},
+        {"value": "rectilinear-grid", "label": "Rectilinear Grid"},
+        {"value": "honeycomb", "label": "Honeycomb"},
+        {"value": "lightning", "label": "Lightning"},
+        {"value": "default", "label": "Default"},
+        {"value": "hollow", "label": "Hollow"}
+      ]
+    },
+    {
+      "key": "support_base_pattern_spacing",
+      "label": "Support Pattern Spacing",
+      "type": "number",
+      "category": "support",
+      "description": "Spacing between support lines",
+      "unit": "mm",
+      "step": 0.1
+    },
+    {
+      "key": "support_interface_top_layers",
+      "label": "Support Interface Top Layers",
+      "type": "number",
+      "category": "support",
+      "description": "Number of interface layers on top"
+    },
+    {
+      "key": "support_interface_bottom_layers",
+      "label": "Support Interface Bottom Layers",
+      "type": "number",
+      "category": "support",
+      "description": "Number of interface layers on bottom"
+    },
+    {
+      "key": "support_interface_spacing",
+      "label": "Support Interface Spacing",
+      "type": "number",
+      "category": "support",
+      "description": "Spacing of interface pattern",
+      "unit": "mm",
+      "step": 0.1
+    },
+    {
+      "key": "support_object_xy_distance",
+      "label": "Support XY Distance",
+      "type": "number",
+      "category": "support",
+      "description": "Gap between support and object",
+      "unit": "mm",
+      "step": 0.1
+    },
+    {
+      "key": "support_top_z_distance",
+      "label": "Support Top Z Distance",
+      "type": "number",
+      "category": "support",
+      "description": "Gap between support top and object",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "support_bottom_z_distance",
+      "label": "Support Bottom Z Distance",
+      "type": "number",
+      "category": "support",
+      "description": "Gap between object and support top",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "support_on_build_plate_only",
+      "label": "Support On Build Plate Only",
+      "type": "boolean",
+      "category": "support",
+      "description": "Only generate support from build plate"
+    },
+    {
+      "key": "support_critical_regions_only",
+      "label": "Support Critical Regions Only",
+      "type": "boolean",
+      "category": "support",
+      "description": "Only support critical overhangs"
+    },
+    {
+      "key": "brim_type",
+      "label": "Brim Type",
+      "type": "select",
+      "category": "adhesion",
+      "description": "Type of brim to generate",
+      "options": [
+        {"value": "no_brim", "label": "No Brim"},
+        {"value": "auto_brim", "label": "Auto"},
+        {"value": "outer_only", "label": "Outer Only"},
+        {"value": "inner_only", "label": "Inner Only"},
+        {"value": "outer_and_inner", "label": "Outer and Inner"},
+        {"value": "brim_ears", "label": "Brim Ears"}
+      ]
+    },
+    {
+      "key": "brim_width",
+      "label": "Brim Width",
+      "type": "number",
+      "category": "adhesion",
+      "description": "Width of the brim",
+      "unit": "mm",
+      "min": 0,
+      "max": 20
+    },
+    {
+      "key": "brim_object_gap",
+      "label": "Brim-Object Gap",
+      "type": "number",
+      "category": "adhesion",
+      "description": "Gap between brim and object",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "skirt_loops",
+      "label": "Skirt Loops",
+      "type": "number",
+      "category": "adhesion",
+      "description": "Number of skirt loops",
+      "min": 0,
+      "max": 10
+    },
+    {
+      "key": "skirt_distance",
+      "label": "Skirt Distance",
+      "type": "number",
+      "category": "adhesion",
+      "description": "Distance from object to skirt",
+      "unit": "mm"
+    },
+    {
+      "key": "skirt_height",
+      "label": "Skirt Height",
+      "type": "number",
+      "category": "adhesion",
+      "description": "Height of skirt in layers"
+    },
+    {
+      "key": "raft_layers",
+      "label": "Raft Layers",
+      "type": "number",
+      "category": "adhesion",
+      "description": "Number of raft layers"
+    },
+    {
+      "key": "prime_tower_enable",
+      "label": "Enable Prime Tower",
+      "type": "boolean",
+      "category": "multimaterial",
+      "description": "Generate prime/wipe tower"
+    },
+    {
+      "key": "prime_tower_width",
+      "label": "Prime Tower Width",
+      "type": "number",
+      "category": "multimaterial",
+      "description": "Width of prime tower",
+      "unit": "mm"
+    },
+    {
+      "key": "prime_tower_brim_width",
+      "label": "Prime Tower Brim Width",
+      "type": "number",
+      "category": "multimaterial",
+      "description": "Brim width for prime tower",
+      "unit": "mm"
+    },
+    {
+      "key": "wipe_tower_no_sparse_layers",
+      "label": "No Sparse Layers in Tower",
+      "type": "boolean",
+      "category": "multimaterial",
+      "description": "Disable sparse layers in wipe tower"
+    },
+    {
+      "key": "flush_into_infill",
+      "label": "Flush Into Infill",
+      "type": "boolean",
+      "category": "multimaterial",
+      "description": "Purge into infill instead of tower"
+    },
+    {
+      "key": "flush_into_support",
+      "label": "Flush Into Support",
+      "type": "boolean",
+      "category": "multimaterial",
+      "description": "Purge into support instead of tower"
+    },
+    {
+      "key": "flush_into_objects",
+      "label": "Flush Into Objects",
+      "type": "boolean",
+      "category": "multimaterial",
+      "description": "Purge into object infill"
+    },
+    {
+      "key": "prime_volume",
+      "label": "Prime Volume",
+      "type": "number",
+      "category": "multimaterial",
+      "description": "Volume to prime after tool change",
+      "unit": "mm³"
+    },
+    {
+      "key": "seam_position",
+      "label": "Seam Position",
+      "type": "select",
+      "category": "quality",
+      "description": "Position of layer start/seam",
+      "options": [
+        {"value": "nearest", "label": "Nearest"},
+        {"value": "aligned", "label": "Aligned"},
+        {"value": "back", "label": "Back"},
+        {"value": "random", "label": "Random"}
+      ]
+    },
+    {
+      "key": "staggered_inner_seams",
+      "label": "Staggered Inner Seams",
+      "type": "boolean",
+      "category": "quality",
+      "description": "Stagger seams on inner walls"
+    },
+    {
+      "key": "wall_sequence",
+      "label": "Wall Sequence",
+      "type": "select",
+      "category": "quality",
+      "description": "Order of printing walls",
+      "options": [
+        {"value": "inner wall/outer wall", "label": "Inner/Outer"},
+        {"value": "outer wall/inner wall", "label": "Outer/Inner"},
+        {"value": "inner-outer-inner wall", "label": "Inner-Outer-Inner"}
+      ]
+    },
+    {
+      "key": "only_one_wall_top",
+      "label": "Only One Wall on Top",
+      "type": "boolean",
+      "category": "quality",
+      "description": "Use single wall on top surface"
+    },
+    {
+      "key": "detect_thin_wall",
+      "label": "Detect Thin Walls",
+      "type": "boolean",
+      "category": "quality",
+      "description": "Enable thin wall detection"
+    },
+    {
+      "key": "enable_overhang_speed",
+      "label": "Enable Overhang Speed",
+      "type": "boolean",
+      "category": "quality",
+      "description": "Slow down for overhangs"
+    },
+    {
+      "key": "overhang_speed_classic",
+      "label": "Classic Overhang Speed",
+      "type": "boolean",
+      "category": "quality",
+      "description": "Use classic overhang speed calculation"
+    },
+    {
+      "key": "bridge_flow",
+      "label": "Bridge Flow Ratio",
+      "type": "number",
+      "category": "quality",
+      "description": "Flow ratio for bridges",
+      "step": 0.01
+    },
+    {
+      "key": "thick_bridges",
+      "label": "Thick Bridges",
+      "type": "boolean",
+      "category": "quality",
+      "description": "Use thicker bridges"
+    },
+    {
+      "key": "ironing_type",
+      "label": "Ironing Type",
+      "type": "select",
+      "category": "quality",
+      "description": "Type of ironing",
+      "options": [
+        {"value": "no ironing", "label": "No Ironing"},
+        {"value": "top", "label": "Top Surface Only"},
+        {"value": "topmost", "label": "Topmost Surface Only"},
+        {"value": "allsolid", "label": "All Solid Layers"}
+      ]
+    },
+    {
+      "key": "ironing_speed",
+      "label": "Ironing Speed",
+      "type": "number",
+      "category": "quality",
+      "description": "Speed for ironing",
+      "unit": "mm/s"
+    },
+    {
+      "key": "ironing_flow",
+      "label": "Ironing Flow",
+      "type": "number",
+      "category": "quality",
+      "description": "Flow rate for ironing",
+      "unit": "%"
+    },
+    {
+      "key": "ironing_spacing",
+      "label": "Ironing Spacing",
+      "type": "number",
+      "category": "quality",
+      "description": "Spacing between ironing lines",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "fuzzy_skin",
+      "label": "Fuzzy Skin",
+      "type": "select",
+      "category": "quality",
+      "description": "Add texture to outer walls",
+      "options": [
+        {"value": "none", "label": "None"},
+        {"value": "external", "label": "External"},
+        {"value": "all", "label": "All Walls"},
+        {"value": "allwalls", "label": "All Walls"}
+      ]
+    },
+    {
+      "key": "fuzzy_skin_thickness",
+      "label": "Fuzzy Skin Thickness",
+      "type": "number",
+      "category": "quality",
+      "description": "Thickness of fuzzy skin texture",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "fuzzy_skin_point_dist",
+      "label": "Fuzzy Skin Point Distance",
+      "type": "number",
+      "category": "quality",
+      "description": "Distance between fuzzy skin points",
+      "unit": "mm",
+      "step": 0.1
+    },
+    {
+      "key": "xy_hole_compensation",
+      "label": "XY Hole Compensation",
+      "type": "number",
+      "category": "quality",
+      "description": "Compensation for holes",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "xy_contour_compensation",
+      "label": "XY Contour Compensation",
+      "type": "number",
+      "category": "quality",
+      "description": "Compensation for contours",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "elefant_foot_compensation",
+      "label": "Elephant Foot Compensation",
+      "type": "number",
+      "category": "quality",
+      "description": "Compensation for first layer expansion",
+      "unit": "mm",
+      "step": 0.01
+    },
+    {
+      "key": "resolution",
+      "label": "Resolution",
+      "type": "number",
+      "category": "advanced",
+      "description": "G-code resolution",
+      "unit": "mm",
+      "step": 0.001
+    },
+    {
+      "key": "gcode_comments",
+      "label": "Verbose G-code",
+      "type": "boolean",
+      "category": "advanced",
+      "description": "Add comments to G-code"
+    },
+    {
+      "key": "reduce_crossing_wall",
+      "label": "Avoid Crossing Walls",
+      "type": "boolean",
+      "category": "advanced",
+      "description": "Avoid crossing walls during travel"
+    },
+    {
+      "key": "max_travel_detour_distance",
+      "label": "Max Travel Detour",
+      "type": "number",
+      "category": "advanced",
+      "description": "Maximum detour to avoid crossing walls",
+      "unit": "mm"
+    },
+    {
+      "key": "timelapse_type",
+      "label": "Timelapse Type",
+      "type": "select",
+      "category": "special",
+      "description": "Type of timelapse recording",
+      "options": [
+        {"value": "0", "label": "Traditional"},
+        {"value": "1", "label": "Smooth"}
+      ]
+    },
+    {
+      "key": "enable_arc_fitting",
+      "label": "Enable Arc Fitting",
+      "type": "boolean",
+      "category": "advanced",
+      "description": "Convert linear moves to arcs"
+    }
+  ]
+}

+ 1 - 1
backend/app/services/bambu_cloud.py

@@ -174,7 +174,7 @@ class BambuCloudService:
         except httpx.RequestError as e:
         except httpx.RequestError as e:
             raise BambuCloudError(f"Request failed: {e}")
             raise BambuCloudError(f"Request failed: {e}")
 
 
-    async def get_slicer_settings(self, version: str = "01.09.00.00") -> dict:
+    async def get_slicer_settings(self, version: str = "02.04.00.70") -> dict:
         """
         """
         Get all slicer settings (filament, printer, process presets).
         Get all slicer settings (filament, printer, process presets).
 
 

+ 29 - 1
frontend/src/api/client.ts

@@ -316,6 +316,30 @@ export interface SlicerSettingDeleteResponse {
   message: string;
   message: string;
 }
 }
 
 
+export interface FieldOption {
+  value: string;
+  label: string;
+}
+
+export interface FieldDefinition {
+  key: string;
+  label: string;
+  type: 'text' | 'number' | 'boolean' | 'select';
+  category: string;
+  description?: string;
+  options?: FieldOption[];
+  unit?: string;
+  min?: number;
+  max?: number;
+  step?: number;
+}
+
+export interface FieldDefinitionsResponse {
+  version: string;
+  description: string;
+  fields: FieldDefinition[];
+}
+
 export interface CloudDevice {
 export interface CloudDevice {
   dev_id: string;
   dev_id: string;
   name: string;
   name: string;
@@ -1044,7 +1068,7 @@ export const api = {
     }),
     }),
   cloudLogout: () =>
   cloudLogout: () =>
     request<{ success: boolean }>('/cloud/logout', { method: 'POST' }),
     request<{ success: boolean }>('/cloud/logout', { method: 'POST' }),
-  getCloudSettings: (version = '01.09.00.00') =>
+  getCloudSettings: (version = '02.04.00.70') =>
     request<SlicerSettingsResponse>(`/cloud/settings?version=${version}`),
     request<SlicerSettingsResponse>(`/cloud/settings?version=${version}`),
   getCloudSettingDetail: (settingId: string) =>
   getCloudSettingDetail: (settingId: string) =>
     request<SlicerSettingDetail>(`/cloud/settings/${settingId}`),
     request<SlicerSettingDetail>(`/cloud/settings/${settingId}`),
@@ -1063,6 +1087,10 @@ export const api = {
       method: 'DELETE',
       method: 'DELETE',
     }),
     }),
   getCloudDevices: () => request<CloudDevice[]>('/cloud/devices'),
   getCloudDevices: () => request<CloudDevice[]>('/cloud/devices'),
+  getCloudFields: (presetType: 'filament' | 'print' | 'process' | 'printer') =>
+    request<FieldDefinitionsResponse>(`/cloud/fields/${presetType}`),
+  getAllCloudFields: () =>
+    request<Record<string, FieldDefinitionsResponse>>('/cloud/fields'),
 
 
   // Smart Plugs
   // Smart Plugs
   getSmartPlugs: () => request<SmartPlug[]>('/smart-plugs/'),
   getSmartPlugs: () => request<SmartPlug[]>('/smart-plugs/'),

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1174 - 178
frontend/src/pages/ProfilesPage.tsx


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
static/assets/index-BPFlIKJb.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
static/assets/index-CZD79C6y.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
static/assets/index-CvhOt4Al.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
static/assets/index-ub2z8B-A.css


+ 2 - 2
static/index.html

@@ -7,8 +7,8 @@
     <link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png" />
     <link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png" />
     <link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png" />
     <link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png" />
     <link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png" />
     <link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png" />
-    <script type="module" crossorigin src="/assets/index-CZD79C6y.js"></script>
-    <link rel="stylesheet" crossorigin href="/assets/index-BPFlIKJb.css">
+    <script type="module" crossorigin src="/assets/index-CvhOt4Al.js"></script>
+    <link rel="stylesheet" crossorigin href="/assets/index-ub2z8B-A.css">
   </head>
   </head>
   <body>
   <body>
     <div id="root"></div>
     <div id="root"></div>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است