Skip to main content

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/ckeditor5-react@2.1.0 @ckeditor/ckeditor5-build-classic@19.0.0

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.

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;
}
note

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()
note

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.

components/Composer.tsx
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>
);
}
note

You can see the final result here.