diff --git a/src/core/client/embed/PymControl.ts b/src/core/client/embed/PymControl.ts
index 1255d0854..92a8dbefc 100644
--- a/src/core/client/embed/PymControl.ts
+++ b/src/core/client/embed/PymControl.ts
@@ -25,7 +25,6 @@ export default class PymControl {
title: config.title,
id: `${config.id}_iframe`,
name: `${config.id}_iframe`,
- optionalparams: "",
});
this.cleanups = decorators
diff --git a/src/core/client/embed/__snapshots__/PymControl.spec.ts.snap b/src/core/client/embed/__snapshots__/PymControl.spec.ts.snap
index e4f013f5d..4ab9f246a 100644
--- a/src/core/client/embed/__snapshots__/PymControl.spec.ts.snap
+++ b/src/core/client/embed/__snapshots__/PymControl.spec.ts.snap
@@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`PymControl should create iframe 1`] = `""`;
+exports[`PymControl should create iframe 1`] = `""`;
exports[`PymControl should send message 1`] = `"pymxPYMxpymcontrol-test-idxPYMxtestxPYMxhello world"`;
diff --git a/src/core/client/embed/__snapshots__/index.spec.ts.snap b/src/core/client/embed/__snapshots__/index.spec.ts.snap
index 1307f9fad..18f558868 100644
--- a/src/core/client/embed/__snapshots__/index.spec.ts.snap
+++ b/src/core/client/embed/__snapshots__/index.spec.ts.snap
@@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Basic integration test should render iframe 1`] = `""`;
+exports[`Basic integration test should render iframe 1`] = `""`;
-exports[`Basic integration test should use canonical link 1`] = `""`;
+exports[`Basic integration test should use canonical link 1`] = `""`;
diff --git a/src/core/client/framework/helpers/getURLWithCommentID.tsx b/src/core/client/framework/helpers/getURLWithCommentID.tsx
new file mode 100644
index 000000000..421032782
--- /dev/null
+++ b/src/core/client/framework/helpers/getURLWithCommentID.tsx
@@ -0,0 +1,8 @@
+import { modifyQuery } from "talk-framework/utils";
+
+export default function getURLWithCommentID(
+ assetURL: string,
+ commentID?: string
+) {
+ return modifyQuery(assetURL, { commentID });
+}
diff --git a/src/core/client/framework/helpers/index.ts b/src/core/client/framework/helpers/index.ts
index 653f66d98..e4a5c898f 100644
--- a/src/core/client/framework/helpers/index.ts
+++ b/src/core/client/framework/helpers/index.ts
@@ -1 +1,2 @@
export { default as getMe } from "./getMe";
+export { default as getURLWithCommentID } from "./getURLWithCommentID";
diff --git a/src/core/client/stream/tabs/comments/components/Comment/ButtonsBar.spec.tsx b/src/core/client/stream/tabs/comments/components/Comment/ButtonsBar.spec.tsx
new file mode 100644
index 000000000..ef21fa796
--- /dev/null
+++ b/src/core/client/stream/tabs/comments/components/Comment/ButtonsBar.spec.tsx
@@ -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 = {
+ children: "children",
+ };
+ const wrapper = shallow();
+ expect(wrapper).toMatchSnapshot();
+});
diff --git a/src/core/client/stream/tabs/comments/components/Comment/ButtonsBar.tsx b/src/core/client/stream/tabs/comments/components/Comment/ButtonsBar.tsx
new file mode 100644
index 000000000..f9e2e9f49
--- /dev/null
+++ b/src/core/client/stream/tabs/comments/components/Comment/ButtonsBar.tsx
@@ -0,0 +1,13 @@
+import React, { StatelessComponent } from "react";
+
+import { Flex } from "talk-ui/components";
+
+const ButtonsBar: StatelessComponent = props => {
+ return (
+
+ {props.children}
+
+ );
+};
+
+export default ButtonsBar;
diff --git a/src/core/client/stream/tabs/comments/components/Comment/Comment.tsx b/src/core/client/stream/tabs/comments/components/Comment/Comment.tsx
index b30621913..7ed3d93f9 100644
--- a/src/core/client/stream/tabs/comments/components/Comment/Comment.tsx
+++ b/src/core/client/stream/tabs/comments/components/Comment/Comment.tsx
@@ -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 = props => {
{props.topBarRight && {props.topBarRight}
}
- {props.body || ""}
-
+
+ {props.body || ""}
{props.footer}
-
+
);
};
diff --git a/src/core/client/stream/tabs/comments/components/Comment/ShowConversationLink.spec.tsx b/src/core/client/stream/tabs/comments/components/Comment/ShowConversationLink.spec.tsx
new file mode 100644
index 000000000..6ec618b47
--- /dev/null
+++ b/src/core/client/stream/tabs/comments/components/Comment/ShowConversationLink.spec.tsx
@@ -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 = {
+ id: "id",
+ onClick: noop,
+ href: "http://localhost/comment",
+ };
+ const wrapper = shallow();
+ expect(wrapper).toMatchSnapshot();
+});
diff --git a/src/core/client/stream/tabs/comments/components/Comment/ShowConversationLink.tsx b/src/core/client/stream/tabs/comments/components/Comment/ShowConversationLink.tsx
new file mode 100644
index 000000000..23ff05e4a
--- /dev/null
+++ b/src/core/client/stream/tabs/comments/components/Comment/ShowConversationLink.tsx
@@ -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;
+}
+
+const ShowConversationLink: StatelessComponent<
+ ShowConversationLinkProps
+> = props => {
+ return (
+
+ );
+};
+
+export default ShowConversationLink;
diff --git a/src/core/client/stream/tabs/comments/components/Comment/__snapshots__/ButtonsBar.spec.tsx.snap b/src/core/client/stream/tabs/comments/components/Comment/__snapshots__/ButtonsBar.spec.tsx.snap
new file mode 100644
index 000000000..164113601
--- /dev/null
+++ b/src/core/client/stream/tabs/comments/components/Comment/__snapshots__/ButtonsBar.spec.tsx.snap
@@ -0,0 +1,10 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders correctly 1`] = `
+
+ children
+
+`;
diff --git a/src/core/client/stream/tabs/comments/components/Comment/__snapshots__/Comment.spec.tsx.snap b/src/core/client/stream/tabs/comments/components/Comment/__snapshots__/Comment.spec.tsx.snap
index 09cd14a62..f1eceef62 100644
--- a/src/core/client/stream/tabs/comments/components/Comment/__snapshots__/Comment.spec.tsx.snap
+++ b/src/core/client/stream/tabs/comments/components/Comment/__snapshots__/Comment.spec.tsx.snap
@@ -30,15 +30,11 @@ exports[`renders username and body 1`] = `
topBarRight
-
- Woof
-
-
+
+
+ Woof
+
footer
-
+
`;
diff --git a/src/core/client/stream/tabs/comments/components/Comment/__snapshots__/ShowConversationLink.spec.tsx.snap b/src/core/client/stream/tabs/comments/components/Comment/__snapshots__/ShowConversationLink.spec.tsx.snap
new file mode 100644
index 000000000..5426c46e2
--- /dev/null
+++ b/src/core/client/stream/tabs/comments/components/Comment/__snapshots__/ShowConversationLink.spec.tsx.snap
@@ -0,0 +1,19 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`renders correctly 1`] = `
+
+`;
diff --git a/src/core/client/stream/tabs/comments/components/Comment/index.ts b/src/core/client/stream/tabs/comments/components/Comment/index.ts
index e89d4b958..d05ab70f8 100644
--- a/src/core/client/stream/tabs/comments/components/Comment/index.ts
+++ b/src/core/client/stream/tabs/comments/components/Comment/index.ts
@@ -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";
diff --git a/src/core/client/stream/tabs/comments/components/ReplyList.spec.tsx b/src/core/client/stream/tabs/comments/components/ReplyList.spec.tsx
index c8b3dcbb2..76707a974 100644
--- a/src/core/client/stream/tabs/comments/components/ReplyList.spec.tsx
+++ b/src/core/client/stream/tabs/comments/components/ReplyList.spec.tsx
@@ -14,7 +14,10 @@ it("renders correctly", () => {
const props: PropTypesOf = {
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,
diff --git a/src/core/client/stream/tabs/comments/components/ReplyList.tsx b/src/core/client/stream/tabs/comments/components/ReplyList.tsx
index 896120b91..87f9eb610 100644
--- a/src/core/client/stream/tabs/comments/components/ReplyList.tsx
+++ b/src/core/client/stream/tabs/comments/components/ReplyList.tsx
@@ -15,7 +15,9 @@ export interface ReplyListProps {
id: string;
};
comments: ReadonlyArray<
- { id: string } & PropTypesOf["comment"]
+ { id: string; showConversationLink?: boolean } & PropTypesOf<
+ typeof CommentContainer
+ >["comment"]
>;
onShowAll?: () => void;
hasMore?: boolean;
@@ -52,6 +54,7 @@ const ReplyList: StatelessComponent = props => {
indentLevel={props.indentLevel}
localReply={props.localReply}
disableReplies={props.disableReplies}
+ showConversationLink={!!comment.showConversationLink}
/>
{getReplyListElement(props, comment)}
diff --git a/src/core/client/stream/tabs/comments/components/__snapshots__/ReplyList.spec.tsx.snap b/src/core/client/stream/tabs/comments/components/__snapshots__/ReplyList.spec.tsx.snap
index 0b4cbcd15..6e66b20e5 100644
--- a/src/core/client/stream/tabs/comments/components/__snapshots__/ReplyList.spec.tsx.snap
+++ b/src/core/client/stream/tabs/comments/components/__snapshots__/ReplyList.spec.tsx.snap
@@ -8,7 +8,7 @@ exports[`renders correctly 1`] = `
-
-
@@ -58,7 +61,7 @@ exports[`when there is more disables load more button 1`] = `
-
-
-
-
-
-
-
-
-
-
-
- {
const props: PropTypesOf = {
me: null,
asset: {
- id: "asset-id",
+ url: "http://localhost/asset",
},
comment: {
id: "comment-id",
@@ -32,6 +32,7 @@ it("renders username and body", () => {
},
indentLevel: 1,
showAuthPopup: noop as any,
+ setCommentID: noop as any,
localReply: false,
disableReplies: false,
};
@@ -44,7 +45,7 @@ it("renders body only", () => {
const props: PropTypesOf = {
me: null,
asset: {
- id: "asset-id",
+ url: "http://localhost/asset",
},
comment: {
id: "comment-id",
@@ -62,6 +63,7 @@ it("renders body only", () => {
},
indentLevel: 1,
showAuthPopup: noop as any,
+ setCommentID: noop as any,
};
const wrapper = shallow();
@@ -72,7 +74,7 @@ it("hide reply button", () => {
const props: PropTypesOf = {
me: null,
asset: {
- id: "asset-id",
+ url: "http://localhost/asset",
},
comment: {
id: "comment-id",
@@ -90,6 +92,7 @@ it("hide reply button", () => {
},
indentLevel: 1,
showAuthPopup: noop as any,
+ setCommentID: noop as any,
localReply: false,
disableReplies: true,
};
@@ -97,3 +100,35 @@ it("hide reply button", () => {
const wrapper = shallow();
expect(wrapper).toMatchSnapshot();
});
+
+it("shows conversation link", () => {
+ const props: PropTypesOf = {
+ 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();
+ expect(wrapper).toMatchSnapshot();
+});
diff --git a/src/core/client/stream/tabs/comments/containers/CommentContainer.tsx b/src/core/client/stream/tabs/comments/containers/CommentContainer.tsx
index f9db4932c..dc1b2b3e1 100644
--- a/src/core/client/stream/tabs/comments/containers/CommentContainer.tsx
+++ b/src/core/client/stream/tabs/comments/containers/CommentContainer.tsx
@@ -1,20 +1,26 @@
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";
import { CommentContainer_comment as CommentData } from "talk-stream/__generated__/CommentContainer_comment.graphql";
import { CommentContainer_me as MeData } from "talk-stream/__generated__/CommentContainer_me.graphql";
import {
+ SetCommentIDMutation,
ShowAuthPopupMutation,
+ withSetCommentIDMutation,
withShowAuthPopupMutation,
} from "talk-stream/mutations";
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";
@@ -26,6 +32,7 @@ interface InnerProps {
asset: AssetData;
indentLevel?: number;
showAuthPopup: ShowAuthPopupMutation;
+ setCommentID: SetCommentIDMutation;
/**
* localReply will integrate the mutation response into
* localReplies
@@ -33,6 +40,8 @@ interface InnerProps {
localReply?: boolean;
/** disableReplies will remove the ReplyButton */
disableReplies?: boolean;
+ /** showConversationLink will render a link to the conversation */
+ showConversationLink?: boolean;
}
interface State {
@@ -113,6 +122,12 @@ export class CommentContainer extends Component {
return;
}
+ private handleShowConversation = (e: MouseEvent) => {
+ e.preventDefault();
+ this.props.setCommentID({ id: this.props.comment.id });
+ return false;
+ };
+
public render() {
const {
comment,
@@ -120,6 +135,7 @@ export class CommentContainer extends Component {
indentLevel,
localReply,
disableReplies,
+ showConversationLink,
} = this.props;
const { showReplyDialog, showEditDialog, editable } = this.state;
if (showEditDialog) {
@@ -157,14 +173,28 @@ export class CommentContainer extends Component {
}
footer={
<>
- {!disableReplies && (
-