mirror of
https://github.com/astuto/astuto.git
synced 2025-12-16 03:37:56 +01:00
Post follow and updates notifications V1 (#111)
* It is now possible to follow a post in order to receive updates about it * Notifications are now sent when updates are published * Post status changes are now tracked * Update sidebar now shows the post status history * Mark a comment as a post update using the comment form * ... more ...
This commit is contained in:
committed by
GitHub
parent
ce7be1b30c
commit
dad382d2b1
@@ -7,7 +7,7 @@ import { MutedText } from '../shared/CustomTexts';
|
||||
|
||||
import { ReplyFormState } from '../../reducers/replyFormReducer';
|
||||
|
||||
import friendlyDate from '../../helpers/friendlyDate';
|
||||
import friendlyDate from '../../helpers/datetime';
|
||||
|
||||
interface Props {
|
||||
id: number;
|
||||
@@ -21,7 +21,7 @@ interface Props {
|
||||
handleToggleCommentReply(): void;
|
||||
handleCommentReplyBodyChange(e: React.FormEvent): void;
|
||||
handleToggleIsCommentUpdate(commentId: number, currentIsPostUpdate: boolean): void;
|
||||
handleSubmitComment(body: string, parentId: number): void;
|
||||
handleSubmitComment(body: string, parentId: number, isPostUpdate: boolean): void;
|
||||
|
||||
isLoggedIn: boolean;
|
||||
isPowerUser: boolean;
|
||||
@@ -48,7 +48,7 @@ const Comment = ({
|
||||
}: Props) => (
|
||||
<div className="comment">
|
||||
<div className="commentHeader">
|
||||
<Gravatar email={userEmail} size={24} className="gravatar" />
|
||||
<Gravatar email={userEmail} size={28} className="gravatar" />
|
||||
<span className="commentAuthor">{userFullName}</span>
|
||||
{ isPostUpdate ? <span className="postUpdateBadge">Post update</span> : null }
|
||||
</div>
|
||||
@@ -89,12 +89,15 @@ const Comment = ({
|
||||
<NewComment
|
||||
body={replyForm.body}
|
||||
parentId={id}
|
||||
postUpdateFlagValue={replyForm.isPostUpdate}
|
||||
isSubmitting={replyForm.isSubmitting}
|
||||
error={replyForm.error}
|
||||
handleChange={handleCommentReplyBodyChange}
|
||||
handlePostUpdateFlag={() => null}
|
||||
handleSubmit={handleSubmitComment}
|
||||
|
||||
isLoggedIn={isLoggedIn}
|
||||
isPowerUser={isPowerUser}
|
||||
userEmail={currentUserEmail}
|
||||
/>
|
||||
:
|
||||
|
||||
@@ -14,7 +14,7 @@ interface Props {
|
||||
toggleCommentReply(commentId: number): void;
|
||||
setCommentReplyBody(commentId: number, body: string): void;
|
||||
handleToggleIsCommentUpdate(commentId: number, currentIsPostUpdate: boolean): void;
|
||||
handleSubmitComment(body: string, parentId: number): void;
|
||||
handleSubmitComment(body: string, parentId: number, isPostUpdate: boolean): void;
|
||||
|
||||
isLoggedIn: boolean;
|
||||
isPowerUser: boolean;
|
||||
|
||||
@@ -23,6 +23,7 @@ interface Props {
|
||||
requestComments(postId: number, page?: number): void;
|
||||
toggleCommentReply(commentId: number): void;
|
||||
setCommentReplyBody(commentId: number, body: string): void;
|
||||
toggleCommentIsPostUpdateFlag(): void;
|
||||
toggleCommentIsPostUpdate(
|
||||
postId: number,
|
||||
commentId: number,
|
||||
@@ -33,6 +34,7 @@ interface Props {
|
||||
postId: number,
|
||||
body: string,
|
||||
parentId: number,
|
||||
isPostUpdate: boolean,
|
||||
authenticityToken: string,
|
||||
): void;
|
||||
}
|
||||
@@ -51,11 +53,12 @@ class CommentsP extends React.Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
_handleSubmitComment = (body: string, parentId: number) => {
|
||||
_handleSubmitComment = (body: string, parentId: number, isPostUpdate: boolean) => {
|
||||
this.props.submitComment(
|
||||
this.props.postId,
|
||||
body,
|
||||
parentId,
|
||||
isPostUpdate,
|
||||
this.props.authenticityToken,
|
||||
);
|
||||
}
|
||||
@@ -73,6 +76,7 @@ class CommentsP extends React.Component<Props> {
|
||||
|
||||
toggleCommentReply,
|
||||
setCommentReplyBody,
|
||||
toggleCommentIsPostUpdateFlag,
|
||||
} = this.props;
|
||||
|
||||
const postReply = replyForms.find(replyForm => replyForm.commentId === null);
|
||||
@@ -82,6 +86,7 @@ class CommentsP extends React.Component<Props> {
|
||||
<NewComment
|
||||
body={postReply && postReply.body}
|
||||
parentId={null}
|
||||
postUpdateFlagValue={postReply && postReply.isPostUpdate}
|
||||
isSubmitting={postReply && postReply.isSubmitting}
|
||||
error={postReply && postReply.error}
|
||||
handleChange={
|
||||
@@ -89,9 +94,11 @@ class CommentsP extends React.Component<Props> {
|
||||
setCommentReplyBody(null, (e.target as HTMLTextAreaElement).value)
|
||||
)
|
||||
}
|
||||
handlePostUpdateFlag={toggleCommentIsPostUpdateFlag}
|
||||
handleSubmit={this._handleSubmitComment}
|
||||
|
||||
isLoggedIn={isLoggedIn}
|
||||
isPowerUser={isPowerUser}
|
||||
userEmail={userEmail}
|
||||
/>
|
||||
|
||||
@@ -99,7 +106,7 @@ class CommentsP extends React.Component<Props> {
|
||||
{ error ? <DangerText>{error}</DangerText> : null }
|
||||
|
||||
<div className="commentsTitle">
|
||||
activity • {comments.length} comments
|
||||
activity • {comments.length} comment{comments.length === 1 ? '' : 's'}
|
||||
</div>
|
||||
|
||||
<CommentList
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import Gravatar from 'react-gravatar';
|
||||
|
||||
import NewCommentUpdateSection from './NewCommentUpdateSection';
|
||||
|
||||
import Button from '../shared/Button';
|
||||
import Spinner from '../shared/Spinner';
|
||||
import { DangerText } from '../shared/CustomTexts';
|
||||
@@ -8,24 +10,34 @@ import { DangerText } from '../shared/CustomTexts';
|
||||
interface Props {
|
||||
body: string;
|
||||
parentId: number;
|
||||
postUpdateFlagValue: boolean;
|
||||
isSubmitting: boolean;
|
||||
error: string;
|
||||
handleChange(e: React.FormEvent): void;
|
||||
handleSubmit(body: string, parentId: number): void;
|
||||
handlePostUpdateFlag(): void;
|
||||
handleSubmit(
|
||||
body: string,
|
||||
parentId: number,
|
||||
isPostUpdate: boolean
|
||||
): void;
|
||||
|
||||
isLoggedIn: boolean;
|
||||
isPowerUser: boolean;
|
||||
userEmail: string;
|
||||
}
|
||||
|
||||
const NewComment = ({
|
||||
body,
|
||||
parentId,
|
||||
postUpdateFlagValue,
|
||||
isSubmitting,
|
||||
error,
|
||||
handleChange,
|
||||
handlePostUpdateFlag,
|
||||
handleSubmit,
|
||||
|
||||
isLoggedIn,
|
||||
isPowerUser,
|
||||
userEmail,
|
||||
}: Props) => (
|
||||
<React.Fragment>
|
||||
@@ -33,18 +45,29 @@ const NewComment = ({
|
||||
{
|
||||
isLoggedIn ?
|
||||
<React.Fragment>
|
||||
<Gravatar email={userEmail} size={36} className="currentUserAvatar" />
|
||||
<textarea
|
||||
value={body}
|
||||
onChange={handleChange}
|
||||
placeholder="Leave a comment"
|
||||
className="newCommentBody"
|
||||
/>
|
||||
<Button
|
||||
onClick={() => handleSubmit(body, parentId)}
|
||||
className="submitCommentButton">
|
||||
{ isSubmitting ? <Spinner color="light" /> : 'Submit' }
|
||||
</Button>
|
||||
<div className="commentBodyForm">
|
||||
<Gravatar email={userEmail} size={48} className="currentUserAvatar" />
|
||||
<textarea
|
||||
value={body}
|
||||
onChange={handleChange}
|
||||
placeholder="Leave a comment"
|
||||
className="newCommentBody"
|
||||
/>
|
||||
<Button
|
||||
onClick={() => handleSubmit(body, parentId, postUpdateFlagValue)}
|
||||
className="submitCommentButton">
|
||||
{ isSubmitting ? <Spinner color="light" /> : 'Submit' }
|
||||
</Button>
|
||||
</div>
|
||||
{
|
||||
isPowerUser && parentId == null ?
|
||||
<NewCommentUpdateSection
|
||||
postUpdateFlagValue={postUpdateFlagValue}
|
||||
handlePostUpdateFlag={handlePostUpdateFlag}
|
||||
/>
|
||||
:
|
||||
null
|
||||
}
|
||||
</React.Fragment>
|
||||
:
|
||||
<a href="/users/sign_in" className="loginInfo">You need to log in to post comments.</a>
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import * as React from 'react';
|
||||
import { MutedText } from '../shared/CustomTexts';
|
||||
|
||||
interface Props {
|
||||
postUpdateFlagValue: boolean;
|
||||
handlePostUpdateFlag(): void;
|
||||
}
|
||||
|
||||
const NewCommentUpdateSection = ({
|
||||
postUpdateFlagValue,
|
||||
handlePostUpdateFlag,
|
||||
}: Props) => (
|
||||
<div className="commentIsUpdateForm">
|
||||
<div>
|
||||
<input
|
||||
id="isPostUpdateFlag"
|
||||
type="checkbox"
|
||||
onChange={handlePostUpdateFlag}
|
||||
checked={postUpdateFlagValue || false}
|
||||
/>
|
||||
|
||||
<label htmlFor="isPostUpdateFlag">Mark as post update</label>
|
||||
</div>
|
||||
{
|
||||
postUpdateFlagValue ?
|
||||
<MutedText>Users that follow this post will be notified</MutedText>
|
||||
:
|
||||
null
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default NewCommentUpdateSection;
|
||||
Reference in New Issue
Block a user