Merge branch 'next' into next-respect

This commit is contained in:
Chi Vinh Le
2018-10-04 19:15:00 +02:00
102 changed files with 13134 additions and 9240 deletions
+10
View File
@@ -0,0 +1,10 @@
const path = require("path");
module.exports = {
extends: "../.babelrc.js",
plugins: [
[
"babel-plugin-relay",
{ artifactDirectory: path.resolve(__dirname, "./__generated__") },
],
],
};
+4
View File
@@ -0,0 +1,4 @@
.root {
width: 1080px;
margin: 0 auto;
}
+13
View File
@@ -0,0 +1,13 @@
import React, { StatelessComponent } from "react";
import { HorizontalGutter } from "talk-ui/components";
import styles from "./App.css";
import Navigation from "./Navigation";
const App: StatelessComponent = ({ children }) => (
<HorizontalGutter className={styles.root}>
<Navigation />
{children}
</HorizontalGutter>
);
export default App;
@@ -0,0 +1,10 @@
import React, { StatelessComponent } from "react";
import { HorizontalGutter, Typography } from "talk-ui/components";
const Community: StatelessComponent = ({ children }) => (
<HorizontalGutter>
<Typography variant="heading3">Community</Typography>
</HorizontalGutter>
);
export default Community;
@@ -0,0 +1,10 @@
import React, { StatelessComponent } from "react";
import { HorizontalGutter, Typography } from "talk-ui/components";
const Configure: StatelessComponent = ({ children }) => (
<HorizontalGutter>
<Typography variant="heading3">Configure</Typography>
</HorizontalGutter>
);
export default Configure;
@@ -0,0 +1,10 @@
import React, { StatelessComponent } from "react";
import { HorizontalGutter, Typography } from "talk-ui/components";
const Moderate: StatelessComponent = ({ children }) => (
<HorizontalGutter>
<Typography variant="heading3">Moderate</Typography>
</HorizontalGutter>
);
export default Moderate;
@@ -0,0 +1,7 @@
.link {
text-decoration: none;
}
.active {
border-bottom: 3px solid var(--palette-primary-main);
}
@@ -0,0 +1,40 @@
import { Link } from "found";
import React, { StatelessComponent } from "react";
import { Button, Flex, Typography } from "talk-ui/components";
import styles from "./Navigation.css";
const Navigation: StatelessComponent = () => (
<Flex itemGutter="double">
<Typography variant="heading1">Talk</Typography>
<Link
to="/admin/moderate"
className={styles.link}
activeClassName={styles.active}
>
<Button>Moderate</Button>
</Link>
<Link
to="/admin/community"
className={styles.link}
activeClassName={styles.active}
>
<Button>Community</Button>
</Link>
<Link
to="/admin/stories"
className={styles.link}
activeClassName={styles.active}
>
<Button>Stories</Button>
</Link>
<Link
to="/admin/configure"
className={styles.link}
activeClassName={styles.active}
>
<Button>Configure</Button>
</Link>
</Flex>
);
export default Navigation;
@@ -0,0 +1,10 @@
import React, { StatelessComponent } from "react";
import { HorizontalGutter, Typography } from "talk-ui/components";
const Stories: StatelessComponent = ({ children }) => (
<HorizontalGutter>
<Typography variant="heading3">Stories</Typography>
</HorizontalGutter>
);
export default Stories;
+15
View File
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>Talk - Admin</title>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no">
</head>
<body>
<div id="app"></div>
</body>
</html>
+40
View File
@@ -0,0 +1,40 @@
import { BrowserProtocol, queryMiddleware } from "farce";
import { createFarceRouter, createRender } from "found";
import { Resolver } from "found-relay";
import React, { StatelessComponent } from "react";
import ReactDOM from "react-dom";
import { createManaged } from "talk-framework/lib/bootstrap";
import { TalkContextConsumer } from "talk-framework/lib/bootstrap/TalkContext";
import { initLocalState } from "./local";
import localesData from "./locales";
import routeConfig from "./routeConfig";
async function main() {
const ManagedTalkContextProvider = await createManaged({
initLocalState,
localesData,
userLocales: navigator.languages,
});
const Router = createFarceRouter({
historyProtocol: new BrowserProtocol(),
historyMiddlewares: [queryMiddleware],
routeConfig,
render: createRender({}),
});
const Index: StatelessComponent = () => (
<ManagedTalkContextProvider>
<TalkContextConsumer>
{({ relayEnvironment }) => (
<Router resolver={new Resolver(relayEnvironment)} />
)}
</TalkContextConsumer>
</ManagedTalkContextProvider>
);
ReactDOM.render(<Index />, document.getElementById("app"));
}
main();
+1
View File
@@ -0,0 +1 @@
export { default as initLocalState } from "./initLocalState";
@@ -0,0 +1,21 @@
import { commitLocalUpdate, Environment } from "relay-runtime";
import {
createAndRetain,
LOCAL_ID,
LOCAL_TYPE,
} from "talk-framework/lib/relay";
/**
* Initializes the local state, before we start the App.
*/
export default async function initLocalState(environment: Environment) {
commitLocalUpdate(environment, s => {
const root = s.getRoot();
// Create the Local Record which is the Root for the client states.
const localRecord = createAndRetain(environment, s, LOCAL_ID, LOCAL_TYPE);
root.setLinkedRecord(localRecord, "local");
});
}
@@ -0,0 +1,7 @@
type Local {
authToken: String
}
extend type Query {
local: Local!
}
+9
View File
@@ -0,0 +1,9 @@
/**
* The actual content of this file is being generated by our `locales-loader`.
* Please check `./src/loaders` and the webpack config for more information.
*
* This file only represents the types that gets exported.
*/
import { LocalesData } from "talk-framework/lib/i18n";
export default {} as LocalesData;
+17
View File
@@ -0,0 +1,17 @@
import { makeRouteConfig, Route } from "found";
import React from "react";
import App from "./components/App";
import Community from "./components/Community";
import Configure from "./components/Configure";
import Moderate from "./components/Moderate";
import Stories from "./components/Stories";
export default makeRouteConfig(
<Route path="admin" Component={App}>
<Route path="moderate" Component={Moderate} />
<Route path="community" Component={Community} />
<Route path="stories" Component={Stories} />
<Route path="configure" Component={Configure} />
</Route>
);
-1
View File
@@ -25,7 +25,6 @@ export default class PymControl {
title: config.title,
id: `${config.id}_iframe`,
name: `${config.id}_iframe`,
optionalparams: "",
});
this.cleanups = decorators
@@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PymControl should create iframe 1`] = `"<iframe src=\\"http://coralproject.net/?initialWidth=0&amp;childId=pymcontrol-test-id\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"iFrame title\\" id=\\"pymcontrol-test-id_iframe\\" name=\\"pymcontrol-test-id_iframe\\"></iframe>"`;
exports[`PymControl should create iframe 1`] = `"<iframe src=\\"http://coralproject.net/?initialWidth=0&amp;childId=pymcontrol-test-id&amp;parentTitle=&amp;parentUrl=http%3A%2F%2Flocalhost%2F\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"iFrame title\\" id=\\"pymcontrol-test-id_iframe\\" name=\\"pymcontrol-test-id_iframe\\"></iframe>"`;
exports[`PymControl should send message 1`] = `"pymxPYMxpymcontrol-test-idxPYMxtestxPYMxhello world"`;
@@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Basic integration test should render iframe 1`] = `"<iframe src=\\"http://localhost/stream.html?assetURL=http%3A%2F%2Flocalhost%2F&amp;initialWidth=0&amp;childId=basic-integration-test-id\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"Talk Embed Stream\\" id=\\"basic-integration-test-id_iframe\\" name=\\"basic-integration-test-id_iframe\\" style=\\"width: 1px; min-width: 100%;\\"></iframe>"`;
exports[`Basic integration test should render iframe 1`] = `"<iframe src=\\"http://localhost/stream.html?assetURL=http%3A%2F%2Flocalhost%2F&amp;initialWidth=0&amp;childId=basic-integration-test-id&amp;parentTitle=&amp;parentUrl=http%3A%2F%2Flocalhost%2F\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"Talk Embed Stream\\" id=\\"basic-integration-test-id_iframe\\" name=\\"basic-integration-test-id_iframe\\" style=\\"width: 1px; min-width: 100%;\\"></iframe>"`;
exports[`Basic integration test should use canonical link 1`] = `"<iframe src=\\"http://localhost/stream.html?assetURL=http%3A%2F%2Flocalhost%2Fcanonical&amp;initialWidth=0&amp;childId=basic-integration-test-id\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"Talk Embed Stream\\" name=\\"basic-integration-test-id_iframe\\" style=\\"width: 1px; min-width: 100%;\\"></iframe>"`;
exports[`Basic integration test should use canonical link 1`] = `"<iframe src=\\"http://localhost/stream.html?assetURL=http%3A%2F%2Flocalhost%2Fcanonical&amp;initialWidth=0&amp;childId=basic-integration-test-id&amp;parentTitle=&amp;parentUrl=http%3A%2F%2Flocalhost%2F\\" width=\\"100%\\" scrolling=\\"no\\" marginheight=\\"0\\" frameborder=\\"0\\" title=\\"Talk Embed Stream\\" name=\\"basic-integration-test-id_iframe\\" style=\\"width: 1px; min-width: 100%;\\"></iframe>"`;
@@ -0,0 +1,8 @@
import { modifyQuery } from "talk-framework/utils";
export default function getURLWithCommentID(
assetURL: string,
commentID?: string
) {
return modifyQuery(assetURL, { commentID });
}
@@ -1 +1,2 @@
export { default as getMe } from "./getMe";
export { default as getURLWithCommentID } from "./getURLWithCommentID";
@@ -14,3 +14,7 @@
.root {
width: 100%;
}
.tabContent {
padding-top: var(--spacing-unit);
}
@@ -1,14 +1,9 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import App from "./App";
import AppContainer from "../containers/AppContainer";
it("renders comments", () => {
const props: PropTypesOf<typeof App> = {
activeTab: "COMMENTS",
};
const wrapper = shallow(<App {...props} />);
const wrapper = shallow(<AppContainer />);
expect(wrapper).toMatchSnapshot();
});
+43 -14
View File
@@ -1,28 +1,57 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import {
HorizontalGutter,
Tab,
TabBar,
TabContent,
TabPane,
} from "talk-ui/components";
import { Flex } from "talk-ui/components";
import { PropTypesOf } from "talk-ui/types";
import IfLoggedInContainer from "../containers/IfLoggedInContainer";
import CommentsPaneContainer from "../tabs/comments/containers/CommentsPaneContainer";
import ProfileQuery from "../tabs/profile/queries/ProfileQuery";
import * as styles from "./App.css";
type TabValue = "COMMENTS" | "PROFILE" | "%future added value";
export interface AppProps {
activeTab: "COMMENTS" | "%future added value";
activeTab: TabValue;
onTabClick: (tab: TabValue) => void;
}
const CommentsTab: StatelessComponent<PropTypesOf<typeof Tab>> = props => (
<Localized id="general-app-commentsTab">
<Tab {...props}>Comments</Tab>
</Localized>
);
const MyProfileTab: StatelessComponent<PropTypesOf<typeof Tab>> = props => (
<IfLoggedInContainer>
<Localized id="general-app-myProfileTab">
<Tab {...props}>My Profile</Tab>
</Localized>
</IfLoggedInContainer>
);
const App: StatelessComponent<AppProps> = props => {
let view: React.ReactElement<any>;
switch (props.activeTab) {
case "COMMENTS":
view = <CommentsPaneContainer />;
break;
default:
throw new Error(`Unknown tab ${props.activeTab}`);
}
return (
<Flex justifyContent="center" className={styles.root}>
{view}
</Flex>
<HorizontalGutter className={styles.root}>
<TabBar activeTab={props.activeTab} onTabClick={props.onTabClick}>
<CommentsTab tabId="COMMENTS" />
<MyProfileTab tabId="PROFILE" />
</TabBar>
<TabContent activeTab={props.activeTab} className={styles.tabContent}>
<TabPane tabId="COMMENTS">
<CommentsPaneContainer />
</TabPane>
<TabPane tabId="PROFILE">
<ProfileQuery />
</TabPane>
</TabContent>
</HorizontalGutter>
);
};
@@ -1,3 +1,4 @@
import cn from "classnames";
import dompurify from "dompurify";
import React, { StatelessComponent } from "react";
@@ -5,11 +6,15 @@ import styles from "./HTMLContent.css";
interface HTMLContentProps {
children: string;
className?: string;
}
const HTMLContent: StatelessComponent<HTMLContentProps> = ({ children }) => (
const HTMLContent: StatelessComponent<HTMLContentProps> = ({
children,
className,
}) => (
<div
className={styles.root}
className={cn(styles.root, className)}
dangerouslySetInnerHTML={{ __html: dompurify.sanitize(children) }}
/>
);
@@ -1,10 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders comments 1`] = `
<withPropsOnChange(Flex)
className="App-root"
justifyContent="center"
>
<withContext(withLocalStateContainer(CommentsPaneContainer)) />
</withPropsOnChange(Flex)>
`;
exports[`renders comments 1`] = `<Consumer />`;
@@ -1,20 +1,33 @@
import * as React from "react";
import { StatelessComponent } from "react";
import React from "react";
import { graphql, withLocalStateContainer } from "talk-framework/lib/relay";
import { AppContainerLocal as Local } from "talk-stream/__generated__/AppContainerLocal.graphql";
import {
SetActiveTabInput,
SetActiveTabMutation,
withSetActiveTabMutation,
} from "talk-stream/mutations";
import App from "../components/App";
interface InnerProps {
local: Local;
setActiveTab: SetActiveTabMutation;
}
const AppContainer: StatelessComponent<InnerProps> = ({
local: { activeTab },
}) => {
return <App activeTab={activeTab} />;
};
class AppContainer extends React.Component<InnerProps> {
private handleSetActiveTab = (tab: SetActiveTabInput["tab"]) => {
this.props.setActiveTab({ tab });
};
public render() {
const {
local: { activeTab },
} = this.props;
return <App activeTab={activeTab} onTabClick={this.handleSetActiveTab} />;
}
}
const enhanced = withLocalStateContainer(
graphql`
@@ -22,6 +35,6 @@ const enhanced = withLocalStateContainer(
activeTab
}
`
)(AppContainer);
)(withSetActiveTabMutation(AppContainer));
export default enhanced;
@@ -0,0 +1,34 @@
import React, { Component } from "react";
import { graphql, QueryRenderer } from "talk-framework/lib/relay";
import { IfLoggedInContainerQuery as QueryTypes } from "talk-stream/__generated__/IfLoggedInContainerQuery.graphql";
class IfLoggedInContainer extends Component {
public render() {
return (
<QueryRenderer<QueryTypes>
query={graphql`
query IfLoggedInContainerQuery {
me {
id
}
}
`}
render={({ error, props }) => {
if (error) {
return <div>{error.message}</div>;
}
if (props && props.me) {
return <>{this.props.children}</>;
}
return null;
}}
variables={{}}
/>
);
}
}
export default IfLoggedInContainer;
+1 -1
View File
@@ -4,8 +4,8 @@ import { StatelessComponent } from "react";
import ReactDOM from "react-dom";
import { createManaged } from "talk-framework/lib/bootstrap";
import AppContainer from "talk-stream/containers/AppContainer";
import AppContainer from "./containers/AppContainer";
import {
OnPostMessageAuthError,
OnPostMessageSetAuthToken,
@@ -3,7 +3,7 @@ import { commitLocalUpdate, Environment } from "relay-runtime";
import { createMutationContainer, LOCAL_ID } from "talk-framework/lib/relay";
export interface SetActiveTabInput {
tab: "COMMENTS";
tab: "COMMENTS" | "PROFILE" | "%future added value";
}
export type SetActiveTabMutation = (input: SetActiveTabInput) => Promise<void>;
@@ -18,6 +18,7 @@ export async function commit(
return commitLocalUpdate(environment, store => {
const record = store.get(LOCAL_ID)!;
record.setValue(input.id, "commentID");
record.setValue("COMMENTS", "activeTab");
if (pym) {
// This sets the comment id on the parent url.
pym.sendMessage("setCommentID", input.id || "");
@@ -27,6 +27,7 @@ export {
SetAuthPopupStateMutation,
} from "./SetAuthPopupStateMutation";
export {
SetActiveTabInput,
withSetActiveTabMutation,
SetActiveTabMutation,
} from "./SetActiveTabMutation";
@@ -0,0 +1,14 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import ButtonsBar from "./ButtonsBar";
it("renders correctly", () => {
const props: PropTypesOf<typeof ButtonsBar> = {
children: "children",
};
const wrapper = shallow(<ButtonsBar {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -0,0 +1,13 @@
import React, { StatelessComponent } from "react";
import { Flex } from "talk-ui/components";
const ButtonsBar: StatelessComponent = props => {
return (
<Flex direction="row" itemGutter="half">
{props.children}
</Flex>
);
};
export default ButtonsBar;
@@ -2,7 +2,7 @@ import React, { StatelessComponent } from "react";
import HTMLContent from "talk-stream/components/HTMLContent";
import Timestamp from "talk-stream/components/Timestamp";
import { Flex } from "talk-ui/components";
import { Flex, HorizontalGutter } from "talk-ui/components";
import * as styles from "./Comment.css";
import EditedMarker from "./EditedMarker";
@@ -43,10 +43,10 @@ const Comment: StatelessComponent<CommentProps> = props => {
</TopBarLeft>
{props.topBarRight && <div>{props.topBarRight}</div>}
</Flex>
<HTMLContent>{props.body || ""}</HTMLContent>
<Flex className={styles.footer} direction="row" itemGutter="half">
<HorizontalGutter>
<HTMLContent>{props.body || ""}</HTMLContent>
{props.footer}
</Flex>
</HorizontalGutter>
</div>
);
};
@@ -0,0 +1,17 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import ShowConversationLink from "./ShowConversationLink";
it("renders correctly", () => {
const props: PropTypesOf<typeof ShowConversationLink> = {
id: "id",
onClick: noop,
href: "http://localhost/comment",
};
const wrapper = shallow(<ShowConversationLink {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -0,0 +1,33 @@
import React, { EventHandler, MouseEvent } from "react";
import { StatelessComponent } from "react";
import { Localized } from "fluent-react/compat";
import { Button } from "talk-ui/components";
export interface ShowConversationLinkProps {
id?: string;
href?: string;
onClick?: EventHandler<MouseEvent>;
}
const ShowConversationLink: StatelessComponent<
ShowConversationLinkProps
> = props => {
return (
<Localized id="comments-showConversationLink-readMore">
<Button
id={props.id}
variant="underlined"
color="primary"
href={props.href}
onClick={props.onClick}
target="_parent"
anchor
>
Read More of this Conversation >
</Button>
</Localized>
);
};
export default ShowConversationLink;
@@ -0,0 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<withPropsOnChange(Flex)
direction="row"
itemGutter="half"
>
children
</withPropsOnChange(Flex)>
`;
@@ -30,15 +30,11 @@ exports[`renders username and body 1`] = `
topBarRight
</div>
</withPropsOnChange(Flex)>
<HTMLContent>
Woof
</HTMLContent>
<withPropsOnChange(Flex)
className="Comment-footer"
direction="row"
itemGutter="half"
>
<withPropsOnChange(HorizontalGutter)>
<HTMLContent>
Woof
</HTMLContent>
footer
</withPropsOnChange(Flex)>
</withPropsOnChange(HorizontalGutter)>
</div>
`;
@@ -0,0 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<Localized
id="comments-showConversationLink-readMore"
>
<withPropsOnChange(Button)
anchor={true}
color="primary"
href="http://localhost/comment"
id="id"
onClick={[Function]}
target="_parent"
variant="underlined"
>
Read More of this Conversation &gt;
</withPropsOnChange(Button)>
</Localized>
`;
@@ -1,3 +1,5 @@
export { default, default as IndentedComment } from "./IndentedComment";
export { default as TopBarLeft } from "./TopBarLeft";
export { default as Username } from "./Username";
export { default as ButtonsBar } from "./ButtonsBar";
export { default as ShowConversationLink } from "./ShowConversationLink";
@@ -14,7 +14,10 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof ReplyListN> = {
asset: { id: "asset-id" },
comment: { id: "comment-id" },
comments: [{ id: "comment-1" }, { id: "comment-2" }],
comments: [
{ id: "comment-1" },
{ id: "comment-2", showConversationLink: true },
],
onShowAll: noop,
hasMore: false,
disableShowAll: false,
@@ -15,9 +15,11 @@ export interface ReplyListProps {
id: string;
};
comments: ReadonlyArray<
{ id: string; replyListElement?: React.ReactElement<any> } & PropTypesOf<
typeof CommentContainer
>["comment"]
{
id: string;
replyListElement?: React.ReactElement<any>;
showConversationLink?: boolean;
} & PropTypesOf<typeof CommentContainer>["comment"]
>;
settings: PropTypesOf<typeof CommentContainer>["settings"];
onShowAll?: () => void;
@@ -45,6 +47,7 @@ const ReplyList: StatelessComponent<ReplyListProps> = props => {
indentLevel={props.indentLevel}
localReply={props.localReply}
disableReplies={props.disableReplies}
showConversationLink={!!comment.showConversationLink}
/>
{comment.replyListElement}
</HorizontalGutter>
@@ -8,7 +8,7 @@ exports[`renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -32,12 +32,13 @@ exports[`renders correctly 1`] = `
},
}
}
showConversationLink={false}
/>
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -46,6 +47,7 @@ exports[`renders correctly 1`] = `
comment={
Object {
"id": "comment-2",
"showConversationLink": true,
}
}
disableReplies={false}
@@ -61,6 +63,7 @@ exports[`renders correctly 1`] = `
},
}
}
showConversationLink={true}
/>
</withPropsOnChange(HorizontalGutter)>
</withPropsOnChange(HorizontalGutter)>
@@ -74,7 +77,7 @@ exports[`when there is more disables load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -96,12 +99,13 @@ exports[`when there is more disables load more button 1`] = `
},
}
}
showConversationLink={false}
/>
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -123,6 +127,7 @@ exports[`when there is more disables load more button 1`] = `
},
}
}
showConversationLink={false}
/>
</withPropsOnChange(HorizontalGutter)>
<Indent
@@ -155,7 +160,7 @@ exports[`when there is more renders a load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -177,12 +182,13 @@ exports[`when there is more renders a load more button 1`] = `
},
}
}
showConversationLink={false}
/>
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -204,6 +210,7 @@ exports[`when there is more renders a load more button 1`] = `
},
}
}
showConversationLink={false}
/>
</withPropsOnChange(HorizontalGutter)>
<Indent
@@ -21,7 +21,7 @@ exports[`renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -69,7 +69,7 @@ exports[`renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -139,7 +139,7 @@ exports[`when there is more disables load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -187,7 +187,7 @@ exports[`when there is more disables load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -271,7 +271,7 @@ exports[`when there is more renders a load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -319,7 +319,7 @@ exports[`when there is more renders a load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -405,7 +405,7 @@ exports[`when use is logged in renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -453,7 +453,7 @@ exports[`when use is logged in renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<withContext(createMutationContainer(Relay(CommentContainer)))
<withContext(createMutationContainer(withContext(createMutationContainer(Relay(CommentContainer)))))
asset={
Object {
"id": "asset-id",
@@ -14,7 +14,7 @@ it("renders username and body", () => {
const props: PropTypesOf<typeof CommentContainerN> = {
me: null,
asset: {
id: "asset-id",
url: "http://localhost/asset",
},
comment: {
id: "comment-id",
@@ -38,6 +38,7 @@ it("renders username and body", () => {
},
indentLevel: 1,
showAuthPopup: noop as any,
setCommentID: noop as any,
localReply: false,
disableReplies: false,
};
@@ -50,7 +51,7 @@ it("renders body only", () => {
const props: PropTypesOf<typeof CommentContainerN> = {
me: null,
asset: {
id: "asset-id",
url: "http://localhost/asset",
},
comment: {
id: "comment-id",
@@ -74,6 +75,7 @@ it("renders body only", () => {
},
indentLevel: 1,
showAuthPopup: noop as any,
setCommentID: noop as any,
};
const wrapper = shallow(<CommentContainerN {...props} />);
@@ -84,7 +86,7 @@ it("hide reply button", () => {
const props: PropTypesOf<typeof CommentContainerN> = {
me: null,
asset: {
id: "asset-id",
url: "http://localhost/asset",
},
comment: {
id: "comment-id",
@@ -108,6 +110,7 @@ it("hide reply button", () => {
},
indentLevel: 1,
showAuthPopup: noop as any,
setCommentID: noop as any,
localReply: false,
disableReplies: true,
};
@@ -115,3 +118,35 @@ it("hide reply button", () => {
const wrapper = shallow(<CommentContainerN {...props} />);
expect(wrapper).toMatchSnapshot();
});
it("shows conversation link", () => {
const props: PropTypesOf<typeof CommentContainerN> = {
me: null,
asset: {
url: "http://localhost/asset",
},
comment: {
id: "comment-id",
author: {
id: "author-id",
username: "Marvin",
},
body: "Woof",
createdAt: "1995-12-17T03:24:00.000Z",
editing: {
edited: false,
editableUntil: "1995-12-17T03:24:30.000Z",
},
pending: false,
},
indentLevel: 1,
showAuthPopup: noop as any,
setCommentID: noop as any,
localReply: false,
disableReplies: false,
showConversationLink: true,
};
const wrapper = shallow(<CommentContainerN {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -1,8 +1,9 @@
import { Localized } from "fluent-react/compat";
import React, { Component } from "react";
import React, { Component, MouseEvent } from "react";
import { graphql } from "react-relay";
import { isBeforeDate } from "talk-common/utils";
import { getURLWithCommentID } from "talk-framework/helpers";
import withFragmentContainer from "talk-framework/lib/relay/withFragmentContainer";
import { PropTypesOf } from "talk-framework/types";
import { CommentContainer_asset as AssetData } from "talk-stream/__generated__/CommentContainer_asset.graphql";
@@ -10,13 +11,18 @@ import { CommentContainer_comment as CommentData } from "talk-stream/__generated
import { CommentContainer_me as MeData } from "talk-stream/__generated__/CommentContainer_me.graphql";
import { CommentContainer_settings as SettingsData } from "talk-stream/__generated__/CommentContainer_settings.graphql";
import {
SetCommentIDMutation,
ShowAuthPopupMutation,
withSetCommentIDMutation,
withShowAuthPopupMutation,
} from "talk-stream/mutations";
import ReactionButtonContainer from "talk-stream/tabs/comments/containers/ReactionButtonContainer";
import { Button } from "talk-ui/components";
import Comment from "../components/Comment";
import Comment, {
ButtonsBar,
ShowConversationLink,
} from "../components/Comment";
import ReplyButton from "../components/Comment/ReplyButton";
import EditCommentFormContainer from "./EditCommentFormContainer";
import PermalinkButtonContainer from "./PermalinkButtonContainer";
@@ -29,6 +35,7 @@ interface InnerProps {
settings: SettingsData;
indentLevel?: number;
showAuthPopup: ShowAuthPopupMutation;
setCommentID: SetCommentIDMutation;
/**
* localReply will integrate the mutation response into
* localReplies
@@ -36,6 +43,8 @@ interface InnerProps {
localReply?: boolean;
/** disableReplies will remove the ReplyButton */
disableReplies?: boolean;
/** showConversationLink will render a link to the conversation */
showConversationLink?: boolean;
}
interface State {
@@ -116,6 +125,12 @@ export class CommentContainer extends Component<InnerProps, State> {
return;
}
private handleShowConversation = (e: MouseEvent) => {
e.preventDefault();
this.props.setCommentID({ id: this.props.comment.id });
return false;
};
public render() {
const {
comment,
@@ -124,6 +139,7 @@ export class CommentContainer extends Component<InnerProps, State> {
indentLevel,
localReply,
disableReplies,
showConversationLink,
} = this.props;
const { showReplyDialog, showEditDialog, editable } = this.state;
if (showEditDialog) {
@@ -161,18 +177,32 @@ export class CommentContainer extends Component<InnerProps, State> {
}
footer={
<>
{!disableReplies && (
<ReplyButton
id={`comments-commentContainer-replyButton-${comment.id}`}
onClick={this.openReplyDialog}
active={showReplyDialog}
/>
)}
<PermalinkButtonContainer commentID={comment.id} />
{this.props.me && (
<ReactionButtonContainer
comment={comment}
settings={settings}
<ButtonsBar>
{!disableReplies && (
<ReplyButton
id={`comments-commentContainer-replyButton-${comment.id}`}
onClick={this.openReplyDialog}
active={showReplyDialog}
/>
)}
<PermalinkButtonContainer commentID={comment.id} />
{this.props.me && (
<ReactionButtonContainer
comment={comment}
settings={settings}
/>
)}
</ButtonsBar>
{showConversationLink && (
<ShowConversationLink
id={`comments-commentContainer-showConversation-${
comment.id
}`}
onClick={this.handleShowConversation}
href={getURLWithCommentID(
this.props.asset.url,
this.props.comment.id
)}
/>
)}
</>
@@ -191,43 +221,46 @@ export class CommentContainer extends Component<InnerProps, State> {
}
}
const enhanced = withShowAuthPopupMutation(
withFragmentContainer<InnerProps>({
me: graphql`
fragment CommentContainer_me on User {
id
}
`,
asset: graphql`
fragment CommentContainer_asset on Asset {
...ReplyCommentFormContainer_asset
}
`,
comment: graphql`
fragment CommentContainer_comment on Comment {
id
author {
const enhanced = withSetCommentIDMutation(
withShowAuthPopupMutation(
withFragmentContainer<InnerProps>({
me: graphql`
fragment CommentContainer_me on User {
id
username
}
body
createdAt
editing {
edited
editableUntil
`,
asset: graphql`
fragment CommentContainer_asset on Asset {
url
...ReplyCommentFormContainer_asset
}
pending
...ReplyCommentFormContainer_comment
...EditCommentFormContainer_comment
...ReactionButtonContainer_comment
}
`,
settings: graphql`
fragment CommentContainer_settings on Settings {
...ReactionButtonContainer_settings
}
`,
})(CommentContainer)
`,
comment: graphql`
fragment CommentContainer_comment on Comment {
id
author {
id
username
}
body
createdAt
editing {
edited
editableUntil
}
pending
...ReplyCommentFormContainer_comment
...EditCommentFormContainer_comment
...ReactionButtonContainer_comment
}
`,
settings: graphql`
fragment CommentContainer_settings on Settings {
...ReactionButtonContainer_settings
}
`,
})(CommentContainer)
)
);
export type CommentContainerProps = PropTypesOf<typeof enhanced>;
@@ -1,7 +1,7 @@
import React, { StatelessComponent } from "react";
import { graphql } from "react-relay";
import { getURLWithCommentID } from "talk-framework/helpers";
import { withLocalStateContainer } from "talk-framework/lib/relay";
import { modifyQuery } from "talk-framework/utils";
import { PermalinkButtonContainerLocal as Local } from "talk-stream/__generated__/PermalinkButtonContainerLocal.graphql";
import PermalinkButton from "../components/PermalinkButton";
@@ -18,7 +18,7 @@ export const PermalinkContainer: StatelessComponent<InnerProps> = ({
return local.assetURL ? (
<PermalinkButton
commentID={commentID}
url={modifyQuery(local.assetURL, { commentID })}
url={getURLWithCommentID(local.assetURL, commentID)}
/>
) : null;
};
@@ -1,10 +1,10 @@
import { Child as PymChild } from "pym.js";
import qs from "query-string";
import React, { MouseEvent } from "react";
import { graphql } from "react-relay";
import { getURLWithCommentID } from "talk-framework/helpers";
import { withContext } from "talk-framework/lib/bootstrap";
import { withFragmentContainer } from "talk-framework/lib/relay";
import { buildURL, parseURL } from "talk-framework/utils";
import { PermalinkViewContainer_asset as AssetData } from "talk-stream/__generated__/PermalinkViewContainer_asset.graphql";
import { PermalinkViewContainer_comment as CommentData } from "talk-stream/__generated__/PermalinkViewContainer_comment.graphql";
import { PermalinkViewContainer_me as MeData } from "talk-stream/__generated__/PermalinkViewContainer_me.graphql";
@@ -34,13 +34,8 @@ class PermalinkViewContainer extends React.Component<
};
private getShowAllCommentsHref() {
const { pym } = this.props;
const urlParts = parseURL((pym && pym.parentUrl) || window.location.href);
const search = qs.stringify({
...qs.parse(urlParts.search),
commentID: undefined,
});
// Remove the commentId url param.
return buildURL({ ...urlParts, search });
const url = (pym && pym.parentUrl) || window.location.href;
return getURLWithCommentID(url, undefined);
}
public componentDidMount() {
@@ -12,12 +12,16 @@ import {
COMMENT_SORT,
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 LocalReplyListContainer from "./LocalReplyListContainer";
type UnpackArray<T> = T extends ReadonlyArray<infer U> ? U : any;
type ReplyNode5 = UnpackArray<Comment5Data["replies"]["edges"]>["node"];
export interface BaseProps {
me: MeData | null;
asset: AssetData;
@@ -62,6 +66,8 @@ export class ReplyListContainer extends React.Component<InnerProps> {
settings={this.props.settings}
/>
),
// ReplyListContainer5 contains replyCount.
showConversationLink: ((edge.node as any) as ReplyNode5).replyCount > 0,
}));
return (
<ReplyList
@@ -181,6 +187,7 @@ const ReplyListContainer5 = createReplyListContainer(
edges {
node {
id
replyCount
...CommentContainer_comment
...LocalReplyListContainer_comment
}
@@ -14,9 +14,11 @@ exports[`hide reply button 1`] = `
createdAt="1995-12-17T03:24:00.000Z"
footer={
<React.Fragment>
<withContext(withLocalStateContainer(PermalinkContainer))
commentID="comment-id"
/>
<ButtonsBar>
<withContext(withLocalStateContainer(PermalinkContainer))
commentID="comment-id"
/>
</ButtonsBar>
</React.Fragment>
}
id="comment-comment-id"
@@ -40,14 +42,16 @@ exports[`renders body only 1`] = `
createdAt="1995-12-17T03:24:00.000Z"
footer={
<React.Fragment>
<ReplyButton
active={false}
id="comments-commentContainer-replyButton-comment-id"
onClick={[Function]}
/>
<withContext(withLocalStateContainer(PermalinkContainer))
commentID="comment-id"
/>
<ButtonsBar>
<ReplyButton
active={false}
id="comments-commentContainer-replyButton-comment-id"
onClick={[Function]}
/>
<withContext(withLocalStateContainer(PermalinkContainer))
commentID="comment-id"
/>
</ButtonsBar>
</React.Fragment>
}
id="comment-comment-id"
@@ -71,14 +75,54 @@ exports[`renders username and body 1`] = `
createdAt="1995-12-17T03:24:00.000Z"
footer={
<React.Fragment>
<ReplyButton
active={false}
id="comments-commentContainer-replyButton-comment-id"
<ButtonsBar>
<ReplyButton
active={false}
id="comments-commentContainer-replyButton-comment-id"
onClick={[Function]}
/>
<withContext(withLocalStateContainer(PermalinkContainer))
commentID="comment-id"
/>
</ButtonsBar>
</React.Fragment>
}
id="comment-comment-id"
indentLevel={1}
showEditedMarker={false}
/>
</React.Fragment>
`;
exports[`shows conversation link 1`] = `
<React.Fragment>
<IndentedComment
author={
Object {
"id": "author-id",
"username": "Marvin",
}
}
blur={false}
body="Woof"
createdAt="1995-12-17T03:24:00.000Z"
footer={
<React.Fragment>
<ButtonsBar>
<ReplyButton
active={false}
id="comments-commentContainer-replyButton-comment-id"
onClick={[Function]}
/>
<withContext(withLocalStateContainer(PermalinkContainer))
commentID="comment-id"
/>
</ButtonsBar>
<ShowConversationLink
href="http://localhost/asset?commentID=comment-id"
id="comments-commentContainer-showConversation-comment-id"
onClick={[Function]}
/>
<withContext(withLocalStateContainer(PermalinkContainer))
commentID="comment-id"
/>
</React.Fragment>
}
id="comment-comment-id"
@@ -51,6 +51,7 @@ exports[`renders correctly 1`] = `
}
}
/>,
"showConversationLink": false,
},
Object {
"id": "comment-2",
@@ -75,6 +76,7 @@ exports[`renders correctly 1`] = `
}
}
/>,
"showConversationLink": false,
},
]
}
@@ -127,10 +129,12 @@ exports[`when has more replies renders hasMore 1`] = `
Object {
"id": "comment-1",
"replyListElement": undefined,
"showConversationLink": false,
},
Object {
"id": "comment-2",
"replyListElement": undefined,
"showConversationLink": false,
},
]
}
@@ -182,10 +186,12 @@ exports[`when has more replies when showing all disables show all button 1`] = `
Object {
"id": "comment-1",
"replyListElement": undefined,
"showConversationLink": false,
},
Object {
"id": "comment-2",
"replyListElement": undefined,
"showConversationLink": false,
},
]
}
@@ -237,10 +243,12 @@ exports[`when has more replies when showing all enable show all button after loa
Object {
"id": "comment-1",
"replyListElement": undefined,
"showConversationLink": false,
},
Object {
"id": "comment-2",
"replyListElement": undefined,
"showConversationLink": false,
},
]
}
@@ -0,0 +1,36 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { HorizontalGutter, Typography } from "talk-ui/components";
import HistoryComment from "./HistoryComment";
interface Comment {
id: string;
body: string | null;
createdAt: any;
replyCount: number | null;
asset: {
title: string | null;
};
conversationURL: string;
onGotoConversation: (e: React.MouseEvent) => void;
}
interface CommentsHistoryProps {
comments: Comment[];
}
const CommentsHistory: StatelessComponent<CommentsHistoryProps> = props => {
return (
<HorizontalGutter>
<Localized id="profile-historyComment-commentHistory">
<Typography variant="heading3">Comment History</Typography>
</Localized>
{props.comments.map(comment => (
<HistoryComment key={comment.id} {...comment} />
))}
</HorizontalGutter>
);
};
export default CommentsHistory;
@@ -0,0 +1,18 @@
.icon {
color: var(--palette-text-secondary);
}
.button,
.replies,
.story {
composes: button from "talk-ui/shared/typography.css";
}
.sideBar {
min-width: 180px;
padding-left: var(--spacing-unit);
}
.body {
word-break: break-all;
}
@@ -0,0 +1,79 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import Timestamp from "talk-stream/components/Timestamp";
import {
Button,
Flex,
HorizontalGutter,
Icon,
Typography,
} from "talk-ui/components";
import HTMLContent from "../../../components/HTMLContent";
import * as styles from "./HistoryComment.css";
export interface HistoryCommentProps {
body: string | null;
createdAt: string;
replyCount: number | null;
asset: {
title: string | null;
};
conversationURL: string;
onGotoConversation: (e: React.MouseEvent) => void;
}
const HistoryComment: StatelessComponent<HistoryCommentProps> = props => {
return (
<HorizontalGutter>
<Flex direction="row" justifyContent="space-between">
<Typography variant="bodyCopy" container="div">
{props.body && (
<HTMLContent className={styles.body}>{props.body}</HTMLContent>
)}
</Typography>
<Flex className={styles.sideBar} direction="column">
<Flex direction="row" alignItems="center" itemGutter="half">
<Button
variant="underlined"
target="_parent"
href={props.conversationURL}
onClick={props.onGotoConversation}
anchor
>
<Icon>launch</Icon>
<Localized id="profile-historyComment-viewConversation">
<span>View Conversation</span>
</Localized>
</Button>
</Flex>
<Flex direction="row" alignItems="center" itemGutter="half">
<Icon className={styles.icon}>schedule</Icon>
<Timestamp>{props.createdAt}</Timestamp>
</Flex>
</Flex>
</Flex>
{!!props.replyCount && (
<Flex
direction="row"
alignItems="center"
itemGutter="half"
className={styles.replies}
>
<Icon className={styles.icon}>reply</Icon>
<Localized
id="profile-historyComment-replies"
$replyCount={props.replyCount}
>
<span>{"Replies {$replyCount}"}</span>
</Localized>
</Flex>
)}
<Localized id="profile-historyComment-story" $title={props.asset.title}>
<span className={styles.story}>{"Story: {$title}"}</span>
</Localized>
</HorizontalGutter>
);
};
export default HistoryComment;
@@ -0,0 +1,25 @@
import * as React from "react";
import { StatelessComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import UserBoxContainer from "talk-stream/containers/UserBoxContainer";
import { HorizontalGutter } from "talk-ui/components";
import CommentsHistoryContainer from "../containers/CommentsHistoryContainer";
export interface ProfileProps {
asset: PropTypesOf<typeof CommentsHistoryContainer>["asset"];
me: PropTypesOf<typeof UserBoxContainer>["me"] &
PropTypesOf<typeof CommentsHistoryContainer>["me"];
}
const Profile: StatelessComponent<ProfileProps> = props => {
return (
<HorizontalGutter size="double">
<UserBoxContainer me={props.me} />
{props.me && (
<CommentsHistoryContainer me={props.me} asset={props.asset} />
)}
</HorizontalGutter>
);
};
export default Profile;
@@ -0,0 +1,70 @@
import React from "react";
import { graphql } from "react-relay";
import { getURLWithCommentID } from "talk-framework/helpers";
import { withFragmentContainer } from "talk-framework/lib/relay";
import { CommentsHistoryContainer_asset as AssetData } from "talk-stream/__generated__/CommentsHistoryContainer_asset.graphql";
import { CommentsHistoryContainer_me as CommentsData } from "talk-stream/__generated__/CommentsHistoryContainer_me.graphql";
import {
SetCommentIDMutation,
withSetCommentIDMutation,
} from "talk-stream/mutations";
import CommentsHistory from "../components/CommentsHistory";
interface CommentsHistoryContainerProps {
setCommentID: SetCommentIDMutation;
me: CommentsData;
asset: AssetData;
}
export class CommentsHistoryContainer extends React.Component<
CommentsHistoryContainerProps
> {
private onGoToConversation = (id: string) => {
this.props.setCommentID({ id });
};
public render() {
const comments = this.props.me.comments.edges.map(edge => ({
...edge.node,
conversationURL: getURLWithCommentID(edge.node.asset.url, edge.node.id),
onGotoConversation: (e: React.MouseEvent) => {
if (this.props.asset.id === edge.node.asset.id) {
this.onGoToConversation(edge.node.id);
e.preventDefault();
}
},
}));
return <CommentsHistory comments={comments} />;
}
}
const enhanced = withSetCommentIDMutation(
withFragmentContainer<CommentsHistoryContainerProps>({
asset: graphql`
fragment CommentsHistoryContainer_asset on Asset {
id
}
`,
me: graphql`
fragment CommentsHistoryContainer_me on User {
comments {
edges {
node {
id
body
createdAt
replyCount
asset {
id
title
url
}
}
}
}
}
`,
})(CommentsHistoryContainer)
);
export default enhanced;
@@ -0,0 +1,34 @@
import React from "react";
import { graphql } from "react-relay";
import { withFragmentContainer } from "talk-framework/lib/relay";
import { ProfileContainer_asset as AssetData } from "talk-stream/__generated__/ProfileContainer_asset.graphql";
import { ProfileContainer_me as MeData } from "talk-stream/__generated__/ProfileContainer_me.graphql";
import Profile from "../components/Profile";
interface ProfileContainerProps {
me: MeData;
asset: AssetData;
}
export class StreamContainer extends React.Component<ProfileContainerProps> {
public render() {
return <Profile me={this.props.me} asset={this.props.asset} />;
}
}
const enhanced = withFragmentContainer<ProfileContainerProps>({
asset: graphql`
fragment ProfileContainer_asset on Asset {
...CommentsHistoryContainer_asset
}
`,
me: graphql`
fragment ProfileContainer_me on User {
...UserBoxContainer_me
...CommentsHistoryContainer_me
}
`,
})(StreamContainer);
export default enhanced;
@@ -0,0 +1,80 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import { ReadyState } from "react-relay";
import {
graphql,
QueryRenderer,
withLocalStateContainer,
} from "talk-framework/lib/relay";
import { ProfileQuery as QueryTypes } from "talk-stream/__generated__/ProfileQuery.graphql";
import { ProfileQueryLocal as Local } from "talk-stream/__generated__/ProfileQueryLocal.graphql";
import { Spinner } from "talk-ui/components";
import ProfileContainer from "../containers/ProfileContainer";
interface InnerProps {
local: Local;
}
export const render = ({
error,
props,
}: ReadyState<QueryTypes["response"]>) => {
if (error) {
return <div>{error.message}</div>;
}
if (props) {
if (!props.me) {
return (
<Localized id="profile-profileQuery-errorLoadingProfile">
<div>Error loading profile</div>
</Localized>
);
}
if (!props.asset) {
return (
<Localized id="comments-profileQuery-assetNotFound">
<div>Asset not found</div>
</Localized>
);
}
return <ProfileContainer me={props.me} asset={props.asset} />;
}
return <Spinner />;
};
const ProfileQuery: StatelessComponent<InnerProps> = ({
local: { assetID, assetURL },
}) => (
<QueryRenderer<QueryTypes>
query={graphql`
query ProfileQuery($assetID: ID, $assetURL: String) {
asset(id: $assetID, url: $assetURL) {
...ProfileContainer_asset
}
me {
...ProfileContainer_me
}
}
`}
variables={{
assetID,
assetURL,
}}
render={render}
/>
);
const enhanced = withLocalStateContainer(
graphql`
fragment ProfileQueryLocal on Local {
assetID
assetURL
}
`
)(ProfileQuery);
export default enhanced;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -2,280 +2,98 @@
exports[`renders permalink view 1`] = `
<div
className="Flex-root App-root Flex-flex Flex-justifyCenter"
className="HorizontalGutter-root App-root HorizontalGutter-full"
>
<div
className="PermalinkView-root"
<ul
className="TabBar-root TabBar-primary"
role="tablist"
>
<a
className="BaseButton-root Button-root PermalinkView-button Button-sizeRegular Button-colorPrimary Button-variantOutlined Button-fullWidth"
href="http://localhost/"
id="talk-comments-permalinkView-showAllComments"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
target="_parent"
type="button"
<li
className="Tab-root"
id="tab-COMMENTS"
role="presentation"
>
Show All Comments
</a>
<div
className="Indent-root"
>
<div
className=""
<button
aria-controls="tabPane-COMMENTS"
aria-selected={true}
className="BaseButton-root Tab-button Tab-primary Tab-active"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
role="tab"
type="button"
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-0"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-0"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`show all comments 1`] = `
<div
className="Flex-root App-root Flex-flex Flex-justifyCenter"
>
<div
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
Comments
</button>
</li>
</ul>
<section
aria-labelledby="tab-COMMENTS"
className="App-tabContent"
id="tabPane-COMMENTS"
role="tabpanel"
>
<div
className="HorizontalGutter-root HorizontalGutter-half"
className="PermalinkView-root"
>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignCenter"
<a
className="BaseButton-root Button-root PermalinkView-button Button-sizeRegular Button-colorPrimary Button-variantOutlined Button-fullWidth"
href="http://localhost/"
id="talk-comments-permalinkView-showAllComments"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
target="_parent"
type="button"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Sign in
</button>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantOutlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Register
</button>
</div>
Show All Comments
</a>
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
className="Indent-root"
>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Bold"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Italic"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Blockquote"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
onBlur={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="submit"
>
Sign in and Join the Conversation
</button>
</div>
</div>
<div
aria-live="polite"
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-stream-log"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
className=""
>
<div
className=""
className="Comment-root"
role="article"
>
<div
className="Comment-root"
role="article"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-0"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-0"
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
@@ -285,7 +103,7 @@ exports[`show all comments 1`] = `
}
/>
<div
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
@@ -309,6 +127,264 @@ exports[`show all comments 1`] = `
</div>
</div>
</div>
</div>
</section>
</div>
`;
exports[`show all comments 1`] = `
<div
className="HorizontalGutter-root App-root HorizontalGutter-full"
>
<ul
className="TabBar-root TabBar-primary"
role="tablist"
>
<li
className="Tab-root"
id="tab-COMMENTS"
role="presentation"
>
<button
aria-controls="tabPane-COMMENTS"
aria-selected={true}
className="BaseButton-root Tab-button Tab-primary Tab-active"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
role="tab"
type="button"
>
Comments
</button>
</li>
</ul>
<section
aria-labelledby="tab-COMMENTS"
className="App-tabContent"
id="tabPane-COMMENTS"
role="tabpanel"
>
<div
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
>
<div
className="HorizontalGutter-root HorizontalGutter-half"
>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignCenter"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Sign in
</button>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantOutlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Register
</button>
</div>
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Bold"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Italic"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Blockquote"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
onBlur={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="submit"
>
Sign in and Join the Conversation
</button>
</div>
</div>
<div
aria-live="polite"
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-stream-log"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className=""
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-0"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-0"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
`;
@@ -2,10 +2,44 @@
exports[`renders permalink view with unknown asset 1`] = `
<div
className="Flex-root App-root Flex-flex Flex-justifyCenter"
className="HorizontalGutter-root App-root HorizontalGutter-full"
>
<div>
Asset not found
</div>
<ul
className="TabBar-root TabBar-primary"
role="tablist"
>
<li
className="Tab-root"
id="tab-COMMENTS"
role="presentation"
>
<button
aria-controls="tabPane-COMMENTS"
aria-selected={true}
className="BaseButton-root Tab-button Tab-primary Tab-active"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
role="tab"
type="button"
>
Comments
</button>
</li>
</ul>
<section
aria-labelledby="tab-COMMENTS"
className="App-tabContent"
id="tabPane-COMMENTS"
role="tabpanel"
>
<div>
Asset not found
</div>
</section>
</div>
`;
@@ -2,252 +2,324 @@
exports[`renders permalink view with unknown comment 1`] = `
<div
className="Flex-root App-root Flex-flex Flex-justifyCenter"
className="HorizontalGutter-root App-root HorizontalGutter-full"
>
<div
className="PermalinkView-root"
<ul
className="TabBar-root TabBar-primary"
role="tablist"
>
<a
className="BaseButton-root Button-root PermalinkView-button Button-sizeRegular Button-colorPrimary Button-variantOutlined Button-fullWidth"
href="http://localhost/"
id="talk-comments-permalinkView-showAllComments"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
target="_parent"
type="button"
<li
className="Tab-root"
id="tab-COMMENTS"
role="presentation"
>
Show All Comments
</a>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
<button
aria-controls="tabPane-COMMENTS"
aria-selected={true}
className="BaseButton-root Tab-button Tab-primary Tab-active"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
role="tab"
type="button"
>
Comments
</button>
</li>
</ul>
<section
aria-labelledby="tab-COMMENTS"
className="App-tabContent"
id="tabPane-COMMENTS"
role="tabpanel"
>
<div
className="PermalinkView-root"
>
Comment not found
</p>
</div>
<a
className="BaseButton-root Button-root PermalinkView-button Button-sizeRegular Button-colorPrimary Button-variantOutlined Button-fullWidth"
href="http://localhost/"
id="talk-comments-permalinkView-showAllComments"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
target="_parent"
type="button"
>
Show All Comments
</a>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Comment not found
</p>
</div>
</section>
</div>
`;
exports[`show all comments 1`] = `
<div
className="Flex-root App-root Flex-flex Flex-justifyCenter"
className="HorizontalGutter-root App-root HorizontalGutter-full"
>
<div
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
<ul
className="TabBar-root TabBar-primary"
role="tablist"
>
<li
className="Tab-root"
id="tab-COMMENTS"
role="presentation"
>
<button
aria-controls="tabPane-COMMENTS"
aria-selected={true}
className="BaseButton-root Tab-button Tab-primary Tab-active"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
role="tab"
type="button"
>
Comments
</button>
</li>
</ul>
<section
aria-labelledby="tab-COMMENTS"
className="App-tabContent"
id="tabPane-COMMENTS"
role="tabpanel"
>
<div
className="HorizontalGutter-root HorizontalGutter-half"
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignCenter"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Sign in
</button>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantOutlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Register
</button>
</div>
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
className="HorizontalGutter-root HorizontalGutter-half"
>
<div
aria-hidden="true"
className="Flex-root Flex-flex Flex-itemGutter Flex-alignCenter"
>
<div>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Sign in
</button>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantOutlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Register
</button>
</div>
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Bold"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Italic"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Blockquote"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
onBlur={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="submit"
>
Sign in and Join the Conversation
</button>
</div>
</div>
<div
aria-live="polite"
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-stream-log"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Bold"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Italic"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Blockquote"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
onBlur={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="submit"
>
Sign in and Join the Conversation
</button>
</div>
</div>
<div
aria-live="polite"
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-stream-log"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className=""
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-0"
className="Comment-root"
role="article"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-0"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
2018-07-06T18:24:00.000Z
</time>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-0"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-0"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
`;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -2,290 +2,332 @@
exports[`renders comment stream 1`] = `
<div
className="Flex-root App-root Flex-flex Flex-justifyCenter"
className="HorizontalGutter-root App-root HorizontalGutter-full"
>
<div
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
<ul
className="TabBar-root TabBar-primary"
role="tablist"
>
<li
className="Tab-root"
id="tab-COMMENTS"
role="presentation"
>
<button
aria-controls="tabPane-COMMENTS"
aria-selected={true}
className="BaseButton-root Tab-button Tab-primary Tab-active"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
role="tab"
type="button"
>
Comments
</button>
</li>
</ul>
<section
aria-labelledby="tab-COMMENTS"
className="App-tabContent"
id="tabPane-COMMENTS"
role="tabpanel"
>
<div
className="HorizontalGutter-root HorizontalGutter-half"
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignCenter"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Sign in
</button>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantOutlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Register
</button>
</div>
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
className="HorizontalGutter-root HorizontalGutter-half"
>
<div
aria-hidden="true"
className="Flex-root Flex-flex Flex-itemGutter Flex-alignCenter"
>
<div>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Sign in
</button>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantOutlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Register
</button>
</div>
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Bold"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Italic"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Blockquote"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
onBlur={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="submit"
>
Sign in and Join the Conversation
</button>
</div>
</div>
<div
aria-live="polite"
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-stream-log"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Bold"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Italic"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Blockquote"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
onBlur={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="submit"
>
Sign in and Join the Conversation
</button>
</div>
</div>
<div
aria-live="polite"
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-stream-log"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className=""
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-0"
className="Comment-root"
role="article"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-0"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
2018-07-06T18:24:00.000Z
</time>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
</div>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-0"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<span>
Reply
</span>
</button>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-0"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className=""
className="Indent-root"
>
<div
className="Comment-root"
role="article"
className=""
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-1"
className="Comment-root"
role="article"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-1"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
2018-07-06T18:24:00.000Z
</time>
Lukas
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
</div>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
}
}
/>
<div
className="Flex-root Comment-footer Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-1"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<span>
Reply
</span>
</button>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-1"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
`;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,806 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders comment stream 1`] = `
<div
className="HorizontalGutter-root App-root HorizontalGutter-full"
>
<ul
className="TabBar-root TabBar-primary"
role="tablist"
>
<li
className="Tab-root"
id="tab-COMMENTS"
role="presentation"
>
<button
aria-controls="tabPane-COMMENTS"
aria-selected={true}
className="BaseButton-root Tab-button Tab-primary Tab-active"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
role="tab"
type="button"
>
Comments
</button>
</li>
</ul>
<section
aria-labelledby="tab-COMMENTS"
className="App-tabContent"
id="tabPane-COMMENTS"
role="tabpanel"
>
<div
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
>
<div
className="HorizontalGutter-root HorizontalGutter-half"
>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignCenter"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Sign in
</button>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantOutlined"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
Register
</button>
</div>
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Bold"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Italic"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
title="Blockquote"
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-md"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
onBlur={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="submit"
>
Sign in and Join the Conversation
</button>
</div>
</div>
<div
aria-live="polite"
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-stream-log"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className=""
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-with-deepest-replies"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "body 0",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-with-deepest-replies"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-replyList-log--comment-with-deepest-replies"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className="Indent-level1"
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-with-deepest-replies-1"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "body 1",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-with-deepest-replies-1"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-replyList-log--comment-with-deepest-replies-1"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className="Indent-level2"
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-with-deepest-replies-2"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "body 2",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-with-deepest-replies-2"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-replyList-log--comment-with-deepest-replies-2"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className="Indent-level3"
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-with-deepest-replies-3"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "body 3",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-with-deepest-replies-3"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-replyList-log--comment-with-deepest-replies-3"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className="Indent-level4"
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-with-deepest-replies-4"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "body 4",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-with-deepest-replies-4"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
id="talk-comments-replyList-log--comment-with-deepest-replies-4"
role="log"
>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="Indent-root"
>
<div
className="Indent-level5"
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-with-deepest-replies-5"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "body 5",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-with-deepest-replies-5"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
<a
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantUnderlined"
href="http://localhost/assets/asset-with-replies?commentID=comment-with-deepest-replies-5"
id="comments-commentContainer-showConversation-comment-with-deepest-replies-5"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
target="_parent"
type="button"
>
Read More of this Conversation &gt;
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
`;
exports[`shows conversation 1`] = `
<div
className="HorizontalGutter-root App-root HorizontalGutter-full"
>
<ul
className="TabBar-root TabBar-primary"
role="tablist"
>
<li
className="Tab-root"
id="tab-COMMENTS"
role="presentation"
>
<button
aria-controls="tabPane-COMMENTS"
aria-selected={true}
className="BaseButton-root Tab-button Tab-primary Tab-active"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
role="tab"
type="button"
>
Comments
</button>
</li>
</ul>
<section
aria-labelledby="tab-COMMENTS"
className="App-tabContent"
id="tabPane-COMMENTS"
role="tabpanel"
>
<div
className="PermalinkView-root"
>
<a
className="BaseButton-root Button-root PermalinkView-button Button-sizeRegular Button-colorPrimary Button-variantOutlined Button-fullWidth"
href="http://localhost/"
id="talk-comments-permalinkView-showAllComments"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
target="_parent"
type="button"
>
Show All Comments
</a>
<div
className="Indent-root"
>
<div
className=""
>
<div
className="Comment-root"
role="article"
>
<div
className="Flex-root Comment-topBar Flex-flex Flex-justifySpaceBetween Flex-directionRow"
id="comment-comment-with-deepest-replies-5"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
Markus
</span>
<div
className="Flex-root Flex-flex Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<time
className="Timestamp-root RelativeTime-root"
dateTime="2018-07-06T18:24:00.000Z"
title="2018-07-06T18:24:00.000Z"
>
2018-07-06T18:24:00.000Z
</time>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorRegular Button-variantGhost"
id="comments-commentContainer-replyButton-comment-with-deepest-replies-5"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseDown={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
onTouchEnd={[Function]}
type="button"
>
<span>
Reply
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
`;
@@ -63,6 +63,7 @@ it("show all comments", async () => {
const mockEvent = {
preventDefault: sinon.mock().once(),
};
testRenderer.root
.findByProps({
id: "talk-comments-permalinkView-showAllComments",
@@ -0,0 +1,67 @@
import { ReactTestRenderer } from "react-test-renderer";
import sinon from "sinon";
import { timeout } from "talk-common/utils";
import { createSinonStub } from "talk-framework/testHelpers";
import { assetWithDeepestReplies, comments, settings } from "../fixtures";
import create from "./create";
let testRenderer: ReactTestRenderer;
beforeEach(() => {
const resolvers = {
Query: {
asset: createSinonStub(
s => s.throws(),
s => s.returns(assetWithDeepestReplies)
),
comment: createSinonStub(
s => s.throws(),
s =>
s
.withArgs(undefined, { id: "comment-with-deepest-replies-5" })
.returns({
...comments[0],
id: "comment-with-deepest-replies-5",
})
),
settings: sinon.stub().returns(settings),
},
};
({ testRenderer } = create({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: localRecord => {
localRecord.setValue(assetWithDeepestReplies.id, "assetID");
},
}));
});
it("renders comment stream", async () => {
// Wait for loading.
await timeout();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
it("shows conversation", async () => {
const mockEvent = {
preventDefault: sinon.mock().once(),
};
// Wait for loading.
await timeout();
testRenderer.root
.findByProps({
id:
"comments-commentContainer-showConversation-comment-with-deepest-replies-5",
})
.props.onClick(mockEvent);
// Wait for loading.
await timeout();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
+10
View File
@@ -26,6 +26,7 @@ export const baseComment = {
body: "Comment Body",
createdAt: "2018-07-06T18:24:00.000Z",
replies: { edges: [], pageInfo: { endCursor: null, hasNextPage: false } },
replyCount: 0,
editing: {
edited: false,
editableUntil: "2018-07-06T18:24:30.000Z",
@@ -90,6 +91,7 @@ export const commentWithReplies = {
hasNextPage: false,
},
},
replyCount: 2,
};
export const commentWithDeepReplies = {
@@ -106,12 +108,14 @@ export const commentWithDeepReplies = {
hasNextPage: false,
},
},
replyCount: 2,
};
export const commentWithDeepestReplies = {
...baseComment,
id: "comment-with-deepest-replies",
body: "body 0",
replyCount: 1,
replies: {
...baseComment.replies,
edges: [
@@ -121,6 +125,7 @@ export const commentWithDeepestReplies = {
...baseComment,
id: "comment-with-deepest-replies-1",
body: "body 1",
replyCount: 1,
replies: {
...baseComment.replies,
edges: [
@@ -130,6 +135,7 @@ export const commentWithDeepestReplies = {
...baseComment,
id: "comment-with-deepest-replies-2",
body: "body 2",
replyCount: 1,
replies: {
...baseComment.replies,
edges: [
@@ -139,6 +145,7 @@ export const commentWithDeepestReplies = {
...baseComment,
id: "comment-with-deepest-replies-3",
body: "body 3",
replyCount: 1,
replies: {
...baseComment.replies,
edges: [
@@ -148,6 +155,7 @@ export const commentWithDeepestReplies = {
...baseComment,
id: "comment-with-deepest-replies-4",
body: "body 4",
replyCount: 1,
replies: {
...baseComment.replies,
edges: [
@@ -157,6 +165,7 @@ export const commentWithDeepestReplies = {
...baseComment,
id: "comment-with-deepest-replies-5",
body: "body 5",
replyCount: 1,
replies: {
...baseComment.replies,
edges: [
@@ -167,6 +176,7 @@ export const commentWithDeepestReplies = {
id:
"comment-with-deepest-replies-6",
body: "body 6",
replyCount: 1,
replies: {
...baseComment.replies,
edges: [],
@@ -5,10 +5,14 @@ export interface TabContentProps {
* Active tab id/name
*/
activeTab?: string;
/**
* classNames
*/
className?: string;
}
const TabContent: StatelessComponent<TabContentProps> = props => {
const { children, activeTab } = props;
const { children, activeTab, className } = props;
return (
<>
{React.Children.toArray(children)
@@ -18,6 +22,7 @@ const TabContent: StatelessComponent<TabContentProps> = props => {
.map((child: React.ReactElement<any>, i) =>
React.cloneElement(child, {
tabId: child.props.tabId ? child.props.tabId : i,
className,
})
)}
</>