-
Notifications
You must be signed in to change notification settings - Fork 4
iteration1 #193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
iteration1 #193
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ import PDFViewerModal from "./PDFViewerModal"; | |
| import { VersionHistoryModal } from "@/components/workspace/VersionHistoryModal"; | ||
| import type { WorkspaceEvent } from "@/lib/workspace/events"; | ||
| import { useUIStore } from "@/lib/stores/ui-store"; | ||
| import { ResizablePanel, ResizableHandle, ResizablePanelGroup } from "@/components/ui/resizable"; | ||
|
|
||
| interface ModalManagerProps { | ||
| // Card Detail Modal | ||
|
|
@@ -67,28 +68,95 @@ export function ModalManager({ | |
|
|
||
| return ( | ||
| <> | ||
| {/* Card Detail Modal or PDF Viewer Modal - only shown when item is maximized */} | ||
| {activeItemId && currentItem && maximizedItemId === currentItem.id && ( | ||
| currentItem.type === 'pdf' ? ( | ||
| <PDFViewerModal | ||
| key={currentItem.id} | ||
| item={currentItem} | ||
| isOpen={true} | ||
| onClose={() => handleClose(currentItem.id)} | ||
| onUpdateItem={(updates) => onUpdateItem(currentItem.id, updates)} | ||
| renderInline={workspaceSplitViewActive} | ||
| /> | ||
| ) : ( | ||
| <CardDetailModal | ||
| key={currentItem.id} | ||
| item={currentItem} | ||
| isOpen={true} | ||
| onClose={() => handleClose(currentItem.id)} | ||
| onUpdateItem={(updates) => onUpdateItem(currentItem.id, updates)} | ||
| onUpdateItemData={(updater) => onUpdateItemData(currentItem.id, updater)} | ||
| onFlushPendingChanges={onFlushPendingChanges} | ||
| renderInline={workspaceSplitViewActive} | ||
| /> | ||
| {/* Dual-Panel Mode: Render both panels when openPanelIds.length === 2 and split view is active */} | ||
| {workspaceSplitViewActive && openPanelIds.length === 2 ? ( | ||
| <ResizablePanelGroup orientation="horizontal" className="h-full w-full"> | ||
| {/* First Panel (Left) */} | ||
| <ResizablePanel id="dual-panel-left" defaultSize={50} minSize={30}> | ||
|
Comment on lines
71
to
75
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resizable panels missing Group In dual-panel mode you render |
||
| {openPanelIds[0] && (() => { | ||
| const item1 = items.find(i => i.id === openPanelIds[0]); | ||
| if (!item1) return null; | ||
|
|
||
| return item1.type === 'pdf' ? ( | ||
| <PDFViewerModal | ||
| key={item1.id} | ||
| item={item1} | ||
| isOpen={true} | ||
| onClose={() => handleClose(item1.id)} | ||
| onUpdateItem={(updates) => onUpdateItem(item1.id, updates)} | ||
| renderInline={true} | ||
| /> | ||
| ) : ( | ||
| <CardDetailModal | ||
| key={item1.id} | ||
| item={item1} | ||
| isOpen={true} | ||
| onClose={() => handleClose(item1.id)} | ||
| onUpdateItem={(updates) => onUpdateItem(item1.id, updates)} | ||
| onUpdateItemData={(updater) => onUpdateItemData(item1.id, updater)} | ||
| onFlushPendingChanges={onFlushPendingChanges} | ||
| renderInline={true} | ||
| /> | ||
| ); | ||
| })()} | ||
| </ResizablePanel> | ||
|
|
||
| <ResizableHandle className="border-r border-sidebar-border" /> | ||
|
|
||
| {/* Second Panel (Right) */} | ||
| <ResizablePanel id="dual-panel-right" defaultSize={50} minSize={30}> | ||
| {openPanelIds[1] && (() => { | ||
| const item2 = items.find(i => i.id === openPanelIds[1]); | ||
| if (!item2) return null; | ||
|
|
||
| return item2.type === 'pdf' ? ( | ||
| <PDFViewerModal | ||
| key={item2.id} | ||
| item={item2} | ||
| isOpen={true} | ||
| onClose={() => handleClose(item2.id)} | ||
| onUpdateItem={(updates) => onUpdateItem(item2.id, updates)} | ||
| renderInline={true} | ||
| /> | ||
| ) : ( | ||
| <CardDetailModal | ||
| key={item2.id} | ||
| item={item2} | ||
| isOpen={true} | ||
| onClose={() => handleClose(item2.id)} | ||
| onUpdateItem={(updates) => onUpdateItem(item2.id, updates)} | ||
| onUpdateItemData={(updater) => onUpdateItemData(item2.id, updater)} | ||
| onFlushPendingChanges={onFlushPendingChanges} | ||
| renderInline={true} | ||
| /> | ||
| ); | ||
| })()} | ||
| </ResizablePanel> | ||
|
Comment on lines
+76
to
+134
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Extract repeated panel-rendering logic to eliminate duplication. The left-panel block (lines 76–101) and right-panel block (lines 108–133) are nearly identical — the only difference is the index into Suggested refactor+ // Render a single panel item (reused for left & right in dual mode)
+ const renderPanelItem = (panelId: string | undefined) => {
+ if (!panelId) return null;
+ const item = items.find(i => i.id === panelId);
+ if (!item) return null;
+
+ return item.type === 'pdf' ? (
+ <PDFViewerModal
+ key={item.id}
+ item={item}
+ isOpen={true}
+ onClose={() => handleClose(item.id)}
+ onUpdateItem={(updates) => onUpdateItem(item.id, updates)}
+ renderInline={true}
+ />
+ ) : (
+ <CardDetailModal
+ key={item.id}
+ item={item}
+ isOpen={true}
+ onClose={() => handleClose(item.id)}
+ onUpdateItem={(updates) => onUpdateItem(item.id, updates)}
+ onUpdateItemData={(updater) => onUpdateItemData(item.id, updater)}
+ onFlushPendingChanges={() => onFlushPendingChanges(item.id)}
+ renderInline={true}
+ />
+ );
+ };Then the dual-panel JSX collapses to: <ResizablePanelGroup orientation="horizontal" className="h-full w-full">
<ResizablePanel id="dual-panel-left" defaultSize={50} minSize={30}>
{renderPanelItem(openPanelIds[0])}
</ResizablePanel>
<ResizableHandle className="border-r border-sidebar-border" />
<ResizablePanel id="dual-panel-right" defaultSize={50} minSize={30}>
{renderPanelItem(openPanelIds[1])}
</ResizablePanel>
</ResizablePanelGroup>🤖 Prompt for AI Agents |
||
| </ResizablePanelGroup> | ||
|
Comment on lines
+71
to
+135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Wrap it the same way you wrap Proposed fix <CardDetailModal
key={item1.id}
item={item1}
isOpen={true}
onClose={() => handleClose(item1.id)}
onUpdateItem={(updates) => onUpdateItem(item1.id, updates)}
onUpdateItemData={(updater) => onUpdateItemData(item1.id, updater)}
- onFlushPendingChanges={onFlushPendingChanges}
+ onFlushPendingChanges={() => onFlushPendingChanges(item1.id)}
renderInline={true}
/>Apply the same fix for the right panel ( <CardDetailModal
key={item2.id}
item={item2}
isOpen={true}
onClose={() => handleClose(item2.id)}
onUpdateItem={(updates) => onUpdateItem(item2.id, updates)}
onUpdateItemData={(updater) => onUpdateItemData(item2.id, updater)}
- onFlushPendingChanges={onFlushPendingChanges}
+ onFlushPendingChanges={() => onFlushPendingChanges(item2.id)}
renderInline={true}
/>Note: the same issue exists at Line 156 in the single-panel path, but that's pre-existing code. 🤖 Prompt for AI Agents |
||
| ) : ( | ||
| /* Single Panel Mode: Card Detail Modal or PDF Viewer Modal - only shown when item is maximized */ | ||
| activeItemId && currentItem && maximizedItemId === currentItem.id && ( | ||
| currentItem.type === 'pdf' ? ( | ||
| <PDFViewerModal | ||
| key={currentItem.id} | ||
| item={currentItem} | ||
| isOpen={true} | ||
| onClose={() => handleClose(currentItem.id)} | ||
| onUpdateItem={(updates) => onUpdateItem(currentItem.id, updates)} | ||
| renderInline={workspaceSplitViewActive} | ||
| /> | ||
| ) : ( | ||
| <CardDetailModal | ||
| key={currentItem.id} | ||
| item={currentItem} | ||
| isOpen={true} | ||
| onClose={() => handleClose(currentItem.id)} | ||
| onUpdateItem={(updates) => onUpdateItem(currentItem.id, updates)} | ||
| onUpdateItemData={(updater) => onUpdateItemData(currentItem.id, updater)} | ||
| onFlushPendingChanges={onFlushPendingChanges} | ||
| renderInline={workspaceSplitViewActive} | ||
| /> | ||
| ) | ||
| ) | ||
| )} | ||
|
|
||
|
|
@@ -105,4 +173,3 @@ export function ModalManager({ | |
| </> | ||
| ); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
workspaceSplitViewActivecomes from props whileopenPanelIdsis read from the store — risk of desync.DashboardLayoutreceivesworkspaceSplitViewActiveas a prop (line 71), butModalManagersubscribes to the same flag directly from the store (line 48 in ModalManager.tsx). If the parent passes a stale or different value, the two components will disagree on whether dual-panel mode is active (e.g.,DashboardLayoutrenders the dual wrapper whileModalManagerfalls into the single-panel branch, or vice-versa).Consider reading
workspaceSplitViewActivefrom the store here as well (consistent withopenPanelIds), or conversely pass it down toModalManageras a prop — pick one source of truth.🤖 Prompt for AI Agents