feat: added drag and drop in tweet list; mark tweets on error

This commit is contained in:
overflowerror 2021-08-21 16:29:05 +02:00
parent 5d3f35234d
commit 75fca7d41b
3 changed files with 90 additions and 42 deletions

View file

@ -12,12 +12,14 @@
"@types/jest": "^26.0.15",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-beautiful-dnd": "^13.1.1",
"@types/react-dom": "^17.0.0",
"@types/react-router-dom": "^5.1.8",
"axios": "^0.21.1",
"formik": "^2.2.9",
"formik-material-ui": "^3.0.1",
"react": "^17.0.2",
"react-beautiful-dnd": "^13.1.0",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",

View file

@ -18,7 +18,7 @@ const emptyThread = (): Thread => ({
status: ThreadStatus.SCHEDULED,
tweets: [
{
id: "",
id: "new",
text: "",
status: TweetStatus.SCHEDULED,
tweet_id: null,

View file

@ -1,4 +1,4 @@
import {FunctionComponent, useState} from "react";
import React, {FunctionComponent, useState} from "react";
import {
Button,
Dialog,
@ -16,6 +16,7 @@ import AddIcon from "@material-ui/icons/Add";
import {TweetStatus} from "../../api/entities/Tweet";
import CustomDate from "../../utils/CustomDate";
import {Alert} from "@material-ui/lab";
import {DragDropContext, Draggable, Droppable} from "react-beautiful-dnd";
export type ThreadFormProps = {
open: boolean
@ -34,9 +35,15 @@ const Index: FunctionComponent<ThreadFormProps> = (
onCancel
}
) => {
const [_idCounter, _setIdCounter] = useState<number>(0)
const getId = () => {
_setIdCounter(_idCounter + 1)
return _idCounter
}
const [thread, setThread] = useState<Thread>(initial)
const [error, setError] = useState<string|null>(null)
const [error, setError] = useState<string | null>(null)
return (
<Dialog open={open}>
@ -62,11 +69,39 @@ const Index: FunctionComponent<ThreadFormProps> = (
}}
/>
</Grid>
<DragDropContext onDragEnd={() => {
}}>
<Droppable droppableId={"1"}>
{(provided, snapshot) => (
<Grid
container
item
xs={12}
{...provided.droppableProps}
ref={provided.innerRef}
>
{
thread.tweets.map((tweet, index) => (
<>
<Draggable draggableId={tweet.id} index={index}>
{(provided, snapshot) => (
<Grid
container
item
xs={12}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
...provided.draggableProps.style,
background: snapshot.isDragging ? "lightgrey" : undefined
}}
>
<Grid item xs={11}>
<TextField
error={
thread.tweets[index].text.trim().length == 0 ||
thread.tweets[index].text.length > 280
}
id="outlined-multiline-static"
label={"Tweet " + (index + 1)}
multiline
@ -94,16 +129,23 @@ const Index: FunctionComponent<ThreadFormProps> = (
})
}}
>
<DeleteIcon fontSize="medium" />
<DeleteIcon fontSize="medium"/>
</IconButton>
</Grid>
</>
</Grid>
)}
</Draggable>
))
}
{provided.placeholder}
</Grid>
)}
</Droppable>
</DragDropContext>
<Grid item xs={12}>
<IconButton aria-label="add" onClick={() => {
thread.tweets.push({
id: "",
id: "new" + getId(),
text: "",
status: TweetStatus.SCHEDULED,
tweet_id: null,
@ -117,7 +159,7 @@ const Index: FunctionComponent<ThreadFormProps> = (
</IconButton>
</Grid>
</Grid>
{ error && <Alert severity="error">{error}</Alert> }
{error && <Alert severity="error">{error}</Alert>}
</DialogContent>
<DialogActions>
<Button onClick={() => {
@ -131,6 +173,10 @@ const Index: FunctionComponent<ThreadFormProps> = (
setError("Empty tweets are not allowed!")
return
}
if (!thread.tweets.every(t => t.text.length <= 280)) {
setError("Tweets can't be longer than 280 characters!")
return
}
setError(null)
onSubmit(thread)
}} color="primary">