Create News
We can easily create a new page to submit news. We use CKEditor as our rich text editor.
1. Install and Configure CKEditor
Install the CKEditor with the following command.
yarn add @ckeditor/[email protected] @ckeditor/[email protected]
Because CKEditor does not come with types we use a little trick to make it work in our project.
Add the following code to the typings.d.ts
.
declare module "@ckeditor/ckeditor5-react" {
const CKEditor: any;
export default CKEditor;
}
declare module "@ckeditor/ckeditor5-build-classic" {
const ClassicEditor: any;
export = ClassicEditor;
}
declare module "react-infinite-scroller" {
export default any;
}
You have to install the exact version of the ckeditor for these typings to work.
2. Create Composer component
Create a new component called Composer
and route /submit
to it.
To create a new post we use useAddPost
hook.
const {mutateAsync: addPost} = useAddPost()
We use mutateAsync
because we want to redirect the user to the homepage after the post is created.
Use the spaces
query to find the id of the "General" space and
use the postTypes
query to find the id of the "Discussion" post type.
Then we can use these ids to create a "Discussion" post in "General" space.
addPost({
spaceId: 'dy3eAqs9cDCC',
input: {
postTypeId: 'nizYc5RZXWArXJW',
publish: true,
mappingFields: [
{
key: 'title',
type: PostMappingTypeEnum.TEXT,
value: JSON.stringify(title)
},
{
key: 'content',
type: PostMappingTypeEnum.HTML,
value: JSON.stringify(data),
}
]
}
})
Put them all together with some styling and the component should look similar to this.
import CKEditor from '@ckeditor/ckeditor5-react'
import ClassicEditor from '@ckeditor/ckeditor5-build-classic'
import {useState} from "react";
import {useAddPost} from "@tribeplatform/react-sdk/hooks";
import {PostMappingTypeEnum} from "@tribeplatform/gql-client/types";
import {useNavigate} from "react-router-dom";
export const Composer = () => {
const navigate = useNavigate()
const [data, setData] = useState<string>('')
const [title, setTitle] = useState<string>('')
const {mutateAsync: addPost} = useAddPost()
return (
<div className="w-1/2 mx-auto mt-5">
<h1 className="text-2xl mb-5">Submit News</h1>
<label className="block text-gray-700 text-sm font-bold mb-2">
Title
</label>
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline mb-5"
type="text" placeholder="Title" onChange={event => setTitle(event.target.value)}
/>
<label className="block text-gray-700 text-sm font-bold mb-2">
Content
</label>
<CKEditor
editor={ClassicEditor}
data="<p>Whats new?</p>"
onChange={(event: any, editor: any) => {
setData(editor.getData());
}}
/>
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mt-5"
onClick={() => {
addPost({
spaceId: 'dy3eAqs9cDCC',
input: {
postTypeId: 'nizYc5RZXWArXJW',
publish: true,
mappingFields: [
{
key: 'title',
type: PostMappingTypeEnum.TEXT,
value: JSON.stringify(title)
},
{
key: 'content',
type: PostMappingTypeEnum.HTML,
value: JSON.stringify(data),
}
]
}
}).then(() => {
navigate('/');
})
}}
>
Submit
</button>
</div>
);
}
You can see the final result here.