From da473482736a173fcfb196ac28de57596f7aaa61 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 27 Oct 2021 23:25:08 +0100 Subject: [PATCH] feat(categories): basic dnd kanban board --- package.json | 1 + src/pages/settings/server/Categories.tsx | 227 +++++++++++++++++++++-- yarn.lock | 7 + 3 files changed, 217 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 94ac4338..21f3b6a7 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "@types/node": "^15.12.4", "@types/preact-i18n": "^2.3.0", "@types/prismjs": "^1.16.5", + "@types/react-beautiful-dnd": "^13.1.2", "@types/react-helmet": "^6.1.1", "@types/react-router-dom": "^5.1.7", "@types/react-scroll": "^1.8.2", diff --git a/src/pages/settings/server/Categories.tsx b/src/pages/settings/server/Categories.tsx index b8ed1482..38cdbee9 100644 --- a/src/pages/settings/server/Categories.tsx +++ b/src/pages/settings/server/Categories.tsx @@ -1,5 +1,6 @@ import isEqual from "lodash.isequal"; import { observer } from "mobx-react-lite"; +import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd"; import { Category } from "revolt-api/types/Servers"; import { Server } from "revolt.js/dist/maps/Servers"; import styled from "styled-components"; @@ -28,10 +29,25 @@ const KanbanEntry = styled.div` align-items: center; justify-content: center; + gap: 4px; margin: 4px; height: 40px; + padding: 8px; flex-shrink: 0; + font-size: 0.9em; background: var(--primary-background); + + img { + flex-shrink: 0; + } + + span { + min-width: 0; + + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } `; const KanbanList = styled.div` @@ -42,15 +58,33 @@ const KanbanList = styled.div` overflow-y: auto; flex-direction: column; background: var(--secondary-background); + + > [data-rbd-droppable-id] { + min-height: 24px; + } +`; + +const KanbanListTitle = styled.div` + height: 42px; + display: grid; + place-items: center; `; const KanbanBoard = styled.div` gap: 8px; display: flex; - overflow-x: scroll; flex-direction: row; `; +const FullSize = styled.div` + flex-grow: 1; + + > * { + height: 100%; + overflow-x: scroll; + } +`; + interface Props { server: Server; } @@ -61,24 +95,181 @@ export const Categories = observer(({ server }: Props) => { ); return ( - - {categories.map((category, i) => ( - -

{category.title}

- {category.channels.map((x) => { - const channel = server.client.channels.get(x); - if (!channel) return null; + { + const { destination, source, draggableId, type } = target; - return ( - - {" "} - {channel.name} - - ); - })} -
- ))} -
+ if ( + !destination || + (destination.droppableId === source.droppableId && + destination.index === source.index) + ) { + return; + } + + if (type === "column") { + // Remove from array. + const cat = categories.find((x) => x.id === draggableId); + const arr = categories.filter((x) => x.id !== draggableId); + + // Insert at new position. + arr.splice(destination.index, 0, cat!); + setCategories(arr); + } else { + setCategories( + categories.map((category) => { + if (category.id === destination.droppableId) { + const channels = category.channels.filter( + (x) => x !== draggableId, + ); + + channels.splice( + destination.index, + 0, + draggableId, + ); + + return { + ...category, + channels, + }; + } else if (category.id === source.droppableId) { + return { + ...category, + channels: category.channels.filter( + (x) => x !== draggableId, + ), + }; + } + + return category; + }), + ); + } + }}> + + + {(provided) => + ( +
+ + {categories.map((category, index) => ( + + {(provided) => + ( +
+ + + + { + category.title + } + + + + {(provided) => + ( +
+ {category.channels.map( + ( + x, + index, + ) => { + const channel = + server.client.channels.get( + x, + ); + if ( + !channel + ) + return null; + + return ( + + {( + provided, + ) => + ( +
+ + + + { + channel.name + } + + +
+ ) as any + } +
+ ); + }, + )} + { + provided.placeholder + } +
+ ) as any + } +
+
+
+ ) as any + } +
+ ))} + {provided.placeholder} +
+
+ ) as any + } +
+
+ ); }); diff --git a/yarn.lock b/yarn.lock index 1965b5bf..725fac8c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1398,6 +1398,13 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== +"@types/react-beautiful-dnd@^13.1.2": + version "13.1.2" + resolved "https://registry.yarnpkg.com/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.2.tgz#510405abb09f493afdfd898bf83995dc6385c130" + integrity sha512-+OvPkB8CdE/bGdXKyIhc/Lm2U7UAYCCJgsqmopFmh9gbAudmslkI8eOrPDjg4JhwSE6wytz4a3/wRjKtovHVJg== + dependencies: + "@types/react" "*" + "@types/react-helmet@^6.1.1": version "6.1.2" resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-6.1.2.tgz#e9d7d16b29e4ec5716711c52c35c3cec45819eac"