updated data panel and added zones

This commit is contained in:
Nalvazhuthi
2025-03-17 11:38:11 +05:30
parent 4e43fe1aba
commit 2da7011462
4 changed files with 172 additions and 79 deletions

View File

@@ -38,6 +38,34 @@
height: 600px; height: 600px;
background-color: rgb(235, 235, 235); background-color: rgb(235, 235, 235);
margin: 0 30px; margin: 0 30px;
.zoon-wrapper {
display: flex;
background-color: #E0DFFF80;
position: absolute;
bottom: 10px;
left: 50%;
transform: translate(-50%, 0);
gap: 6px;
padding: 4px;
border-radius: 8px;
max-width: 80%;
overflow: auto;
&::-webkit-scrollbar {
display: none;
}
.zone {
width: auto;
background-color: #FCFDFD;
border-radius: 6px;
padding: 4px 8px;
white-space: nowrap;
}
}
} }
// + button // + button
@@ -388,6 +416,10 @@
flex-direction: column; flex-direction: column;
gap: 5px; gap: 5px;
align-items: center; align-items: center;
.active {
// background-color: red;
}
} }
.icon { .icon {
@@ -426,6 +458,7 @@
.extra-buttons { .extra-buttons {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
} }
} }

View File

@@ -1,59 +1,47 @@
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect } from "react";
import { DropDownIcon } from '../../../assets/images/svgExports';
interface DropdownProps { interface DropdownProps {
header: string; header: string;
options: string[]; options: string[];
onSelect: (option: string) => void; // Callback for option selection onSelect: (option: string) => void;
} }
const RegularDropDown: React.FC<DropdownProps> = ({ header, options, onSelect }) => { const RegularDropDown: React.FC<DropdownProps> = ({
header,
options,
onSelect,
}) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [selectedOption, setSelectedOption] = useState<string | null>(null); const [selectedOption, setSelectedOption] = useState<string | null>(null);
// Reference to the dropdown container // Reset selectedOption when the dropdown closes
const dropdownRef = useRef<HTMLDivElement | null>(null); useEffect(() => {
if (!isOpen) {
setSelectedOption(null); // Clear local state when the dropdown closes
}
}, [isOpen]);
// Reset selectedOption when the header prop changes
useEffect(() => {
setSelectedOption(null); // Ensure the dropdown reflects the updated header
}, [header]);
// Toggle dropdown visibility
const toggleDropdown = () => { const toggleDropdown = () => {
setIsOpen(prev => !prev); setIsOpen((prev) => !prev);
}; };
// Handle option selection
const handleOptionClick = (option: string) => { const handleOptionClick = (option: string) => {
setSelectedOption(option); setSelectedOption(option);
onSelect(option); // Call the onSelect function passed from the parent onSelect(option); // Call the onSelect function passed from the parent
setIsOpen(false); // Close the dropdown after selection setIsOpen(false); // Close the dropdown after selection
}; };
// Handle clicks outside the dropdown
useEffect(() => {
const handleOuterClick = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setIsOpen(false); // Close the dropdown if clicked outside
}
};
// Attach the event listener
document.addEventListener('mousedown', handleOuterClick);
// Cleanup the event listener on component unmount
return () => {
document.removeEventListener('mousedown', handleOuterClick);
};
}, []);
return ( return (
<div className="regularDropdown-container" ref={dropdownRef}> <div className="regularDropdown-container">
{/* Dropdown Header */} {/* Dropdown Header */}
<div className="dropdown-header flex-sb" onClick={toggleDropdown}> <div className="dropdown-header flex-sb" onClick={toggleDropdown}>
<div className="key">{selectedOption || header}</div> <div className="key">{selectedOption || header}</div>
<div className="icon"> <div className="icon"></div>
<DropDownIcon />
</div>
</div> </div>
{/* Dropdown Options */} {/* Dropdown Options */}
@@ -63,7 +51,7 @@ const RegularDropDown: React.FC<DropdownProps> = ({ header, options, onSelect })
<div <div
className="option" className="option"
key={index} key={index}
onClick={() => handleOptionClick(option)} // Handle option click onClick={() => handleOptionClick(option)}
> >
{option} {option}
</div> </div>

View File

@@ -21,7 +21,7 @@ const Data = () => {
easing: "Connecter 1", easing: "Connecter 1",
children: [ children: [
{ id: 1, easing: "Linear" }, { id: 1, easing: "Linear" },
{ id: 2, easing: "Linear" }, { id: 2, easing: "Ease Out" },
{ id: 3, easing: "Linear" }, { id: 3, easing: "Linear" },
], ],
}, },
@@ -70,21 +70,26 @@ const Data = () => {
}); });
}; };
const removeChild = (childId: number) => { const removeChild = (groupId: number, childId: number) => {
setGroups((groups) => setGroups((currentGroups) =>
groups currentGroups.map((group) => {
.map((group) => ({ if (group.id === groupId) {
...group, return {
children: group.children.filter((c) => c.id !== childId), ...group,
})) children: group.children.map((child) =>
.filter((group) => group.children.length > 0) child.id === childId ? { ...child, easing: "Linear" } : child
),
};
}
return group;
})
); );
}; };
return ( return (
<div className="dataSideBar"> <div className="dataSideBar">
<div className="sideBarHeader">{selectedWidget}</div> <div className="sideBarHeader">{selectedWidget}</div>
{groups.map((group, groupIndex) => ( {groups.map((group) => (
<div key={group.id} className="selectedMain-container"> <div key={group.id} className="selectedMain-container">
<div className="selectedMain"> <div className="selectedMain">
<span className="bulletPoint"></span> <span className="bulletPoint"></span>
@@ -107,6 +112,7 @@ const Data = () => {
{group.children.map((child) => ( {group.children.map((child) => (
<div key={child.id} className="selectedMain child"> <div key={child.id} className="selectedMain child">
<main>Input {child.id}</main> <main>Input {child.id}</main>
{/* Pass the current easing as the header */}
<RegularDropDown <RegularDropDown
header={child.easing} header={child.easing}
options={["Linear", "Ease In", "Ease Out", "Ease In-Out"]} options={["Linear", "Ease In", "Ease Out", "Ease In-Out"]}
@@ -124,7 +130,10 @@ const Data = () => {
<div className="icon" onClick={() => handleLinkClick(child.id)}> <div className="icon" onClick={() => handleLinkClick(child.id)}>
<LinkIcon /> <LinkIcon />
</div> </div>
<div className="icon" onClick={() => removeChild(child.id)}> <div
className="icon"
onClick={() => removeChild(group.id, child.id)}
>
<RemoveIcon /> <RemoveIcon />
</div> </div>
</div> </div>

View File

@@ -49,17 +49,11 @@ const DraggableWidget = ({ widget }: { widget: any }) => {
}; };
const handlePointerDown = () => { const handlePointerDown = () => {
// Set selected chart when pointer down event occurs (i.e., when it's clicked, not dragged)
if (!isDragging) { if (!isDragging) {
setSelectedChartId(widget); // Update selected chart in the store setSelectedChartId(widget);
} }
}; };
// Log to see the selectedChartId updates
useEffect(() => {
console.log("selectedChartID: ", selectedChartId);
}, [selectedChartId]);
return ( return (
<div <div
key={widget.id} key={widget.id}
@@ -68,7 +62,7 @@ const DraggableWidget = ({ widget }: { widget: any }) => {
{...attributes} {...attributes}
{...listeners} {...listeners}
style={style} style={style}
onPointerDown={handlePointerDown} // Use onPointerDown instead of onPointerUp onPointerDown={handlePointerDown}
> >
<ChartComponent <ChartComponent
type={widget.type} type={widget.type}
@@ -82,19 +76,28 @@ const DraggableWidget = ({ widget }: { widget: any }) => {
}; };
const RealTimeVisualization = () => { const RealTimeVisualization = () => {
const [zone, setZone] = useState([
"Manufacturing unit",
"Assembly unit",
"Packing unit",
"Warehouse",
"Inventory",
]);
const [activeSides, setActiveSides] = useState<Side[]>([]); const [activeSides, setActiveSides] = useState<Side[]>([]);
const [panelOrder, setPanelOrder] = useState<Side[]>([]); const [panelOrder, setPanelOrder] = useState<Side[]>([]);
const [selectedSide, setSelectedSide] = useState<Side | null>(null); const [selectedSide, setSelectedSide] = useState<Side | null>(null);
const [lockedPanels, setLockedPanels] = useState<Side[]>([]);
const [activeExtraButton, setActiveExtraButton] = useState<{
[key in Side]?: string;
}>({});
const { draggedAsset, addWidget, widgets, setWidgets } = useWidgetStore(); const { draggedAsset, addWidget, widgets, setWidgets } = useWidgetStore();
// Sensors for drag-and-drop (Pointer and Keyboard)
const sensors = useSensors( const sensors = useSensors(
useSensor(PointerSensor), useSensor(PointerSensor),
useSensor(KeyboardSensor) useSensor(KeyboardSensor)
); );
useEffect(() => {}, [widgets]);
const toggleSide = (side: Side) => { const toggleSide = (side: Side) => {
setActiveSides((prev) => { setActiveSides((prev) => {
const newActive = prev.includes(side) const newActive = prev.includes(side)
@@ -102,17 +105,24 @@ const RealTimeVisualization = () => {
: [...prev, side]; : [...prev, side];
setPanelOrder(newActive); setPanelOrder(newActive);
// Reset selectedSide if the panel is being closed
if (prev.includes(side)) { if (prev.includes(side)) {
setSelectedSide(null); // Hide extra buttons when the panel is closed setSelectedSide(null);
} else { } else {
setSelectedSide(side); // Show extra buttons when the panel is opened setSelectedSide(side);
} }
return newActive; return newActive;
}); });
}; };
const toggleLockPanel = (side: Side) => {
setLockedPanels((prev) =>
prev.includes(side)
? prev.filter((panel) => panel !== side)
: [...prev, side]
);
};
const getPanelStyle = (currentSide: Side) => { const getPanelStyle = (currentSide: Side) => {
const currentIndex = panelOrder.indexOf(currentSide); const currentIndex = panelOrder.indexOf(currentSide);
const previousPanels = panelOrder.slice(0, currentIndex); const previousPanels = panelOrder.slice(0, currentIndex);
@@ -159,9 +169,6 @@ const RealTimeVisualization = () => {
} }
}; };
const leftHeader = useMemo(() => ["Overview", "Widgets", "Templates"], []);
const rightHeader = useMemo(() => ["Data", "Design"], []);
const handleDragEnd = (event: any) => { const handleDragEnd = (event: any) => {
const { active, over } = event; const { active, over } = event;
@@ -171,14 +178,11 @@ const RealTimeVisualization = () => {
const newPanel = const newPanel =
widgets.find((widget) => widget.id === over.id)?.panel || active.panel; widgets.find((widget) => widget.id === over.id)?.panel || active.panel;
// Ensure widgets are reordered within the same panel or moved to a new panel
if (active.panel === newPanel) { if (active.panel === newPanel) {
// Reorder within the same panel
const newIndex = widgets.findIndex((widget) => widget.id === over.id); const newIndex = widgets.findIndex((widget) => widget.id === over.id);
const reorderedWidgets = arrayMove(widgets, oldIndex, newIndex); const reorderedWidgets = arrayMove(widgets, oldIndex, newIndex);
setWidgets(reorderedWidgets); setWidgets(reorderedWidgets);
} else { } else {
// Move to a different panel
const updatedWidgets = widgets.map((widget) => const updatedWidgets = widgets.map((widget) =>
widget.id === active.id ? { ...widget, panel: newPanel } : widget widget.id === active.id ? { ...widget, panel: newPanel } : widget
); );
@@ -200,12 +204,19 @@ const RealTimeVisualization = () => {
onDragEnd={handleDragEnd} onDragEnd={handleDragEnd}
> >
<div className="content-container realTime-viz flex"> <div className="content-container realTime-viz flex">
<SideBar header={leftHeader} defaultActive={"Widgets"} /> <SideBar
header={["Overview", "Widgets", "Templates"]}
defaultActive={"Widgets"}
/>
<div className="main-container relative"> <div className="main-container relative">
<div className="zoon-wrapper">
{zone.map((zone, index) => (
<div className="zone">{zone}</div>
))}
</div>
{(["top", "right", "bottom", "left"] as Side[]).map((side) => ( {(["top", "right", "bottom", "left"] as Side[]).map((side) => (
<div key={side} className={`side-button-container ${side}`}> <div key={side} className={`side-button-container ${side}`}>
{/* Side Button */}
<button <button
className={`side-button ${side}`} className={`side-button ${side}`}
onClick={() => toggleSide(side)} onClick={() => toggleSide(side)}
@@ -214,23 +225,71 @@ const RealTimeVisualization = () => {
+ +
</button> </button>
{/* Extra Buttons */}
<div <div
className="extra-buttons" className="extra-buttons"
style={{ style={{
display: activeSides.includes(side) ? "flex" : "none", // Show if the panel is active display: activeSides.includes(side) ? "flex" : "none",
}} }}
> >
<div className="icon" title="Disable Sorting"> <div
className={`icon ${
activeExtraButton[side] === "Disable Sorting"
? "active"
: ""
}`}
title="Disable Sorting"
onClick={() =>
setActiveExtraButton((prev) => ({
...prev,
[side]: "Disable Sorting",
}))
}
>
<DisableSorting /> <DisableSorting />
</div> </div>
<div className="icon" title="Hide Panel"> <div
className={`icon ${
activeExtraButton[side] === "Hide Panel" ? "active" : ""
}`}
title="Hide Panel"
onClick={() =>
setActiveExtraButton((prev) => ({
...prev,
[side]: "Hide Panel",
}))
}
>
<EyeIcon /> <EyeIcon />
</div> </div>
<div className="icon" title="Clean Panel"> <div
className={`icon ${
activeExtraButton[side] === "Clean Panel" ? "active" : ""
}`}
title="Clean Panel"
onClick={() =>
setActiveExtraButton((prev) => ({
...prev,
[side]: "Clean Panel",
}))
}
>
<CleanPannel /> <CleanPannel />
</div> </div>
<div className="icon" title="Lock Panel"> <div
className={`icon ${
activeExtraButton[side] === "Lock Panel" ? "active" : ""
}`}
title={
lockedPanels.includes(side) ? "Unlock Panel" : "Lock Panel"
}
onClick={() => {
toggleLockPanel(side);
setActiveExtraButton((prev) => ({
...prev,
[side]: "Lock Panel",
}));
}}
>
<LockIcon /> <LockIcon />
</div> </div>
</div> </div>
@@ -245,7 +304,13 @@ const RealTimeVisualization = () => {
onDrop={(e) => handleDrop(e, side)} onDrop={(e) => handleDrop(e, side)}
onDragOver={(e) => e.preventDefault()} onDragOver={(e) => e.preventDefault()}
> >
<div className="panel-content"> <div
className="panel-content"
style={{
pointerEvents: lockedPanels.includes(side) ? "none" : "auto",
opacity: lockedPanels.includes(side) ? "0.8" : "1",
}}
>
<SortableContext <SortableContext
items={widgets items={widgets
.filter((w) => w.panel === side) .filter((w) => w.panel === side)
@@ -255,9 +320,7 @@ const RealTimeVisualization = () => {
{widgets {widgets
.filter((w) => w.panel === side) .filter((w) => w.panel === side)
.map((widget) => ( .map((widget) => (
<> <DraggableWidget widget={widget} key={widget.id} />
<DraggableWidget widget={widget} />
</>
))} ))}
</SortableContext> </SortableContext>
</div> </div>
@@ -265,7 +328,7 @@ const RealTimeVisualization = () => {
))} ))}
</div> </div>
<SideBar header={rightHeader} defaultActive={"Data"} /> <SideBar header={["Data", "Design"]} defaultActive={"Data"} />
</div> </div>
</DndContext> </DndContext>
); );