diff --git a/src/components/CancelDeployment/index.js b/src/components/CancelDeployment/index.js index 0a3c8cb3..bf4839fe 100644 --- a/src/components/CancelDeployment/index.js +++ b/src/components/CancelDeployment/index.js @@ -1,6 +1,7 @@ import React from 'react'; import { Mutation } from 'react-apollo'; +import { notification } from 'antd'; import Button from 'components/Button'; import gql from 'graphql-tag'; @@ -10,20 +11,28 @@ const CANCEL_DEPLOYMENT_MUTATION = gql` } `; -export const CancelDeploymentButton = ({ action, success, loading, error, beforeText, afterText }) => ( - <> - +export const CancelDeploymentButton = ({ action, success, loading, error, beforeText, afterText }) => { + const [api, contextHolder] = notification.useNotification(); - {error && ( -
-

There was a problem cancelling deployment.

-

{error.message}

-
- )} - -); + const openNotificationWithIcon = errorMessage => { + api['error']({ + message: 'There was a problem cancelling deployment.', + description: errorMessage, + placement: 'top', + duration: 0, + style: { width: '500px' }, + }); + }; + return ( + <> + {contextHolder} + + {error && openNotificationWithIcon(error.message)} + + ); +}; const CancelDeployment = ({ deployment, beforeText, afterText }) => ( void; + success: boolean; + loading: boolean; + error: ApolloError | undefined; + beforeText: string; + afterText: string; +} + +export const CancelTaskButton: FC = ({ + action, + success, + loading, + error, + beforeText, + afterText, +}) => { + const [api, contextHolder] = notification.useNotification(); + + const openNotificationWithIcon = (errorMessage: string) => { + api['error']({ + message: 'There was a problem cancelling a task.', + description: errorMessage, + placement: 'top', + duration: 0, + style: { width: '500px' }, + }); + }; + + return ( + <> + {contextHolder} + + + {error && openNotificationWithIcon(error.message)} + + ); +}; + +const CancelTask: FC = ({ + task, + environmentId, + projectId, + beforeText = 'Cancel', + afterText = 'Cancelled', +}) => ( + + mutation={CANCEL_TASK_MUTATION} + variables={{ + taskId: task.id, + taskName: task.taskName, + environmentId, + projectId, + }} + onError={(e: ApolloError) => console.error(e.message)} + > + {(cancelTask, { loading, error, data }) => ( + { + void cancelTask(); + }} + success={(data && data.cancelTask === 'success') || false} + loading={loading} + error={error} + beforeText={beforeText} + afterText={afterText} + /> + )} + +); + +export default CancelTask; diff --git a/src/components/Deployments/DeploymentsSkeleton.tsx b/src/components/Deployments/DeploymentsSkeleton.tsx index 803f5aee..d8e814e9 100644 --- a/src/components/Deployments/DeploymentsSkeleton.tsx +++ b/src/components/Deployments/DeploymentsSkeleton.tsx @@ -7,18 +7,23 @@ const DeploymentsSkeleton = () => { const numberOfDeploymentFields = typeof window !== 'undefined' ? Math.floor((window.innerHeight * 8) / 10 / 65) : 10; const skeletonItem = ( -
-
- +
+
+
+ +
+
+ +
+
+ +
+
+ +
-
- -
-
- -
-
- +
+
); diff --git a/src/components/Deployments/StyledDeployments.tsx b/src/components/Deployments/StyledDeployments.tsx index 56a82ed8..8fb938a7 100644 --- a/src/components/Deployments/StyledDeployments.tsx +++ b/src/components/Deployments/StyledDeployments.tsx @@ -3,12 +3,12 @@ import styled from 'styled-components'; export const StyledDeployments = styled.div` .header { + width: 90%; @media ${bp.tinyUp} { align-items: center; display: flex; justify-content: space-between; margin: 0 0 14px; - padding-right: 40px; } @media ${bp.smallOnly} { flex-wrap: wrap; @@ -18,9 +18,10 @@ export const StyledDeployments = styled.div` } label { + width:25%; display: none; - padding-left: 20px; - width: 25%; + display:inline-block; + padding-left:20px; @media ${bp.tinyUp} { display: block; } @@ -45,6 +46,36 @@ export const StyledDeployments = styled.div` border-radius: 3px; box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.03); + .deploymentRow { + display: flex; + align-items: center; + border: 1px solid ${props => props.theme.borders.tableRow}; + transition: all 0.2s ease; + transition: all 0.3s ease; + &:hover { + border: 1px solid #2bc0d8; + } + & > :nth-child(1) { + width: 90% !important; + } + & > :nth-child(2) { + padding: unset; + height: 30px; + &.btn--disabled { + margin-right: unset; + } + } + .cancel-button { + width: 10%; + button { + width:90%; + padding:0 !important; + margin-right: unset !important; + height:30px; + } + max-height: 100px; + } + } .data-none { border: 1px solid ${props => props.theme.borders.tableRow}; border-bottom: 1px solid ${props => props.theme.borders.tableRow}; @@ -56,33 +87,24 @@ export const StyledDeployments = styled.div` } .data-row { - background-image: url('/static/images/right-arrow.svg'); - background-position: right 20px center; - background-repeat: no-repeat; - background-size: 18px 11px; - border: 1px solid ${props => props.theme.borders.tableRow}; - border-bottom: 1px solid ${props => props.theme.borders.tableRow}; + border: 0px transparent; + border-bottom: 0px solid transparent; border-radius: 0; line-height: 1.5rem; padding: 8px 0 7px 0; - transition: all 0.3s ease; @media ${bp.tinyUp} { display: flex; justify-content: space-between; - padding-right: 40px; } & > div { padding-left: 20px; - @media ${bp.tinyUp} { - width: 25%; - } + width: 25%; } &:hover { - border: 1px solid ${color.brightBlue}; + border-width: 0px !important; } - &:first-child { border-top-left-radius: 3px; border-top-right-radius: 3px; diff --git a/src/components/Deployments/index.tsx b/src/components/Deployments/index.tsx index 2faeba09..a0c56f83 100644 --- a/src/components/Deployments/index.tsx +++ b/src/components/Deployments/index.tsx @@ -1,5 +1,6 @@ import React, { FC } from 'react'; +import CancelDeployment from 'components/CancelDeployment'; import { getDeploymentDuration } from 'components/Deployment'; import BulkDeploymentLink from 'components/link/BulkDeployment'; import DeploymentLink from 'components/link/Deployment'; @@ -32,28 +33,38 @@ const Deployments: FC = ({ deployments, environmentSlug, proje
{!deployments.length &&
No Deployments
} {deployments.map(deployment => ( - -
-
- {deployment.name} - {deployment.bulkId && ( - - )} +
+ +
+
+ {deployment.name} + {deployment.bulkId && ( + + )} +
+
+ {moment.utc(deployment.created).local().format('DD MMM YYYY, HH:mm:ss (Z)')} +
+
+ {deployment.status.charAt(0).toUpperCase() + deployment.status.slice(1)} +
+
{getDeploymentDuration(deployment)}
-
{moment.utc(deployment.created).local().format('DD MMM YYYY, HH:mm:ss (Z)')}
-
- {deployment.status.charAt(0).toUpperCase() + deployment.status.slice(1)} -
-
{getDeploymentDuration(deployment)}
+
+ +
+ {['new', 'pending', 'queued', 'running'].includes(deployment.status) && ( + + )}
- +
))}
diff --git a/src/components/Task/StyledTask.tsx b/src/components/Task/StyledTask.tsx index 86ac061e..a6360791 100644 --- a/src/components/Task/StyledTask.tsx +++ b/src/components/Task/StyledTask.tsx @@ -30,6 +30,13 @@ export const StyledTask = styled.div` } .field-wrapper { + .cancel-button { + button { + margin-right: unset !important; + } + max-height: 100px; + max-width: 120px; + } & > div:first-of-type { margin-left: 14px; } diff --git a/src/components/Task/index.tsx b/src/components/Task/index.tsx index 6744a419..69804b00 100644 --- a/src/components/Task/index.tsx +++ b/src/components/Task/index.tsx @@ -1,5 +1,6 @@ import React, { FC } from 'react'; +import CancelTask from 'components/CancelTask'; import LogViewer from 'components/LogViewer'; import moment from 'moment'; @@ -12,19 +13,23 @@ type TaskFile = { }; interface TaskProps { task: { + id: string; created: string; service: string; status: string; files: TaskFile[]; logs: string; + taskName: string; }; + projectId: number; + environmentId: number; } /** * Displays information about an environment task. */ -const Task: FC = ({ task }) => { - if (!task) return

Task not found

; +const Task: FC = ({ task, projectId, environmentId }) => { + if (!task) return

Task not found

; return (
@@ -45,7 +50,20 @@ const Task: FC = ({ task }) => {
{task.status.charAt(0).toUpperCase() + task.status.slice(1)}
+ + {['new', 'pending', 'queued', 'running'].includes(task.status) && ( +
+ +
+ )}
+ {task.files.length > 0 && (
diff --git a/src/components/Tasks/StyledTasks.tsx b/src/components/Tasks/StyledTasks.tsx index 39417052..43c1baff 100644 --- a/src/components/Tasks/StyledTasks.tsx +++ b/src/components/Tasks/StyledTasks.tsx @@ -3,6 +3,7 @@ import styled from 'styled-components'; export const StyledTasks = styled.div` .header { + width: calc(90% - 20px); @media ${bp.tinyUp} { align-items: center; display: flex; @@ -41,7 +42,28 @@ export const TasksTable = styled.div` border: 1px solid ${props => props.theme.borders.tableRow}; border-radius: 3px; box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.03); - + .taskRow { + display: flex; + align-items: center; + border: 1px solid ${props => props.theme.borders.tableRow}; + transition: all 0.2s ease; + padding-right: 20px; + &:hover { + border: 1px solid #2bc0d8; + } + & > :nth-child(1) { + flex-basis: 90%; + } + & > :nth-child(2) { + flex-basis: 10%; + max-width: 120px; + padding: unset; + height: 30px; + &.btn--disabled { + margin-right: unset; + } + } + } .data-none { border: 1px solid ${props => props.theme.borders.tableRow}; border-bottom: 1px solid ${props => props.theme.borders.tableRow}; @@ -52,15 +74,13 @@ export const TasksTable = styled.div` } .data-row { - background-image: url('/static/images/right-arrow.svg'); - background-position: right 20px center; - background-repeat: no-repeat; - background-size: 18px 11px; - border: 1px solid ${props => props.theme.borders.tableRow}; - border-bottom: 1px solid ${props => props.theme.borders.tableRow}; border-radius: 0; line-height: 1.5rem; padding: 8px 0 7px 0; + &:hover { + // override shared style + border-width: 0px !important; + } @media ${bp.tinyUp} { display: flex; justify-content: space-between; diff --git a/src/components/Tasks/TasksSkeleton.tsx b/src/components/Tasks/TasksSkeleton.tsx index 87e133e6..a5fe4008 100644 --- a/src/components/Tasks/TasksSkeleton.tsx +++ b/src/components/Tasks/TasksSkeleton.tsx @@ -7,21 +7,24 @@ const TasksSkeleton = () => { const numberOfItems = typeof window !== 'undefined' ? Math.floor((window.innerHeight * 8) / 10 / 65) : 10; const itemRender = ( -
-
- -
-
- +
+
+
+ +
+
+ +
+
+ +
+
+ +
-
+
-
- - - -
); diff --git a/src/components/Tasks/index.tsx b/src/components/Tasks/index.tsx index acd4ee5b..7be1a722 100644 --- a/src/components/Tasks/index.tsx +++ b/src/components/Tasks/index.tsx @@ -1,5 +1,6 @@ import React, { FC } from 'react'; +import CancelTask from 'components/CancelTask'; import TaskLink from 'components/link/Task'; import moment from 'moment'; @@ -7,6 +8,7 @@ import { StyledTasks, TasksTable } from './StyledTasks'; interface TasksProps { tasks: { + id:string; taskName: string; name: string; adminOnlyView: boolean; @@ -15,13 +17,15 @@ interface TasksProps { status: string; }[]; environmentSlug: string; + environmentId: number; projectSlug: string; + projectId: number; } /** * Displays an environment's list of tasks. */ -const Tasks: FC = ({ tasks, environmentSlug, projectSlug }) => ( +const Tasks: FC = ({ tasks, environmentSlug, environmentId, projectSlug, projectId }) => (
@@ -32,24 +36,35 @@ const Tasks: FC = ({ tasks, environmentSlug, projectSlug }) => ( {!tasks.length &&
No Tasks
} {tasks.map(task => ( - -
-
- {task.name} - {task.adminOnlyView && } +
+ +
+
+ {task.name} + {task.adminOnlyView && } +
+
{moment.utc(task.created).local().format('DD MMM YYYY, HH:mm:ss (Z)')}
+
{task.service}
+
+ {task.status.charAt(0).toUpperCase() + task.status.slice(1)} +
-
{moment.utc(task.created).local().format('DD MMM YYYY, HH:mm:ss (Z)')}
-
{task.service}
-
- {task.status.charAt(0).toUpperCase() + task.status.slice(1)} -
-
- + + {['new', 'pending', 'queued', 'running'].includes(task.status) && ( + + )} +
))} diff --git a/src/lib/query/EnvironmentWithTask.js b/src/lib/query/EnvironmentWithTask.js index 7ce5dee1..6fc9d461 100644 --- a/src/lib/query/EnvironmentWithTask.js +++ b/src/lib/query/EnvironmentWithTask.js @@ -7,11 +7,13 @@ export default gql` name openshiftProjectName project { + id name problemsUi factsUi } tasks(taskName: $taskName) { + id name taskName status diff --git a/src/lib/query/EnvironmentWithTasks.js b/src/lib/query/EnvironmentWithTasks.js index e172ddc8..765d29bc 100644 --- a/src/lib/query/EnvironmentWithTasks.js +++ b/src/lib/query/EnvironmentWithTasks.js @@ -7,6 +7,7 @@ export default gql` name openshiftProjectName project { + id name problemsUi factsUi diff --git a/src/pages/task.js b/src/pages/task.js index 4da0ccc5..04015d5b 100644 --- a/src/pages/task.js +++ b/src/pages/task.js @@ -48,21 +48,17 @@ export const PageTask = ({ router }) => { {`${router.query.taskName} | Task`} - - - - + + + + - - -
- -
-
+ + +
+ +
+
); @@ -116,7 +112,11 @@ export const PageTask = ({ router }) => {
- +
diff --git a/src/pages/tasks.js b/src/pages/tasks.js index 4277cd56..05db88d7 100644 --- a/src/pages/tasks.js +++ b/src/pages/tasks.js @@ -117,7 +117,7 @@ export const PageTasks = ({ router, renderAddTasks }) => { /> ); } - + subscribeToMore({ document: TasksSubscription, variables: { environment: environment.id }, @@ -170,8 +170,10 @@ export const PageTasks = ({ router, renderAddTasks }) => { {!renderAddTasks && }