- Created Card type
- Implemented drag and drop for the server list section
This commit is contained in:
1 parent
03ce805e9f
commit
b1f056809f
4 files changed
+137
-26
No files matched your search
@@ -0,0 +1,4 @@
|
||||
export default {
|
||||
CARD: 'card',
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import TextInput from "../../../Inputs/TextInput";
|
||||
import { ServerStartAdornment, ServerEndAdornment } from "../../../Inputs/TextInput/Adornments";
|
||||
import TextInput from "../../../../Inputs/TextInput";
|
||||
import { ServerStartAdornment, ServerEndAdornment } from "../../../../Inputs/TextInput/Adornments";
|
||||
|
||||
|
||||
const Server = ({ id, removeItem, value }) => {
|
||||
@@ -0,0 +1,90 @@
|
||||
import React, { useRef } from "react";
|
||||
import { useDrag, useDrop } from "react-dnd";
|
||||
import ItemTypes from "./ItemTypes";
|
||||
import Card from "@mui/material/Card";
|
||||
import CardActionArea from "@mui/material/CardActionArea";
|
||||
import CardContent from "@mui/material/CardContent";
|
||||
import Server from "./Server"
|
||||
|
||||
const CustomCard = React.forwardRef((props, ref) => (
|
||||
<Card ref={ref}>
|
||||
<CardActionArea>
|
||||
<CardContent>
|
||||
<Server
|
||||
id={props.id}
|
||||
removeItem={props.removeCard}
|
||||
value={props.value}
|
||||
/>
|
||||
</CardContent>
|
||||
</CardActionArea>
|
||||
</Card>
|
||||
));
|
||||
|
||||
const MyCard = ({ id, index, moveCard, removeCard, value }) => {
|
||||
const ref = useRef(null);
|
||||
const [, drop] = useDrop({
|
||||
accept: ItemTypes.CARD,
|
||||
hover(item, monitor) {
|
||||
if (!ref.current) {
|
||||
return;
|
||||
}
|
||||
const dragIndex = item.index;
|
||||
const hoverIndex = index;
|
||||
|
||||
// Don't replace items with themselves
|
||||
if (dragIndex === hoverIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine rectangle on screen
|
||||
const hoverBoundingRect = ref.current.getBoundingClientRect();
|
||||
// Get vertical middle
|
||||
const hoverMiddleY =
|
||||
(hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
|
||||
// Determine mouse position
|
||||
const clientOffset = monitor.getClientOffset();
|
||||
// Get pixels to the top
|
||||
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
|
||||
// Only perform the move when the mouse has crossed half of the items height
|
||||
// When dragging downwards, only move when the cursor is below 50%
|
||||
// When dragging upwards, only move when the cursor is above 50%
|
||||
// Dragging downwards
|
||||
|
||||
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
|
||||
return;
|
||||
}
|
||||
// Dragging upwards
|
||||
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Time to actually perform the action
|
||||
moveCard(dragIndex, hoverIndex);
|
||||
// Note: we're mutating the monitor item here!
|
||||
// Generally it's better to avoid mutations,
|
||||
// but it's good here for the sake of performance
|
||||
// to avoid expensive index searches.
|
||||
item.index = hoverIndex;
|
||||
}
|
||||
});
|
||||
const [ {isDragging}, drag] = useDrag({
|
||||
type: ItemTypes.CARD,
|
||||
item: {id: id, index:index},
|
||||
collect: monitor => ({
|
||||
isDragging: monitor.isDragging()
|
||||
})
|
||||
});
|
||||
drag(drop(ref));
|
||||
return (
|
||||
<CustomCard
|
||||
ref={ref}
|
||||
id={id}
|
||||
removeCard={removeCard}
|
||||
value={value}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default MyCard;
|
||||
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useCallback } from "react";
|
||||
import { Button, Box, Stack, Typography } from "@mui/material";
|
||||
import { ConfigBox } from "../../../Pages/Settings/styled";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import TabPanel from "@mui/lab/TabPanel";
|
||||
import {
|
||||
publicPageGeneralSettingsValidation,
|
||||
} from "../../../Validation/validation";
|
||||
import { publicPageGeneralSettingsValidation } from "../../../Validation/validation";
|
||||
import { buildErrors } from "../../../Validation/error";
|
||||
import { hasValidationErrors } from "../../../Validation/error";
|
||||
import Server from "./Server"
|
||||
import Card from "./Card";
|
||||
import update from "immutability-helper";
|
||||
|
||||
const ContentPanel = () => {
|
||||
const theme = useTheme();
|
||||
const [errors, setErrors] = useState({});
|
||||
// Local state for form data, errors, and file handling
|
||||
const [localData, setLocalData] = useState({
|
||||
monitors: []
|
||||
monitors: [],
|
||||
});
|
||||
|
||||
const [cards, setCards] = useState(localData.monitors);
|
||||
|
||||
// Clears specific error from errors state
|
||||
const clearError = (err) => {
|
||||
setErrors((prev) => {
|
||||
@@ -25,6 +28,21 @@ const ContentPanel = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const moveCard = useCallback(
|
||||
(dragIndex, hoverIndex) => {
|
||||
const dragCard = cards[dragIndex];
|
||||
setCards(
|
||||
update(cards, {
|
||||
$splice: [
|
||||
[dragIndex, 1],
|
||||
[hoverIndex, 0, dragCard],
|
||||
],
|
||||
})
|
||||
);
|
||||
},
|
||||
[cards]
|
||||
);
|
||||
|
||||
const handleChange = (event) => {
|
||||
event.preventDefault();
|
||||
const { value, id } = event.target;
|
||||
@@ -41,16 +59,11 @@ const ContentPanel = () => {
|
||||
};
|
||||
|
||||
const handleAddNew = () => {
|
||||
let arr = localData.monitors;
|
||||
arr.push({ id: "" + Math.random() });
|
||||
setLocalData({ ...localData, monitors: arr });
|
||||
}
|
||||
|
||||
const removeItem = (id) =>{
|
||||
const currentMonitors = localData.monitors.filter(m => m.id !=id)
|
||||
setLocalData({...localData, monitors: currentMonitors})
|
||||
}
|
||||
|
||||
setCards([...cards, { id: "" + Math.random() }]);
|
||||
};
|
||||
const removeCard = (id) => {
|
||||
setCards(cards.filter((c) => c?.id != id));
|
||||
};
|
||||
const handleBlur = (event) => {
|
||||
event.preventDefault();
|
||||
const { value, id } = event.target;
|
||||
@@ -122,22 +135,26 @@ const ContentPanel = () => {
|
||||
</Typography>
|
||||
<Button onClick={handleAddNew}>Add New</Button>
|
||||
</Stack>
|
||||
{localData.monitors.length > 0 && (
|
||||
{cards.length > 0 && (
|
||||
<Stack
|
||||
direction="column"
|
||||
alignItems="center"
|
||||
gap={theme.spacing(6)}
|
||||
sx={{ml: theme.spacing(4),
|
||||
sx={{
|
||||
ml: theme.spacing(4),
|
||||
mr: theme.spacing(8),
|
||||
mb: theme.spacing(8)
|
||||
mb: theme.spacing(8),
|
||||
}}
|
||||
>
|
||||
{localData.monitors.map((m, idx) => (
|
||||
<Server
|
||||
{cards.map((card, idx) => (
|
||||
<Card
|
||||
key={idx}
|
||||
id={m.id ?? "" + Math.random()}
|
||||
removeItem={removeItem}
|
||||
value={m.url}
|
||||
index={idx}
|
||||
id={card?.id ?? "" + Math.random()}
|
||||
text={"" + idx}
|
||||
moveCard={moveCard}
|
||||
removeCard={removeCard}
|
||||
value={card?.url ?? card?.id}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
|
||||
Reference in new issue
Block a user