Browse Source

fix: remove cleanup script, show lock icon on locked groups

- Remove obsolete scripts/cleanup-workflow.js
- Revert locked guards from group drag/resize/rename (lock is
  execution-only, not interaction)
- Add lock icon in group title pill for visual feedback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 4 months ago
parent
commit
e46bbd526f
  1. 72
      scripts/cleanup-workflow.js
  2. 13
      src/components/GroupsOverlay.tsx

72
scripts/cleanup-workflow.js

@ -1,72 +0,0 @@
/**
* One-time script to clean up outputGallery nodes with embedded images
* This fixes workflows saved before the outputGallery externalization bug was fixed
*/
const fs = require('fs');
const path = require('path');
const workflowPath = process.argv[2];
if (!workflowPath) {
console.error('Usage: node cleanup-workflow.js <path-to-workflow.json>');
process.exit(1);
}
console.log(`Reading workflow: ${workflowPath}`);
const workflow = JSON.parse(fs.readFileSync(workflowPath, 'utf8'));
let cleaned = false;
let totalSizeBefore = 0;
let totalSizeAfter = 0;
workflow.nodes.forEach((node, index) => {
if (node.type === 'outputGallery' && node.data.images && node.data.images.length > 0) {
const sizeBefore = JSON.stringify(node.data.images).length;
const imageCount = node.data.images.filter(img => img && img.startsWith('data:')).length;
if (imageCount > 0) {
const removedImages = node.data.images.filter(img => img && img.startsWith('data:'));
const removedSize = removedImages.reduce((sum, img) => sum + img.length, 0);
console.log(`\nNode ${index} (${node.id}):`);
console.log(` Found ${imageCount} embedded images`);
console.log(` Size: ${(removedSize / 1024 / 1024).toFixed(2)} MB`);
node.data.images = node.data.images.filter(img => !(img && img.startsWith('data:')));
totalSizeBefore += removedSize;
cleaned = true;
}
}
if (node.type === 'output' && node.data.image && node.data.image.startsWith('data:')) {
const sizeBefore = node.data.image.length;
console.log(`\nNode ${index} (${node.id}):`);
console.log(` Found embedded output image`);
console.log(` Size: ${(sizeBefore / 1024 / 1024).toFixed(2)} MB`);
node.data.image = null;
totalSizeBefore += sizeBefore;
cleaned = true;
}
});
if (cleaned) {
const backupPath = workflowPath.replace('.json', '.backup.json');
console.log(`\nCreating backup: ${backupPath}`);
fs.copyFileSync(workflowPath, backupPath);
console.log(`Writing cleaned workflow...`);
fs.writeFileSync(workflowPath, JSON.stringify(workflow, null, 2));
const finalSize = fs.statSync(workflowPath).size;
const originalSize = fs.statSync(backupPath).size;
console.log(`\n✅ Done!`);
console.log(` Original size: ${(originalSize / 1024 / 1024).toFixed(2)} MB`);
console.log(` New size: ${(finalSize / 1024 / 1024).toFixed(2)} MB`);
console.log(` Saved: ${((originalSize - finalSize) / 1024 / 1024).toFixed(2)} MB`);
console.log(`\nBackup saved to: ${backupPath}`);
} else {
console.log('\n✓ No embedded images found - workflow is already clean!');
}

13
src/components/GroupsOverlay.tsx

@ -152,7 +152,6 @@ function GroupControls({ groupId, zoom }: GroupControlsProps) {
// Header drag handlers
const handleHeaderMouseDown = useCallback(
(e: React.MouseEvent) => {
if (group?.locked) return;
if (
(e.target as HTMLElement).closest("button") ||
(e.target as HTMLElement).closest("input")
@ -164,13 +163,12 @@ function GroupControls({ groupId, zoom }: GroupControlsProps) {
setIsDragging(true);
dragStartRef.current = { x: e.clientX, y: e.clientY };
},
[group?.locked]
[]
);
// Resize handlers
const handleResizeMouseDown = useCallback(
(e: React.MouseEvent, handle: string) => {
if (group?.locked) return;
e.stopPropagation();
e.preventDefault();
setIsResizing(true);
@ -184,7 +182,7 @@ function GroupControls({ groupId, zoom }: GroupControlsProps) {
posY: group.position.y,
};
},
[group?.locked, group?.size, group?.position]
[group?.size, group?.position]
);
useEffect(() => {
@ -319,6 +317,11 @@ function GroupControls({ groupId, zoom }: GroupControlsProps) {
className="flex items-center rounded-md px-2 py-0.5"
style={{ backgroundColor: bgColor }}
>
{group.locked && (
<svg className="w-3 h-3 text-white/70 mr-1 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
)}
{isEditing ? (
<input
ref={inputRef}
@ -334,7 +337,7 @@ function GroupControls({ groupId, zoom }: GroupControlsProps) {
<span
className="text-xs font-medium text-white truncate"
style={{ maxWidth: 200 }}
onDoubleClick={(e) => { e.stopPropagation(); if (!group.locked) setIsEditing(true); }}
onDoubleClick={(e) => { e.stopPropagation(); setIsEditing(true); }}
>
{group.name}
</span>

Loading…
Cancel
Save