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;
background-color: rgb(235, 235, 235);
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
@@ -388,6 +416,10 @@
flex-direction: column;
gap: 5px;
align-items: center;
.active {
// background-color: red;
}
}
.icon {
@@ -426,6 +458,7 @@
.extra-buttons {
display: flex;
flex-direction: row;
}
}

View File

@@ -1,59 +1,47 @@
import React, { useState, useEffect, useRef } from 'react';
import { DropDownIcon } from '../../../assets/images/svgExports';
import React, { useState, useEffect } from "react";
interface DropdownProps {
header: 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 [selectedOption, setSelectedOption] = useState<string | null>(null);
// Reference to the dropdown container
const dropdownRef = useRef<HTMLDivElement | null>(null);
// Reset selectedOption when the dropdown closes
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 = () => {
setIsOpen(prev => !prev);
setIsOpen((prev) => !prev);
};
// Handle option selection
const handleOptionClick = (option: string) => {
setSelectedOption(option);
onSelect(option); // Call the onSelect function passed from the parent
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 (
<div className="regularDropdown-container" ref={dropdownRef}>
<div className="regularDropdown-container">
{/* Dropdown Header */}
<div className="dropdown-header flex-sb" onClick={toggleDropdown}>
<div className="key">{selectedOption || header}</div>
<div className="icon">
<DropDownIcon />
</div>
<div className="icon"></div>
</div>
{/* Dropdown Options */}
@@ -63,7 +51,7 @@ const RegularDropDown: React.FC<DropdownProps> = ({ header, options, onSelect })
<div
className="option"
key={index}
onClick={() => handleOptionClick(option)} // Handle option click
onClick={() => handleOptionClick(option)}
>
{option}
</div>

View File

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

View File

@@ -49,17 +49,11 @@ const DraggableWidget = ({ widget }: { widget: any }) => {
};
const handlePointerDown = () => {
// Set selected chart when pointer down event occurs (i.e., when it's clicked, not dragged)
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 (
<div
key={widget.id}
@@ -68,7 +62,7 @@ const DraggableWidget = ({ widget }: { widget: any }) => {
{...attributes}
{...listeners}
style={style}
onPointerDown={handlePointerDown} // Use onPointerDown instead of onPointerUp
onPointerDown={handlePointerDown}
>
<ChartComponent
type={widget.type}
@@ -82,19 +76,28 @@ const DraggableWidget = ({ widget }: { widget: any }) => {
};
const RealTimeVisualization = () => {
const [zone, setZone] = useState([
"Manufacturing unit",
"Assembly unit",
"Packing unit",
"Warehouse",
"Inventory",
]);
const [activeSides, setActiveSides] = useState<Side[]>([]);
const [panelOrder, setPanelOrder] = useState<Side[]>([]);
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();
// Sensors for drag-and-drop (Pointer and Keyboard)
const sensors = useSensors(
useSensor(PointerSensor),
useSensor(KeyboardSensor)
);
useEffect(() => {}, [widgets]);
const toggleSide = (side: Side) => {
setActiveSides((prev) => {
const newActive = prev.includes(side)
@@ -102,17 +105,24 @@ const RealTimeVisualization = () => {
: [...prev, side];
setPanelOrder(newActive);
// Reset selectedSide if the panel is being closed
if (prev.includes(side)) {
setSelectedSide(null); // Hide extra buttons when the panel is closed
setSelectedSide(null);
} else {
setSelectedSide(side); // Show extra buttons when the panel is opened
setSelectedSide(side);
}
return newActive;
});
};
const toggleLockPanel = (side: Side) => {
setLockedPanels((prev) =>
prev.includes(side)
? prev.filter((panel) => panel !== side)
: [...prev, side]
);
};
const getPanelStyle = (currentSide: Side) => {
const currentIndex = panelOrder.indexOf(currentSide);
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 { active, over } = event;
@@ -171,14 +178,11 @@ const RealTimeVisualization = () => {
const newPanel =
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) {
// Reorder within the same panel
const newIndex = widgets.findIndex((widget) => widget.id === over.id);
const reorderedWidgets = arrayMove(widgets, oldIndex, newIndex);
setWidgets(reorderedWidgets);
} else {
// Move to a different panel
const updatedWidgets = widgets.map((widget) =>
widget.id === active.id ? { ...widget, panel: newPanel } : widget
);
@@ -200,12 +204,19 @@ const RealTimeVisualization = () => {
onDragEnd={handleDragEnd}
>
<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="zoon-wrapper">
{zone.map((zone, index) => (
<div className="zone">{zone}</div>
))}
</div>
{(["top", "right", "bottom", "left"] as Side[]).map((side) => (
<div key={side} className={`side-button-container ${side}`}>
{/* Side Button */}
<button
className={`side-button ${side}`}
onClick={() => toggleSide(side)}
@@ -214,23 +225,71 @@ const RealTimeVisualization = () => {
+
</button>
{/* Extra Buttons */}
<div
className="extra-buttons"
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 />
</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 />
</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 />
</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 />
</div>
</div>
@@ -245,7 +304,13 @@ const RealTimeVisualization = () => {
onDrop={(e) => handleDrop(e, side)}
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
items={widgets
.filter((w) => w.panel === side)
@@ -255,9 +320,7 @@ const RealTimeVisualization = () => {
{widgets
.filter((w) => w.panel === side)
.map((widget) => (
<>
<DraggableWidget widget={widget} />
</>
<DraggableWidget widget={widget} key={widget.id} />
))}
</SortableContext>
</div>
@@ -265,7 +328,7 @@ const RealTimeVisualization = () => {
))}
</div>
<SideBar header={rightHeader} defaultActive={"Data"} />
<SideBar header={["Data", "Design"]} defaultActive={"Data"} />
</div>
</DndContext>
);