implement reorder/moving of sections between blocks

This commit is contained in:
Amruth Pillai
2020-07-05 13:34:04 +05:30
parent 202c7f5ad4
commit 03e1de1d14
8 changed files with 240 additions and 5 deletions

View File

@ -1,8 +1,23 @@
import React from "react";
import React, { useContext } from "react";
import TemplateContext from "../../../contexts/TemplateContext";
import styles from "./Artboard.module.css";
const Artboard = () => {
return <div className={styles.container}></div>;
const { blocks } = useContext(TemplateContext);
return (
<div className={styles.container}>
<div className={`grid gap-8 grid-cols-${blocks.length}`}>
{blocks.map((block, ind) => (
<div key={ind} className="col-span-1">
{block.map((x) => (
<div key={x.id}>{x.name}</div>
))}
</div>
))}
</div>
</div>
);
};
export default Artboard;

View File

@ -1,5 +1,5 @@
import React from "react";
import Profile from "../sections/Profile";
import Layout from "../sections/Layout";
import RightNavbar from "./RightNavbar";
import styles from "./RightSidebar.module.css";
@ -7,7 +7,7 @@ const RightSidebar = () => {
return (
<div className="flex">
<div className={styles.container}>
<Profile />
<Layout />
</div>
<RightNavbar />

View File

@ -0,0 +1,63 @@
import cx from "classnames";
import React, { useContext } from "react";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
import TemplateContext from "../../../contexts/TemplateContext";
import Heading from "../../shared/Heading";
import styles from "./Layout.module.css";
const Layout = () => {
const { blocks, onDragEnd } = useContext(TemplateContext);
return (
<section>
<Heading>Layout</Heading>
<p>
This template supports {blocks.length} blocks. You can re-order or move
sections by dragging/dropping the section names across lists.
</p>
<div className={`grid gap-8 grid-cols-${blocks.length}`}>
<DragDropContext onDragEnd={onDragEnd}>
{blocks.map((el, ind) => (
<Droppable key={ind} droppableId={`${ind}`}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
className={cx(styles.droppable, {
[styles.draggingOver]: snapshot.isDraggingOver,
})}
{...provided.droppableProps}
>
<div className="grid gap-3">
{el.map((item, index) => (
<Draggable
key={item.id}
draggableId={item.id}
index={index}
>
{(provided) => (
<div
ref={provided.innerRef}
className={styles.draggable}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
{item.name}
</div>
)}
</Draggable>
))}
</div>
{provided.placeholder}
</div>
)}
</Droppable>
))}
</DragDropContext>
</div>
</section>
);
};
export default Layout;

View File

@ -0,0 +1,11 @@
.droppable {
@apply px-4 py-6 bg-gray-100 col-span-1 rounded;
}
.droppable.dragging-over {
@apply bg-gray-200;
}
.draggable {
@apply px-4 py-2 font-medium rounded bg-gray-300;
}

View File

@ -0,0 +1,88 @@
import React, { createContext, useState } from "react";
const defaultState = {
selected: "Pikachu",
setSelected: () => {},
blocks: [
[
{ id: "1", name: "Profile" },
{ id: "2", name: "Work" },
],
[
{ id: "3", name: "Education" },
{ id: "4", name: "Skills" },
{ id: "5", name: "Hobbies" },
],
],
setBlocks: () => {},
};
const TemplateContext = createContext(defaultState);
const TemplateProvider = ({ children }) => {
const [selected, setSelected] = useState(defaultState.selected);
const [blocks, setBlocks] = useState(defaultState.blocks);
const reorder = (list, startIndex, endIndex) => {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
};
const move = (source, destination, droppableSource, droppableDestination) => {
const sourceClone = Array.from(source);
const destClone = Array.from(destination);
const [removed] = sourceClone.splice(droppableSource.index, 1);
destClone.splice(droppableDestination.index, 0, removed);
const result = {};
result[droppableSource.droppableId] = sourceClone;
result[droppableDestination.droppableId] = destClone;
return result;
};
const onDragEnd = (result) => {
const { source, destination } = result;
if (!destination) {
return;
}
const sInd = +source.droppableId;
const dInd = +destination.droppableId;
if (sInd === dInd) {
const items = reorder(blocks[sInd], source.index, destination.index);
const newState = [...blocks];
newState[sInd] = items;
setBlocks(newState);
} else {
const result = move(blocks[sInd], blocks[dInd], source, destination);
const newState = [...blocks];
newState[sInd] = result[sInd];
newState[dInd] = result[dInd];
setBlocks(newState);
}
};
return (
<TemplateContext.Provider
value={{
selected,
setSelected,
blocks,
setBlocks,
onDragEnd,
}}
>
{children}
</TemplateContext.Provider>
);
};
export default TemplateContext;
export { TemplateProvider };