Merge pull request #1874 from coralproject/next-profile

[next] - Introducing Comment Tab, My Profile Tab, Comment History
This commit is contained in:
Kiwi
2018-10-04 17:39:42 +02:00
committed by GitHub
40 changed files with 12082 additions and 10132 deletions
+3 -1
View File
@@ -1,4 +1,6 @@
type Local {}
type Local {
authToken: String
}
extend type Query {
local: Local!
@@ -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,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,321 +2,389 @@
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>
<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="Indent-root"
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=""
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-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="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
className="HorizontalGutter-root HorizontalGutter-full"
>
<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="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<span>
Reply
</span>
</button>
<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>
`;
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="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,256 +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="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>
`;
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,291 +2,325 @@
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="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
className="HorizontalGutter-root HorizontalGutter-full"
>
<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="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<span>
Reply
</span>
</button>
<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:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
<span
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
>
2018-07-06T18:20: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:20:00.000Z"
title="2018-07-06T18:20:00.000Z"
>
2018-07-06T18:20:00.000Z
</time>
</div>
</div>
</div>
</div>
<div
className="HorizontalGutter-root HorizontalGutter-full"
>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
className="HorizontalGutter-root HorizontalGutter-full"
>
<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="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
}
}
/>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-directionRow"
>
<span>
Reply
</span>
</button>
<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>
@@ -294,6 +328,6 @@ exports[`renders comment stream 1`] = `
</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
@@ -62,6 +62,7 @@ it("show all comments", async () => {
const mockEvent = {
preventDefault: sinon.mock().once(),
};
testRenderer.root
.findByProps({
id: "talk-comments-permalinkView-showAllComments",
@@ -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,
})
)}
</>
@@ -12,6 +12,7 @@ import {
retrieveCommentAssetConnection,
retrieveCommentParentsConnection,
retrieveCommentRepliesConnection,
retrieveCommentUserConnection,
retrieveManyComments,
} from "talk-server/models/comment";
import { Connection } from "talk-server/models/connection";
@@ -37,6 +38,20 @@ export default (ctx: Context) => ({
comment: new DataLoader((ids: string[]) =>
retrieveManyComments(ctx.mongo, ctx.tenant.id, ids)
),
forUser: (
userID: string,
// Apply the graph schema defaults at the loader.
{
first = 10,
orderBy = GQLCOMMENT_SORT.CREATED_AT_DESC,
after,
}: AssetToCommentsArgs
) =>
retrieveCommentUserConnection(ctx.mongo, ctx.tenant.id, userID, {
first,
orderBy,
after,
}),
forAsset: (
assetID: string,
// Apply the graph schema defaults at the loader.
@@ -78,6 +78,8 @@ const Comment: GQLCommentTypeResolver<Comment> = {
comment.parent_id
? ctx.loaders.Comments.parents(comment, input)
: createConnection(),
asset: (comment, input, ctx) =>
ctx.loaders.Assets.asset.load(comment.asset_id),
};
export default Comment;
@@ -8,6 +8,7 @@ import CommentCounts from "./comment_counts";
import Mutation from "./mutation";
import Profile from "./profile";
import Query from "./query";
import User from "./user";
const Resolvers: GQLResolver = {
Asset,
@@ -18,6 +19,7 @@ const Resolvers: GQLResolver = {
Mutation,
Profile,
Query,
User,
};
export default Resolvers;
@@ -0,0 +1,8 @@
import { GQLUserTypeResolver } from "talk-server/graph/tenant/schema/__generated__/types";
import { User } from "talk-server/models/user";
const User: GQLUserTypeResolver<User> = {
comments: (user, input, ctx) => ctx.loaders.Comments.forUser(user.id, input),
};
export default User;
@@ -5,7 +5,7 @@
"""
auth is a directive that will enforce authorization rules on the schema
definition. It will restrict the viewer of the field based on roles or if the
`userIDField` is specified, it will see if the current users ID equals the field
`userIDField` is specified, it will see if the current users ID equals the field
specified. This allows users that own a specific resource (like a comment, or a
flag) see their own content, but restrict it to everyone else. If the directive
is used without options, it simply requires a logged in user.
@@ -562,6 +562,15 @@ type User {
role is the current role of the User.
"""
role: USER_ROLE! @auth(roles: [ADMIN, MODERATOR], userIDField: "id")
"""
comments are the comments of the User.
"""
comments(
first: Int = 10
orderBy: COMMENT_SORT = CREATED_AT_DESC
after: Cursor
): CommentsConnection! @auth(roles: [ADMIN, MODERATOR], userIDField: "id")
}
################################################################################
@@ -687,6 +696,11 @@ type Comment {
editing returns details about the edit status of a Comment.
"""
editing: EditInfo!
"""
asset is the Asset that the Comment was written on.
"""
asset: Asset!
}
type PageInfo {
+24
View File
@@ -422,6 +422,30 @@ export async function retrieveCommentAssetConnection(
return retrieveConnection(input, query);
}
/**
* retrieveCommentUserConnection returns a Connection<Comment> for a given User's
* comments.
*
* @param db database connection
* @param userID the User id for the comment to retrieve
* @param input connection configuration
*/
export async function retrieveCommentUserConnection(
db: Db,
tenantID: string,
userID: string,
input: ConnectionInput
) {
// Create the query.
const query = new Query(collection(db)).where({
tenant_id: tenantID,
author_id: userID,
});
// Return a connection for the comments query.
return retrieveConnection(input, query);
}
/**
* retrieveConnection returns a Connection<Comment> for the given input and
* Query.
+11 -1
View File
@@ -12,6 +12,9 @@ general-userBoxAuthenticated-signedInAs =
general-userBoxAuthenticated-notYou =
Not you? <button>Sign Out</button>
general-app-commentsTab = Comments
general-app-myProfileTab = My Profile
## Comments Tab
comments-streamQuery-assetNotFound = Asset not found
@@ -68,5 +71,12 @@ comments-editCommentForm-rte =
comments-editCommentForm-editRemainingTime = Edit: <time></time> remaining
comments-editCommentForm-editTimeExpired = Edit time has expired. You can no longer edit this comment. Why not post another one?
comments-editedMarker-edited = Edited
comments-showConversationLink-readMore = Read More of this Conversation >
## Profile Tab
profile-historyComment-viewConversation = View Conversation
profile-historyComment-replies = Replies {$replyCount}
profile-historyComment-commentHistory = Comment History
profile-historyComment-story = Story: {$title}
profile-profileQuery-errorLoadingProfile = Error loading profile
profile-profileQuery-assetNotFound = Asset not found