All checks were successful
Publish Docker Image / Publish Docker Image (push) Successful in 39s
176 lines
5.4 KiB
TypeScript
Executable File
176 lines
5.4 KiB
TypeScript
Executable File
import parseHtml from 'react-html-parser'
|
|
import type {
|
|
DeleteProjectMutation,
|
|
DeleteProjectMutationVariables,
|
|
AdminFindProjectById,
|
|
} from 'types/graphql'
|
|
|
|
import { Link, routes, navigate } from '@redwoodjs/router'
|
|
import { useMutation } from '@redwoodjs/web'
|
|
import type { TypedDocumentNode } from '@redwoodjs/web'
|
|
import { toast } from '@redwoodjs/web/toast'
|
|
|
|
import { calculateLuminance } from 'src/lib/color'
|
|
import { timeTag } from 'src/lib/formatters'
|
|
import { batchDelete } from 'src/lib/tus'
|
|
|
|
const DELETE_PROJECT_MUTATION: TypedDocumentNode<
|
|
DeleteProjectMutation,
|
|
DeleteProjectMutationVariables
|
|
> = gql`
|
|
mutation DeleteProjectMutation($id: Int!) {
|
|
deleteProject(id: $id) {
|
|
id
|
|
}
|
|
}
|
|
`
|
|
|
|
interface Props {
|
|
project: NonNullable<AdminFindProjectById['project']>
|
|
}
|
|
|
|
const AdminProject = ({ project }: Props) => {
|
|
const [deleteProject] = useMutation(DELETE_PROJECT_MUTATION, {
|
|
onCompleted: () => {
|
|
toast.success('Project deleted')
|
|
navigate(routes.adminProjects())
|
|
},
|
|
onError: (error) => toast.error(error.message),
|
|
})
|
|
|
|
const onDeleteClick = (id: DeleteProjectMutationVariables['id']) => {
|
|
if (confirm('Are you sure you want to delete project ' + id + '?')) {
|
|
batchDelete(project.images)
|
|
deleteProject({ variables: { id } })
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="flex justify-center">
|
|
<div>
|
|
<div className="overflow-hidden overflow-x-auto rounded-xl bg-base-100">
|
|
<table className="table">
|
|
<thead className="bg-base-200 font-syne">
|
|
<tr>
|
|
<th colSpan={2}>
|
|
Project {project.id}: {project.title}
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<th className="text-right">ID</th>
|
|
<td>{project.id}</td>
|
|
</tr>
|
|
<tr>
|
|
<th className="text-right">Title</th>
|
|
<td>{project.title}</td>
|
|
</tr>
|
|
<tr>
|
|
<th className="text-right">Description</th>
|
|
<td>
|
|
<article className="prose">
|
|
{parseHtml(project.description)}
|
|
</article>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th className="text-right">Date</th>
|
|
<td>{timeTag(project.date)}</td>
|
|
</tr>
|
|
<tr>
|
|
<th className="text-right">Images</th>
|
|
<td>
|
|
<div className="flex flex-wrap gap-2">
|
|
{project.images.map((image, i) => (
|
|
<a
|
|
key={i}
|
|
href={image}
|
|
target="_blank"
|
|
className={`btn btn-sm btn-square ${i === 0 && 'btn-primary'}`}
|
|
rel="noreferrer"
|
|
>
|
|
{i + 1}
|
|
</a>
|
|
))}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th className="text-right">Tags</th>
|
|
<td>
|
|
<div className="flex flex-wrap gap-2">
|
|
{project.tags.map((tag, i) => (
|
|
<div
|
|
key={i}
|
|
className="badge whitespace-nowrap"
|
|
style={{
|
|
backgroundColor: tag.color,
|
|
color:
|
|
calculateLuminance(tag.color) > 0.5
|
|
? 'black'
|
|
: 'white',
|
|
}}
|
|
>
|
|
{tag.tag}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th className="text-right">Links</th>
|
|
<td>
|
|
<div className="flex flex-wrap gap-2">
|
|
{project.links.map((link, i) => (
|
|
<>
|
|
<a
|
|
href={link}
|
|
target="_blank"
|
|
className="hidden sm:flex badge badge-ghost text-nowrap"
|
|
key={i}
|
|
rel="noreferrer"
|
|
>
|
|
{link}
|
|
</a>
|
|
<a
|
|
href={link}
|
|
target="_blank"
|
|
className="btn btn-sm btn-square sm:hidden"
|
|
key={i}
|
|
rel="noreferrer"
|
|
>
|
|
{i + 1}
|
|
</a>
|
|
</>
|
|
))}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<nav className="my-2 flex justify-center space-x-2">
|
|
<Link
|
|
to={routes.editProject({ id: project.id })}
|
|
title={'Edit project ' + project.id}
|
|
className="btn btn-primary btn-sm uppercase"
|
|
>
|
|
Edit
|
|
</Link>
|
|
<button
|
|
type="button"
|
|
title={'Delete project ' + project.id}
|
|
className="btn btn-error btn-sm uppercase"
|
|
onClick={() => onDeleteClick(project.id)}
|
|
>
|
|
Delete
|
|
</button>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default AdminProject
|