From dddab7369bf85d7d4d3d729afae166a8c7cd30ca Mon Sep 17 00:00:00 2001 From: noah Date: Sat, 26 Feb 2022 11:47:52 +0900 Subject: [PATCH 1/2] Refactoring the deployment page --- ui/src/components/DeployConfirm.tsx | 202 ------------------ .../DeploymentDescriptor.tsx | 62 ++++++ .../components/DeploymentDescriptor/index.tsx | 3 + ui/src/components/DeploymentStatusSteps.tsx | 16 +- ui/src/components/ReviewerList.tsx | 97 ++++----- ui/src/components/UserAvatar.tsx | 12 +- ui/src/views/Deployment.tsx | 51 +++-- 7 files changed, 164 insertions(+), 279 deletions(-) delete mode 100644 ui/src/components/DeployConfirm.tsx create mode 100644 ui/src/components/DeploymentDescriptor/DeploymentDescriptor.tsx create mode 100644 ui/src/components/DeploymentDescriptor/index.tsx diff --git a/ui/src/components/DeployConfirm.tsx b/ui/src/components/DeployConfirm.tsx deleted file mode 100644 index a6a15633..00000000 --- a/ui/src/components/DeployConfirm.tsx +++ /dev/null @@ -1,202 +0,0 @@ -import { Form, Typography, Avatar, Button, Collapse, Timeline } from "antd" -import moment from "moment" -import { useState } from "react" - -import { Deployment, Commit, Review } from "../models" -import DeploymentRefCode from "./DeploymentRefCode" -import DeploymentStatusBadge from "./DeploymentStatusBadge" -import DeploymentStatusSteps from "./DeploymentStatusSteps" -import ReviewerList, { ReviewStatus } from "./ReviewerList" - -const { Paragraph, Text } = Typography -const { Panel } = Collapse - -interface DeployConfirmProps { - isDeployable: boolean - deploying: boolean - deployment: Deployment - changes: Commit[] - reviews: Review[] - onClickDeploy(): void -} - -export default function DeployConfirm(props: DeployConfirmProps): JSX.Element { - const layout = { - labelCol: { span: 5}, - wrapperCol: { span: 16 }, - style: {marginBottom: 12} - }; - const submitLayout = { - wrapperCol: { offset: 6, span: 16 }, - }; - - // Form makes it to display organized. - return ( -
- - {props.deployment.env} - - - - - 0)? {marginBottom: 0} : {marginBottom: 12}} - > - {(props.deployment.statuses && props.deployment.statuses.length > 0)? - - } - style={{position: "relative", top: "-5px", left: "-15px"}} - > - - - : - - } - - - {(props.deployment.deployer)? - - {props.deployment.deployer.login} - : - - U - } - - - {moment(props.deployment.createdAt).format("YYYY-MM-DD HH:mm:ss")} - - 0)? {marginBottom: 0} : {}} - > - {(props.reviews.length > 0)? - - } - style={{position: "relative", top: "-5px", left: "-15px"}} - > - - - : - No Reviewers} - - - - - - - - - - {(props.isDeployable)? - : - } - -
- ) -} - -interface CommitChangesProps { - changes: Commit[] -} - -function CommitChanges(props: CommitChangesProps): JSX.Element { - if (props.changes.length === 0) { - return
There are no commits.
- } - - return ( - - {props.changes.map((change, idx) => { - return - - - })} - - ) -} - -interface CommitChangeProps { - commit: Commit -} - -function CommitChange(props: CommitChangeProps): JSX.Element { - const [message, ...description] = props.commit.message.split(/(\r\n|\n|\r)/g) - - const [hide, setHide] = useState(true) - - const onClickHide = () => { - setHide(!hide) - } - - return ( - - - {message} - - {(description.length) ? - : - null} - {/* Display the description of the commit. */} - {(!hide) ? - -
-                        {description.join("").trim()}
-                    
-
: - null} -
- {(props.commit?.author) ? - -   {props.commit.author.login} committed {moment(props.commit.author?.date).fromNow()} - : - null} -
- ) -} \ No newline at end of file diff --git a/ui/src/components/DeploymentDescriptor/DeploymentDescriptor.tsx b/ui/src/components/DeploymentDescriptor/DeploymentDescriptor.tsx new file mode 100644 index 00000000..989ed0bc --- /dev/null +++ b/ui/src/components/DeploymentDescriptor/DeploymentDescriptor.tsx @@ -0,0 +1,62 @@ +import { Button, Descriptions, Modal, Typography } from "antd" +import moment from "moment" + +import DeploymentStatusBadge from "../DeploymentStatusBadge" +import UserAvatar from "../UserAvatar" + +import { Deployment } from "../../models" +import { getShortRef } from "../../libs" +import { useState } from "react" + +const { Text } = Typography + +interface DeploymentDescriptorProps { + deployment: Deployment +} + +export default function DeploymentDescriptor(props: DeploymentDescriptorProps): JSX.Element { + const [visible, setVisible] = useState(false) + + const showModal = () => { + setVisible(true) + } + + const hideModal = () => { + setVisible(false) + } + + return ( + + {props.deployment.env} + + {getShortRef(props.deployment)} + + + + + + + + + {moment(props.deployment.createdAt).format("YYYY-MM-DD HH:mm:ss")} + + + + + TODO: Show commits + + + + ) +} \ No newline at end of file diff --git a/ui/src/components/DeploymentDescriptor/index.tsx b/ui/src/components/DeploymentDescriptor/index.tsx new file mode 100644 index 00000000..eccc5548 --- /dev/null +++ b/ui/src/components/DeploymentDescriptor/index.tsx @@ -0,0 +1,3 @@ +import DeploymentDescriptor from "./DeploymentDescriptor" + +export default DeploymentDescriptor diff --git a/ui/src/components/DeploymentStatusSteps.tsx b/ui/src/components/DeploymentStatusSteps.tsx index 1ef622bf..ba502bd4 100644 --- a/ui/src/components/DeploymentStatusSteps.tsx +++ b/ui/src/components/DeploymentStatusSteps.tsx @@ -1,9 +1,10 @@ import { Timeline, Typography } from "antd" +import { ClockCircleOutlined } from "@ant-design/icons" import moment from "moment" import { DeploymentStatus } from "../models" -const { Paragraph, Text, Link } = Typography +const { Text, Link } = Typography interface DeploymentStatusStepsProps { statuses: DeploymentStatus[] @@ -17,13 +18,14 @@ export default function DeploymentStatusSteps(props: DeploymentStatusStepsProps) - - {status.description} - {(status.logUrl !== "")? View : <>}
- Updated {status.status} at {moment(status.createdAt).format('HH:mm:ss')} -
+ {moment(status.createdAt).format("YYYY-MM-DD HH:mm:ss")}
+ {status.description}   + {(status.logUrl !== "")? + View Detail + : + <>}
+ Updated {status.status} {moment(status.createdAt).fromNow()}
) })} diff --git a/ui/src/components/ReviewerList.tsx b/ui/src/components/ReviewerList.tsx index 60b8f722..8364cd5b 100644 --- a/ui/src/components/ReviewerList.tsx +++ b/ui/src/components/ReviewerList.tsx @@ -1,53 +1,62 @@ -import { List, Avatar, Popover, Button } from "antd" +import { Popover, Button, Descriptions, Typography } from "antd" import { CheckOutlined, CloseOutlined, CommentOutlined, ClockCircleOutlined } from "@ant-design/icons" -import { User, Review, ReviewStatusEnum } from "../models" +import { Review, ReviewStatusEnum } from "../models" +import UserAvatar from "./UserAvatar" +const { Text } = Typography export interface ReviewerListProps { reviews: Review[] } export default function ReviewerList(props: ReviewerListProps): JSX.Element { + if (props.reviews.length === 0) { + return ( + + No reviewers + + ) + } + return ( - { + + {props.reviews.map((review, idx) => { return ( -
- -
+ +   +   + + ) - }} - /> + })} +
) } -function ReviewItem(props: {review: Review}): JSX.Element { - const status = (status: ReviewStatusEnum) => { - switch (status) { - case ReviewStatusEnum.Pending: - return - case ReviewStatusEnum.Approved: - return - case ReviewStatusEnum.Rejected: - return - default: - return - } +function ReviewStatusIcon(props: {review: Review}): JSX.Element { + switch (props.review.status) { + case ReviewStatusEnum.Pending: + return + case ReviewStatusEnum.Approved: + return + case ReviewStatusEnum.Rejected: + return + default: + return } +} - const avatar = (user?: User) => { - return user? - {user.login}: - U - } +function ReviewCommentIcon(props: {review: Review}): JSX.Element { + const comment = props.review.comment - const commentIcon = (comment: string) => { - return comment !== ""? + return ( + comment? {comment}} + content={ +
{comment}
+ } > -
: + + : <> - } - - return ( -

- {status(props.review.status)} {avatar(props.review.user)} {commentIcon(props.review.comment)} -

) } -export function ReviewStatus(props: {reviews: Review[]}): JSX.Element { - for (let i = 0; i < props.reviews.length; i++) { - if (props.reviews[i].status === ReviewStatusEnum.Rejected) { - return - Rejected - - } - } - - for (let i = 0; i < props.reviews.length; i++) { - if (props.reviews[i].status === ReviewStatusEnum.Approved) { - return - Approved - - } - } - - return   Pending -} diff --git a/ui/src/components/UserAvatar.tsx b/ui/src/components/UserAvatar.tsx index a54a460e..0699ff19 100644 --- a/ui/src/components/UserAvatar.tsx +++ b/ui/src/components/UserAvatar.tsx @@ -5,13 +5,21 @@ import { User } from "../models"; const { Text } = Typography interface UserAvatarProps { + boldName?: boolean user?: User } export default function UserAvatar(props: UserAvatarProps): JSX.Element { + const boldName = props.boldName === undefined? true : props.boldName return ( props.user? - {props.user.login} : - U + +   + {props.user.login} + + : + + U + ) } \ No newline at end of file diff --git a/ui/src/views/Deployment.tsx b/ui/src/views/Deployment.tsx index 900c1a7d..81c80485 100644 --- a/ui/src/views/Deployment.tsx +++ b/ui/src/views/Deployment.tsx @@ -1,8 +1,8 @@ import { useEffect } from "react" -import { Breadcrumb, PageHeader, Result } from "antd" import { shallowEqual } from 'react-redux' import { useParams } from "react-router-dom" import { Helmet } from "react-helmet" +import { Breadcrumb, Button, PageHeader, Result, Row, Col } from "antd" import { useAppSelector, useAppDispatch } from "../redux/hooks" import { @@ -27,7 +27,9 @@ import { subscribeEvents } from "../apis" import Main from "./Main" import ReviewModal from "../components/ReviewModal" import Spin from "../components/Spin" -import DeployConfirm from "../components/DeployConfirm" +import DeploymentDescriptor from "../components/DeploymentDescriptor" +import ReviewerList from "../components/ReviewerList" +import DeploymentStatusSteps from "../components/DeploymentStatusSteps" interface Params { namespace: string @@ -150,16 +152,41 @@ export default function DeploymentView(): JSX.Element { onBack={onBack} /> -
- -
+ + + + + + + + + + + {deployment.statuses? + + : + <>} + + + + + {isDeployable(deployment, reviews)? + + : + } + + ) } From b5da8f0c5ad6c6cedb0f8711728782d26581df7d Mon Sep 17 00:00:00 2001 From: noah Date: Sat, 26 Feb 2022 14:01:32 +0900 Subject: [PATCH 2/2] Add the commit changes --- .../DeploymentDescriptor/CommitChanges.tsx | 81 +++++++++++++++++++ .../DeploymentDescriptor.tsx | 11 ++- ui/src/views/Deployment.tsx | 4 +- 3 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 ui/src/components/DeploymentDescriptor/CommitChanges.tsx diff --git a/ui/src/components/DeploymentDescriptor/CommitChanges.tsx b/ui/src/components/DeploymentDescriptor/CommitChanges.tsx new file mode 100644 index 00000000..97c5c1eb --- /dev/null +++ b/ui/src/components/DeploymentDescriptor/CommitChanges.tsx @@ -0,0 +1,81 @@ +import { useState } from "react" +import { Button, Typography, List, Avatar } from "antd" +import moment from "moment" + +import { Commit } from "../../models" + +interface CommitChangesProps { + changes:Commit[] +} + +export default function CommitChanges(props: CommitChangesProps): JSX.Element { + return ( + { + return ( + + ) + }} + /> + ) +} + +function CommitChange(props: {commit: Commit}): JSX.Element { + const [message, ...description] = props.commit.message.split(/(\r\n|\n|\r)/g) + + const [hide, setHide] = useState(true) + + const onClickHide = () => { + setHide(!hide) + } + + return ( + + + {message} + {/* Display the description when the button is clicked. */} + {(description.length)? + + : + <>} + {(!hide) ? + +
+                                    {description.join("").trim()}
+                                
+
+ : + <>} + + } + description={(props.commit?.author)? + <> +   + {props.commit.author.login} committed  + {moment(props.commit.author?.date).fromNow()} + + : + <> + } + /> +
+ +
+
+ ) +} \ No newline at end of file diff --git a/ui/src/components/DeploymentDescriptor/DeploymentDescriptor.tsx b/ui/src/components/DeploymentDescriptor/DeploymentDescriptor.tsx index 989ed0bc..1fb14caa 100644 --- a/ui/src/components/DeploymentDescriptor/DeploymentDescriptor.tsx +++ b/ui/src/components/DeploymentDescriptor/DeploymentDescriptor.tsx @@ -3,8 +3,9 @@ import moment from "moment" import DeploymentStatusBadge from "../DeploymentStatusBadge" import UserAvatar from "../UserAvatar" +import CommitChanges from "./CommitChanges" -import { Deployment } from "../../models" +import { Commit, Deployment } from "../../models" import { getShortRef } from "../../libs" import { useState } from "react" @@ -12,6 +13,7 @@ const { Text } = Typography interface DeploymentDescriptorProps { deployment: Deployment + commits: Commit[] } export default function DeploymentDescriptor(props: DeploymentDescriptorProps): JSX.Element { @@ -51,10 +53,13 @@ export default function DeploymentDescriptor(props: DeploymentDescriptorProps): - TODO: Show commits + diff --git a/ui/src/views/Deployment.tsx b/ui/src/views/Deployment.tsx index 81c80485..6be9abdd 100644 --- a/ui/src/views/Deployment.tsx +++ b/ui/src/views/Deployment.tsx @@ -154,14 +154,14 @@ export default function DeploymentView(): JSX.Element { - + - + {deployment.statuses? :