Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load Comments #45

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions client/components/projects/comment.tsx

This file was deleted.

15 changes: 10 additions & 5 deletions client/components/projects/newComment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import React, { useRef } from 'react';
import { useStore } from 'react-redux';
import { useMutation } from 'urql';

const addComment = `mutation AddComment($storyId: String!, $text: String!) {
createComment(storyId: $storyId, text: $text) {
const addComment = `mutation AddComment($storyId: String!, $projectId: String! $text: String!) {
createComment(storyId: $storyId, projectId: $projectId, text: $text) {
... on Story {
comments {
createdAt
id
personId
personName
text
}
}
Expand All @@ -22,10 +22,11 @@ const addComment = `mutation AddComment($storyId: String!, $text: String!) {
}`;

interface Props {
projectId: string;
storyId: string;
}

const NewComment = ({ storyId }: Props) => {
const NewComment = ({ storyId, projectId }: Props) => {
const state = useStore().getState();

const commentRef = useRef<HTMLInputElement>(null);
Expand All @@ -34,7 +35,11 @@ const NewComment = ({ storyId }: Props) => {

const onSubmit = event => {
event.preventDefault();
executeMutation({ storyId, text: commentRef.current.value });
executeMutation({
storyId,
projectId,
text: commentRef.current.value,
});
commentRef.current.value = '';
};

Expand Down
12 changes: 10 additions & 2 deletions client/components/projects/project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,18 @@ import { ReduxState } from '~redux/reducers';

import StoryPanel from '~components/story-panel';

const Project = () => {
interface ProjectProps {
projectId: string;
}

const Project = ({ projectId }: ProjectProps) => {
const currentStory = useSelector((state: ReduxState) => state.story);

return currentStory.storyPosition != null ? <StoryPanel data={currentStory.story} /> : <></>;
return currentStory.storyPosition != null ? (
<StoryPanel projectId={projectId} key={currentStory.story.id} data={currentStory.story} />
) : (
<></>
);
};

export default Project;
8 changes: 6 additions & 2 deletions client/components/projects/projects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const fetchProjects = `query FetchProjects($filter: String!) {
comments {
id
createdAt
personId
personName
text
}
tasks {
Expand Down Expand Up @@ -69,7 +69,11 @@ const Projects = ({ history }: Props) => {
<>
<NavBar projects={res.data.projects.all} stories={currentProject.stories} />
<LogOut history={history} />
{res.data.projects.all.length > 0 ? <Project /> : <EmptyState />}
{res.data.projects.all.length > 0 ? (
<Project projectId={currentProject.id} />
) : (
<EmptyState />
)}
</>
);
};
Expand Down
4 changes: 2 additions & 2 deletions client/components/projects/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export interface Project {
id: number;
id: string;
name: string;
stories: Story[];
}
Expand All @@ -18,7 +18,7 @@ export interface Story {
export interface Comment {
id: string;
text: string;
personId: number;
personName: string;
createdAt: Date;
}

Expand Down
5 changes: 3 additions & 2 deletions client/components/story-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ const PanelWrapper = styled.div`
`;

interface PanelProps {
projectId: string;
data: StoryType;
}

const StoryPanel = ({ data }: PanelProps) => (
const StoryPanel = ({ projectId, data }: PanelProps) => (
<PanelWrapper>
<Story data={data} />
<Story projectId={projectId} data={data} />
<PointEstimate ptEst={3} />
</PanelWrapper>
);
Expand Down
113 changes: 113 additions & 0 deletions client/components/story/new-comment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React, { useRef } from 'react';
import { useStore } from 'react-redux';
import styled from 'styled-components';
import { useMutation } from 'urql';
import RightArrow from '~assets/images/right-arrow-full.svg';
import { colors, fontSizes, spacing } from '~lib/theme';

const addComment = `mutation AddComment($storyId: String!, $projectId: String! $text: String!) {
createComment(storyId: $storyId, projectId: $projectId, text: $text) {
... on Story {
comments {
createdAt
id
personName
text
}
}
... on Error {
code
error
kind
possibleFix
}
}
}`;

const CommentForm = styled.form`
margin-left: ${spacing.xxl};
margin-bottom: 38px;
width: 560px;
`;

const FormSubmit = styled.button`
outline: none;
width: 60px;
height: 60px;
border: solid 1px #d3d2d2;
display: block;
:hover {
background-color: #ffca41;
}
`;

const InputWrapper = styled.div`
display: flex;
flex-direction: row;
align-items: flex-end;
`;

const FormText = styled.input`
outline: none;
font-size: ${fontSizes.medium}
opacity: 0.5;
font-weight: normal;
line-height: 1.31;
color: ${colors.warmGrey};
width: 500px;
height: 60px;
border: solid 1px #d3d2d2;
padding-left: ${spacing.m}
&:focus {
opacity: 1;
&::-webkit-input-placeholder {
opacity: 0;
}
}
&:focus ~ ${FormSubmit} {
background-color: #ffca41;
}
`;

const SubmitIcon = styled(RightArrow)`
height: 18px;
width: 18px;
`;

interface Props {
projectId: string;
storyId: string;
}

const NewComment = ({ storyId, projectId }: Props) => {
const state = useStore().getState();

const commentRef = useRef<HTMLInputElement>(null);

const [, executeMutation] = useMutation(addComment);

const onSubmit = event => {
event.preventDefault();
executeMutation({
storyId,
projectId,
text: commentRef.current.value,
});
commentRef.current.value = '';
};

return (
<CommentForm onSubmit={onSubmit}>
<InputWrapper>
<FormText placeholder="Post a new comment" ref={commentRef} />
<label>
<FormSubmit type="submit" value="">
<SubmitIcon />
</FormSubmit>
</label>
</InputWrapper>
</CommentForm>
);
};

export default NewComment;
147 changes: 147 additions & 0 deletions client/components/story/story-comment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import React, { useState } from 'react';
import styled from 'styled-components';
import { Comment as CommentType } from '~components/projects/types';
import NewComment from '~components/story/new-comment';
import { parseTimeAndDate } from '~lib/datetime';
import { colors, fontSizes, spacing } from '~lib/theme';

const CommentTitle = styled.div`
color: #363333;
font-size: ${fontSizes.medium};
margin-bottom: 5px;
margin-left: ${spacing.xxl};
float: left;
`;

const CommentBar = styled.rect<CommentDividerProps>`
fill: ${props => (props.commentsShown ? '#ffca41' : '#e1e1e1')};
transition: fill 0.2s ease;
`;

const ShowComments = styled.div`
display: flex;
flex-direction: column;
&:hover ${CommentBar} {
fill: #ffca41;
}
`;

const CommentWrapper = styled.div`
width: 560px;
height: auto;
display: flex;
flex-direction: column;
margin-left: ${spacing.xxl};
`;

const ProfileWrapper = styled.div`
width: 100%;
height: auto;
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: ${spacing.l};
`;

const UserName = styled.div`
color: ${colors.warmGrey};
opacity: 0.5;
font-size: ${fontSizes.medium};
`;

const UserProfile = styled.circle`
fill: #a1a4ad;
margin: 0 auto;
`;

const CreatedAt = styled.div`
opacity: 0.5;
font-size: ${fontSizes.small};
font-weight: normal;
line-height: 1.29;
color: ${colors.warmGrey};
margin-left: auto;
`;

const CommentText = styled.div`
font-size: ${fontSizes.medium};
font-weight: normal;
font-style: normal;
line-height: 1.31;
color: #453d3f;
margin-bottom: 32px;
`;

interface CommentDividerProps {
commentsShown: boolean;
}

const CommentDivider = ({ commentsShown }: CommentDividerProps) => (
<svg
width="100%"
height="4"
style={{ marginBottom: `${spacing.l}`, marginLeft: '83px', float: 'left' }}
>
<CommentBar width="110" height="2" commentsShown={commentsShown} />
</svg>
);

const Divider = () => (
<svg width="100%" height="2" style={{ marginBottom: '22px' }}>
<rect width="560" height="1" fill="#d3d2d2" />
</svg>
);

const ProfileIcon = () => (
<svg width="32" height="32" style={{ marginRight: '11px' }}>
<UserProfile cx="50%" cy="50%" r="16" />
</svg>
);

interface CommentProp {
comment: CommentType;
}

const Comment = ({ comment }: CommentProp) => {
const { id, text, personName, createdAt } = comment;
return (
<CommentWrapper key={id}>
<ProfileWrapper>
<ProfileIcon />
<UserName>{personName}</UserName>
<CreatedAt>{parseTimeAndDate(createdAt)}</CreatedAt>
</ProfileWrapper>
<CommentText>{text}</CommentText>
<Divider />
</CommentWrapper>
);
};

interface CommentsProps {
storyId: string;
projectId: string;
comments: CommentType[];
}

const Comments = ({ storyId, projectId, comments }: CommentsProps) => {
const [showComments, setShowComments] = useState(false);

return (
<>
<ShowComments onClick={() => setShowComments(!showComments)}>
<CommentTitle>{`Comments (${comments.length})`}</CommentTitle>
<CommentDivider commentsShown={showComments} />
</ShowComments>
{showComments && (
<>
<NewComment projectId={projectId} storyId={storyId} />
{comments.map(comment => (
<Comment key={comment.id} comment={comment} />
))}
</>
)}
</>
);
};

export default Comments;
Loading