Adding Attachment and Popover Component

This commit is contained in:
Belén Curcio
2018-07-16 14:04:51 -03:00
94 changed files with 4125 additions and 1256 deletions
+14
View File
@@ -0,0 +1,14 @@
/* Here we add global stylings for body and document */
:global {
body {
margin: "0";
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
}
}
.root {
}
@@ -0,0 +1,22 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import App from "./App";
it("renders correctly", () => {
const props: PropTypesOf<typeof App> = {
asset: {},
};
const wrapper = shallow(<App {...props} />);
expect(wrapper).toMatchSnapshot();
});
it("renders correctly when asset is null", () => {
const props: PropTypesOf<typeof App> = {
asset: null,
};
const wrapper = shallow(<App {...props} />);
expect(wrapper).toMatchSnapshot();
});
+3 -1
View File
@@ -5,6 +5,8 @@ import { Flex } from "talk-ui/components";
import StreamContainer from "../containers/StreamContainer";
import * as styles from "./App.css";
export interface AppProps {
asset: {} | null;
}
@@ -12,7 +14,7 @@ export interface AppProps {
const App: StatelessComponent<AppProps> = props => {
if (props.asset) {
return (
<Flex justifyContent="center">
<Flex justifyContent="center" className={styles.root}>
<StreamContainer asset={props.asset} />
</Flex>
);
@@ -1,10 +0,0 @@
.root {
}
.gutterBottom {
margin-bottom: calc(1px * var(--spacing-unit));
}
.topBar {
margin-bottom: calc(0.5px * var(--spacing-unit));
}
@@ -1,9 +1,12 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import Comment from "./Comment";
it("renders username and body", () => {
<<<<<<< HEAD:src/core/client/stream/components/Comment.spec.tsx
const props = {
id: "id",
author: {
@@ -18,11 +21,14 @@ it("renders username and body", () => {
it("renders with gutterBottom", () => {
const props = {
id: "id",
=======
const props: PropTypesOf<typeof Comment> = {
>>>>>>> abfa39529ff398007bb67cd814c4217a97bdb38b:src/core/client/stream/components/Comment/Comment.spec.tsx
author: {
username: "Marvin",
},
body: "Woof",
gutterBottom: true,
createdAt: "1995-12-17T03:24:00.000Z",
};
const wrapper = shallow(<Comment {...props} />);
expect(wrapper).toMatchSnapshot();
@@ -1,9 +1,9 @@
import cn from "classnames";
import React from "react";
import { StatelessComponent } from "react";
import { Typography } from "talk-ui/components";
import * as styles from "./Comment.css";
import PermalinkPopover from "./PermalinkPopover";
import PermalinkPopover from "../PermalinkPopover";
import Timestamp from "./Timestamp";
import TopBar from "./TopBar";
import Username from "./Username";
export interface CommentProps {
@@ -13,20 +13,18 @@ export interface CommentProps {
username: string;
} | null;
body: string | null;
gutterBottom?: boolean;
createdAt: string;
}
const Comment: StatelessComponent<CommentProps> = props => {
const rootClassName = cn(styles.root, props.className, {
[styles.gutterBottom]: props.gutterBottom,
});
return (
<div className={rootClassName} role="article">
<div className={styles.topBar}>
<div role="article">
<TopBar>
{props.author && <Username>{props.author.username}</Username>}
</div>
<Timestamp>{props.createdAt}</Timestamp>
</TopBar>
<Typography>{props.body}</Typography>
<div className={cn("talk-comment-footer")}>
<div>
<PermalinkPopover commentId={props.id} />
</div>
</div>
@@ -0,0 +1,3 @@
.root {
composes: timestamp from "talk-ui/shared/typography.css";
}
@@ -0,0 +1,14 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import Timestamp from "./Timestamp";
it("renders correctly", () => {
const props: PropTypesOf<typeof Timestamp> = {
children: "1995-12-17T03:24:00.000Z",
};
const wrapper = shallow(<Timestamp {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -0,0 +1,16 @@
import React from "react";
import { StatelessComponent } from "react";
import { RelativeTime } from "talk-ui/components";
import * as styles from "./Timestamp.css";
export interface TimestampProps {
children: string;
}
const Timestamp: StatelessComponent<TimestampProps> = props => (
<RelativeTime className={styles.root} date={props.children} />
);
export default Timestamp;
@@ -0,0 +1,3 @@
.root {
margin-bottom: calc(0.5 * var(--spacing-unit));
}
@@ -0,0 +1,45 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import { PropTypesOf } from "talk-framework/types";
import { UIContext, UIContextProps } from "talk-ui/components";
import TopBar from "./TopBar";
it("renders correctly on small screens", () => {
const props: PropTypesOf<typeof TopBar> = {
children: <div>Hello World</div>,
};
const context: UIContextProps = {
mediaQueryValues: {
width: 320,
},
};
const testRenderer = TestRenderer.create(
<UIContext.Provider value={context}>
<TopBar {...props} />
</UIContext.Provider>
);
expect(testRenderer.toJSON()).toMatchSnapshot();
});
it("renders correctly on big screens", () => {
const props: PropTypesOf<typeof TopBar> = {
children: <div>Hello World</div>,
};
const context: UIContextProps = {
mediaQueryValues: {
width: 1600,
},
};
const testRenderer = TestRenderer.create(
<UIContext.Provider value={context}>
<TopBar {...props} />
</UIContext.Provider>
);
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -0,0 +1,32 @@
import cn from "classnames";
import React from "react";
import { StatelessComponent } from "react";
import { Flex, MatchMedia } from "talk-ui/components";
import * as styles from "./TopBar.css";
export interface TopBarProps {
className?: string;
children: React.ReactNode;
}
const TopBar: StatelessComponent<TopBarProps> = props => {
const rootClassName = cn(styles.root, props.className);
return (
<MatchMedia minWidth="xs">
{matches => (
<Flex
className={rootClassName}
alignItems="baseline"
direction={matches ? "row" : "column"}
itemGutter={matches ? true : "half"}
>
{props.children}
</Flex>
)}
</MatchMedia>
);
};
export default TopBar;
@@ -0,0 +1,3 @@
.root {
line-height: 1;
}
@@ -0,0 +1,45 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import { PropTypesOf } from "talk-framework/types";
import { UIContext, UIContextProps } from "talk-ui/components";
import Username from "./Username";
it("renders correctly on small screens", () => {
const props: PropTypesOf<typeof Username> = {
children: "Marvin",
};
const context: UIContextProps = {
mediaQueryValues: {
width: 320,
},
};
const testRenderer = TestRenderer.create(
<UIContext.Provider value={context}>
<Username {...props} />
</UIContext.Provider>
);
expect(testRenderer.toJSON()).toMatchSnapshot();
});
it("renders correctly on big screens", () => {
const props: PropTypesOf<typeof Username> = {
children: "Marvin",
};
const context: UIContextProps = {
mediaQueryValues: {
width: 1600,
},
};
const testRenderer = TestRenderer.create(
<UIContext.Provider value={context}>
<Username {...props} />
</UIContext.Provider>
);
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -0,0 +1,28 @@
import React from "react";
import { StatelessComponent } from "react";
import { MatchMedia, Typography } from "talk-ui/components";
import * as styles from "./Username.css";
export interface UsernameProps {
children: string;
}
const Username: StatelessComponent<UsernameProps> = props => {
return (
<MatchMedia minWidth="xs">
{matches => (
<Typography
variant={matches ? "heading2" : "heading3"}
className={styles.root}
component="span"
>
{props.children}
</Typography>
)}
</MatchMedia>
);
};
export default Username;
@@ -0,0 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders username and body 1`] = `
<div
role="article"
>
<TopBar>
<Username>
Marvin
</Username>
<Timestamp>
1995-12-17T03:24:00.000Z
</Timestamp>
</TopBar>
<withPropsOnChange(Typography)>
Woof
</withPropsOnChange(Typography)>
</div>
`;
@@ -0,0 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<withPropsOnChange(RelativeTime)
className="Timestamp-root"
date="1995-12-17T03:24:00.000Z"
/>
`;
@@ -0,0 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly on big screens 1`] = `
<div
className="Flex-root TopBar-root Flex-itemGutter Flex-alignBaseline Flex-directionRow"
>
<div>
Hello World
</div>
</div>
`;
exports[`renders correctly on small screens 1`] = `
<div
className="Flex-root TopBar-root Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
>
<div>
Hello World
</div>
</div>
`;
@@ -0,0 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly on big screens 1`] = `
<span
className="Typography-root Typography-heading2 Username-root"
>
Marvin
</span>
`;
exports[`renders correctly on small screens 1`] = `
<span
className="Typography-root Typography-heading3 Username-root"
>
Marvin
</span>
`;
@@ -0,0 +1 @@
export { default, default as Comment, CommentProps } from "./Comment";
+1 -1
View File
@@ -1,6 +1,6 @@
.root {
border-left: 3px solid;
padding-left: calc(1px * var(--spacing-unit));
padding-left: var(--spacing-unit);
}
.level0 {
@@ -0,0 +1,14 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import Indent from "./Indent";
it("renders correctly", () => {
const props: PropTypesOf<typeof Indent> = {
children: <div>Hello World</div>,
};
const wrapper = shallow(<Indent {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -5,7 +5,7 @@
height: 100px;
width: 100%;
box-sizing: border-box;
margin-bottom: calc(1px * var(--spacing-unit));
margin-bottom: var(--spacing-unit);
}
.postButtonContainer {
@@ -3,10 +3,12 @@ import { noop } from "lodash";
import React from "react";
import sinon, { SinonSpy } from "sinon";
import ReplyList, { ReplyListProps } from "./ReplyList";
import { PropTypesOf } from "talk-framework/types";
import ReplyList from "./ReplyList";
it("renders correctly", () => {
const props: ReplyListProps = {
const props: PropTypesOf<typeof ReplyList> = {
commentID: "comment-id",
comments: [{ id: "comment-1" }, { id: "comment-2" }],
onShowAll: noop,
@@ -18,7 +20,7 @@ it("renders correctly", () => {
});
describe("when there is more", () => {
const props: ReplyListProps = {
const props: PropTypesOf<typeof ReplyList> = {
commentID: "comment-id",
comments: [{ id: "comment-1" }, { id: "comment-2" }],
onShowAll: sinon.spy(),
@@ -2,7 +2,7 @@ import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { Button } from "talk-ui/components";
import { Button, Flex } from "talk-ui/components";
import CommentContainer from "../containers/CommentContainer";
import Indent from "./Indent";
@@ -18,9 +18,14 @@ export interface ReplyListProps {
const ReplyList: StatelessComponent<ReplyListProps> = props => {
return (
<Indent>
<div id={`talk-comments-replyList-log--${props.commentID}`} role="log">
<Flex
direction="column"
id={`talk-comments-replyList-log--${props.commentID}`}
role="log"
itemGutter
>
{props.comments.map(comment => (
<CommentContainer key={comment.id} data={comment} gutterBottom />
<CommentContainer key={comment.id} data={comment} />
))}
{props.hasMore && (
<Localized id="comments-replyList-showAll">
@@ -37,7 +42,7 @@ const ReplyList: StatelessComponent<ReplyListProps> = props => {
</Button>
</Localized>
)}
</div>
</Flex>
</Indent>
);
};
@@ -1,12 +1,14 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import sinon from "sinon";
import sinon, { SinonSpy } from "sinon";
import Stream, { StreamProps } from "./Stream";
import { PropTypesOf } from "talk-framework/types";
import Stream from "./Stream";
it("renders correctly", () => {
const props: StreamProps = {
const props: PropTypesOf<typeof Stream> = {
assetID: "asset-id",
isClosed: false,
comments: [{ id: "comment-1" }, { id: "comment-2" }],
@@ -19,7 +21,7 @@ it("renders correctly", () => {
});
describe("when there is more", () => {
const props = {
const props: PropTypesOf<typeof Stream> = {
assetID: "asset-id",
isClosed: false,
comments: [{ id: "comment-1" }, { id: "comment-2" }],
@@ -35,7 +37,7 @@ describe("when there is more", () => {
it("calls onLoadMore", () => {
wrapper.find("#talk-comments-stream-loadMore").simulate("click");
expect(props.onLoadMore.calledOnce).toBe(true);
expect((props.onLoadMore as SinonSpy).calledOnce).toBe(true);
});
const wrapperDisabledButton = shallow(<Stream {...props} disableLoadMore />);
+12 -6
View File
@@ -2,7 +2,7 @@ import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { Button } from "talk-ui/components";
import { Button, Flex } from "talk-ui/components";
import CommentContainer from "../containers/CommentContainer";
import PostCommentFormContainer from "../containers/PostCommentFormContainer";
@@ -24,12 +24,18 @@ const Stream: StatelessComponent<StreamProps> = props => {
<div className={styles.root}>
<Logo gutterBottom />
<PostCommentFormContainer assetID={props.assetID} />
<div id="talk-comments-stream-log" role="log" aria-live="polite">
<Flex
direction="column"
id="talk-comments-stream-log"
role="log"
aria-live="polite"
itemGutter
>
{props.comments.map(comment => (
<div key={comment.id}>
<CommentContainer data={comment} gutterBottom />
<Flex direction="column" key={comment.id} itemGutter>
<CommentContainer data={comment} />
<ReplyListContainer comment={comment} />
</div>
</Flex>
))}
{props.hasMore && (
<Localized id="comments-stream-loadMore">
@@ -46,7 +52,7 @@ const Stream: StatelessComponent<StreamProps> = props => {
</Button>
</Localized>
)}
</div>
</Flex>
</div>
);
};
@@ -1,3 +0,0 @@
.root {
composes: heading4 from "talk-ui/shared/typography.css";
}
@@ -1,12 +0,0 @@
import { shallow } from "enzyme";
import React from "react";
import Username from "./Username";
it("renders correctly", () => {
const props = {
children: "Marvin",
};
const wrapper = shallow(<Username {...props} />);
expect(wrapper).toMatchSnapshot();
});
@@ -1,14 +0,0 @@
import React from "react";
import { StatelessComponent } from "react";
import * as styles from "./Username.css";
export interface CommentProps {
children: string;
}
const Username: StatelessComponent<CommentProps> = props => {
return <span className={styles.root}>{props.children}</span>;
};
export default Username;
@@ -0,0 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<Flex
className="App-root"
justifyContent="center"
>
<Relay(StreamContainer)
asset={Object {}}
/>
</Flex>
`;
exports[`renders correctly when asset is null 1`] = `
<div>
Asset not found
</div>
`;
@@ -1,37 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders username and body 1`] = `
<div
className="Comment-root"
role="article"
>
<div
className="Comment-topBar"
>
<Username>
Marvin
</Username>
</div>
<withPropsOnChange(Typography)>
Woof
</withPropsOnChange(Typography)>
</div>
`;
exports[`renders with gutterBottom 1`] = `
<div
className="Comment-root Comment-gutterBottom"
role="article"
>
<div
className="Comment-topBar"
>
<Username>
Marvin
</Username>
</div>
<withPropsOnChange(Typography)>
Woof
</withPropsOnChange(Typography)>
</div>
`;
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<div
className="Indent-root Indent-level0"
>
<div>
Hello World
</div>
</div>
`;
@@ -2,8 +2,10 @@
exports[`renders correctly 1`] = `
<Indent>
<div
<Flex
direction="column"
id="talk-comments-replyList-log--comment-id"
itemGutter={true}
role="log"
>
<Relay(CommentContainer)
@@ -12,7 +14,6 @@ exports[`renders correctly 1`] = `
"id": "comment-1",
}
}
gutterBottom={true}
key="comment-1"
/>
<Relay(CommentContainer)
@@ -21,17 +22,18 @@ exports[`renders correctly 1`] = `
"id": "comment-2",
}
}
gutterBottom={true}
key="comment-2"
/>
</div>
</Flex>
</Indent>
`;
exports[`when there is more renders a load more button 1`] = `
<Indent>
<div
<Flex
direction="column"
id="talk-comments-replyList-log--comment-id"
itemGutter={true}
role="log"
>
<Relay(CommentContainer)
@@ -40,7 +42,6 @@ exports[`when there is more renders a load more button 1`] = `
"id": "comment-1",
}
}
gutterBottom={true}
key="comment-1"
/>
<Relay(CommentContainer)
@@ -49,7 +50,6 @@ exports[`when there is more renders a load more button 1`] = `
"id": "comment-2",
}
}
gutterBottom={true}
key="comment-2"
/>
<Localized
@@ -67,6 +67,6 @@ exports[`when there is more renders a load more button 1`] = `
Show All Replies
</withPropsOnChange(Button)>
</Localized>
</div>
</Flex>
</Indent>
`;
@@ -10,12 +10,16 @@ exports[`renders correctly 1`] = `
<withContext(createMutationContainer(PostCommentFormContainer))
assetID="asset-id"
/>
<div
<Flex
aria-live="polite"
direction="column"
id="talk-comments-stream-log"
itemGutter={true}
role="log"
>
<div
<Flex
direction="column"
itemGutter={true}
key="comment-1"
>
<Relay(CommentContainer)
@@ -24,7 +28,6 @@ exports[`renders correctly 1`] = `
"id": "comment-1",
}
}
gutterBottom={true}
/>
<Relay(ReplyListContainer)
comment={
@@ -33,8 +36,10 @@ exports[`renders correctly 1`] = `
}
}
/>
</div>
<div
</Flex>
<Flex
direction="column"
itemGutter={true}
key="comment-2"
>
<Relay(CommentContainer)
@@ -43,7 +48,6 @@ exports[`renders correctly 1`] = `
"id": "comment-2",
}
}
gutterBottom={true}
/>
<Relay(ReplyListContainer)
comment={
@@ -52,8 +56,8 @@ exports[`renders correctly 1`] = `
}
}
/>
</div>
</div>
</Flex>
</Flex>
</div>
`;
@@ -67,12 +71,16 @@ exports[`when there is more disables load more button 1`] = `
<withContext(createMutationContainer(PostCommentFormContainer))
assetID="asset-id"
/>
<div
<Flex
aria-live="polite"
direction="column"
id="talk-comments-stream-log"
itemGutter={true}
role="log"
>
<div
<Flex
direction="column"
itemGutter={true}
key="comment-1"
>
<Relay(CommentContainer)
@@ -81,7 +89,6 @@ exports[`when there is more disables load more button 1`] = `
"id": "comment-1",
}
}
gutterBottom={true}
/>
<Relay(ReplyListContainer)
comment={
@@ -90,8 +97,10 @@ exports[`when there is more disables load more button 1`] = `
}
}
/>
</div>
<div
</Flex>
<Flex
direction="column"
itemGutter={true}
key="comment-2"
>
<Relay(CommentContainer)
@@ -100,7 +109,6 @@ exports[`when there is more disables load more button 1`] = `
"id": "comment-2",
}
}
gutterBottom={true}
/>
<Relay(ReplyListContainer)
comment={
@@ -109,7 +117,7 @@ exports[`when there is more disables load more button 1`] = `
}
}
/>
</div>
</Flex>
<Localized
id="comments-stream-loadMore"
>
@@ -125,7 +133,7 @@ exports[`when there is more disables load more button 1`] = `
Load More
</withPropsOnChange(Button)>
</Localized>
</div>
</Flex>
</div>
`;
@@ -139,12 +147,16 @@ exports[`when there is more renders a load more button 1`] = `
<withContext(createMutationContainer(PostCommentFormContainer))
assetID="asset-id"
/>
<div
<Flex
aria-live="polite"
direction="column"
id="talk-comments-stream-log"
itemGutter={true}
role="log"
>
<div
<Flex
direction="column"
itemGutter={true}
key="comment-1"
>
<Relay(CommentContainer)
@@ -153,7 +165,6 @@ exports[`when there is more renders a load more button 1`] = `
"id": "comment-1",
}
}
gutterBottom={true}
/>
<Relay(ReplyListContainer)
comment={
@@ -162,8 +173,10 @@ exports[`when there is more renders a load more button 1`] = `
}
}
/>
</div>
<div
</Flex>
<Flex
direction="column"
itemGutter={true}
key="comment-2"
>
<Relay(CommentContainer)
@@ -172,7 +185,6 @@ exports[`when there is more renders a load more button 1`] = `
"id": "comment-2",
}
}
gutterBottom={true}
/>
<Relay(ReplyListContainer)
comment={
@@ -181,7 +193,7 @@ exports[`when there is more renders a load more button 1`] = `
}
}
/>
</div>
</Flex>
<Localized
id="comments-stream-loadMore"
>
@@ -197,6 +209,6 @@ exports[`when there is more renders a load more button 1`] = `
Load More
</withPropsOnChange(Button)>
</Localized>
</div>
</Flex>
</div>
`;
@@ -1,9 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<span
className="Username-root"
>
Marvin
</span>
`;