Skip to content

Commit daa9567

Browse files
Merge pull request #495 from NEU-DSG/dw-reorder-word-parts
draggable word parts
2 parents f5c4c26 + 3427766 commit daa9567

3 files changed

Lines changed: 213 additions & 57 deletions

File tree

website/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"@reach/dialog": "^0.16.2",
2525
"@reach/tooltip": "^0.16.2",
2626
"@react-hook/debounce": "^4.0.0",
27+
"@types/react-beautiful-dnd": "^13.1.8",
2728
"@urql/core": "^4.1.1",
2829
"@urql/devtools": "^2.0.3",
2930
"@urql/exchange-auth": "^1",
@@ -44,6 +45,7 @@
4445
"pure-react-carousel": "^1.30.1",
4546
"query-string": "^7.1.1",
4647
"react": "17",
48+
"react-beautiful-dnd": "^13.1.1",
4749
"react-date-picker": "^10.5.0",
4850
"react-device-detect": "^2.2.2",
4951
"react-dom": "17",

website/src/word-panel.tsx

Lines changed: 117 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
import { groupBy } from "lodash"
22
import React, { ReactNode, useState } from "react"
3+
import {
4+
DragDropContext,
5+
Draggable,
6+
DropResult,
7+
Droppable,
8+
} from "react-beautiful-dnd"
39
import {
410
AiFillCaretDown,
511
AiFillCaretUp,
612
AiFillSound,
713
} from "react-icons/ai/index"
814
import { IoBookmarks, IoEllipsisHorizontalCircle } from "react-icons/io5/index"
915
import {
16+
MdDragIndicator,
1017
MdNotes,
1118
MdOutlineComment,
1219
MdRecordVoiceOver,
@@ -229,6 +236,22 @@ const EditSegmentation = (p: {
229236
const currentWord = form.values.word as Dailp.FormFieldsFragment
230237
const currentSegments = currentWord.segments
231238

239+
const onDragEnd = (result: DropResult) => {
240+
// dropped outside the list
241+
if (!result.destination) {
242+
return
243+
}
244+
245+
const items = Array.from(currentSegments)
246+
const [reorderedItem] = items.splice(result.source.index, 1)
247+
items.splice(result.destination.index, 0, reorderedItem!)
248+
249+
form.update("word", {
250+
...currentWord,
251+
segments: items,
252+
})
253+
}
254+
232255
const addNewSegment = (e: React.MouseEvent) => {
233256
e.preventDefault()
234257
const newSegment = {
@@ -257,62 +280,100 @@ const EditSegmentation = (p: {
257280
}
258281

259282
return (
260-
<table className={css.tableContainer}>
261-
<tbody>
262-
{currentSegments.map((segment, index) => (
263-
<tr key={index} style={{ display: "flex" }}>
264-
<td className={css.editMorphemeCells}>
265-
<FormInput
266-
{...form}
267-
className={formInput}
268-
name={["word", "segments", index.toString(), "morpheme"]}
269-
/>
270-
</td>
271-
<td className={css.editGlossCells}>
272-
{/* Displays global glosses and allows user to create custom glosses on keyboard input. */}
273-
<EditWordPartGloss
274-
// TODO: this key will need to be changed later since a morpheme can be changed
275-
key={segment.morpheme}
276-
morpheme={segment}
277-
index={index}
278-
options={p.options}
279-
/>
280-
</td>
281-
<td style={{ padding: "0 10px" }}>
282-
<button
283-
onClick={() => deleteSegment(index)}
284-
style={{
285-
padding: "5px 10px",
286-
borderRadius: "4px",
287-
border: "1px solid #ccc",
288-
background: "#f0f0f0",
289-
cursor: "pointer",
290-
color: "#d32f2f",
291-
}}
292-
>
293-
294-
</button>
295-
</td>
296-
</tr>
297-
))}
298-
<tr>
299-
<td colSpan={3} style={{ textAlign: "center", padding: "10px" }}>
300-
<button
301-
onClick={addNewSegment}
302-
style={{
303-
padding: "5px 10px",
304-
borderRadius: "4px",
305-
border: "1px solid #ccc",
306-
background: "#f0f0f0",
307-
cursor: "pointer",
308-
}}
309-
>
310-
Add Segment
311-
</button>
312-
</td>
313-
</tr>
314-
</tbody>
315-
</table>
283+
<DragDropContext onDragEnd={onDragEnd}>
284+
<Droppable droppableId="droppable">
285+
{(provided, snapshot) => (
286+
<table
287+
{...provided.droppableProps}
288+
ref={provided.innerRef}
289+
className={css.tableContainer}
290+
>
291+
<tbody>
292+
{currentSegments.map((segment, index) => (
293+
<Draggable
294+
key={index}
295+
draggableId={index.toString()}
296+
index={index}
297+
>
298+
{(provided, snapshot) => (
299+
<tr
300+
ref={provided.innerRef}
301+
{...provided.draggableProps}
302+
{...provided.dragHandleProps}
303+
key={index}
304+
style={{
305+
display: "flex",
306+
...provided.draggableProps.style,
307+
}}
308+
>
309+
<MdDragIndicator fontSize={"1.5rem"} />
310+
<td className={css.editMorphemeCells}>
311+
{/* This is disabled at the moment to be fully implemented later. */}
312+
<FormInput
313+
{...form}
314+
className={formInput}
315+
name={[
316+
"word",
317+
"segments",
318+
index.toString(),
319+
"morpheme",
320+
]}
321+
/>
322+
</td>
323+
<td className={css.editGlossCells}>
324+
{/* Displays global glosses and allows user to create custom glosses on keyboard input. */}
325+
<EditWordPartGloss
326+
// TODO: this key will need to be changed later since a morpheme can be changed
327+
key={segment.morpheme}
328+
morpheme={segment}
329+
index={index}
330+
options={p.options}
331+
/>
332+
</td>
333+
<td style={{ padding: "0 10px" }}>
334+
<button
335+
onClick={() => deleteSegment(index)}
336+
style={{
337+
padding: "5px 10px",
338+
borderRadius: "4px",
339+
border: "1px solid #ccc",
340+
background: "#f0f0f0",
341+
cursor: "pointer",
342+
color: "#d32f2f",
343+
}}
344+
>
345+
346+
</button>
347+
</td>
348+
</tr>
349+
)}
350+
</Draggable>
351+
))}
352+
{provided.placeholder}
353+
<tr>
354+
<td
355+
colSpan={3}
356+
style={{ textAlign: "center", padding: "10px" }}
357+
>
358+
<button
359+
onClick={addNewSegment}
360+
style={{
361+
padding: "5px 10px",
362+
borderRadius: "4px",
363+
border: "1px solid #ccc",
364+
background: "#f0f0f0",
365+
cursor: "pointer",
366+
}}
367+
>
368+
Add Segment
369+
</button>
370+
</td>
371+
</tr>
372+
</tbody>
373+
</table>
374+
)}
375+
</Droppable>
376+
</DragDropContext>
316377
)
317378
}
318379

0 commit comments

Comments
 (0)