mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-11 12:17:45 +02:00
[Haik]: refactor: restructure Dashboard module boundaries — move ElementSelectionContext (split into ElementSelectionProvider, SelectedElement, useElementSelection), SelectionOverlay, domSelectorHelpers, and useDomElementSelector from global components/ into Dashboard/_shared/element_selection and Dashboard/hooks/useDomElementSelector; relocate types.ts and formatRelativeTime.ts into Dashboard/_shared; update imports in Dashboard.tsx, DashboardCanvas, CanvasControls, DashboardHeader, ViewEditor, useIframeElementSelector, dashboardClipboard, and all Dashboard hooks
This commit is contained in:
@@ -5,9 +5,10 @@ import { toggleExpandSession } from '@/shared/state/agentsSlice';
|
||||
import { UPDATE_DASHBOARD } from '@/shared/backend-bridge/apps/dashboards';
|
||||
import { useCanvasControls } from './hooks/useCanvasControls/useCanvasControls';
|
||||
import { useDashboardSelection } from './hooks/useDashboardSelection';
|
||||
import { ElementSelectionProvider, useElementSelection } from '@/app/components/ElementSelectionContext';
|
||||
import { useDomElementSelector } from '@/app/components/useDomElementSelector';
|
||||
import SelectionOverlay from '@/app/components/SelectionOverlay';
|
||||
import { ElementSelectionProvider } from './_shared/element_selection/ElementSelectionProvider';
|
||||
import { useElementSelection } from './_shared/element_selection/useElementSelection';
|
||||
import { useDomElementSelector } from './hooks/useDomElementSelector/useDomElementSelector';
|
||||
import SelectionOverlay from './SelectionOverlay';
|
||||
import { useDashboardDrag } from './hooks/useDashboardDrag';
|
||||
import { useDashboardKeyboard } from './hooks/useDashboardKeyboard';
|
||||
import { useDashboardThumbnail } from './hooks/useDashboardThumbnail/useDashboardThumbnail';
|
||||
|
||||
@@ -10,9 +10,7 @@ import DashboardToolbar from './components/DashboardToolbar/DashboardToolbar';
|
||||
import DashboardHeader from './components/DashboardHeader/DashboardHeader';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { EXPANDED_CARD_MIN_H, DEFAULT_CARD_W, GRID_GAP } from '@/shared/state/dashboardLayoutSlice';
|
||||
import type { TetherInfo } from '@/app/pages/Dashboard/types/types';
|
||||
import type { CardType } from '@/app/pages/Dashboard/types/types';
|
||||
import type { CanvasActions } from '@/app/pages/Dashboard/types/types';
|
||||
import { type CardType, type CanvasActions, type TetherInfo } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
const TETHER_FADE_MS = 2500;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import AddIcon from '@mui/icons-material/Add';
|
||||
import FitScreenIcon from '@mui/icons-material/FitScreen';
|
||||
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import type { CanvasActions } from '@/app/pages/Dashboard/types/types';
|
||||
import { type CanvasActions } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
interface Props {
|
||||
zoom: number;
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import type { AgentSession } from '@/shared/state/agentsSlice';
|
||||
import type { CardPosition, ViewCardPosition, BrowserCardPosition } from '@/shared/state/dashboardLayoutSlice';
|
||||
import type { App } from '@/shared/backend-bridge/apps/app_builder';
|
||||
import type { CanvasActions } from '@/app/pages/Dashboard/types/types';
|
||||
import { type CanvasActions } from '@/app/pages/Dashboard/_shared/types';
|
||||
import { STATUS_DOT, cleanUrl, CategoryGroup, ItemRow } from './DashboardHeaderParts';
|
||||
|
||||
interface DashboardHeaderProps {
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { OverlayState, DragRect, DragPreviewElement } from './useDomElementSelector';
|
||||
import { useElementSelection } from './ElementSelectionContext';
|
||||
import { type OverlayState, type DragRect, type DragPreviewElement } from './_shared/types';
|
||||
import { useElementSelection } from './_shared/useElementSelection';
|
||||
|
||||
const HIGHLIGHT_COLOR = '#3b82f6';
|
||||
const HIGHLIGHT_BG = 'rgba(59, 130, 246, 0.08)';
|
||||
+2
-41
@@ -1,44 +1,5 @@
|
||||
import React, { createContext, useContext, useState, useRef, useCallback, useMemo, RefObject } from 'react';
|
||||
|
||||
export interface SelectedElement {
|
||||
id: string;
|
||||
selectorPath: string;
|
||||
tagName: string;
|
||||
className: string;
|
||||
outerHTML: string;
|
||||
computedStyles: Record<string, string>;
|
||||
screenshot?: string;
|
||||
boundingRect: { x: number; y: number; width: number; height: number };
|
||||
semanticType?: 'agent-card' | 'message' | 'tool-call' | 'tool-group' | 'view-card' | 'browser-card' | 'dom-element';
|
||||
semanticLabel?: string;
|
||||
semanticData?: Record<string, any>;
|
||||
}
|
||||
|
||||
interface ElementSelectionContextValue {
|
||||
selectMode: boolean;
|
||||
toggleSelectMode: () => void;
|
||||
setSelectMode: (active: boolean) => void;
|
||||
excludeSelectId: string | null;
|
||||
setExcludeSelectId: (id: string | null) => void;
|
||||
activeOwnerId: string | null;
|
||||
setActiveOwnerId: (id: string | null) => void;
|
||||
selectedElements: SelectedElement[];
|
||||
addSelectedElement: (el: SelectedElement) => void;
|
||||
updateSelectedElement: (id: string, patch: Partial<SelectedElement>) => void;
|
||||
removeSelectedElement: (id: string) => void;
|
||||
clearSelectedElements: () => void;
|
||||
elementsByOwner: Record<string, SelectedElement[]>;
|
||||
addElementForOwner: (ownerId: string, el: SelectedElement) => void;
|
||||
removeOwnerElement: (ownerId: string, elementId: string) => void;
|
||||
clearOwnerElements: (ownerId: string) => void;
|
||||
iframeRef: RefObject<HTMLIFrameElement | null>;
|
||||
}
|
||||
|
||||
const ElementSelectionContext = createContext<ElementSelectionContextValue | null>(null);
|
||||
|
||||
export function useElementSelection() {
|
||||
return useContext(ElementSelectionContext);
|
||||
}
|
||||
import React, { useState, useRef, useCallback, useMemo } from 'react';
|
||||
import { type SelectedElement } from './SelectedElement';
|
||||
|
||||
export const ElementSelectionProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [selectMode, setSelectMode] = useState(false);
|
||||
@@ -0,0 +1,13 @@
|
||||
export interface SelectedElement {
|
||||
id: string;
|
||||
selectorPath: string;
|
||||
tagName: string;
|
||||
className: string;
|
||||
outerHTML: string;
|
||||
computedStyles: Record<string, string>;
|
||||
screenshot?: string;
|
||||
boundingRect: { x: number; y: number; width: number; height: number };
|
||||
semanticType?: 'agent-card' | 'message' | 'tool-call' | 'tool-group' | 'view-card' | 'browser-card' | 'dom-element';
|
||||
semanticLabel?: string;
|
||||
semanticData?: Record<string, any>;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { createContext, useContext, RefObject } from 'react';
|
||||
import { type SelectedElement } from './SelectedElement';
|
||||
|
||||
|
||||
interface ElementSelectionContextValue {
|
||||
selectMode: boolean;
|
||||
toggleSelectMode: () => void;
|
||||
setSelectMode: (active: boolean) => void;
|
||||
excludeSelectId: string | null;
|
||||
setExcludeSelectId: (id: string | null) => void;
|
||||
activeOwnerId: string | null;
|
||||
setActiveOwnerId: (id: string | null) => void;
|
||||
selectedElements: SelectedElement[];
|
||||
addSelectedElement: (el: SelectedElement) => void;
|
||||
updateSelectedElement: (id: string, patch: Partial<SelectedElement>) => void;
|
||||
removeSelectedElement: (id: string) => void;
|
||||
clearSelectedElements: () => void;
|
||||
elementsByOwner: Record<string, SelectedElement[]>;
|
||||
addElementForOwner: (ownerId: string, el: SelectedElement) => void;
|
||||
removeOwnerElement: (ownerId: string, elementId: string) => void;
|
||||
clearOwnerElements: (ownerId: string) => void;
|
||||
iframeRef: RefObject<HTMLIFrameElement | null>;
|
||||
}
|
||||
|
||||
const ElementSelectionContext = createContext<ElementSelectionContextValue | null>(null);
|
||||
|
||||
export function useElementSelection() {
|
||||
return useContext(ElementSelectionContext);
|
||||
}
|
||||
+27
@@ -19,4 +19,31 @@ export interface CanvasActions {
|
||||
maxZoom?: number,
|
||||
animate?: boolean,
|
||||
) => void;
|
||||
}
|
||||
|
||||
export interface OverlayState {
|
||||
visible: boolean;
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface DragRect {
|
||||
visible: boolean;
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface DragPreviewElement {
|
||||
selectId: string;
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
label: string;
|
||||
action: 'add' | 'remove';
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState, useCallback, useRef } from 'react';
|
||||
import { useAppDispatch } from '@/shared/hooks';
|
||||
import { moveCards, bringToFront } from '@/shared/state/dashboardLayoutSlice';
|
||||
import type { CardType } from '@/app/pages/Dashboard/types/types';
|
||||
import { type CardType } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
interface DragSelection {
|
||||
isSelected: (id: string) => boolean;
|
||||
|
||||
@@ -14,7 +14,7 @@ import { LIST_APPS } from '@/shared/backend-bridge/apps/app_builder';
|
||||
import { agentsWs } from '@/shared/ws/WebSocketManager';
|
||||
import { initBrowserCommandHandler } from '@/shared/browserCommandHandler';
|
||||
import { clearPendingBrowserUrl, clearPendingFocusAgentId } from '@/shared/state/tempStateSlice';
|
||||
import type { CanvasActions } from '@/app/pages/Dashboard/types/types';
|
||||
import { type CanvasActions } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
interface InitDeps {
|
||||
dashboardId: string | undefined;
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
placeCard,
|
||||
} from '@/shared/state/dashboardLayoutSlice';
|
||||
import { setClipboardCards, getClipboardCards, type ClipboardCard } from '@/shared/dashboardClipboard';
|
||||
import type { CardType } from '@/app/pages/Dashboard/types/types';
|
||||
import { type CardType } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
interface KeyboardDeps {
|
||||
newAgentShortcut: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useCallback, useRef, useEffect, RefObject } from 'react';
|
||||
import type { CardPosition, ViewCardPosition, BrowserCardPosition } from '@/shared/state/dashboardLayoutSlice';
|
||||
import type { CardType } from '@/app/pages/Dashboard/types/types';
|
||||
import { type CardType } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
interface SelectedCard {
|
||||
id: string;
|
||||
|
||||
+2
-28
@@ -1,4 +1,5 @@
|
||||
import { type SelectedElement } from './ElementSelectionContext';
|
||||
import { type SelectedElement } from '@/app/pages/Dashboard/_shared/element_selection/SelectedElement';
|
||||
import { type OverlayState, type DragRect, type DragPreviewElement } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
export const SELECT_ATTR = 'data-select-type';
|
||||
export const SELECT_ID_ATTR = 'data-select-id';
|
||||
@@ -7,23 +8,6 @@ export const SELECT_META_ATTR = 'data-select-meta';
|
||||
const DRAG_SELECT_TYPES = ['agent-card', 'view-card', 'browser-card'] as const;
|
||||
const DRAG_SELECTOR = DRAG_SELECT_TYPES.map((t) => `[${SELECT_ATTR}="${t}"]`).join(',');
|
||||
|
||||
export interface OverlayState {
|
||||
visible: boolean;
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface DragRect {
|
||||
visible: boolean;
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export const EMPTY_OVERLAY: OverlayState = { visible: false, top: 0, left: 0, width: 0, height: 0, label: '' };
|
||||
export const EMPTY_DRAG: DragRect = { visible: false, top: 0, left: 0, width: 0, height: 0 };
|
||||
|
||||
@@ -98,16 +82,6 @@ export function buildSelectedElement(el: Element): SelectedElement {
|
||||
};
|
||||
}
|
||||
|
||||
export interface DragPreviewElement {
|
||||
selectId: string;
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
label: string;
|
||||
action: 'add' | 'remove';
|
||||
}
|
||||
|
||||
export const DRAG_THRESHOLD = 5;
|
||||
|
||||
export interface DomSelectorState {
|
||||
+4
-4
@@ -1,14 +1,14 @@
|
||||
import { useEffect, useRef, useState, useCallback } from 'react';
|
||||
import { useElementSelection } from './ElementSelectionContext';
|
||||
import { useElementSelection } from '@/app/pages/Dashboard/_shared/element_selection/useElementSelection';
|
||||
import {
|
||||
type OverlayState, type DragRect, type DragPreviewElement, type DomSelectorState, type SelectMeta,
|
||||
type SelectMeta,
|
||||
type DomSelectorState,
|
||||
EMPTY_OVERLAY, EMPTY_DRAG, DRAG_THRESHOLD,
|
||||
SELECT_ATTR, SELECT_ID_ATTR, SELECT_META_ATTR,
|
||||
findSelectableAncestor, buildSemanticLabel, buildSelectedElement,
|
||||
computeDragPreview, processDragSelection,
|
||||
} from './domSelectorHelpers';
|
||||
|
||||
export type { OverlayState, DragRect, DragPreviewElement } from './domSelectorHelpers';
|
||||
import { type OverlayState, type DragRect, type DragPreviewElement } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
export function useDomElementSelector(): DomSelectorState {
|
||||
const ctx = useElementSelection();
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { RefObject } from 'react';
|
||||
import { EXPANDED_CARD_MIN_H } from '@/shared/state/dashboardLayoutSlice';
|
||||
import type { TetherInfo } from '@/app/pages/Dashboard/types/types';
|
||||
import { type TetherInfo } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
interface TetherDeps {
|
||||
glowingAgentCards: Record<string, { sourceId: string; fading: boolean; sourceYRatio?: number; label?: string }>;
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
} from '@/shared/state/dashboardLayoutSlice';
|
||||
import { GENERATE_DASHBOARD_NAME } from '@/shared/backend-bridge/apps/dashboards';
|
||||
import type { ContextPath } from '@/shared/state/agentsTypes';
|
||||
import type { CanvasActions } from '@/app/pages/Dashboard/types/types';
|
||||
import { type CanvasActions } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
interface ToolbarDeps {
|
||||
cards: Record<string, CardPosition>;
|
||||
|
||||
@@ -7,7 +7,8 @@ import AgentChat from '../AgentChat/AgentChat';
|
||||
import ViewPreview, { ViewPreviewHandle } from './ViewPreview';
|
||||
import InputSchemaForm, { getDefault, getStubbed } from './InputSchemaForm';
|
||||
import CodeEditor from './CodeEditor';
|
||||
import { ElementSelectionProvider } from '@/app/components/ElementSelectionContext';
|
||||
// TODO: Fix this import, also the the element selection in this component doesnt seem to work so for now its chillin
|
||||
import { ElementSelectionProvider } from '@/app/pages/Dashboard/_shared/element_selection/ElementSelectionProvider';
|
||||
import { FileTreeItem, getEditorLanguage } from './FileTree';
|
||||
import { ConsolePanel } from './ConsolePanel';
|
||||
import { useViewWorkspace } from './hooks/useViewWorkspace';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useRef, useCallback, RefObject } from 'react';
|
||||
import { SelectedElement, useElementSelection } from '@/app/components/ElementSelectionContext';
|
||||
import { useElementSelection } from '@/app/pages/Dashboard/_shared/element_selection/useElementSelection';
|
||||
import { type SelectedElement } from '@/app/pages/Dashboard/_shared/element_selection/SelectedElement';
|
||||
import {
|
||||
OVERLAY_ID, LABEL_ID, STYLE_ID,
|
||||
HIGHLIGHT_COLOR, HIGHLIGHT_BG, FLASH_COLOR, SELECTED_CLASS,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CardType } from '@/app/pages/Dashboard/types/types';
|
||||
import { type CardType } from '@/app/pages/Dashboard/_shared/types';
|
||||
|
||||
export interface ClipboardCard {
|
||||
type: CardType;
|
||||
|
||||
Reference in New Issue
Block a user