[next] Email (#2261)

* feat: suspending, banning, now propogation

* feat: added email rendering + localization support

* fix: fix related to lib

* refactor: moved juicer to queue task

* refactor: cleanup of job processor

* refactor: improved error messaging around failed email

* feat: initial forgot passwor impl

* fix: fixed rebase errors

* feat: send back Content-Language header with requests

* feat: added ban email

* feat: implemented forgotten password API

* fix: linting

* feat: support more emails

* fix: promise patches

* feat: initial confirm email API

* feat: added rate limiting

* feat: added URL support

* feat: added email docs

* fix: updated docs

* chore: documentation review

* fix: fixed build bug

* feat: implement forgot password in auth popup

* test: add tests + fixes

* chore: rename StatelessComponent to FunctionComponent

* fix: types and test fixes

* chore: upgrade deps

* fix: THANK YOU TESTS FOR SAVING MY A**

* chore: reorder imports

* chore: remove obsolete !

* feat: implement accounts bundle

* refactor: review suggestion

* fix: rebase upgrade error

* fix: rebase bug

* feat: reset password link support

* test: add tests for account password reset page

* fix: remove redirect uri

* fix: revert local state changes
This commit is contained in:
Wyatt Johnson
2019-05-09 22:54:56 +02:00
committed by Kiwi
parent 945bd7f2b0
commit df57b4eb17
487 changed files with 6794 additions and 2431 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import TabBarQuery from "talk-stream/queries/TabBarQuery";
import { HorizontalGutter, TabContent, TabPane } from "talk-ui/components";
@@ -15,7 +15,7 @@ export interface AppProps {
activeTab: TabValue;
}
const App: StatelessComponent<AppProps> = props => {
const App: FunctionComponent<AppProps> = props => {
return (
<HorizontalGutter className={styles.root}>
<TabBarQuery />
@@ -1,5 +1,5 @@
import cn from "classnames";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { createPurify } from "talk-common/utils/purify";
@@ -15,7 +15,7 @@ interface HTMLContentProps {
className?: string;
}
const HTMLContent: StatelessComponent<HTMLContentProps> = ({
const HTMLContent: FunctionComponent<HTMLContentProps> = ({
children,
className,
}) => (
@@ -1,5 +1,5 @@
import cn from "classnames";
import React, { ReactNode, StatelessComponent } from "react";
import React, { FunctionComponent, ReactNode } from "react";
import { withStyles } from "talk-ui/hocs";
import styles from "./MessageBox.css";
@@ -19,7 +19,7 @@ interface Props {
classes: typeof styles;
}
const MessageBox: StatelessComponent<Props> = props => {
const MessageBox: FunctionComponent<Props> = props => {
const { className, classes, children, ...rest } = props;
const rootClassName = cn(classes.root, className);
@@ -1,5 +1,5 @@
import cn from "classnames";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Markdown } from "talk-framework/components";
import { withStyles } from "talk-ui/hocs";
@@ -21,7 +21,7 @@ interface Props {
classes: typeof styles;
}
const MessageBox: StatelessComponent<Props> = props => {
const MessageBox: FunctionComponent<Props> = props => {
const { className, classes, children, ...rest } = props;
const rootClassName = cn(classes.root, className);
@@ -1,5 +1,5 @@
import cn from "classnames";
import React, { HTMLAttributes, Ref, StatelessComponent } from "react";
import React, { FunctionComponent, HTMLAttributes, Ref } from "react";
import Icon, { IconProps } from "talk-ui/components/Icon";
import { withForwardRef, withStyles } from "talk-ui/hocs";
@@ -23,7 +23,7 @@ interface Props extends Omit<HTMLAttributes<HTMLSpanElement>, "color"> {
forwardRef?: Ref<HTMLSpanElement>;
}
export const MessageBoxIcon: StatelessComponent<Props> = props => {
export const MessageBoxIcon: FunctionComponent<Props> = props => {
const { classes, className, forwardRef, ...rest } = props;
const rootClassName = cn(classes.root, className);
return <Icon className={rootClassName} {...rest} ref={forwardRef} />;
+2 -2
View File
@@ -1,6 +1,6 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { Icon, MatchMedia, Tab, TabBar } from "talk-ui/components";
type TabValue = "COMMENTS" | "PROFILE" | "%future added value";
@@ -13,7 +13,7 @@ export interface Props {
showConfigureTab: boolean;
}
const AppTabBar: StatelessComponent<Props> = props => {
const AppTabBar: FunctionComponent<Props> = props => {
return (
<TabBar activeTab={props.activeTab} onTabClick={props.onTabClick}>
<Tab tabId="COMMENTS">
@@ -1,5 +1,5 @@
import React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { RelativeTime } from "talk-ui/components";
@@ -9,7 +9,7 @@ export interface TimestampProps {
children: string;
}
const Timestamp: StatelessComponent<TimestampProps> = props => (
const Timestamp: FunctionComponent<TimestampProps> = props => (
<RelativeTime className={styles.root} date={props.children} />
);
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Button, Flex, Typography } from "talk-ui/components";
@@ -9,7 +9,7 @@ export interface UserBoxAuthenticatedProps {
showLogoutButton?: boolean;
}
const UserBoxAuthenticated: StatelessComponent<
const UserBoxAuthenticated: FunctionComponent<
UserBoxAuthenticatedProps
> = props => {
const Username = () => (
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Button, Flex, Typography } from "talk-ui/components";
import MatchMedia from "talk-ui/components/MatchMedia";
@@ -12,7 +12,7 @@ export interface UserBoxUnauthenticatedProps {
showRegisterButton?: boolean;
}
const UserBoxUnauthenticated: StatelessComponent<
const UserBoxUnauthenticated: FunctionComponent<
UserBoxUnauthenticatedProps
> = props => {
return (
+2 -2
View File
@@ -1,6 +1,6 @@
import { Child as PymChild } from "pym.js";
import React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import ReactDOM from "react-dom";
import { createManaged } from "talk-framework/lib/bootstrap";
@@ -34,7 +34,7 @@ async function main() {
pym: new PymChild({ polling: 100 }),
});
const Index: StatelessComponent = () => (
const Index: FunctionComponent = () => (
<ManagedTalkContextProvider>
<>
{listeners}
@@ -1,14 +1,12 @@
import { Component } from "react";
import { TalkContext, withContext } from "talk-framework/lib/bootstrap";
import {
SetAccessTokenMutation,
withSetAccessTokenMutation,
} from "talk-framework/mutations/SetAccessTokenMutation";
import { MutationProp, withMutation } from "talk-framework/lib/relay";
import { SetAccessTokenMutation } from "talk-framework/mutations";
interface Props {
postMessage: TalkContext["postMessage"];
setAccessToken: SetAccessTokenMutation;
setAccessToken: MutationProp<typeof SetAccessTokenMutation>;
}
export class OnPostMessageSetAccessToken extends Component<Props> {
@@ -26,6 +24,6 @@ export class OnPostMessageSetAccessToken extends Component<Props> {
}
const enhanced = withContext(({ postMessage }) => ({ postMessage }))(
withSetAccessTokenMutation(OnPostMessageSetAccessToken)
withMutation(SetAccessTokenMutation)(OnPostMessageSetAccessToken)
);
export default enhanced;
@@ -1,15 +1,13 @@
import { Child } from "pym.js";
import { Component } from "react";
import {
SetAccessTokenMutation,
withSetAccessTokenMutation,
} from "talk-framework/mutations";
import { withContext } from "talk-framework/lib/bootstrap";
import { MutationProp, withMutation } from "talk-framework/lib/relay";
import { SetAccessTokenMutation } from "talk-framework/mutations";
interface Props {
pym: Child;
setAccessToken: SetAccessTokenMutation;
setAccessToken: MutationProp<typeof SetAccessTokenMutation>;
}
export class OnPymLogin extends Component<Props> {
@@ -29,6 +27,6 @@ export class OnPymLogin extends Component<Props> {
const enhanced = withContext(({ pym }) => ({
pym,
}))(withSetAccessTokenMutation(OnPymLogin));
}))(withMutation(SetAccessTokenMutation)(OnPymLogin));
export default enhanced;
@@ -1,8 +1,3 @@
# Extend graph with local types
type Network {
isOffline: Boolean!
}
enum View {
SIGN_UP
SIGN_IN
@@ -28,7 +23,6 @@ extend type Comment {
}
type Local {
network: Network!
accessToken: String
accessTokenExp: Int
accessTokenJTI: String
@@ -1,8 +1,8 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Flex } from "talk-ui/components";
const ButtonsBar: StatelessComponent = props => {
const ButtonsBar: FunctionComponent = props => {
return (
<Flex direction="row" itemGutter="half">
{props.children}
@@ -1,5 +1,5 @@
import cn from "classnames";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import HTMLContent from "talk-stream/components/HTMLContent";
import Timestamp from "talk-stream/components/Timestamp";
@@ -25,7 +25,7 @@ export interface CommentProps {
tags?: ReadonlyArray<string>;
}
const Comment: StatelessComponent<CommentProps> = props => {
const Comment: FunctionComponent<CommentProps> = props => {
return (
<div
role="article"
@@ -1,9 +1,9 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import styles from "./EditedMarker.css";
const EditedMarker: StatelessComponent = () => (
const EditedMarker: FunctionComponent = () => (
<div className={styles.root}>
(
<Localized id="comments-editedMarker-edited">
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Flex, Icon, Typography } from "talk-ui/components";
@@ -9,7 +9,7 @@ interface Props {
username: string;
}
const InReplyTo: StatelessComponent<Props> = ({ username }) => {
const InReplyTo: FunctionComponent<Props> = ({ username }) => {
const Username = () => (
<Typography variant="heading5" container="span" className={styles.username}>
{username}
@@ -1,5 +1,5 @@
import cn from "classnames";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
@@ -13,7 +13,7 @@ export interface IndentedCommentProps extends PropTypesOf<typeof Comment> {
blur?: boolean;
}
const IndentedComment: StatelessComponent<IndentedCommentProps> = props => {
const IndentedComment: FunctionComponent<IndentedCommentProps> = props => {
const { indentLevel, ...rest } = props;
const CommentElement = <Comment {...rest} />;
const CommentwithIndent = (
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { EventHandler, MouseEvent, StatelessComponent } from "react";
import React, { EventHandler, FunctionComponent, MouseEvent } from "react";
import { Button, ButtonIcon, MatchMedia } from "talk-ui/components";
@@ -10,7 +10,7 @@ interface Props {
disabled?: boolean;
}
const ReplyButton: StatelessComponent<Props> = props => (
const ReplyButton: FunctionComponent<Props> = props => (
<Button
id={props.id}
onClick={props.onClick}
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import Timestamp from "talk-stream/components/Timestamp";
import { Flex, Tag } from "talk-ui/components";
@@ -13,7 +13,7 @@ export interface RootParentProps {
tags?: ReadonlyArray<string>;
}
const RootParent: StatelessComponent<RootParentProps> = props => {
const RootParent: FunctionComponent<RootParentProps> = props => {
return (
<Flex direction="row" justifyContent="space-between" id={props.id}>
<TopBarLeft>
@@ -1,5 +1,5 @@
import React, { EventHandler, MouseEvent } from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { Localized } from "fluent-react/compat";
import { Button } from "talk-ui/components";
@@ -10,7 +10,7 @@ export interface ShowConversationLinkProps {
onClick?: EventHandler<MouseEvent>;
}
const ShowConversationLink: StatelessComponent<
const ShowConversationLink: FunctionComponent<
ShowConversationLinkProps
> = props => {
return (
@@ -1,6 +1,6 @@
import cn from "classnames";
import React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { Flex, MatchMedia } from "talk-ui/components";
@@ -9,7 +9,7 @@ export interface TopBarLeftProps {
children: React.ReactNode;
}
const TopBarLeft: StatelessComponent<TopBarLeftProps> = props => {
const TopBarLeft: FunctionComponent<TopBarLeftProps> = props => {
const rootClassName = cn(props.className);
return (
<MatchMedia gtWidth="xs">
@@ -1,5 +1,5 @@
import React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { MatchMedia, Typography } from "talk-ui/components";
@@ -9,7 +9,7 @@ export interface UsernameProps {
children: string;
}
const Username: StatelessComponent<UsernameProps> = props => {
const Username: FunctionComponent<UsernameProps> = props => {
return (
<MatchMedia gtWidth="xs">
{matches => (
@@ -1,5 +1,5 @@
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import StreamQuery from "../queries/StreamQuery";
import PermalinkView from "../views/permalink";
@@ -8,7 +8,7 @@ export interface CommentsPaneProps {
showPermalinkView: boolean;
}
const CommentsPane: StatelessComponent<CommentsPaneProps> = props => {
const CommentsPane: FunctionComponent<CommentsPaneProps> = props => {
return props.showPermalinkView ? <PermalinkView /> : <StreamQuery />;
};
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Markdown } from "talk-framework/components";
import { CallOut } from "talk-ui/components";
@@ -7,7 +7,7 @@ interface Props {
children: string;
}
const CommunityGuidelines: StatelessComponent<Props> = props => {
const CommunityGuidelines: FunctionComponent<Props> = props => {
return (
<CallOut color="primary" fullWidth>
<Markdown>{props.children}</Markdown>
@@ -1,6 +1,6 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import * as styles from "./Divider.css";
const Divider: StatelessComponent = () => <hr className={styles.root} />;
const Divider: FunctionComponent = () => <hr className={styles.root} />;
export default Divider;
@@ -1,11 +1,6 @@
import { CoralRTE } from "@coralproject/rte";
import { Localized } from "fluent-react/compat";
import React, {
EventHandler,
MouseEvent,
Ref,
StatelessComponent,
} from "react";
import React, { EventHandler, FunctionComponent, MouseEvent, Ref } from "react";
import { Field, Form } from "react-final-form";
import { OnSubmit } from "talk-framework/lib/form";
@@ -49,7 +44,7 @@ export interface EditCommentFormProps {
max: number | null;
}
const EditCommentForm: StatelessComponent<EditCommentFormProps> = props => {
const EditCommentForm: FunctionComponent<EditCommentFormProps> = props => {
const inputID = `comments-editCommentForm-rte-${props.id}`;
return (
<Form onSubmit={props.onSubmit} initialValues={props.initialValues}>
@@ -1,5 +1,5 @@
import cn from "classnames";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import styles from "./Indent.css";
@@ -27,7 +27,7 @@ function getLevelClassName(level: number = 0) {
return levels[level];
}
const Indent: StatelessComponent<IndentProps> = props => {
const Indent: FunctionComponent<IndentProps> = props => {
return (
<div className={cn(props.className, styles.root)}>
<div
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import {
Button,
@@ -18,7 +18,7 @@ interface PermalinkProps {
url: string;
}
const Permalink: StatelessComponent<PermalinkProps> = ({ commentID, url }) => {
const Permalink: FunctionComponent<PermalinkProps> = ({ commentID, url }) => {
const popoverID = `permalink-popover-${commentID}`;
return (
<Localized id="comments-permalinkPopover" attrs={{ description: true }}>
@@ -1,6 +1,6 @@
import { FormApi, FormState } from "final-form";
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Field, Form, FormSpy } from "react-final-form";
import { PropTypesOf } from "talk-framework/types";
@@ -33,7 +33,7 @@ interface Props {
story: PropTypesOf<typeof MessageBoxContainer>["story"];
}
const PostCommentForm: StatelessComponent<Props> = props => (
const PostCommentForm: FunctionComponent<Props> = props => (
<div>
{props.showMessageBox && (
<MessageBoxContainer story={props.story} className={styles.messageBox} />
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Markdown } from "talk-framework/components";
import { PropTypesOf } from "talk-framework/types";
@@ -13,7 +13,7 @@ interface Props {
showMessageBox?: boolean;
story: PropTypesOf<typeof MessageBoxContainer>["story"];
}
const PostCommentFormClosed: StatelessComponent<Props> = props => (
const PostCommentFormClosed: FunctionComponent<Props> = props => (
<div>
{props.showMessageBox && (
<MessageBoxContainer story={props.story} className={styles.messageBox} />
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Markdown } from "talk-framework/components";
import { PropTypesOf } from "talk-framework/types";
@@ -13,7 +13,7 @@ interface Props {
showMessageBox?: boolean;
story: PropTypesOf<typeof MessageBoxContainer>["story"];
}
const PostCommentFormClosedSitewide: StatelessComponent<Props> = props => (
const PostCommentFormClosedSitewide: FunctionComponent<Props> = props => (
<HorizontalGutter size="double">
<CallOut fullWidth className={styles.root}>
<Markdown className={styles.message}>{props.message}</Markdown>
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import { Button, HorizontalGutter } from "talk-ui/components";
@@ -14,7 +14,7 @@ interface Props {
story: PropTypesOf<typeof MessageBoxContainer>["story"];
}
const PostCommentFormFake: StatelessComponent<Props> = props => (
const PostCommentFormFake: FunctionComponent<Props> = props => (
<div>
{props.showMessageBox && (
<MessageBoxContainer story={props.story} className={styles.messageBox} />
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Button, Flex, Message } from "talk-ui/components";
@@ -9,7 +9,7 @@ export interface PostCommentInReviewProps {
onDismiss: () => void;
}
const PostCommentInReview: StatelessComponent<
const PostCommentInReview: FunctionComponent<
PostCommentInReviewProps
> = props => {
return (
@@ -1,13 +1,13 @@
import cn from "classnames";
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Typography } from "talk-ui/components";
interface Props {
className: string;
}
const PoweredBy: StatelessComponent<Props> = props => {
const PoweredBy: FunctionComponent<Props> = props => {
return (
<div className={cn(props.className)}>
<Localized
@@ -1,6 +1,6 @@
import { Blockquote, Bold, CoralRTE, Italic } from "@coralproject/rte";
import { Localized as LocalizedOriginal } from "fluent-react/compat";
import React, { Ref, StatelessComponent } from "react";
import React, { FunctionComponent, Ref } from "react";
import { Icon } from "talk-ui/components";
import { PropTypesOf } from "talk-ui/types";
@@ -78,7 +78,7 @@ const features = [
];
// tslint:enable:jsx-wrap-multiline
const RTE: StatelessComponent<RTEProps> = props => {
const RTE: FunctionComponent<RTEProps> = props => {
const {
className,
fullWidth,
@@ -1,6 +1,6 @@
import cn from "classnames";
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Flex, Icon, Typography } from "talk-ui/components";
interface Props {
@@ -8,7 +8,7 @@ interface Props {
remaining: number;
}
const RemainingCharacters: StatelessComponent<Props> = props => {
const RemainingCharacters: FunctionComponent<Props> = props => {
const belowZero = props.remaining < 0;
return (
<Flex
@@ -1,12 +1,7 @@
import { CoralRTE } from "@coralproject/rte";
import { FormApi, FormState } from "final-form";
import { Localized } from "fluent-react/compat";
import React, {
EventHandler,
MouseEvent,
Ref,
StatelessComponent,
} from "react";
import React, { EventHandler, FunctionComponent, MouseEvent, Ref } from "react";
import { Field, Form, FormSpy } from "react-final-form";
import { OnSubmit } from "talk-framework/lib/form";
@@ -43,7 +38,7 @@ export interface ReplyCommentFormProps {
disabledMessage?: React.ReactNode;
}
const ReplyCommentForm: StatelessComponent<ReplyCommentFormProps> = props => {
const ReplyCommentForm: FunctionComponent<ReplyCommentFormProps> = props => {
const inputID = `comments-replyCommentForm-rte-${props.id}`;
return (
<Form onSubmit={props.onSubmit} initialValues={props.initialValues}>
@@ -1,6 +1,6 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import { Button, HorizontalGutter } from "talk-ui/components";
@@ -30,7 +30,7 @@ export interface ReplyListProps {
disableReplies?: boolean;
}
const ReplyList: StatelessComponent<ReplyListProps> = props => {
const ReplyList: FunctionComponent<ReplyListProps> = props => {
return (
<HorizontalGutter
id={`talk-comments-replyList-log--${props.comment.id}`}
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Flex, Icon, Typography } from "talk-ui/components";
@@ -9,7 +9,7 @@ interface Props {
username: string;
}
const ReplyTo: StatelessComponent<Props> = ({ username }) => {
const ReplyTo: FunctionComponent<Props> = ({ username }) => {
const Username = () => (
<Typography variant="heading4" container="span" className={styles.username}>
{username}
@@ -13,7 +13,7 @@ interface Props {
reported: boolean;
}
const ReportButtonWithPopover: React.StatelessComponent<Props> = ({
const ReportButtonWithPopover: React.FunctionComponent<Props> = ({
comment,
reported,
}) => {
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import {
Flex,
@@ -24,7 +24,7 @@ interface Props {
reactionSortLabel: string;
}
const SortMenu: StatelessComponent<Props> = props => (
const SortMenu: FunctionComponent<Props> = props => (
<MatchMedia ltWidth="sm">
{matches => (
<div>
@@ -1,6 +1,6 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import * as styles from "./Divider.css";
const Divider: StatelessComponent = () => <hr className={styles.root} />;
const Divider: FunctionComponent = () => <hr className={styles.root} />;
export default Divider;
@@ -1,6 +1,6 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import UserBoxContainer from "talk-stream/containers/UserBoxContainer";
@@ -47,7 +47,7 @@ export interface StreamProps {
refetching?: boolean;
}
const Stream: StatelessComponent<StreamProps> = props => {
const Stream: FunctionComponent<StreamProps> = props => {
return (
<HorizontalGutter className={styles.root} size="double">
<UserBoxContainer viewer={props.viewer} settings={props.settings} />
@@ -1,5 +1,5 @@
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { graphql, withLocalStateContainer } from "talk-framework/lib/relay";
import { CommentsPaneContainerLocal as Local } from "talk-stream/__generated__/CommentsPaneContainerLocal.graphql";
@@ -10,7 +10,7 @@ interface Props {
local: Local;
}
const CommentsPaneContainer: StatelessComponent<Props> = ({
const CommentsPaneContainer: FunctionComponent<Props> = ({
local: { commentID },
}) => {
return <CommentsPane showPermalinkView={!!commentID} />;
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { withFragmentContainer } from "talk-framework/lib/relay";
import { CommunityGuidelinesContainer_settings as SettingsData } from "talk-stream/__generated__/CommunityGuidelinesContainer_settings.graphql";
@@ -9,7 +9,7 @@ interface Props {
settings: SettingsData;
}
export const CommunityGuidelinesContainerProps: StatelessComponent<Props> = ({
export const CommunityGuidelinesContainerProps: FunctionComponent<Props> = ({
settings,
}) => {
if (
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { withFragmentContainer } from "talk-framework/lib/relay";
@@ -14,7 +14,7 @@ interface Props {
className?: string;
}
const MessageBoxContainer: StatelessComponent<Props> = ({
const MessageBoxContainer: FunctionComponent<Props> = ({
story,
className,
}) => {
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { graphql } from "react-relay";
import { getURLWithCommentID } from "talk-framework/helpers";
import { withFragmentContainer } from "talk-framework/lib/relay";
@@ -11,7 +11,7 @@ interface Props {
commentID: string;
}
export const PermalinkButtonContainer: StatelessComponent<Props> = ({
export const PermalinkButtonContainer: FunctionComponent<Props> = ({
story,
commentID,
}) => {
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import RemainingCharacters from "../components/RemainingCharacters";
import { getHTMLCharacterLength } from "../helpers";
@@ -9,7 +9,7 @@ interface Props {
value: string | undefined;
}
const RemainingCharactersContainer: StatelessComponent<Props> = props => {
const RemainingCharactersContainer: FunctionComponent<Props> = props => {
return (
<RemainingCharacters
className={props.className}
@@ -1,8 +1,9 @@
import React from "react";
import React, { FunctionComponent } from "react";
import { graphql, GraphQLTaggedNode, RelayPaginationProp } from "react-relay";
import { withProps } from "recompose";
import { withPaginationContainer } from "talk-framework/lib/relay";
import { FragmentKeys } from "talk-framework/lib/relay/types";
import { Omit, PropTypesOf } from "talk-framework/types";
import { ReplyListContainer1_comment as CommentData } from "talk-stream/__generated__/ReplyListContainer1_comment.graphql";
import { ReplyListContainer1_settings as SettingsData } from "talk-stream/__generated__/ReplyListContainer1_settings.graphql";
@@ -11,8 +12,6 @@ import { ReplyListContainer1_viewer as ViewerData } from "talk-stream/__generate
import { ReplyListContainer1PaginationQueryVariables } from "talk-stream/__generated__/ReplyListContainer1PaginationQuery.graphql";
import { ReplyListContainer5_comment as Comment5Data } from "talk-stream/__generated__/ReplyListContainer5_comment.graphql";
import { StatelessComponent } from "enzyme";
import { FragmentKeys } from "talk-framework/lib/relay/types";
import ReplyList from "../components/ReplyList";
import { isCommentVisible } from "../helpers";
import LocalReplyListContainer from "./LocalReplyListContainer";
@@ -155,7 +154,7 @@ function createReplyListContainer(
/**
* LastReplyList uses the LocalReplyListContainer.
*/
const LastReplyList: StatelessComponent<
const LastReplyList: FunctionComponent<
PropTypesOf<typeof LocalReplyListContainer>
> = props => <LocalReplyListContainer {...props} indentLevel={6} />;
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { ReadyState } from "react-relay";
import {
graphql,
@@ -50,7 +50,7 @@ export const render = (
);
};
const StreamQuery: StatelessComponent<Props> = props => {
const StreamQuery: FunctionComponent<Props> = props => {
const {
local: { storyID, storyURL, defaultStreamOrderBy },
} = props;
@@ -1,6 +1,6 @@
import cn from "classnames";
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import { Button, Counter, Flex, HorizontalGutter } from "talk-ui/components";
@@ -36,7 +36,7 @@ export interface ConversationThreadProps {
} | null;
}
const ConversationThread: StatelessComponent<
const ConversationThread: FunctionComponent<
ConversationThreadProps
> = props => {
const dataTestID = "comments-permalinkView-conversationThread";
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { MouseEvent, StatelessComponent } from "react";
import React, { FunctionComponent, MouseEvent } from "react";
import { PropTypesOf } from "talk-framework/types";
import { Button, Flex, HorizontalGutter, Typography } from "talk-ui/components";
@@ -28,7 +28,7 @@ export interface PermalinkViewProps {
onShowAllComments: (e: MouseEvent<any>) => void;
}
const PermalinkView: StatelessComponent<PermalinkViewProps> = ({
const PermalinkView: FunctionComponent<PermalinkViewProps> = ({
showAllCommentsHref,
comment,
settings,
@@ -1,6 +1,6 @@
import cn from "classnames";
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import styles from "./Circle.css";
@@ -10,7 +10,7 @@ export interface CircleProps {
end?: boolean;
}
const Circle: StatelessComponent<CircleProps> = props => {
const Circle: FunctionComponent<CircleProps> = props => {
return (
<div className={cn(styles.circleContainer, props.className)}>
<div
@@ -1,6 +1,6 @@
import cn from "classnames";
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import styles from "./Line.css";
@@ -9,7 +9,7 @@ interface LineProps {
dotted?: boolean;
}
const Line: StatelessComponent<LineProps> = props => {
const Line: FunctionComponent<LineProps> = props => {
return (
<div
className={cn(styles.root, props.className, {
@@ -1,6 +1,6 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { ReadyState } from "react-relay";
import {
@@ -49,7 +49,7 @@ export const render = ({
);
};
const PermalinkViewQuery: StatelessComponent<Props> = ({
const PermalinkViewQuery: FunctionComponent<Props> = ({
local: { commentID, storyID, storyURL },
}) => (
<QueryRenderer<QueryTypes>
@@ -1,6 +1,6 @@
import { Localized } from "fluent-react/compat";
import { get } from "lodash";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Field, Form } from "react-final-form";
import { OnSubmit } from "talk-framework/lib/form";
@@ -18,7 +18,7 @@ import {
import PropagateMount from "./PropagateMount";
import styles from "./ReportCommentForm.css";
const RadioField: StatelessComponent<
const RadioField: FunctionComponent<
Pick<
PropTypesOf<typeof Field>,
"validate" | "name" | "value" | "disabled" | "children"
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Button, HorizontalGutter, Typography } from "talk-ui/components";
@@ -12,7 +12,7 @@ interface Props {
class ReportForm extends React.Component<Props> {
public render() {
const { onDismiss } = this.props;
const Content: StatelessComponent = ({ children }) => (
const Content: FunctionComponent = ({ children }) => (
<Typography variant="bodyCopy">
{children}
{" "}
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Button, Flex, Typography } from "talk-ui/components";
@@ -10,7 +10,7 @@ interface Props {
disableButton?: boolean;
}
const CloseStream: StatelessComponent<Props> = ({ onClick, disableButton }) => (
const CloseStream: FunctionComponent<Props> = ({ onClick, disableButton }) => (
<div>
<Localized id="configure-closeStream-title">
<Typography variant="heading2" className={styles.heading}>
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import UserBoxContainer from "talk-stream/containers/UserBoxContainer";
@@ -15,7 +15,7 @@ export interface Props {
PropTypesOf<typeof OpenOrCloseStreamContainer>["story"];
}
const Configure: StatelessComponent<Props> = props => {
const Configure: FunctionComponent<Props> = props => {
return (
<div>
<HorizontalGutter size="double">
@@ -1,6 +1,6 @@
import { FormApi } from "final-form";
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Form } from "react-final-form";
import { FormInitializer } from "talk-framework/lib/form";
@@ -26,7 +26,7 @@ interface Props {
PropTypesOf<typeof MessageBoxConfigContainer>["storySettings"];
}
const ConfigureStream: StatelessComponent<Props> = ({
const ConfigureStream: FunctionComponent<Props> = ({
onSubmit,
storySettings,
}) => (
@@ -1,8 +1,8 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import styles from "./HorizontalRule.css";
const HorizontalRule: StatelessComponent = ({ children }) => (
const HorizontalRule: FunctionComponent = ({ children }) => (
<hr className={styles.root} />
);
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent, Suspense } from "react";
import React, { FunctionComponent, Suspense } from "react";
import { Field } from "react-final-form";
import { MarkdownEditor } from "talk-framework/components/loadables";
@@ -32,7 +32,7 @@ interface Props {
disabled: boolean;
}
const MessageBoxConfig: StatelessComponent<Props> = ({ disabled }) => (
const MessageBoxConfig: FunctionComponent<Props> = ({ disabled }) => (
<Field name="messageBox.enabled" type="checkbox" parse={parseBool}>
{({ input }) => (
<ToggleConfig
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Button, Flex, Typography } from "talk-ui/components";
@@ -10,7 +10,7 @@ interface Props {
disableButton?: boolean;
}
const OpenStream: StatelessComponent<Props> = ({ onClick, disableButton }) => (
const OpenStream: FunctionComponent<Props> = ({ onClick, disableButton }) => (
<div>
<Localized id="configure-openStream-title">
<Typography variant="heading2" className={styles.heading}>
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Field } from "react-final-form";
import ToggleConfig from "./ToggleConfig";
@@ -17,7 +17,7 @@ const format = (v: "PRE" | "POST") => {
return v === "PRE";
};
const PremodConfig: StatelessComponent<Props> = ({ disabled }) => (
const PremodConfig: FunctionComponent<Props> = ({ disabled }) => (
<Field name="moderation" type="checkbox" parse={parse} format={format}>
{({ input }) => (
<ToggleConfig
@@ -1,5 +1,5 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Field } from "react-final-form";
import { parseBool } from "talk-framework/lib/form";
@@ -10,7 +10,7 @@ interface Props {
disabled: boolean;
}
const PremodLinksConfig: StatelessComponent<Props> = ({ disabled }) => (
const PremodLinksConfig: FunctionComponent<Props> = ({ disabled }) => (
<Field name="premodLinksEnable" type="checkbox" parse={parseBool}>
{({ input }) => (
<ToggleConfig
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Omit, PropTypesOf } from "talk-framework/types";
import { CheckBox, Typography } from "talk-ui/components";
@@ -10,7 +10,7 @@ export interface Props extends Omit<PropTypesOf<typeof CheckBox>, "children"> {
children?: React.ReactNode;
}
const ToggleConfig: StatelessComponent<Props> = props => {
const ToggleConfig: FunctionComponent<Props> = props => {
const { title, children, ...rest } = props;
return (
<div>
@@ -1,4 +1,4 @@
import React, { StatelessComponent } from "react";
import React, { FunctionComponent } from "react";
import { Omit, PropTypesOf } from "talk-framework/types";
import { CheckBox, Typography } from "talk-ui/components";
@@ -9,7 +9,7 @@ export interface Props extends Omit<PropTypesOf<typeof CheckBox>, "children"> {
children?: React.ReactNode;
}
const WidthLimitedDescription: StatelessComponent<Props> = props => {
const WidthLimitedDescription: FunctionComponent<Props> = props => {
return (
<Typography variant="detail" color="textSecondary" className={styles.root}>
{props.children}
@@ -1,6 +1,6 @@
import { Localized } from "fluent-react/compat";
import { once } from "lodash";
import React, { StatelessComponent, Suspense } from "react";
import React, { FunctionComponent, Suspense } from "react";
import { ReadyState } from "react-relay";
import {
@@ -71,7 +71,7 @@ export const render = ({
);
};
const ConfigureQuery: StatelessComponent<Props> = ({
const ConfigureQuery: FunctionComponent<Props> = ({
local: { storyID, storyURL },
}) => (
<QueryRenderer<QueryTypes>
@@ -1,6 +1,6 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import { Button, HorizontalGutter, Typography } from "talk-ui/components";
@@ -16,7 +16,7 @@ interface CommentHistoryProps {
disableLoadMore?: boolean;
}
const CommentHistory: StatelessComponent<CommentHistoryProps> = props => {
const CommentHistory: FunctionComponent<CommentHistoryProps> = props => {
return (
<HorizontalGutter size="double" data-testid="profile-commentHistory">
<Localized id="profile-historyComment-commentHistory">
@@ -1,6 +1,6 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import Timestamp from "talk-stream/components/Timestamp";
import {
Flex,
@@ -28,7 +28,7 @@ export interface HistoryCommentProps {
onGotoConversation: (e: React.MouseEvent) => void;
}
const HistoryComment: StatelessComponent<HistoryCommentProps> = props => {
const HistoryComment: FunctionComponent<HistoryCommentProps> = props => {
return (
<HorizontalGutter data-testid={`historyComment-${props.id}`}>
<Localized
@@ -1,5 +1,5 @@
import * as React from "react";
import { StatelessComponent } from "react";
import { FunctionComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import UserBoxContainer from "talk-stream/containers/UserBoxContainer";
import { HorizontalGutter } from "talk-ui/components";
@@ -12,7 +12,7 @@ export interface ProfileProps {
settings: PropTypesOf<typeof UserBoxContainer>["settings"];
}
const Profile: StatelessComponent<ProfileProps> = props => {
const Profile: FunctionComponent<ProfileProps> = props => {
return (
<HorizontalGutter size="double">
<UserBoxContainer viewer={props.viewer} settings={props.settings} />
@@ -1,6 +1,6 @@
import { Localized } from "fluent-react/compat";
import { once } from "lodash";
import React, { StatelessComponent, Suspense } from "react";
import React, { FunctionComponent, Suspense } from "react";
import { ReadyState } from "react-relay";
import {
@@ -67,7 +67,7 @@ export const render = ({
);
};
const ProfileQuery: StatelessComponent<Props> = ({
const ProfileQuery: FunctionComponent<Props> = ({
local: { storyID, storyURL },
}) => (
<QueryRenderer<QueryTypes>