push work

This commit is contained in:
Andreas 2024-07-28 23:42:32 +02:00
parent 7312ab632c
commit d8d0aaa90e
4 changed files with 212 additions and 216 deletions

View File

@ -1,11 +1,14 @@
'use server'; "use server";
import { Project } from "@/models"; import { Project } from "@/models";
import { ActionResult } from "../../ActionResult"; import { ActionResult } from "../../ActionResult";
import { Attributes } from "@sequelize/core"; import { Attributes } from "@sequelize/core";
import { userIsAdmin } from "../../actions"; import { userIsAdmin } from "../../actions";
export async function getProjects(): Promise<ActionResult<Attributes<Project>[]>> { export async function getProjects(): Promise<
if (! await userIsAdmin()) return { error: 'Unauthorized, not fetching Projects' } ActionResult<Attributes<Project>[]>
> {
if (!(await userIsAdmin()))
return { error: "Unauthorized, not fetching Projects" };
const posts = await Project.findAll(); const posts = await Project.findAll();
return { result: JSON.parse(JSON.stringify(posts)) }; return { result: JSON.parse(JSON.stringify(posts)) };
} }

View File

@ -5,161 +5,155 @@ import toast from "react-hot-toast";
import { EditorRenderer, EditorState, PostTableCallbacks } from "./PostEditor"; import { EditorRenderer, EditorState, PostTableCallbacks } from "./PostEditor";
import { Attributes, InferAttributes } from "@sequelize/core"; import { Attributes, InferAttributes } from "@sequelize/core";
import { import {
Project, Project,
Post, Post,
Bucket, Bucket,
User, User,
PostAttributesWithBuckets, PostAttributesWithBuckets,
} from "@/models"; } from "@/models";
import { handleActionResult } from "@/app/lib/actions/clientActionHandler"; import { handleActionResult } from "@/app/lib/actions/clientActionHandler";
import { import {
getPostsWithBucketsAndProject, getPostsWithBucketsAndProject,
GetPostsAttributes, GetPostsAttributes,
} from "@/app/lib/actions/entitymanagement/post/postActions"; } from "@/app/lib/actions/entitymanagement/post/postActions";
import { PostViewProps } from "@/components/views/admin/post"; import { PostViewProps } from "@/components/views/admin/post";
import { StateHook } from "@/util/"; import { StateHook } from "@/util/";
export type PostTableStateProps = { export type PostTableStateProps = {
posts: StateHook<GetPostsAttributes[]>; posts: StateHook<GetPostsAttributes[]>;
editor: StateHook<EditorState>; editor: StateHook<EditorState>;
}; };
export type PostTableProps = PostViewProps & { state: PostTableStateProps }; export type PostTableProps = PostViewProps & { state: PostTableStateProps };
export default function PostTable({ export default function PostTable({
headings, headings,
posts, posts,
projects, projects,
actions, actions,
state, state,
}: PostTableProps) { }: PostTableProps) {
// Define editor controls // Define editor controls
const editorControls = { const editorControls = {
closeEditor: () => { closeEditor: () => {
state.editor.setState({ state.editor.setState({
isEditorOpen: false, isEditorOpen: false,
editorPost: posts[0], editorPost: posts[0],
}); });
}, },
showEditor: (entry: GetPostsAttributes) => { showEditor: (entry: GetPostsAttributes) => {
state.editor.setState({ state.editor.setState({
isEditorOpen: true, isEditorOpen: true,
editorPost: entry, editorPost: entry,
}); });
}, },
}; };
const postActions = { const postActions = {
deletePost: (entry: GetPostsAttributes) => { deletePost: (entry: GetPostsAttributes) => {
if (!entry.id) return; if (!entry.id) return;
actions.deletePost(entry.id).then((actionResult) => { actions.deletePost(entry.id).then((actionResult) => {
const result = handleActionResult(actionResult); const result = handleActionResult(actionResult);
if (!result) return; if (!result) return;
state.posts.state.splice(state.posts.state.indexOf(entry), 1); state.posts.state.splice(state.posts.state.indexOf(entry), 1);
state.posts.setState([...state.posts.state]); state.posts.setState([...state.posts.state]);
toast.success("Removed Post:" + entry.id); toast.success("Removed Post:" + entry.id);
}); });
}, },
refetch: () => { refetch: () => {
actions actions
.getPosts() // Get Posts From Server .getPosts() // Get Posts From Server
.then((getPostsServerActionResult) => { .then((getPostsServerActionResult) => {
// Handle Result and toast error on failure // Handle Result and toast error on failure
const result = handleActionResult( const result = handleActionResult(getPostsServerActionResult);
getPostsServerActionResult // Set Posts state
); if (result) state.posts.setState(result);
// Set Posts state });
if (result) state.posts.setState(result); },
}); savePost: (e: Partial<Attributes<Post>>) => {
}, actions
savePost: (e: Partial<Attributes<Post>>) => { .savePost({
actions id: e.id,
.savePost({ content: e.content,
id: e.id, title: e.title,
content: e.content, project_id: e.project_id,
title: e.title, })
project_id: e.project_id, .then((res) => handleActionResult(res))
}) .then(getPostsWithBucketsAndProject)
.then((res) => handleActionResult(res)) .then((res) => {
.then(getPostsWithBucketsAndProject) const result = handleActionResult(res);
.then((res) => { if (result) state.posts.setState(result);
const result = handleActionResult(res); })
if (result) state.posts.setState(result); .then(editorControls.closeEditor)
}) .then(postActions.refetch);
.then(editorControls.closeEditor) },
.then(postActions.refetch); };
},
};
return ( return (
<EntityManagementTable entityName="Post" headings={headings}> <EntityManagementTable entityName="Post" headings={headings}>
{state.posts.state.map((post: GetPostsAttributes) => ( {state.posts.state.map((post: GetPostsAttributes) => (
<React.Fragment key={`postrow-${post.id}`}> <React.Fragment key={`postrow-${post.id}`}>
<tr> <tr>
<th key={`rowheading-post-${post.id}`} scope="row"> <th key={`rowheading-post-${post.id}`} scope="row">
{post.id} {post.id}
</th> </th>
<td key="title">{post.title}</td> <td key="title">{post.title}</td>
<td key="content"> <td key="content">
{!post.content {!post.content
? "No Content Found" ? "No Content Found"
: post.content.length < 255 : post.content.length < 255
? post.content ? post.content
: `${post.content.substring(0, 255)}...`} : `${post.content.substring(0, 255)}...`}
</td> </td>
<td key="project"> <td key="project">
{projects.find((e) => { {projects.find((e) => {
console.log(e.id); console.log(e.id);
return e.id == post.project.id; return e.id == post.project.id;
})?.readableIdentifier || "uncategorized"} })?.readableIdentifier || "uncategorized"}
</td> </td>
<td key="createdAt">{post.createdAt?.toString()}</td> <td key="createdAt">{post.createdAt?.toString()}</td>
<td key="updatedAt">{post.updatedAt?.toString()}</td> <td key="updatedAt">{post.updatedAt?.toString()}</td>
<td key="edit"> <td key="edit">
{ {
<button <button
key="editbutton" key="editbutton"
type="button" type="button"
className="btn btn-primary" className="btn btn-primary"
onClick={() => onClick={() => editorControls.showEditor(post)}
editorControls.showEditor(post) >
} Edit
> </button>
Edit }
</button> </td>
} <td key="delete">
</td> {
<td key="delete"> <button
{ key="deletebutton"
<button type="button"
key="deletebutton" onClick={() => postActions.deletePost(post)}
type="button" className="btn btn-danger"
onClick={() => postActions.deletePost(post)} >
className="btn btn-danger" {" "}
> Delete
{" "} </button>
Delete }
</button> </td>
} </tr>
</td> <EditorRenderer
</tr> headings={headings}
<EditorRenderer editorPost={post}
headings={headings} editorControls={editorControls}
editorPost={post} editorState={state.editor.state}
editorControls={editorControls} callbacks={{
editorState={state.editor.state} savePost: postActions.savePost,
callbacks={{ closeEditor: editorControls.closeEditor,
savePost: postActions.savePost, refetch: postActions.refetch,
closeEditor: editorControls.closeEditor, uploadAttachment: () => {},
refetch: postActions.refetch, }}
uploadAttachment: () => {}, projects={projects}
}} />
projects={projects} </React.Fragment>
/> ))}
</React.Fragment> </EntityManagementTable>
))} );
</EntityManagementTable>
);
} }

View File

@ -1,11 +1,10 @@
"use client"; "use client";
import PostTable, { import PostTable, {
PostTableStateProps, PostTableStateProps,
} from "@/components/client/admin/PostTable"; } from "@/components/client/admin/PostTable";
import { import {
GetPostsAttributes, GetPostsAttributes,
PostServerActions, PostServerActions,
} from "@/app/lib/actions/entitymanagement/post/postActions"; } from "@/app/lib/actions/entitymanagement/post/postActions";
import { EditorState } from "@/components/client/admin/PostEditor"; import { EditorState } from "@/components/client/admin/PostEditor";
import { Project } from "@/models"; import { Project } from "@/models";
@ -14,38 +13,38 @@ import { Attributes } from "@sequelize/core";
import { parseStateHook } from "@/util/state"; import { parseStateHook } from "@/util/state";
export type PostViewProps = { export type PostViewProps = {
children?: ReactNode; children?: ReactNode;
headings: Array<string>; headings: Array<string>;
posts: GetPostsAttributes[]; posts: GetPostsAttributes[];
projects: Attributes<Project>[]; projects: Attributes<Project>[];
actions: PostServerActions; actions: PostServerActions;
}; };
export function CPostView({ export function CPostView({
// children, // children,
headings, headings,
posts, posts,
projects, projects,
actions, actions,
}: PostViewProps) { }: PostViewProps) {
// Init editor state. Make sure it is not opened by default // Init editor state. Make sure it is not opened by default
const initEditorState: EditorState = { const initEditorState: EditorState = {
isEditorOpen: false, isEditorOpen: false,
editorPost: posts[0], editorPost: posts[0],
}; };
// Set up required state hooks // Set up required state hooks
const state: PostTableStateProps = { const state: PostTableStateProps = {
posts: parseStateHook(useState(posts)), posts: parseStateHook(useState(posts)),
editor: parseStateHook(useState(initEditorState)), editor: parseStateHook(useState(initEditorState)),
}; };
// render out the post table // render out the post table
return ( return (
<PostTable <PostTable
headings={headings} headings={headings}
posts={posts} posts={posts}
projects={projects} projects={projects}
actions={actions} actions={actions}
state={state} state={state}
></PostTable> ></PostTable>
); );
} }

View File

@ -3,11 +3,11 @@ cache: "no-store";
import { ReactNode } from "react"; import { ReactNode } from "react";
import { import {
deletePost, deletePost,
getPostsWithBucketsAndProject, getPostsWithBucketsAndProject,
updatePost, updatePost,
GetPostsAttributes, GetPostsAttributes,
PostServerActions, PostServerActions,
} from "@/app/lib/actions/entitymanagement/post/postActions"; } from "@/app/lib/actions/entitymanagement/post/postActions";
import { getProjects } from "@/app/lib/actions/entitymanagement/post/projectActions"; import { getProjects } from "@/app/lib/actions/entitymanagement/post/projectActions";
import { Bucket, Project, Post, dbSync, Attachment } from "@/models"; import { Bucket, Project, Post, dbSync, Attachment } from "@/models";
@ -15,43 +15,43 @@ import { handleActionResult } from "@/app/lib/actions/clientActionHandler";
import { CPostView } from "@/components/views/admin/post"; import { CPostView } from "@/components/views/admin/post";
type Props = { type Props = {
children?: ReactNode; children?: ReactNode;
}; };
export async function PostView(props: Props) { export async function PostView(props: Props) {
const sync = await dbSync; const sync = await dbSync;
const headings: string[] = [ const headings: string[] = [
"#", "#",
"Title", "Title",
"Content", "Content",
"Project", "Project",
"CreatedAt", "CreatedAt",
"UpdatedAt", "UpdatedAt",
]; ];
const posts: GetPostsAttributes[] | undefined = handleActionResult( const posts: GetPostsAttributes[] | undefined = handleActionResult(
await getPostsWithBucketsAndProject() await getPostsWithBucketsAndProject()
); );
const projects = await Project.findAll().then((projects) => const projects = await Project.findAll().then((projects) =>
projects.map((project) => JSON.parse(JSON.stringify(project))) projects.map((project) => JSON.parse(JSON.stringify(project)))
); );
return ( return (
<div className="w-[100%] min-h-fit bg-gray-100 overflow-scroll"> <div className="w-[100%] min-h-fit bg-gray-100 overflow-scroll">
<div className="w-[100%] m-auto"> <div className="w-[100%] m-auto">
<CPostView <CPostView
posts={posts ? posts : []} posts={posts ? posts : []}
projects={projects} projects={projects}
headings={headings} headings={headings}
actions={{ actions={{
deletePost: deletePost, deletePost: deletePost,
getPosts: getPostsWithBucketsAndProject, getPosts: getPostsWithBucketsAndProject,
getProjects: getProjects, getProjects: getProjects,
savePost: updatePost savePost: updatePost,
}} }}
/> />
</div> </div>
</div> </div>
); );
} }