mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-25 17:08:29 +00:00
feat(posts): add edit support for posts (#9666)
This commit is contained in:
parent
f993f50a04
commit
45236a89aa
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Form, Input, Typography, FormInstance, Radio } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
@ -21,11 +21,18 @@ const SubFormItem = styled(Form.Item)`
|
||||
type Props = {
|
||||
setCreateButtonEnabled: (isEnabled: boolean) => void;
|
||||
form: FormInstance;
|
||||
contentType: PostContentType;
|
||||
};
|
||||
|
||||
export default function CreatePostForm({ setCreateButtonEnabled, form }: Props) {
|
||||
export default function CreatePostForm({ setCreateButtonEnabled, form, contentType }: Props) {
|
||||
const [postType, setPostType] = useState<PostContentType>(PostContentType.Text);
|
||||
|
||||
useEffect(() => {
|
||||
if (contentType) {
|
||||
setPostType(contentType);
|
||||
}
|
||||
}, [contentType]);
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={form}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Form, message, Modal } from 'antd';
|
||||
import CreatePostForm from './CreatePostForm';
|
||||
import {
|
||||
@ -11,9 +11,11 @@ import {
|
||||
} from './constants';
|
||||
import { useEnterKeyListener } from '../../shared/useEnterKeyListener';
|
||||
import { MediaType, PostContentType, PostType } from '../../../types.generated';
|
||||
import { useCreatePostMutation } from '../../../graphql/mutations.generated';
|
||||
import { useCreatePostMutation, useUpdatePostMutation } from '../../../graphql/mutations.generated';
|
||||
import { PostEntry } from './PostsListColumns';
|
||||
|
||||
type Props = {
|
||||
editData: PostEntry;
|
||||
onClose: () => void;
|
||||
onCreate: (
|
||||
contentType: string,
|
||||
@ -22,12 +24,27 @@ type Props = {
|
||||
link: string | undefined,
|
||||
location: string | undefined,
|
||||
) => void;
|
||||
onEdit: () => void;
|
||||
};
|
||||
|
||||
export default function CreatePostModal({ onClose, onCreate }: Props) {
|
||||
export default function CreatePostModal({ onClose, onCreate, editData, onEdit }: Props) {
|
||||
const [createPostMutation] = useCreatePostMutation();
|
||||
const [updatePostMutation] = useUpdatePostMutation();
|
||||
const [createButtonEnabled, setCreateButtonEnabled] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
if (editData) {
|
||||
form.setFieldsValue({
|
||||
description: editData.description,
|
||||
title: editData.title,
|
||||
link: editData.link,
|
||||
location: editData.imageUrl,
|
||||
type: editData.contentType,
|
||||
});
|
||||
}
|
||||
}, [editData, form]);
|
||||
|
||||
const onCreatePost = () => {
|
||||
const contentTypeValue = form.getFieldValue(TYPE_FIELD_NAME) ?? PostContentType.Text;
|
||||
const mediaValue =
|
||||
@ -75,33 +92,86 @@ export default function CreatePostModal({ onClose, onCreate }: Props) {
|
||||
onClose();
|
||||
};
|
||||
|
||||
const onUpdatePost = () => {
|
||||
const contentTypeValue = form.getFieldValue(TYPE_FIELD_NAME) ?? PostContentType.Text;
|
||||
const mediaValue =
|
||||
form.getFieldValue(TYPE_FIELD_NAME) && form.getFieldValue(LOCATION_FIELD_NAME)
|
||||
? {
|
||||
type: MediaType.Image,
|
||||
location: form.getFieldValue(LOCATION_FIELD_NAME) ?? null,
|
||||
}
|
||||
: null;
|
||||
updatePostMutation({
|
||||
variables: {
|
||||
input: {
|
||||
urn: editData?.urn,
|
||||
postType: PostType.HomePageAnnouncement,
|
||||
content: {
|
||||
contentType: contentTypeValue,
|
||||
title: form.getFieldValue(TITLE_FIELD_NAME),
|
||||
description: form.getFieldValue(DESCRIPTION_FIELD_NAME) ?? null,
|
||||
link: form.getFieldValue(LINK_FIELD_NAME) ?? null,
|
||||
media: mediaValue,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(({ errors }) => {
|
||||
if (!errors) {
|
||||
message.success({
|
||||
content: `Updated Post!`,
|
||||
duration: 3,
|
||||
});
|
||||
onEdit();
|
||||
form.resetFields();
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
message.destroy();
|
||||
message.error({ content: 'Failed to update Post! An unknown error occured.', duration: 3 });
|
||||
console.error('Failed to update Post:', e.message);
|
||||
});
|
||||
onClose();
|
||||
};
|
||||
|
||||
// Handle the Enter press
|
||||
useEnterKeyListener({
|
||||
querySelectorToExecuteClick: '#createPostButton',
|
||||
});
|
||||
|
||||
const onCloseModal = () => {
|
||||
form.resetFields();
|
||||
onClose();
|
||||
};
|
||||
|
||||
const titleText = editData ? 'Edit Post' : 'Create new Post';
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Create new Post"
|
||||
title={titleText}
|
||||
open
|
||||
onCancel={onClose}
|
||||
onCancel={onCloseModal}
|
||||
footer={
|
||||
<>
|
||||
<Button onClick={onClose} type="text">
|
||||
<Button onClick={onCloseModal} type="text">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
id={CREATE_POST_BUTTON_ID}
|
||||
data-testid="create-post-button"
|
||||
onClick={onCreatePost}
|
||||
data-testid={!editData ? 'create-post-button' : 'update-post-button'}
|
||||
onClick={!editData ? onCreatePost : onUpdatePost}
|
||||
disabled={!createButtonEnabled}
|
||||
>
|
||||
Create
|
||||
{!editData ? 'Create' : 'Update'}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<CreatePostForm setCreateButtonEnabled={setCreateButtonEnabled} form={form} />
|
||||
<CreatePostForm
|
||||
setCreateButtonEnabled={setCreateButtonEnabled}
|
||||
form={form}
|
||||
contentType={editData?.contentType as PostContentType}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import { DeleteOutlined, EditOutlined } from '@ant-design/icons';
|
||||
import { Dropdown, Menu, message, Modal } from 'antd';
|
||||
import { MenuIcon } from '../../entity/shared/EntityDropdown/EntityDropdown';
|
||||
import { useDeletePostMutation } from '../../../graphql/post.generated';
|
||||
@ -8,9 +8,10 @@ type Props = {
|
||||
urn: string;
|
||||
title: string;
|
||||
onDelete?: () => void;
|
||||
onEdit?: () => void;
|
||||
};
|
||||
|
||||
export default function PostItemMenu({ title, urn, onDelete }: Props) {
|
||||
export default function PostItemMenu({ title, urn, onDelete, onEdit }: Props) {
|
||||
const [deletePostMutation] = useDeletePostMutation();
|
||||
|
||||
const deletePost = () => {
|
||||
@ -53,6 +54,9 @@ export default function PostItemMenu({ title, urn, onDelete }: Props) {
|
||||
<Menu.Item onClick={onConfirmDelete} key="delete">
|
||||
<DeleteOutlined /> Delete
|
||||
</Menu.Item>
|
||||
<Menu.Item onClick={onEdit} key="edit">
|
||||
<EditOutlined /> Edit
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
|
||||
@ -51,6 +51,7 @@ export const PostList = () => {
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
const [isCreatingPost, setIsCreatingPost] = useState(false);
|
||||
const [editData, setEditData] = useState<PostEntry | undefined>(undefined);
|
||||
|
||||
const pageSize = DEFAULT_PAGE_SIZE;
|
||||
const start = (page - 1) * pageSize;
|
||||
@ -82,6 +83,16 @@ export const PostList = () => {
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
const handleEdit = (post: PostEntry) => {
|
||||
setEditData(post);
|
||||
setIsCreatingPost(true);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setEditData(undefined);
|
||||
setIsCreatingPost(false);
|
||||
};
|
||||
|
||||
const allColumns = [
|
||||
{
|
||||
title: 'Title',
|
||||
@ -113,7 +124,7 @@ export const PostList = () => {
|
||||
width: '5%',
|
||||
align: 'right' as AlignType,
|
||||
key: 'menu',
|
||||
render: PostListMenuColumn(handleDelete),
|
||||
render: PostListMenuColumn(handleDelete, handleEdit),
|
||||
},
|
||||
];
|
||||
|
||||
@ -123,6 +134,8 @@ export const PostList = () => {
|
||||
title: post.content.title,
|
||||
description: post.content.description,
|
||||
contentType: post.content.contentType,
|
||||
link: post.content.link,
|
||||
imageUrl: post.content.media?.location,
|
||||
};
|
||||
});
|
||||
|
||||
@ -181,7 +194,9 @@ export const PostList = () => {
|
||||
)}
|
||||
{isCreatingPost && (
|
||||
<CreatePostModal
|
||||
onClose={() => setIsCreatingPost(false)}
|
||||
editData={editData as PostEntry}
|
||||
onClose={handleClose}
|
||||
onEdit={() => setTimeout(() => refetch(), 2000)}
|
||||
onCreate={(urn, title, description) => {
|
||||
addToListPostCache(
|
||||
client,
|
||||
|
||||
@ -9,15 +9,22 @@ export interface PostEntry {
|
||||
contentType: string;
|
||||
description: Maybe<string>;
|
||||
urn: string;
|
||||
link: string;
|
||||
imageUrl: string;
|
||||
}
|
||||
|
||||
const PostText = styled.div<{ minWidth?: number }>`
|
||||
${(props) => props.minWidth !== undefined && `min-width: ${props.minWidth}px;`}
|
||||
`;
|
||||
|
||||
export function PostListMenuColumn(handleDelete: (urn: string) => void) {
|
||||
export function PostListMenuColumn(handleDelete: (urn: string) => void, handleEdit: (urn: PostEntry) => void) {
|
||||
return (record: PostEntry) => (
|
||||
<PostItemMenu title={record.title} urn={record.urn} onDelete={() => handleDelete(record.urn)} />
|
||||
<PostItemMenu
|
||||
title={record.title}
|
||||
urn={record.urn}
|
||||
onDelete={() => handleDelete(record.urn)}
|
||||
onEdit={() => handleEdit(record)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -120,6 +120,10 @@ mutation createPost($input: CreatePostInput!) {
|
||||
createPost(input: $input)
|
||||
}
|
||||
|
||||
mutation updatePost($input: UpdatePostInput!) {
|
||||
updatePost(input: $input)
|
||||
}
|
||||
|
||||
mutation updateLineage($input: UpdateLineageInput!) {
|
||||
updateLineage(input: $input)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user