Files
astuto/app/javascript/components/Board/NewPost.tsx

284 lines
6.5 KiB
TypeScript
Raw Normal View History

2019-09-02 14:32:57 +02:00
import * as React from 'react';
2022-06-06 20:20:03 +02:00
import ReactMarkdown from 'react-markdown';
import I18n from 'i18n-js';
2019-09-02 14:32:57 +02:00
import NewPostForm from './NewPostForm';
import Spinner from '../common/Spinner';
import {
DangerText,
SuccessText,
} from '../common/CustomTexts';
import Button from '../common/Button';
2019-09-02 14:32:57 +02:00
import IBoard from '../../interfaces/IBoard';
import buildRequestHeaders from '../../helpers/buildRequestHeaders';
2022-05-01 18:00:38 +02:00
import HttpStatus from '../../constants/http_status';
2024-07-12 20:38:46 +02:00
import { POST_APPROVAL_STATUS_APPROVED } from '../../interfaces/IPost';
2019-09-02 14:32:57 +02:00
interface Props {
board: IBoard;
isLoggedIn: boolean;
2024-07-12 20:38:46 +02:00
currentUserFullName: string;
isAnonymousFeedbackAllowed: boolean;
2019-09-02 14:32:57 +02:00
authenticityToken: string;
2024-07-12 20:38:46 +02:00
// Time check anti-spam measure
componentRenderedAt: number;
2019-09-02 14:32:57 +02:00
}
interface State {
showForm: boolean;
error: string;
success: string;
isLoading: boolean;
title: string;
description: string;
2024-07-12 20:38:46 +02:00
isSubmissionAnonymous: boolean;
// Honeypot anti-spam measure
// These fields are honeypots: they are not visibile and must not be filled
// dnf = do not fill
dnf1: string;
dnf2: string;
2019-09-02 14:32:57 +02:00
}
class NewPost extends React.Component<Props, State> {
constructor(props: Props) {
2019-09-02 14:32:57 +02:00
super(props);
this.state = {
showForm: false,
error: '',
success: '',
isLoading: false,
title: '',
description: '',
2024-07-12 20:38:46 +02:00
isSubmissionAnonymous: false,
dnf1: '',
dnf2: '',
2019-09-02 14:32:57 +02:00
};
this.toggleForm = this.toggleForm.bind(this);
this.onTitleChange = this.onTitleChange.bind(this);
this.onDescriptionChange = this.onDescriptionChange.bind(this);
this.submitForm = this.submitForm.bind(this);
2024-07-12 20:38:46 +02:00
this.onDnf1Change = this.onDnf1Change.bind(this)
this.onDnf2Change = this.onDnf2Change.bind(this)
2019-09-02 14:32:57 +02:00
}
toggleForm() {
this.setState({
showForm: !this.state.showForm,
error: '',
success: '',
isLoading: false,
});
}
onTitleChange(title: string) {
2019-09-02 14:32:57 +02:00
this.setState({
title,
error: '',
});
}
onDescriptionChange(description: string) {
2019-09-02 14:32:57 +02:00
this.setState({
description,
});
}
2024-07-12 20:38:46 +02:00
onDnf1Change(dnf1: string) {
this.setState({
dnf1,
});
}
onDnf2Change(dnf2: string) {
this.setState({
dnf2,
});
}
async submitForm(e: React.FormEvent) {
2019-09-02 14:32:57 +02:00
e.preventDefault();
this.setState({
error: '',
success: '',
isLoading: true,
});
const boardId = this.props.board.id;
2024-07-12 20:38:46 +02:00
const { authenticityToken, componentRenderedAt } = this.props;
const { title, description, isSubmissionAnonymous, dnf1, dnf2 } = this.state;
2019-09-02 14:32:57 +02:00
if (title === '') {
this.setState({
error: I18n.t('board.new_post.no_title'),
2019-09-02 14:32:57 +02:00
isLoading: false,
});
return;
}
try {
const res = await fetch('/posts', {
2019-09-02 14:32:57 +02:00
method: 'POST',
headers: buildRequestHeaders(authenticityToken),
2019-09-02 14:32:57 +02:00
body: JSON.stringify({
post: {
title,
description,
board_id: boardId,
2024-07-12 20:38:46 +02:00
is_anonymous: isSubmissionAnonymous,
dnf1,
dnf2,
form_rendered_at: componentRenderedAt,
2019-09-02 14:32:57 +02:00
},
}),
});
const json = await res.json();
2019-09-02 14:32:57 +02:00
this.setState({isLoading: false});
2022-05-01 18:00:38 +02:00
if (res.status === HttpStatus.Created) {
2024-07-12 20:38:46 +02:00
if (json.approval_status === POST_APPROVAL_STATUS_APPROVED) {
this.setState({
success: I18n.t('board.new_post.submit_success'),
});
2019-09-06 14:36:26 +02:00
2024-07-12 20:38:46 +02:00
setTimeout(() => (
window.location.href = `/posts/${json.slug || json.id}`
), 1000);
} else {
this.setState({
success: I18n.t('board.new_post.submit_pending'),
title: '',
description: '',
showForm: false,
});
}
2019-09-06 14:36:26 +02:00
} else {
this.setState({error: json.error});
}
2019-09-02 14:32:57 +02:00
} catch (e) {
this.setState({
error: I18n.t('common.errors.unknown')
2019-09-02 14:32:57 +02:00
});
}
}
render() {
2024-07-12 20:38:46 +02:00
const {
board,
isLoggedIn,
currentUserFullName,
isAnonymousFeedbackAllowed
} = this.props;
2019-09-02 14:32:57 +02:00
const {
showForm,
error,
success,
isLoading,
title,
2024-07-12 20:38:46 +02:00
description,
isSubmissionAnonymous,
dnf1,
dnf2,
2019-09-02 14:32:57 +02:00
} = this.state;
return (
<div className="newPostContainer sidebarBox">
2019-09-19 16:42:43 +02:00
<span className="boardTitle">{board.name}</span>
2022-06-06 20:20:03 +02:00
<ReactMarkdown
className="boardDescription"
disallowedTypes={['heading', 'image', 'html']}
unwrapDisallowed
>
{board.description}
</ReactMarkdown>
2024-07-12 20:38:46 +02:00
<Button
onClick={() => {
if (showForm) {
this.toggleForm();
return;
}
if (isLoggedIn) {
this.toggleForm();
this.setState({ isSubmissionAnonymous: false });
} else {
window.location.href = '/users/sign_in';
}
}}
className="submitBtn"
outline={showForm}
>
{
showForm ?
I18n.t('board.new_post.cancel_button')
:
I18n.t('board.new_post.submit_button')
}
</Button>
2019-09-02 14:32:57 +02:00
{
2024-07-12 20:38:46 +02:00
(isAnonymousFeedbackAllowed && !showForm) &&
<div className="anonymousFeedbackLink">
{I18n.t('common.words.or')}
&nbsp;
<a
onClick={() => {
this.toggleForm();
this.setState({ isSubmissionAnonymous: true });
}}
className="link"
>
{I18n.t('board.new_post.submit_anonymous_button').toLowerCase()}
</a>
</div>
2019-09-02 14:32:57 +02:00
}
{
showForm ?
<NewPostForm
title={title}
description={description}
handleTitleChange={this.onTitleChange}
handleDescriptionChange={this.onDescriptionChange}
2024-07-12 20:38:46 +02:00
2019-09-02 14:32:57 +02:00
handleSubmit={this.submitForm}
2024-07-12 20:38:46 +02:00
dnf1={dnf1}
dnf2={dnf2}
handleDnf1Change={this.onDnf1Change}
handleDnf2Change={this.onDnf2Change}
currentUserFullName={currentUserFullName}
isSubmissionAnonymous={isSubmissionAnonymous}
2019-09-02 14:32:57 +02:00
/>
:
null
}
{ isLoading ? <Spinner /> : null }
{ error ? <DangerText>{error}</DangerText> : null }
{ success ? <SuccessText>{success}</SuccessText> : null }
2019-09-02 14:32:57 +02:00
</div>
);
}
}
export default NewPost;