issue-159 Add delete button to part profile (for part owner)
schema had to be update to add a deleted boolean to part. Easier than setting up cascading deletes for comments and reactions. resolves #159
This commit is contained in:
@@ -8,18 +8,23 @@ const Button = ({
|
||||
className,
|
||||
shouldAnimateHover,
|
||||
disabled,
|
||||
type,
|
||||
}) => {
|
||||
return (
|
||||
<button
|
||||
disabled={disabled}
|
||||
className={getActiveClasses(
|
||||
'flex items-center bg-opacity-50 rounded-xl p-2 px-6 text-indigo-600',
|
||||
{
|
||||
'bg-gray-300 shadow-none hover:shadow-none': disabled,
|
||||
'text-red-600 bg-red-200 border border-red-600': type === 'danger',
|
||||
'text-indigo-600': !type,
|
||||
},
|
||||
'flex items-center bg-opacity-50 rounded-xl p-2 px-6',
|
||||
{
|
||||
'mx-px transform hover:-translate-y-px transition-all duration-150':
|
||||
shouldAnimateHover && !disabled,
|
||||
},
|
||||
className,
|
||||
{ 'bg-gray-300 shadow-none hover:shadow-none': disabled }
|
||||
className
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
|
||||
38
web/src/components/ConfirmDialog/ConfirmDialog.js
Normal file
38
web/src/components/ConfirmDialog/ConfirmDialog.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import Button from 'src/components/Button'
|
||||
|
||||
const ConfirmDialog = ({ open, onClose, message, onConfirm }) => {
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose}>
|
||||
<div className="bg-gray-100 max-w-3xl rounded-lg shadow-lg">
|
||||
<div className="p-4">
|
||||
<span className="text-gray-600 text-center">{message}</span>
|
||||
<div className="flex gap-4">
|
||||
<Button
|
||||
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200 relative z-20"
|
||||
shouldAnimateHover
|
||||
iconName={'save'}
|
||||
onClick={onClose}
|
||||
>
|
||||
Don't delete
|
||||
</Button>
|
||||
<Button
|
||||
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-red-200 relative z-20"
|
||||
shouldAnimateHover
|
||||
iconName={'trash'}
|
||||
onClick={() => {
|
||||
onClose()
|
||||
onConfirm()
|
||||
}}
|
||||
type="danger"
|
||||
>
|
||||
Yes, Delete
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default ConfirmDialog
|
||||
@@ -0,0 +1,7 @@
|
||||
import ConfirmDialog from './ConfirmDialog'
|
||||
|
||||
export const generated = () => {
|
||||
return <ConfirmDialog />
|
||||
}
|
||||
|
||||
export default { title: 'Components/ConfirmDialog' }
|
||||
11
web/src/components/ConfirmDialog/ConfirmDialog.test.js
Normal file
11
web/src/components/ConfirmDialog/ConfirmDialog.test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import ConfirmDialog from './ConfirmDialog'
|
||||
|
||||
describe('ConfirmDialog', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<ConfirmDialog />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -84,6 +84,18 @@ const CREATE_COMMENT_MUTATION = gql`
|
||||
}
|
||||
}
|
||||
`
|
||||
const DELETE_PART_MUTATION = gql`
|
||||
mutation DeletePartMutation($id: String!) {
|
||||
deletePart(id: $id) {
|
||||
id
|
||||
title
|
||||
user {
|
||||
id
|
||||
userName
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const Loading = () => <div>Loading...</div>
|
||||
|
||||
@@ -123,6 +135,16 @@ export const Success = ({ userPart, variables: { isEditable }, refetch }) => {
|
||||
}
|
||||
updateUser({ variables: { id, input } })
|
||||
}
|
||||
const [deletePart] = useMutation(DELETE_PART_MUTATION, {
|
||||
onCompleted: ({ deletePart }) => {
|
||||
navigate(routes.home())
|
||||
addMessage('Part deleted.', { classes: 'rw-flash-success' })
|
||||
},
|
||||
})
|
||||
|
||||
const onDelete = () => {
|
||||
userPart?.Part?.id && deletePart({ variables: { id: userPart?.Part?.id } })
|
||||
}
|
||||
|
||||
const [toggleReaction] = useMutation(TOGGLE_REACTION_MUTATION, {
|
||||
onCompleted: () => refetch(),
|
||||
@@ -156,6 +178,7 @@ export const Success = ({ userPart, variables: { isEditable }, refetch }) => {
|
||||
<PartProfile
|
||||
userPart={userPart}
|
||||
onSave={onSave}
|
||||
onDelete={onDelete}
|
||||
loading={loading}
|
||||
error={error}
|
||||
isEditable={isEditable}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Link, navigate, routes } from '@redwoodjs/router'
|
||||
import Editor from 'rich-markdown-editor'
|
||||
|
||||
import ImageUploader from 'src/components/ImageUploader'
|
||||
import ConfirmDialog from 'src/components/ConfirmDialog'
|
||||
import Breadcrumb from 'src/components/Breadcrumb'
|
||||
import EmojiReaction from 'src/components/EmojiReaction'
|
||||
import Button from 'src/components/Button'
|
||||
@@ -14,14 +15,15 @@ const PartProfile = ({
|
||||
userPart,
|
||||
isEditable,
|
||||
onSave,
|
||||
onDelete,
|
||||
onReaction,
|
||||
onComment,
|
||||
}) => {
|
||||
const [comment, setComment] = useState('')
|
||||
const [isConfirmDialogOpen, setIsConfirmDialogOpen] = useState(false)
|
||||
const { currentUser } = useAuth()
|
||||
const canEdit = currentUser?.sub === userPart.id
|
||||
const part = userPart?.Part
|
||||
console.log(part)
|
||||
const emotes = countEmotes(part?.Reaction)
|
||||
const userEmotes = part?.userReactions.map(({ emote }) => emote)
|
||||
useEffect(() => {
|
||||
@@ -100,7 +102,7 @@ const PartProfile = ({
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200"
|
||||
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200 w-full justify-end"
|
||||
shouldAnimateHover
|
||||
iconName="terminal"
|
||||
onClick={() => {}}
|
||||
@@ -109,15 +111,27 @@ const PartProfile = ({
|
||||
</Button>
|
||||
</Link>
|
||||
{canEdit && (
|
||||
<Button
|
||||
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200 relative z-20"
|
||||
shouldAnimateHover
|
||||
iconName={isEditable ? 'save' : 'pencil'}
|
||||
onClick={onEditSaveClick}
|
||||
>
|
||||
{isEditable ? 'Save Details' : 'Edit Details'}
|
||||
</Button>
|
||||
<>
|
||||
<Button
|
||||
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200 relative z-20 w-full justify-end"
|
||||
shouldAnimateHover
|
||||
iconName={isEditable ? 'save' : 'pencil'}
|
||||
onClick={onEditSaveClick}
|
||||
>
|
||||
{isEditable ? 'Save Details' : 'Edit Details'}
|
||||
</Button>
|
||||
<Button
|
||||
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-red-200 relative z-20 w-full justify-end"
|
||||
shouldAnimateHover
|
||||
iconName={'trash'}
|
||||
onClick={() => setIsConfirmDialogOpen(true)}
|
||||
type="danger"
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{/* gray overlay */}
|
||||
{isEditable && (
|
||||
<div className="absolute inset-0 bg-gray-300 opacity-75 z-10 transform scale-x-110 -ml-1 -mt-2" />
|
||||
)}
|
||||
@@ -216,6 +230,12 @@ const PartProfile = ({
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
<ConfirmDialog
|
||||
open={isConfirmDialogOpen}
|
||||
onClose={() => setIsConfirmDialogOpen(false)}
|
||||
onConfirm={onDelete}
|
||||
message="Are you sure you want to delete? This action cannot be undone."
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -307,6 +307,21 @@ const Svg = ({ name, className: className2, strokeWidth = 2 }) => {
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
trash: (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={strokeWidth}
|
||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
}
|
||||
|
||||
return <div className={className2 || 'h-10 w-10'}>{svgs[name]}</div>
|
||||
|
||||
Reference in New Issue
Block a user