feat: add post add interface

This commit is contained in:
0x29a
2021-06-27 23:15:42 +02:00
committed by Mehak Nasir
parent 7138e63cf0
commit b06832ae13
6 changed files with 204 additions and 6 deletions

View File

@@ -1,15 +1,18 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { Route, Switch } from 'react-router';
import { PostActionsBar } from '../../components';
import { Routes } from '../../data/constants';
import { CommentsView } from '../comments';
import { BreadcrumbMenu, NavigationBar } from '../navigation';
import { PostsView } from '../posts';
import { PostEditor, PostsView } from '../posts';
import { TopicsView } from '../topics';
export default function DiscussionsHome() {
const postEditorVisible = useSelector(state => state.threads.postEditorVisible);
return (
<main className="container my-4 d-flex flex-row">
<div className="d-flex flex-column w-50 mr-1">
@@ -34,9 +37,14 @@ export default function DiscussionsHome() {
</div>
<div className="d-flex w-50 pl-1 flex-column">
<PostActionsBar />
<Route path={Routes.COMMENTS.PATH}>
<CommentsView />
</Route>
{
postEditorVisible ? <PostEditor />
: (
<Route path={Routes.COMMENTS.PATH}>
<CommentsView />
</Route>
)
}
</div>
</main>
);

View File

@@ -55,6 +55,7 @@ const threadsSlice = createSlice({
myPosts: MyPostsFilter.MY_POSTS,
search: '',
},
postEditorVisible: false,
sortedBy: ThreadOrdering.BY_LAST_ACTIVITY,
},
reducers: {
@@ -150,6 +151,12 @@ const threadsSlice = createSlice({
setSearchQuery: (state, { payload }) => {
state.filters.search = payload;
},
showPostEditor: (state) => {
state.postEditorVisible = true;
},
hidePostEditor: (state) => {
state.postEditorVisible = false;
},
},
});
@@ -179,6 +186,8 @@ export const {
setSortedBy,
setStatusFilter,
setSearchQuery,
showPostEditor,
hidePostEditor,
} = threadsSlice.actions;
export const threadsReducer = threadsSlice.reducer;

View File

@@ -1,2 +1,3 @@
/* eslint-disable import/prefer-default-export */
export { default as PostsView } from './PostsView';
export { default as PostEditor } from './post-editor/PostEditor';

View File

@@ -5,7 +5,7 @@ import { useDispatch } from 'react-redux';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Button, SearchField } from '@edx/paragon';
import { setSearchQuery } from '../data';
import { setSearchQuery, showPostEditor } from '../data';
import messages from './messages';
function PostActionsBar({ intl }) {
@@ -17,7 +17,11 @@ function PostActionsBar({ intl }) {
onSubmit={(value) => dispatch(setSearchQuery(value))}
placeholder={intl.formatMessage(messages.searchAllPosts)}
/>
<Button variant="outline-primary" className="ml-2">
<Button
variant="outline-primary"
className="ml-2"
onClick={() => dispatch(showPostEditor())}
>
{intl.formatMessage(messages.addAPost)}
</Button>
</div>

View File

@@ -0,0 +1,110 @@
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import React from 'react';
import { useDispatch } from 'react-redux';
import { Button, Form } from '@edx/paragon';
import { faComments, faQuestion, faStar } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { hidePostEditor } from '../data';
import messages from './messages';
function PostEditor({ intl }) {
const dispatch = useDispatch();
const cancelAdding = () => dispatch(hidePostEditor());
return (
<div className="mx-4 my-2">
<Form>
<Form.Group>
<Form.Label>
{intl.formatMessage(messages.type)}
</Form.Label>
<Form.Text className="mb-3" muted>
{intl.formatMessage(messages.typeDescription)} ({intl.formatMessage(messages.required)})
</Form.Text>
<Form.Check inline type="radio" id="question">
<Form.Check.Input type="radio" />
<Form.Check.Label>
<FontAwesomeIcon icon={faQuestion} />
<span className="ml-2">{intl.formatMessage(messages.questionType)}</span>
</Form.Check.Label>
</Form.Check>
<Form.Check inline type="radio" id="discussion">
<Form.Check.Input type="radio" />
<Form.Check.Label>
<FontAwesomeIcon icon={faComments} />
<span className="ml-2">{intl.formatMessage(messages.discussionType)}</span>
</Form.Check.Label>
</Form.Check>
</Form.Group>
<Form.Group>
<Form.Label>
{intl.formatMessage(messages.topicArea)}
</Form.Label>
<Form.Text id="topicAreaInput" muted>
{intl.formatMessage(messages.topicAreaDescription)} ({intl.formatMessage(messages.required)})
</Form.Text>
<Form.Control
as="select"
defaultValue="General"
aria-describedby="topicAreaInput"
>
{/* TODO: topics has to be filled in another PR */}
<option>General</option>
</Form.Control>
</Form.Group>
<Form.Group>
<Form.Label>
{intl.formatMessage(messages.title)}
</Form.Label>
<Form.Text id="titleInput" muted>
{intl.formatMessage(messages.titleDescription)} ({intl.formatMessage(messages.required)})
</Form.Text>
<Form.Control type="text" aria-describedby="titleInput" />
</Form.Group>
<Form.Group>
<Form.Label>
{intl.formatMessage(messages.questionText)}
</Form.Label>
<Form.Control as="textarea" rows="3" />
</Form.Group>
<Form.Group>
<Form.Check inline type="checkbox" id="follow">
<Form.Check.Input type="checkbox" />
<Form.Check.Label>
<FontAwesomeIcon icon={faStar} />
<span className="ml-2">{intl.formatMessage(messages.followPost)}</span>
</Form.Check.Label>
</Form.Check>
<Form.Check inline type="checkbox" id="anonymous">
<Form.Check.Input type="checkbox" />
<Form.Check.Label>
<span className="ml-2">{intl.formatMessage(messages.anonymousPost)}</span>
</Form.Check.Label>
</Form.Check>
</Form.Group>
<Button className="rounded-lg" variant="primary">
{intl.formatMessage(messages.submit)}
</Button>
<Button className="rounded-lg ml-2" variant="outline-primary" onClick={cancelAdding}>
{intl.formatMessage(messages.cancel)}
</Button>
</Form>
</div>
);
}
PostEditor.propTypes = {
intl: intlShape.isRequired,
};
export default injectIntl(PostEditor);

View File

@@ -0,0 +1,66 @@
import { defineMessages } from '@edx/frontend-platform/i18n';
const messages = defineMessages({
type: {
id: 'discussions.post.editor.type',
defaultMessage: 'Post type',
},
typeDescription: {
id: 'discussions.post.editor.typeDescription',
defaultMessage: 'Questions raise issues that need answers. Discussions share ideas and start conversations.',
},
required: {
id: 'discussions.post.editor.required',
defaultMessage: 'Required',
},
questionType: {
id: 'discussions.post.editor.questionType',
defaultMessage: 'Question',
},
discussionType: {
id: 'discussions.post.editor.discussionType',
defaultMessage: 'Discussion',
},
topicArea: {
id: 'discussions.post.editor.topicArea',
defaultMessage: 'Topic area',
},
topicAreaDescription: {
id: 'discussions.post.editor.topicAreaDescription',
defaultMessage: 'Add your post to a relevant topic to help others find it.',
},
title: {
id: 'discussions.post.editor.title',
defaultMessage: 'Title',
},
titleDescription: {
id: 'discussions.post.editor.titleDescription',
defaultMessage: 'Add a clear and descriptive title to encourage participation.',
},
questionText: {
id: 'discussions.post.editor.questionText',
defaultMessage: 'Your question or idea (required)',
},
preview: {
id: 'discussions.post.editor.preview',
defaultMessage: 'Preview',
},
followPost: {
id: 'discussions.post.editor.followPost',
defaultMessage: 'follow this post',
},
anonymousPost: {
id: 'discussions.post.editor.anonymousPost',
defaultMessage: 'post anonymously',
},
submit: {
id: 'discussions.post.editor.submit',
defaultMessage: 'Submit',
},
cancel: {
id: 'discussions.post.editor.cancel',
defaultMessage: 'Cancel',
},
});
export default messages;