Fix giao diện tollbar
This commit is contained in:
parent
a37e647674
commit
ae09fe1917
|
|
@ -458,7 +458,8 @@ function App() {
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
}}>
|
}}>
|
||||||
<ScrollArea
|
<ScrollArea
|
||||||
h={expandedBottomBar ? "80vh" : "85vh"}
|
// h={expandedBottomBar ? "80vh" : "85vh"}
|
||||||
|
h={expandedBottomBar ? "73vh" : "83vh"}
|
||||||
type="scroll"
|
type="scroll"
|
||||||
scrollbars="y"
|
scrollbars="y"
|
||||||
style={{ overflowX: "hidden" }}
|
style={{ overflowX: "hidden" }}
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,7 @@ const BottomToolBar = ({
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={false}
|
initial={false}
|
||||||
animate={{
|
animate={{
|
||||||
height: isExpand ? "150px" : 0,
|
height: isExpand ? "150px" : "60px",
|
||||||
y: 0,
|
y: 0,
|
||||||
}}
|
}}
|
||||||
transition={{ type: "spring", stiffness: 180, damping: 20 }}
|
transition={{ type: "spring", stiffness: 180, damping: 20 }}
|
||||||
|
|
@ -362,18 +362,19 @@ const BottomToolBar = ({
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
overflow: "hidden",
|
overflow: "visible",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box style={{ position: "relative", height: isExpand ? "150px" : "0px" }}>
|
{/* ActionIcon đặt bên ngoài Box để không bị overflow: hidden cắt */}
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: isExpand ? -4 : -24,
|
top: isExpand ? "-4px" : "-30px",
|
||||||
left: "50%",
|
left: "50%",
|
||||||
translate: "-19px 0",
|
transform: "translateX(-50%)",
|
||||||
backgroundColor: "#e3e0e0",
|
backgroundColor: "#e3e0e0",
|
||||||
width: "55px",
|
width: "55px",
|
||||||
|
height: "30px",
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
}}
|
}}
|
||||||
variant="light"
|
variant="light"
|
||||||
|
|
@ -382,14 +383,15 @@ const BottomToolBar = ({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isExpand ? (
|
{isExpand ? (
|
||||||
<IconCaretDown color="green" />
|
<IconCaretDown color="green" size={20} />
|
||||||
) : (
|
) : (
|
||||||
<IconCaretUp color="green" />
|
<IconCaretUp color="green" size={20} />
|
||||||
)}
|
)}
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
|
<Box style={{ position: "relative", height: isExpand ? "150px" : "60px", overflow: "hidden" }}>
|
||||||
<Grid style={{ height: "100%" }}>
|
<Grid style={{ height: "100%" }}>
|
||||||
<Grid.Col span={isExpand ? 1 : 3.5}></Grid.Col>
|
<Grid.Col span={isExpand ? 1 : 2}></Grid.Col>
|
||||||
<Grid.Col span={isExpand ? 10 : 5}>
|
<Grid.Col span={isExpand ? 10 : 8 }>
|
||||||
{isExpand ? (
|
{isExpand ? (
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue="command"
|
defaultValue="command"
|
||||||
|
|
@ -399,7 +401,7 @@ const BottomToolBar = ({
|
||||||
setActiveTabBottom(val || "command");
|
setActiveTabBottom(val || "command");
|
||||||
}}
|
}}
|
||||||
className={classes.containerBottom}
|
className={classes.containerBottom}
|
||||||
style={{ height: "100%" }}
|
style={{ height: "100%",backgroundColor: "white", }}
|
||||||
>
|
>
|
||||||
<Tabs.List>
|
<Tabs.List>
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
|
|
@ -443,11 +445,11 @@ const BottomToolBar = ({
|
||||||
<Tabs.Panel
|
<Tabs.Panel
|
||||||
value="command"
|
value="command"
|
||||||
p={4}
|
p={4}
|
||||||
style={{ height: "100%", overflow: "auto" }}
|
style={{ height: "200px", overflow: "auto" }}
|
||||||
>
|
>
|
||||||
<Flex justify={"space-between"} align="flex-start">
|
<Flex justify={"space-between"} align="flex-start">
|
||||||
<Box>
|
<Box>
|
||||||
<ScrollArea h={"8vh"}>
|
<ScrollArea h={"11vh"}>
|
||||||
<Flex wrap={"wrap"} gap={"8px"} w={"420px"}>
|
<Flex wrap={"wrap"} gap={"8px"} w={"420px"}>
|
||||||
{selectedLines.map((el) => (
|
{selectedLines.map((el) => (
|
||||||
<Box
|
<Box
|
||||||
|
|
@ -692,9 +694,17 @@ const BottomToolBar = ({
|
||||||
</Tabs>
|
</Tabs>
|
||||||
) : (
|
) : (
|
||||||
<Box p={3} >
|
<Box p={3} >
|
||||||
<Flex direction="column" gap="xs">
|
<Flex direction="row" align="center" gap="xs" wrap="nowrap" style={{ height: "100%" }}>
|
||||||
<Flex justify={"space-between"} align={"center"} wrap="wrap" gap="xs">
|
{/* Danh sách Line - chiếm 1 phần, cố định width và height, hiển thị 2 hàng */}
|
||||||
<Flex wrap={"wrap"} gap={"6px"} style={{ flex: 1, minWidth: 0 }}>
|
<Box
|
||||||
|
style={{
|
||||||
|
flex: "1 1 0",
|
||||||
|
width: "100%",
|
||||||
|
height: "50px",
|
||||||
|
overflow: "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex wrap={"wrap"} gap={"6px"} style={{ height: "100%" }}>
|
||||||
{selectedLines.map((el) => (
|
{selectedLines.map((el) => (
|
||||||
<Box
|
<Box
|
||||||
key={el.id}
|
key={el.id}
|
||||||
|
|
@ -705,6 +715,7 @@ const BottomToolBar = ({
|
||||||
width: "55px",
|
width: "55px",
|
||||||
backgroundColor: "#d4e3ff",
|
backgroundColor: "#d4e3ff",
|
||||||
borderRadius: "6px",
|
borderRadius: "6px",
|
||||||
|
flexShrink: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CloseButton
|
<CloseButton
|
||||||
|
|
@ -749,6 +760,7 @@ const BottomToolBar = ({
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
|
flexShrink: 0,
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
selectedLines.forEach((line) => {
|
selectedLines.forEach((line) => {
|
||||||
|
|
@ -767,11 +779,39 @@ const BottomToolBar = ({
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex align={"center"} gap="xs">
|
</Box>
|
||||||
|
|
||||||
|
{/* Selected count - ở giữa */}
|
||||||
|
<Flex align={"center"} style={{ flex: "0 0 auto", flexShrink: 0 }}>
|
||||||
<Text fz={"10px"} c="dark" fw={600}>
|
<Text fz={"10px"} c="dark" fw={600}>
|
||||||
Selected: {selectedLines.length} /{" "}
|
Selected: {selectedLines.length} /{" "}
|
||||||
{station.lines.length}
|
{station.lines.length}
|
||||||
</Text>
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
{/* Input + Select All - chiếm 1 phần */}
|
||||||
|
<Flex
|
||||||
|
direction="row"
|
||||||
|
align="center"
|
||||||
|
gap="xs"
|
||||||
|
style={{
|
||||||
|
flex: "1 1 0",
|
||||||
|
minWidth: "200px",
|
||||||
|
overflow: "hidden",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Input */}
|
||||||
|
<Box style={{ flexGrow: 1.5, flexShrink: 1, flexBasis: "auto", maxWidth: "100%", overflow: "hidden" }}>
|
||||||
|
<InputHistory
|
||||||
|
selectedLines={selectedLines}
|
||||||
|
socket={socket}
|
||||||
|
station={station}
|
||||||
|
inputStyle={{ width: "100%" }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Select All */}
|
||||||
|
<Flex align={"center"} style={{ flex: "0 0 auto", flexShrink: 0 }}>
|
||||||
<ButtonSelect
|
<ButtonSelect
|
||||||
selectedLines={selectedLines}
|
selectedLines={selectedLines}
|
||||||
setSelectedLines={setSelectedLines}
|
setSelectedLines={setSelectedLines}
|
||||||
|
|
@ -806,13 +846,6 @@ const BottomToolBar = ({
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Box style={{ width: "100%" }}>
|
|
||||||
<InputHistory
|
|
||||||
selectedLines={selectedLines}
|
|
||||||
socket={socket}
|
|
||||||
station={station}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
@ -822,6 +855,129 @@ const BottomToolBar = ({
|
||||||
</Box>
|
</Box>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
{openScenarioModal && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "fixed",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
backgroundColor: "rgba(0,0,0,0.6)",
|
||||||
|
zIndex: 99998,
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
backdropFilter: "blur(3px)",
|
||||||
|
}}
|
||||||
|
onClick={() => setOpenScenarioModal(false)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: "white",
|
||||||
|
borderRadius: "12px",
|
||||||
|
maxWidth: "90vw",
|
||||||
|
width: "90%",
|
||||||
|
height: "85vh",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
boxShadow: "0 20px 60px rgba(0,0,0,0.3)",
|
||||||
|
overflowY: "auto",
|
||||||
|
overflowX: "visible",
|
||||||
|
}}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{/* Header */}
|
||||||
|
<Flex
|
||||||
|
justify="space-between"
|
||||||
|
align="center"
|
||||||
|
p="lg"
|
||||||
|
style={{
|
||||||
|
borderBottom: "1px solid #e9ecef",
|
||||||
|
flexShrink: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text fw={700} size="xl">
|
||||||
|
🎯 Select Scenario to Run
|
||||||
|
</Text>
|
||||||
|
<Flex gap="md" align="center">
|
||||||
|
<Button
|
||||||
|
leftSection={<IconPlus size={16} />}
|
||||||
|
variant="light"
|
||||||
|
color="green"
|
||||||
|
size="sm"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setOpenDrawerScenario(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add/Edit Scenario
|
||||||
|
</Button>
|
||||||
|
<CloseButton
|
||||||
|
size="lg"
|
||||||
|
onClick={() => setOpenScenarioModal(false)}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: "20px",
|
||||||
|
overflowY: "auto",
|
||||||
|
overflowX: "visible",
|
||||||
|
flex: 1,
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
|
className={classes.hideScrollBar}
|
||||||
|
>
|
||||||
|
{scenarios.length > 0 ? (
|
||||||
|
<Grid
|
||||||
|
gutter="md"
|
||||||
|
style={{
|
||||||
|
margin: 0,
|
||||||
|
overflow: "visible",
|
||||||
|
position: "relative",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{scenarios.map((scenario, index) => (
|
||||||
|
<ScenarioCard
|
||||||
|
key={scenario.id}
|
||||||
|
scenario={scenario}
|
||||||
|
index={index}
|
||||||
|
isDisable={isDisable}
|
||||||
|
selectedLines={selectedLines}
|
||||||
|
user={user}
|
||||||
|
socket={socket}
|
||||||
|
setOpenScenarioModal={setOpenScenarioModal}
|
||||||
|
setIsDisable={setIsDisable}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
) : (
|
||||||
|
<Flex
|
||||||
|
direction="column"
|
||||||
|
align="center"
|
||||||
|
justify="center"
|
||||||
|
style={{ minHeight: "300px" }}
|
||||||
|
gap="md"
|
||||||
|
>
|
||||||
|
<Text size="xl" c="dimmed">
|
||||||
|
📋
|
||||||
|
</Text>
|
||||||
|
<Text ta="center" c="dimmed" size="lg">
|
||||||
|
No scenarios available
|
||||||
|
</Text>
|
||||||
|
<Text ta="center" c="dimmed" size="sm">
|
||||||
|
Please create a new scenario to get started
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Drawer Scenario để Add/Edit */}
|
{/* Drawer Scenario để Add/Edit */}
|
||||||
<DrawerScenario
|
<DrawerScenario
|
||||||
scenarios={scenarios}
|
scenarios={scenarios}
|
||||||
|
|
|
||||||
|
|
@ -1164,7 +1164,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Grid.Col span={12} pt={"4px"}>
|
<Grid.Col span={12} pt={"0px"}>
|
||||||
{listPorts?.length > 0 && (
|
{listPorts?.length > 0 && (
|
||||||
<Box>
|
<Box>
|
||||||
<Flex gap={"8px"} wrap={"wrap"}>
|
<Flex gap={"8px"} wrap={"wrap"}>
|
||||||
|
|
@ -1217,6 +1217,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
style={{
|
style={{
|
||||||
flex: "0 0 auto",
|
flex: "0 0 auto",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
|
justifyContent: "center",
|
||||||
width: "34px",
|
width: "34px",
|
||||||
height: "28px",
|
height: "28px",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
|
|
@ -1248,7 +1249,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
flexWrap: "wrap",
|
flexWrap: "wrap",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text fw={500} fz={"9px"}>
|
<Text fw={600} fz={"10px"}>
|
||||||
{normalizePortName(port.name)}
|
{normalizePortName(port.name)}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -1288,8 +1289,9 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
style={{
|
style={{
|
||||||
flex: "0 0 auto",
|
flex: "0 0 auto",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
width: "40px",
|
justifyContent: "center",
|
||||||
height: "32px",
|
width: "34px",
|
||||||
|
height: "28px",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
port.poe === "ON"
|
port.poe === "ON"
|
||||||
? "#f2dcf8"
|
? "#f2dcf8"
|
||||||
|
|
@ -1319,7 +1321,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
flexWrap: "wrap",
|
flexWrap: "wrap",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text fw={500} fz={"11px"}>
|
<Text fw={600} fz={"10px"}>
|
||||||
{normalizePortName(port.name)}
|
{normalizePortName(port.name)}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -1359,11 +1361,11 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
<Box
|
<Box
|
||||||
style={{
|
style={{
|
||||||
width: "fit-content",
|
width: "fit-content",
|
||||||
minWidth: "40px",
|
minWidth: "32px",
|
||||||
minHeight: "56px",
|
minHeight: "56px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex gap={"6px"} wrap={"nowrap"}>
|
<Flex gap={"4px"} wrap={"nowrap"}>
|
||||||
{sortedPorts(group)
|
{sortedPorts(group)
|
||||||
.slice(
|
.slice(
|
||||||
0,
|
0,
|
||||||
|
|
@ -1382,8 +1384,9 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
style={{
|
style={{
|
||||||
flex: "0 0 auto",
|
flex: "0 0 auto",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
width: "40px",
|
justifyContent: "center",
|
||||||
height: "32px",
|
width: "34px",
|
||||||
|
height: "28px",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
port.poe === "ON"
|
port.poe === "ON"
|
||||||
? "#f2dcf8"
|
? "#f2dcf8"
|
||||||
|
|
@ -1413,7 +1416,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
flexWrap: "wrap",
|
flexWrap: "wrap",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text fw={500} fz={"10px"}>
|
<Text fw={600} fz={"10px"}>
|
||||||
{normalizePortName(port.name)}
|
{normalizePortName(port.name)}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -1434,7 +1437,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex gap={"6px"} wrap={"nowrap"} mt={"6px"}>
|
<Flex gap={"4px"} wrap={"nowrap"} mt={"4px"}>
|
||||||
{sortedPorts(group)
|
{sortedPorts(group)
|
||||||
.slice(
|
.slice(
|
||||||
Math.ceil(sortedPorts(group).length / 2),
|
Math.ceil(sortedPorts(group).length / 2),
|
||||||
|
|
@ -1453,8 +1456,9 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
style={{
|
style={{
|
||||||
flex: "0 0 auto",
|
flex: "0 0 auto",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
width: "50px",
|
justifyContent: "center",
|
||||||
height: "40px",
|
width: "34px",
|
||||||
|
height: "28px",
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
port.poe === "ON"
|
port.poe === "ON"
|
||||||
? "#f2dcf8"
|
? "#f2dcf8"
|
||||||
|
|
@ -1484,7 +1488,7 @@ export const DrawerSwitchControl: React.FC<DrawerProps> = ({
|
||||||
flexWrap: "wrap",
|
flexWrap: "wrap",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text fw={500} fz={"11px"}>
|
<Text fw={600} fz={"10px"}>
|
||||||
{normalizePortName(port.name)}
|
{normalizePortName(port.name)}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,12 @@ export default function InputHistory({
|
||||||
selectedLines,
|
selectedLines,
|
||||||
socket,
|
socket,
|
||||||
station,
|
station,
|
||||||
|
inputStyle,
|
||||||
}: {
|
}: {
|
||||||
selectedLines: TLine[];
|
selectedLines: TLine[];
|
||||||
socket: Socket | null;
|
socket: Socket | null;
|
||||||
station: TStation;
|
station: TStation;
|
||||||
|
inputStyle?: React.CSSProperties;
|
||||||
}) {
|
}) {
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
const [history, setHistory] = useState<string[]>([]);
|
const [history, setHistory] = useState<string[]>([]);
|
||||||
|
|
@ -115,6 +117,7 @@ export default function InputHistory({
|
||||||
style={{
|
style={{
|
||||||
width: "30vw",
|
width: "30vw",
|
||||||
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
|
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.1)",
|
||||||
|
...inputStyle,
|
||||||
}}
|
}}
|
||||||
placeholder={"Send command to port(s)"}
|
placeholder={"Send command to port(s)"}
|
||||||
value={value}
|
value={value}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue