fix(canvas): Add Save/Reload buttons and expand IntrospectionPanel to show all model data

CanvasView:
- Fix Save button visibility - now shows when spec is loaded (grayed if no changes)
- Separate logic for spec mode vs legacy mode save buttons
- Fix Reload button visibility

IntrospectionPanel:
- Add Mass Properties section (mass, volume, surface area, CoG, body count)
- Add Linked Parts section showing file dependencies
- Add Bodies section (solid/sheet body counts)
- Add Units section showing unit system
- Type-safe access to all nested properties
This commit is contained in:
2026-01-20 14:47:09 -05:00
parent ced79b8d39
commit 91cf9ca1fd
2 changed files with 201 additions and 6 deletions

View File

@@ -296,17 +296,34 @@ export function CanvasView() {
{/* Action Buttons */}
<div className="flex items-center gap-2">
{/* Save Button - only show when there's a study and changes */}
{activeStudyId && (
{/* Save Button - always show in spec mode with study, grayed when no changes */}
{useSpecMode && spec && (
<button
onClick={saveToConfig}
disabled={isSaving || (useSpecMode ? !specIsDirty : !hasUnsavedChanges)}
disabled={isSaving || !specIsDirty}
className={`px-3 py-1.5 text-sm rounded-lg transition-colors flex items-center gap-1.5 ${
(useSpecMode ? specIsDirty : hasUnsavedChanges)
specIsDirty
? 'bg-green-600 hover:bg-green-500 text-white'
: 'bg-dark-700 text-dark-400 cursor-not-allowed border border-dark-600'
}`}
title={(useSpecMode ? specIsDirty : hasUnsavedChanges) ? `Save changes to ${useSpecMode ? 'atomizer_spec.json' : 'optimization_config.json'}` : 'No changes to save'}
title={specIsDirty ? 'Save changes to atomizer_spec.json' : 'No changes to save'}
>
<Save size={14} />
{isSaving ? 'Saving...' : 'Save'}
</button>
)}
{/* Legacy Save Button */}
{!useSpecMode && activeStudyId && (
<button
onClick={saveToConfig}
disabled={isSaving || !hasUnsavedChanges}
className={`px-3 py-1.5 text-sm rounded-lg transition-colors flex items-center gap-1.5 ${
hasUnsavedChanges
? 'bg-green-600 hover:bg-green-500 text-white'
: 'bg-dark-700 text-dark-400 cursor-not-allowed border border-dark-600'
}`}
title={hasUnsavedChanges ? 'Save changes to optimization_config.json' : 'No changes to save'}
>
<Save size={14} />
{isSaving ? 'Saving...' : 'Save'}
@@ -314,7 +331,7 @@ export function CanvasView() {
)}
{/* Reload Button */}
{activeStudyId && (
{(useSpecMode ? spec : activeStudyId) && (
<button
onClick={handleReload}
disabled={isLoading || specLoading}