From 193306a8689595c6986f475a587aae28c80a88b5 Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Tue, 21 Dec 2021 18:11:30 -0500 Subject: [PATCH 01/24] feat: setup pipelines activity details --- config-ui/package-lock.json | 11 + config-ui/package.json | 1 + config-ui/src/App.js | 9 +- config-ui/src/hooks/usePipelineManager.jsx | 8 +- config-ui/src/pages/pipelines/activity.jsx | 506 +++++++++++++++++++++ config-ui/src/pages/pipelines/create.jsx | 2 +- 6 files changed, 531 insertions(+), 6 deletions(-) create mode 100644 config-ui/src/pages/pipelines/activity.jsx diff --git a/config-ui/package-lock.json b/config-ui/package-lock.json index e59c2fdab7f..ee9d0c9682f 100644 --- a/config-ui/package-lock.json +++ b/config-ui/package-lock.json @@ -13,6 +13,7 @@ "@blueprintjs/select": "^3.18.10", "axios": "^0.21.4", "babel-plugin-module-resolver": "^4.1.0", + "dayjs": "^1.10.7", "dotenv": "^10.0.0", "dotenv-webpack": "^7.0.3", "react": "17.0.2", @@ -6655,6 +6656,11 @@ "node": ">=10" } }, + "node_modules/dayjs": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz", + "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==" + }, "node_modules/debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -26966,6 +26972,11 @@ "whatwg-url": "^8.0.0" } }, + "dayjs": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz", + "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==" + }, "debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", diff --git a/config-ui/package.json b/config-ui/package.json index 471e267024e..41157bf5cd6 100644 --- a/config-ui/package.json +++ b/config-ui/package.json @@ -15,6 +15,7 @@ "@blueprintjs/select": "^3.18.10", "axios": "^0.21.4", "babel-plugin-module-resolver": "^4.1.0", + "dayjs": "^1.10.7", "dotenv": "^10.0.0", "dotenv-webpack": "^7.0.3", "react": "17.0.2", diff --git a/config-ui/src/App.js b/config-ui/src/App.js index 17b5fca2b2a..15edea9a015 100644 --- a/config-ui/src/App.js +++ b/config-ui/src/App.js @@ -22,7 +22,7 @@ import Offline from '@/pages/offline/index' // #963 Create Pipelines import CreatePipeline from '@/pages/pipelines/create' // #965 Pipeline Activity -// import PipelineActivity from '@/pages/pipelines/activity' +import PipelineActivity from '@/pages/pipelines/activity' function App () { return ( @@ -55,9 +55,12 @@ function App () { {/* #964 */} - {/* #965 + - */} + + + + diff --git a/config-ui/src/hooks/usePipelineManager.jsx b/config-ui/src/hooks/usePipelineManager.jsx index 5068d39bf1f..3c53de68ddb 100644 --- a/config-ui/src/hooks/usePipelineManager.jsx +++ b/config-ui/src/hooks/usePipelineManager.jsx @@ -18,7 +18,7 @@ function usePipelineManager (pipelineName = `COLLECTION ${Date.now()}`, initialT ] }) - const [activePipeline, setActivePipeline] = useState() + const [activePipeline, setActivePipeline] = useState(NullPipelineRun) const [lastRunId, setLastRunId] = useState(null) const [pipelineRun, setPipelineRun] = useState(NullPipelineRun) @@ -72,6 +72,10 @@ function usePipelineManager (pipelineName = `COLLECTION ${Date.now()}`, initialT }, []) const fetchPipeline = useCallback((pipelineID, refresh = false) => { + if (!pipelineID) { + console.log('>> !ABORT! Pipeline ID Missing! Aborting Fetch...') + // return ToastNotification.show({ message: 'Pipeline ID Missing! Aborting Fetch...', intent: 'danger', icon: 'warning-sign' }) + } try { setIsFetching(true) setErrors([]) @@ -84,7 +88,7 @@ function usePipelineManager (pipelineName = `COLLECTION ${Date.now()}`, initialT console.log('>> RAW PIPELINE TASKS DATA FROM API...', t.data) setActivePipeline({ ...p.data, - tasks: t.data + tasks: [...t.data.tasks] }) setPipelineRun((pR) => refresh ? { ...p.data, tasks: [...t.data.tasks] } : pR) setLastRunId((lrId) => refresh ? p.data?.ID : lrId) diff --git a/config-ui/src/pages/pipelines/activity.jsx b/config-ui/src/pages/pipelines/activity.jsx new file mode 100644 index 00000000000..9fc5dce3527 --- /dev/null +++ b/config-ui/src/pages/pipelines/activity.jsx @@ -0,0 +1,506 @@ +import React, { Fragment, useEffect, useCallback, useState, useRef } from 'react' +import { CSSTransition } from 'react-transition-group' +import { useHistory, useParams } from 'react-router-dom' +import { ToastNotification } from '@/components/Toast' +import { GRAFANA_URL } from '@/utils/config' +import request from '@/utils/request' +import { + H2, Button, Icon, Intent, + ButtonGroup, InputGroup, Input, + Card, Elevation, Tag, + Popover, + Tooltip, + Position, + Spinner, + Colors, + Link, + Classes +} from '@blueprintjs/core' +import { integrationsData } from '@/data/integrations' +import usePipelineManager from '@/hooks/usePipelineManager' +import Nav from '@/components/Nav' +import Sidebar from '@/components/Sidebar' +import AppCrumbs from '@/components/Breadcrumbs' +import Content from '@/components/Content' +import ContentLoader from '@/components/loaders/ContentLoader' +import { ReactComponent as GitlabProviderIcon } from '@/images/integrations/gitlab.svg' +import { ReactComponent as JenkinsProviderIcon } from '@/images/integrations/jenkins.svg' +import { ReactComponent as JiraProviderIcon } from '@/images/integrations/jira.svg' +import { ReactComponent as GitHubProviderIcon } from '@/images/integrations/github.svg' + +import '@/styles/offline.scss' +import { TAB_LIST } from '@blueprintjs/core/lib/esm/common/classes' + +const PipelineActivity = (props) => { + const history = useHistory() + const { pId } = useParams() + + const [pipelineId, setPipelineId] = useState() // @todo REMOVE TEST RUN ID! + const [activeProvider, setActiveProvider] = useState(integrationsData[0]) + const [pipelineName, setPipelineName] = useState() + + const { + runPipeline, + cancelPipeline, + fetchPipeline, + activePipeline, + // pipelineRun, + isRunning, + isFetching, + errors: pipelineErrors, + // setSettings: setPipelineSettings, + lastRunId + } = usePipelineManager(pipelineName) + + // useEffect(() => { + // setActiveProvider(providerId ? integrationsData.find(p => p.id === providerId) : integrationsData[0]) + // }, [providerId]) + + useEffect(() => { + setPipelineId(pId) + console.log('>>> REQUESTED PIPELINE ID ===', pId) + }, [pId]) + + useEffect(() => { + if (pipelineId) { + fetchPipeline(pipelineId) + } + }, [pipelineId, fetchPipeline]) + + useEffect(() => { + console.log('>>> TASKS KEY', activePipeline.tasks) + }, []) + + return ( + <> +
+
+ +

+ {activePipeline.finishedTasks}/{activePipeline.totalTasks} Tasks Completed + + Created {activePipeline.CreatedAt} +

+ + +
+

+ Stages and Tasks +

+

Monitor Duration and Progress for all tasks. Grafana access will be enabled when the pipeline completes.

+

Stage 1

+
+ {activePipeline?.ID && activePipeline.tasks && activePipeline.tasks.map((t, tIdx) => ( +
+
+ {t.status === 'TASK_COMPLETED' && ( + + )} + {t.status === 'TASK_FAILED' && ( + + )} + {t.status === 'TASK_RUNNING' && ( + + )} +
+
+ + {t.plugin} + + {/*
+ + {t.plugin !== 'jenkins' && ( + + {Object.keys(t.options)[0]} + + )} + {t.plugin === 'github' && ( + +
{Object.keys(t.options)[1]} +
+ )} +
+
+
+ + {t.plugin !== 'jenkins' && ( + + {t.options[Object.keys(t.options)[0]]} + + )} + {t.plugin === 'github' && ( + +
{t.options[Object.keys(t.options)[1]]} +
+ )} +
+
*/} + {/* {t.status === 'TASK_COMPLETED' && ( + + )} + {t.status === 'TASK_FAILED' && ( + + )} */} +
+
{t.spentSeconds >= 60 ? `${Number(t.spentSeconds / 60).toFixed(2)}mins` : `${t.spentSeconds}secs`} +
+
+ + {Number(t.status === 'TASK_COMPLETED' ? 100 : (t.progress / 1) * 100).toFixed(2)}% + +
+
+ {t.plugin !== 'jenkins' && ( + <> + + {t.options[Object.keys(t.options)[0]]} + + {t.plugin === 'github' && ( + /{t.options[Object.keys(t.options)[1]]} + )} + + )} + {t.message && (<>{t.message})} +
+
+ ))} +
+
+ +
+

+ Run Settings +

+

Data Provider settings configured for this pipeline execution.

+ +
+
+
+ +
+
+
+ (No Settings) +
+
+
+
+ +
+
+ + {activePipeline.tasks.filter(t => t.plugin === 'jira').map((t, tIdx) => ( +
+ + + {t.options[Object.keys(t.options)[0]]} on Server #{t.options[Object.keys(t.options)[1]]}
+
+
+ ))} +
+
+
+
+ +
+
+ + {activePipeline.tasks.filter(t => t.plugin === 'gitlab').map((t, tIdx) => ( +
+ + + {t.options[Object.keys(t.options)[0]]}
+
+
+ ))} +
+
+
+
+ +
+
+ + {activePipeline.tasks.filter(t => t.plugin === 'github').map((t, tIdx) => ( +
+ + + {t.options[Object.keys(t.options)[0]]}/ + {t.options[Object.keys(t.options)[1]]} + +
+ ))} +
+
+
+
+ + )} + + {!pipelineId && ( + +
+

Pipeline Run ID Missing...

+

Please provide a Pipeline ID to load Run activity and details.
Check the Address URL in your Browser and try again.

+
+
+ )} + +
+ +
+ See All Jobs to monitor all pipeline activity. +
+
+
+
+ + + + + + + + ) +} + +export default PipelineActivity diff --git a/config-ui/src/pages/pipelines/create.jsx b/config-ui/src/pages/pipelines/create.jsx index 3ee2ef96a1a..fb3e16cb57a 100644 --- a/config-ui/src/pages/pipelines/create.jsx +++ b/config-ui/src/pages/pipelines/create.jsx @@ -234,7 +234,7 @@ const CreatePipeline = (props) => { return ( <> -
+
- {isFetching && ( + {!autoRefresh && isFetching && ( )} - {!isFetching && activePipeline?.ID && ( + {activePipeline?.ID && ( <> +
@@ -229,9 +247,9 @@ const PipelineActivity = (props) => {
-
+
- {activePipeline.status} + {activePipeline.status.replace('TASK_', '')} {activePipeline.status === 'TASK_FAILED' && ( {
-
+
{/* {activePipeline.spentSeconds >= 60 ? `${Number(activePipeline.spentSeconds / 60).toFixed(2)}mins` : `${activePipeline.spentSeconds}secs`} */} {activePipeline.status === 'TASK_RUNNING' ? dayjs(activePipeline.CreatedAt).toNow(true) : dayjs(activePipeline.UpdatedAt).from(activePipeline.CreatedAt, true)}
@@ -282,7 +300,7 @@ const PipelineActivity = (props) => { position={Position.BOTTOM} autoFocus={false} enforceFocus={false} - usePortal={false} + usePortal={true} disabled={activePipeline.status !== 'TASK_RUNNING'} >
+ -

- {activePipeline.finishedTasks}/{activePipeline.totalTasks} Tasks Completed - - Created {activePipeline.CreatedAt} -

+
+
+ + + <> +
+
+ Stages and Tasks +
+

+ Monitor Duration and Progress completion for all tasks. Grafana access will be enabled when the pipeline completes. + +

+ +
+ +
+ + {activePipeline.finishedTasks}/{activePipeline.totalTasks} Tasks Completed + + + + Created {activePipeline.CreatedAt} +
+
+ {isFetching && ( Refreshing Activity...)} +
+
-

+ {/*

Stages and Tasks

Monitor Duration and Progress completion for all tasks. Grafana access will be enabled when the pipeline completes. Warning messages will also be displayed here when present. -

- */} + {/* { {Number((activePipeline.finishedTasks / activePipeline.totalTasks) * 100).toFixed(1)}%
- -
*/} + {/* */} + {/*
{ > {t.plugin} - {/*
- - {t.plugin !== 'jenkins' && ( - - {Object.keys(t.options)[0]} - - )} - {t.plugin === 'github' && ( - -
{Object.keys(t.options)[1]} -
- )} -
-
-
- - {t.plugin !== 'jenkins' && ( - - {t.options[Object.keys(t.options)[0]]} - - )} - {t.plugin === 'github' && ( - -
{t.options[Object.keys(t.options)[1]]} -
- )} -
-
*/} - {/* {t.status === 'TASK_COMPLETED' && ( - - )} - {t.status === 'TASK_FAILED' && ( - - )} */}
{ textAlign: 'right' }} > - {/* {t.spentSeconds >= 60 ? `${Number(t.spentSeconds / 60).toFixed(2)}mins` : `${t.spentSeconds}secs`} */} - {/* {t.status === 'TASK_COMPLETED' ? dayjs(t.UpdatedAt).from(t.CreatedAt, true) : dayjs(t.CreatedAt).toNow(true)} */} {(() => { let statusRelativeTime = dayjs(t.CreatedAt).toNow(true) switch (t.status) { @@ -591,14 +596,21 @@ const PipelineActivity = (props) => {
))} -
+
*/}
-

- Run Settings -

-

Data Provider settings configured for this pipeline execution.

+
+
+ +
+
+

+ Run Settings +

+

Data Provider settings configured for this pipeline execution.

+
+
diff --git a/config-ui/src/styles/pipelines.scss b/config-ui/src/styles/pipelines.scss index 9b77925c056..bf987aee0ec 100644 --- a/config-ui/src/styles/pipelines.scss +++ b/config-ui/src/styles/pipelines.scss @@ -207,25 +207,33 @@ } .activity-panel-enter { - transform: rotateX(-50deg); - opacity: 0.6; - transition: opacity 300ms, transform 300ms; + // transform: rotateX(-50deg); + transform: scale(1.01); + background-color: #f0f0f0; + opacity: 1; + transition: opacity 300ms, transform 300ms, background-color 800ms; } .activity-panel-enter-done { - transform: rotateX(0deg); + // transform: rotateX(0deg); + transform: scale(1); + background-color: #ffffff; opacity: 1; - transition: opacity 300ms, transform 300ms; + transition: opacity 300ms, transform 300ms, background-color 800ms; } .activity-panel-exit { - transform: rotateX(20deg); - transition: opacity 300ms, transform 300ms; + // transform: rotateX(20deg); + background-color: #f7f7f7; + opacity: 1; + transition: opacity 300ms, transform 300ms, background-color 800ms; } .activity-panel-exit-active { - transform: rotateX(40deg); - transition: opacity 300ms, transform 300ms; + // transform: rotateX(40deg); + background-color: #eeeeee; + opacity: 1; + transition: opacity 300ms, transform 300ms, background-color 800ms; } .bp3-spinner { From 1e3b0dc379864d7e52a19fe1841946be6ce3ce39 Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Wed, 22 Dec 2021 18:40:32 -0500 Subject: [PATCH 06/24] fix: cleanup unused code blocks --- .../src/components/pipelines/StagePanel.jsx | 40 ++- .../src/components/pipelines/TaskActivity.jsx | 10 - config-ui/src/pages/pipelines/activity.jsx | 264 ++---------------- 3 files changed, 56 insertions(+), 258 deletions(-) diff --git a/config-ui/src/components/pipelines/StagePanel.jsx b/config-ui/src/components/pipelines/StagePanel.jsx index 66fbac321e5..511c4c2083d 100644 --- a/config-ui/src/components/pipelines/StagePanel.jsx +++ b/config-ui/src/components/pipelines/StagePanel.jsx @@ -1,21 +1,12 @@ import React from 'react' import { CSSTransition } from 'react-transition-group' import { - // Classes, Card, - Button, Icon, Intent, Switch, - // H2, Card, Elevation, Tag, - // Menu, - FormGroup, + Button, Icon, ButtonGroup, Elevation, - InputGroup, - Popover, - Tooltip, - Position, - // Spinner, Colors, - // Alignment + // Alignment, Classes, Spinner } from '@blueprintjs/core' import { ReactComponent as PipelineRunningIcon } from '@/images/synchronize.svg' import { ReactComponent as PipelineFailedIcon } from '@/images/no-synchronize.svg' @@ -53,7 +44,13 @@ const StagePanel = (props) => { case 'TASK_COMPLETED': statusIcon = ( } + icon={} size={24} /> ) @@ -61,7 +58,14 @@ const StagePanel = (props) => { case 'TASK_FAILED': statusIcon = ( } + icon={} size={24} /> ) @@ -70,7 +74,14 @@ const StagePanel = (props) => { default: statusIcon = ( } + icon={} size={24} /> ) @@ -80,6 +91,7 @@ const StagePanel = (props) => { })()} + {/* @todo: re-active "stage" ux in a future release */} {/*
-
- {/*

- Stages and Tasks -

-

Monitor Duration and Progress completion for all tasks. Grafana access will be enabled when the pipeline completes. - Warning messages will also be displayed here when present. -

*/} - {/* - - - - - - -
+ {/*
+
*/}
@@ -605,7 +390,7 @@ const PipelineActivity = (props) => {
-

+

Run Settings

Data Provider settings configured for this pipeline execution.

@@ -692,7 +477,8 @@ const PipelineActivity = (props) => {
- {t.options[Object.keys(t.options)[0]]}/ + {t.options[Object.keys(t.options)[0]]} + / {t.options[Object.keys(t.options)[1]]}
@@ -707,8 +493,15 @@ const PipelineActivity = (props) => { {!pipelineId && (
-

Pipeline Run ID Missing...

-

Please provide a Pipeline ID to load Run activity and details.
Check the Address URL in your Browser and try again.

+

+ Pipeline Run ID Missing... +

+

Please provide a Pipeline ID to load Run activity and details. +
Check the Address URL in your Browser and try again. +

)} @@ -763,7 +556,10 @@ const PipelineActivity = (props) => {

application/json JSON RESPONSE

-

If you are submitting a Bug-Report regarding a Pipeline Run, include the output below for better debugging.

+

+ If you are submitting a + Bug-Report regarding a Pipeline Run, include the output below for better debugging. +

Date: Wed, 22 Dec 2021 18:54:06 -0500 Subject: [PATCH 07/24] fix: extract time utility --- .../src/components/pipelines/TaskActivity.jsx | 3 +- config-ui/src/pages/pipelines/activity.jsx | 47 ++++++++++--------- config-ui/src/utils/time.js | 27 +++++++++++ 3 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 config-ui/src/utils/time.js diff --git a/config-ui/src/components/pipelines/TaskActivity.jsx b/config-ui/src/components/pipelines/TaskActivity.jsx index df3fc4a95dc..dd72f69b88e 100644 --- a/config-ui/src/components/pipelines/TaskActivity.jsx +++ b/config-ui/src/components/pipelines/TaskActivity.jsx @@ -8,9 +8,10 @@ import { Colors, // Alignment } from '@blueprintjs/core' +import dayjs from '@/utils/time' const TaskActivity = (props) => { - const { activePipeline, dayjs } = props + const { activePipeline } = props return ( <> diff --git a/config-ui/src/pages/pipelines/activity.jsx b/config-ui/src/pages/pipelines/activity.jsx index ba0fdecc80c..b85eb70c14e 100644 --- a/config-ui/src/pages/pipelines/activity.jsx +++ b/config-ui/src/pages/pipelines/activity.jsx @@ -2,9 +2,10 @@ import React, { Fragment, useEffect, useState, useRef } from 'react' import { CSSTransition } from 'react-transition-group' import { useHistory, useParams } from 'react-router-dom' import { GRAFANA_URL } from '@/utils/config' -import * as dayjs from 'dayjs' -import * as relativeTime from 'dayjs/plugin/relativeTime' -import * as updateLocale from 'dayjs/plugin/updateLocale' +import dayjs from '@/utils/time' +// import * as dayjs from 'dayjs' +// import * as relativeTime from 'dayjs/plugin/relativeTime' +// import * as updateLocale from 'dayjs/plugin/updateLocale' import { Button, Icon, Intent, Card, Elevation, @@ -67,25 +68,25 @@ const PipelineActivity = (props) => { useEffect(() => { setPipelineId(pId) - dayjs.extend(relativeTime) - dayjs.extend(updateLocale) - dayjs.updateLocale('en', { - relativeTime: { - future: 'in %s', - past: '%s ago', - s: '< 1min', - m: 'a minute', - mm: '%d minutes', - h: 'an hour', - hh: '%d hours', - d: 'a day', - dd: '%d days', - M: 'a month', - MM: '%d months', - y: 'a year', - yy: '%d years' - } - }) + // dayjs.extend(relativeTime) + // dayjs.extend(updateLocale) + // dayjs.updateLocale('en', { + // relativeTime: { + // future: 'in %s', + // past: '%s ago', + // s: '< 1min', + // m: 'a minute', + // mm: '%d minutes', + // h: 'an hour', + // hh: '%d hours', + // d: 'a day', + // dd: '%d days', + // M: 'a month', + // MM: '%d months', + // y: 'a year', + // yy: '%d years' + // } + // }) console.log('>>> REQUESTED PIPELINE ID ===', pId) }, [pId]) @@ -331,7 +332,7 @@ const PipelineActivity = (props) => {
- +
diff --git a/config-ui/src/utils/time.js b/config-ui/src/utils/time.js new file mode 100644 index 00000000000..4b528d34451 --- /dev/null +++ b/config-ui/src/utils/time.js @@ -0,0 +1,27 @@ +import * as dayjs from 'dayjs' +import * as relativeTime from 'dayjs/plugin/relativeTime' +import * as updateLocale from 'dayjs/plugin/updateLocale' + +const localeConfiguration = { + relativeTime: { + future: 'in %s', + past: '%s ago', + s: '< 1min', + m: 'a minute', + mm: '%d minutes', + h: 'an hour', + hh: '%d hours', + d: 'a day', + dd: '%d days', + M: 'a month', + MM: '%d months', + y: 'a year', + yy: '%d years' + } +} + +dayjs.extend(relativeTime) +dayjs.extend(updateLocale) +dayjs.updateLocale('en', localeConfiguration) + +export default dayjs From f28f146845bbd21a9a733ee1af58c375d84b6fca Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Wed, 22 Dec 2021 19:01:46 -0500 Subject: [PATCH 08/24] fix: cleanup unused code blocks --- config-ui/src/pages/pipelines/activity.jsx | 65 +++++++++------------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/config-ui/src/pages/pipelines/activity.jsx b/config-ui/src/pages/pipelines/activity.jsx index b85eb70c14e..5a1afe69ad7 100644 --- a/config-ui/src/pages/pipelines/activity.jsx +++ b/config-ui/src/pages/pipelines/activity.jsx @@ -1,11 +1,8 @@ import React, { Fragment, useEffect, useState, useRef } from 'react' import { CSSTransition } from 'react-transition-group' -import { useHistory, useParams } from 'react-router-dom' +import { useHistory, useParams, Link } from 'react-router-dom' import { GRAFANA_URL } from '@/utils/config' import dayjs from '@/utils/time' -// import * as dayjs from 'dayjs' -// import * as relativeTime from 'dayjs/plugin/relativeTime' -// import * as updateLocale from 'dayjs/plugin/updateLocale' import { Button, Icon, Intent, Card, Elevation, @@ -32,7 +29,7 @@ import { ReactComponent as GitlabProviderIcon } from '@/images/integrations/gitl import { ReactComponent as JenkinsProviderIcon } from '@/images/integrations/jenkins.svg' import { ReactComponent as JiraProviderIcon } from '@/images/integrations/jira.svg' import { ReactComponent as GitHubProviderIcon } from '@/images/integrations/github.svg' - +import { ReactComponent as BackArrowIcon } from '@/images/undo.svg' import { ReactComponent as HelpIcon } from '@/images/help.svg' const PipelineActivity = (props) => { @@ -55,11 +52,11 @@ const PipelineActivity = (props) => { fetchPipeline, activePipeline, // pipelineRun, - isRunning, + // isRunning, isFetching, errors: pipelineErrors, // setSettings: setPipelineSettings, - lastRunId + // lastRunId } = usePipelineManager(pipelineName) // useEffect(() => { @@ -68,25 +65,6 @@ const PipelineActivity = (props) => { useEffect(() => { setPipelineId(pId) - // dayjs.extend(relativeTime) - // dayjs.extend(updateLocale) - // dayjs.updateLocale('en', { - // relativeTime: { - // future: 'in %s', - // past: '%s ago', - // s: '< 1min', - // m: 'a minute', - // mm: '%d minutes', - // h: 'an hour', - // hh: '%d hours', - // d: 'a day', - // dd: '%d days', - // M: 'a month', - // MM: '%d months', - // y: 'a year', - // yy: '%d years' - // } - // }) console.log('>>> REQUESTED PIPELINE ID ===', pId) }, [pId]) @@ -101,10 +79,6 @@ const PipelineActivity = (props) => { } }, [pipelineId, activePipeline.status, fetchPipeline]) - useEffect(() => { - console.log('>>> TASKS KEY', activePipeline.tasks) - }, []) - useEffect(() => { setPipelineReady(activePipeline.ID !== null && !isFetching) }, [activePipeline.ID, isFetching]) @@ -136,9 +110,19 @@ const PipelineActivity = (props) => { ]} />
- {/* - Go Back - */} + + + } size={16} + /> Go Back +
@@ -264,8 +248,9 @@ const PipelineActivity = (props) => {
- {/* {activePipeline.spentSeconds >= 60 ? `${Number(activePipeline.spentSeconds / 60).toFixed(2)}mins` : `${activePipeline.spentSeconds}secs`} */} - {activePipeline.status === 'TASK_RUNNING' ? dayjs(activePipeline.CreatedAt).toNow(true) : dayjs(activePipeline.UpdatedAt).from(activePipeline.CreatedAt, true)} + {activePipeline.status === 'TASK_RUNNING' + ? dayjs(activePipeline.CreatedAt).toNow(true) + : dayjs(activePipeline.UpdatedAt).from(activePipeline.CreatedAt, true)}
@@ -345,7 +330,9 @@ const PipelineActivity = (props) => { enforceFocus={false} usePortal={false} > - + + + <>
{ Stages and Tasks

- Monitor Duration and Progress completion for all tasks. Grafana access will be enabled when the pipeline completes. - + Monitor Duration and Progress completion for all tasks. + Grafana access will be enabled when the pipeline completes.

@@ -374,7 +361,7 @@ const PipelineActivity = (props) => {
{isFetching && ( - + Refreshing Activity... )} From d49593e2ddc61324c378d12438d3740467ccb17c Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Wed, 22 Dec 2021 19:10:43 -0500 Subject: [PATCH 09/24] fix: extract code inspector drawer panel --- .../components/pipelines/CodeInspector.jsx | 61 +++++++++++++++++++ config-ui/src/pages/pipelines/activity.jsx | 44 +------------ 2 files changed, 63 insertions(+), 42 deletions(-) create mode 100644 config-ui/src/components/pipelines/CodeInspector.jsx diff --git a/config-ui/src/components/pipelines/CodeInspector.jsx b/config-ui/src/components/pipelines/CodeInspector.jsx new file mode 100644 index 00000000000..894ea22914d --- /dev/null +++ b/config-ui/src/components/pipelines/CodeInspector.jsx @@ -0,0 +1,61 @@ +import React from 'react' +// import { CSSTransition } from 'react-transition-group' +import { + Classes, + Drawer, + DrawerSize, + Card, + Elevation, + Position, +} from '@blueprintjs/core' + +const CodeInspector = (props) => { + const { activePipeline, isOpen, onClose } = props + + return ( + onClose(false)} + title={`Inspect RUN #${activePipeline.ID}`} + position={Position.RIGHT} + size={DrawerSize.SMALL} + autoFocus + canEscapeKeyClose + canOutsideClickClose + enforceFocus + hasBackdrop + isOpen={isOpen} + usePortal + > +
+
+

+ application/json JSON RESPONSE +

+

+ If you are submitting a + Bug-Report regarding a Pipeline Run, include the output below for better debugging. +

+
+ + + +
+                  {JSON.stringify(activePipeline, null, '  ')}
+                
+
+
+
+
+
+
+ + ) +} + +export default CodeInspector diff --git a/config-ui/src/pages/pipelines/activity.jsx b/config-ui/src/pages/pipelines/activity.jsx index 5a1afe69ad7..85d5e0de32d 100644 --- a/config-ui/src/pages/pipelines/activity.jsx +++ b/config-ui/src/pages/pipelines/activity.jsx @@ -25,6 +25,7 @@ import Content from '@/components/Content' import ContentLoader from '@/components/loaders/ContentLoader' import StagePanel from '@/components/pipelines/StagePanel' import TaskActivity from '@/components/pipelines/TaskActivity' +import CodeInspector from '@/components/pipelines/CodeInspector' import { ReactComponent as GitlabProviderIcon } from '@/images/integrations/gitlab.svg' import { ReactComponent as JenkinsProviderIcon } from '@/images/integrations/jenkins.svg' import { ReactComponent as JiraProviderIcon } from '@/images/integrations/jira.svg' @@ -524,48 +525,7 @@ const PipelineActivity = (props) => {
- setShowInspector(false)} - title={`RUN No. ${activePipeline.ID} JSON Payload`} - position={Position.RIGHT} - size={DrawerSize.SMALL} - autoFocus - canEscapeKeyClose - canOutsideClickClose - enforceFocus - hasBackdrop - isOpen={showInspector} - usePortal - > -
-
-

- application/json JSON RESPONSE -

-

- If you are submitting a - Bug-Report regarding a Pipeline Run, include the output below for better debugging. -

-
- - - -
-                    {JSON.stringify(activePipeline, null, '  ')}
-                  
-
-
-
-
-
-
- + ) } From b1f7b2512028ffd42c870a084386ba39fd56c49b Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Thu, 23 Dec 2021 00:15:47 -0500 Subject: [PATCH 10/24] fix: use provider configuration labels --- config-ui/src/pages/pipelines/activity.jsx | 193 +++++++++++---------- 1 file changed, 105 insertions(+), 88 deletions(-) diff --git a/config-ui/src/pages/pipelines/activity.jsx b/config-ui/src/pages/pipelines/activity.jsx index 85d5e0de32d..9e9988ca2ec 100644 --- a/config-ui/src/pages/pipelines/activity.jsx +++ b/config-ui/src/pages/pipelines/activity.jsx @@ -17,6 +17,10 @@ import { // ButtonGroup, InputGroup, Input, Tag,H2, TextArea,Link } from '@blueprintjs/core' import { integrationsData } from '@/data/integrations' +import { + Providers, + ProviderLabels +} from '@/data/Providers' import usePipelineManager from '@/hooks/usePipelineManager' import Nav from '@/components/Nav' import Sidebar from '@/components/Sidebar' @@ -38,8 +42,7 @@ const PipelineActivity = (props) => { const { pId } = useParams() const pollInterval = useRef() - const [pipelineId, setPipelineId] = useState() // @todo REMOVE TEST RUN ID! - const [activeProvider, setActiveProvider] = useState(integrationsData[0]) + const [pipelineId, setPipelineId] = useState() const [pipelineName, setPipelineName] = useState() const [pollTimer, setPollTimer] = useState(5000) const [autoRefresh, setAutoRefresh] = useState(false) @@ -60,9 +63,9 @@ const PipelineActivity = (props) => { // lastRunId } = usePipelineManager(pipelineName) - // useEffect(() => { - // setActiveProvider(providerId ? integrationsData.find(p => p.id === providerId) : integrationsData[0]) - // }, [providerId]) + const pipelineHasProvider = (providerId) => { + return activePipeline.tasks.some(t => t.plugin === providerId) + } useEffect(() => { setPipelineId(pId) @@ -387,93 +390,107 @@ const PipelineActivity = (props) => {
-
-
- -
-
- - (No Settings) -
-
-
-
- -
-
- - {activePipeline.tasks.filter(t => t.plugin === 'jira').map((t, tIdx) => ( -
- - - {t.options[Object.keys(t.options)[0]]} on Server #{t.options[Object.keys(t.options)[1]]}
-
-
- ))} -
-
-
-
- + {pipelineHasProvider(Providers.JENKINS) && ( +
+
+ +
+
+ + (No Settings) +
-
- - {activePipeline.tasks.filter(t => t.plugin === 'gitlab').map((t, tIdx) => ( -
- - - {t.options[Object.keys(t.options)[0]]}
-
-
- ))} + )} + {pipelineHasProvider(Providers.JIRA) && ( +
+
+ +
+
+ + {activePipeline.tasks.filter(t => t.plugin === Providers.JIRA).map((t, tIdx) => ( +
+ + + {t.options[Object.keys(t.options)[0]]} on Server #{t.options[Object.keys(t.options)[1]]}
+
+
+ ))} +
-
-
-
- + )} + {pipelineHasProvider(Providers.GITLAB) && ( +
+
+ +
+
+ + {activePipeline.tasks.filter(t => t.plugin === 'gitlab').map((t, tIdx) => ( +
+ + + {t.options[Object.keys(t.options)[0]]}
+
+
+ ))} +
-
- - {activePipeline.tasks.filter(t => t.plugin === 'github').map((t, tIdx) => ( -
- - - {t.options[Object.keys(t.options)[0]]} - / - {t.options[Object.keys(t.options)[1]]} - -
- ))} + )} + {pipelineHasProvider(Providers.GITHUB) && ( +
+
+ +
+
+ + {activePipeline.tasks.filter(t => t.plugin === Providers.GITHUB).map((t, tIdx) => ( +
+ + + {t.options[Object.keys(t.options)[0]]} + / + {t.options[Object.keys(t.options)[1]]} + +
+ ))} +
-
+ )} +
From 5dae8234861d1da56a113fb98a31e95ac78fdf76 Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Thu, 23 Dec 2021 10:24:00 -0500 Subject: [PATCH 11/24] fix: enhance stage panel display --- .../src/components/pipelines/StagePanel.jsx | 106 ++++++++++++------ .../src/components/pipelines/TaskActivity.jsx | 21 +++- config-ui/src/data/NullPipelineTask.js | 22 ++++ config-ui/src/pages/pipelines/activity.jsx | 37 +++++- 4 files changed, 144 insertions(+), 42 deletions(-) create mode 100644 config-ui/src/data/NullPipelineTask.js diff --git a/config-ui/src/components/pipelines/StagePanel.jsx b/config-ui/src/components/pipelines/StagePanel.jsx index 511c4c2083d..3d05dab7a88 100644 --- a/config-ui/src/components/pipelines/StagePanel.jsx +++ b/config-ui/src/components/pipelines/StagePanel.jsx @@ -13,7 +13,7 @@ import { ReactComponent as PipelineFailedIcon } from '@/images/no-synchronize.sv import { ReactComponent as PipelineCompleteIcon } from '@/images/check-circle.svg' const StagePanel = (props) => { - const { activePipeline, pipelineReady = false } = props + const { activePipeline, pipelineReady = false, stages, activeStageId = 1 } = props return ( <> @@ -30,14 +30,17 @@ const StagePanel = (props) => { justifySelf: 'flex-start', marginBottom: '8px', padding: 0, - backgroundColor: activePipeline.status === 'TASK_COMPLETED' ? 'rgba(245, 255, 250, 0.99)' : 'inherit' + backgroundColor: activePipeline.status === 'TASK_COMPLETED' ? 'rgba(245, 255, 250, 0.99)' : 'inherit', + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis' }} > {/* @todo: re-active "stage" ux in a future release */} - {/* */} - {/* */} - + + ) + : null + } + > +

+ Stage {sIdx + 1} +

+ + ))} + +
{ const [showInspector, setShowInspector] = useState(false) const [pipelineReady, setPipelineReady] = useState(false) + const [stages, setStages] = useState() + const [activeStageId, setActiveStageId] = useState(1) const { runPipeline, @@ -67,6 +69,23 @@ const PipelineActivity = (props) => { return activePipeline.tasks.some(t => t.plugin === providerId) } + const buildPipelineStages = useCallback((tasks = []) => { + let stages = {} + tasks?.forEach(tS => { + stages = { + ...stages, + [tS.pipelineRow]: tasks?.filter(t => t.pipelineRow === tS.pipelineRow) + } + }) + console.log('>>> BUILDING PIPELINE STAGES...', stages) + return stages + }, []) + + const findActiveStageId = (tasks = []) => { + const activeTask = tasks.find(t => t.status === 'TASK_RUNNING') + return activeTask?.pipelineRow || 1 + } + useEffect(() => { setPipelineId(pId) console.log('>>> REQUESTED PIPELINE ID ===', pId) @@ -99,6 +118,16 @@ const PipelineActivity = (props) => { } }, [autoRefresh, fetchPipeline, pipelineId, pollTimer]) + useEffect(() => { + if (activePipeline.ID) { + setStages(buildPipelineStages(activePipeline.tasks)) + } + }, [activePipeline, buildPipelineStages]) + + useEffect(() => { + + }, [stages]) + return ( <>
@@ -178,7 +207,11 @@ const PipelineActivity = (props) => { )} {activePipeline?.ID && ( <> - +
Date: Thu, 23 Dec 2021 11:00:21 -0500 Subject: [PATCH 12/24] fix: apply html element cleanups --- config-ui/src/components/pipelines/StagePanel.jsx | 14 +++++++++----- .../src/components/pipelines/TaskActivity.jsx | 8 ++------ config-ui/src/hooks/usePipelineManager.jsx | 1 + 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/config-ui/src/components/pipelines/StagePanel.jsx b/config-ui/src/components/pipelines/StagePanel.jsx index 3d05dab7a88..0256a864774 100644 --- a/config-ui/src/components/pipelines/StagePanel.jsx +++ b/config-ui/src/components/pipelines/StagePanel.jsx @@ -39,7 +39,7 @@ const StagePanel = (props) => { ))} - {/* @todo: re-active "stage" ux in a future release */} + {/* @todo: re-activate "stage" ux in a future release */} {Object.keys(stages).length > 0 && ( <> {Object.keys(stages).map((s, sIdx) => ( @@ -166,20 +189,24 @@ const StagePanel = (props) => { )} -

Finished Tasks · {activePipeline.finishedTasks} - /{activePipeline.totalTasks} -

-
- - {Number((activePipeline.finishedTasks / activePipeline.totalTasks) * 100).toFixed(1)}% +
+

Finished Tasks · {activePipeline.finishedTasks} + /{activePipeline.totalTasks} +

+ {/* */} + {/* {Number((activePipeline.finishedTasks / activePipeline.totalTasks) * 100).toFixed(1)}% */}
diff --git a/config-ui/src/components/pipelines/TaskActivity.jsx b/config-ui/src/components/pipelines/TaskActivity.jsx index e69298c45fa..ffcc3093a96 100644 --- a/config-ui/src/components/pipelines/TaskActivity.jsx +++ b/config-ui/src/components/pipelines/TaskActivity.jsx @@ -32,7 +32,7 @@ const TaskActivity = (props) => { key={`pipeline-task-key-${tIdx}`} style={{ display: 'flex', - padding: '4px 6px', + padding: '4px 0', justifyContent: 'space-between', fontSize: '12px', opacity: t.status === 'TASK_CREATED' ? 0.7 : 1 diff --git a/config-ui/src/pages/pipelines/activity.jsx b/config-ui/src/pages/pipelines/activity.jsx index b1e988deb0c..3b35d3e1f64 100644 --- a/config-ui/src/pages/pipelines/activity.jsx +++ b/config-ui/src/pages/pipelines/activity.jsx @@ -202,15 +202,17 @@ const PipelineActivity = (props) => {
- {!autoRefresh && isFetching && ( + {/* (using native loader instead...) */} + {/* {!autoRefresh && isFetching && ( - )} + )} */} {activePipeline?.ID && ( <>
{ const [repositoryName, setRepositoryName] = useState('') const [owner, setOwner] = useState('') + const [autoRedirect, setAutoRedirect] = useState(true) + const { runPipeline, cancelPipeline, @@ -209,7 +211,10 @@ const CreatePipeline = (props) => { useEffect(() => { console.log('>> PIPELINE LAST RUN OBJECT CHANGED!!...', pipelineRun) - }, [pipelineRun]) + if (pipelineRun.ID && autoRedirect) { + history.push(`/pipelines/activity/${pipelineRun.ID}`) + } + }, [pipelineRun, autoRedirect, history]) useEffect(() => { console.log(namePrefix, nameSuffix) From 5905189220fadd19551c04d37b23d83ccdbb3b72 Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Thu, 23 Dec 2021 18:51:25 -0500 Subject: [PATCH 15/24] fix: add restart pipeline feature --- config-ui/src/hooks/usePipelineManager.jsx | 4 -- config-ui/src/pages/pipelines/activity.jsx | 50 +++++++++++++--- config-ui/src/pages/pipelines/create.jsx | 69 +++++++++++++++++++++- 3 files changed, 110 insertions(+), 13 deletions(-) diff --git a/config-ui/src/hooks/usePipelineManager.jsx b/config-ui/src/hooks/usePipelineManager.jsx index dd5e4161376..65fea687b0e 100644 --- a/config-ui/src/hooks/usePipelineManager.jsx +++ b/config-ui/src/hooks/usePipelineManager.jsx @@ -126,10 +126,6 @@ function usePipelineManager (pipelineName = `COLLECTION ${Date.now()}`, initialT // } - useEffect(() => { - // setIntegrations(integrationsData) - }, []) - useEffect(() => { console.log('>> PIPELINE MANAGER - RECEIVED RUN/TASK SETTINGS', settings) }, [settings]) diff --git a/config-ui/src/pages/pipelines/activity.jsx b/config-ui/src/pages/pipelines/activity.jsx index 3b35d3e1f64..426d2b9d9df 100644 --- a/config-ui/src/pages/pipelines/activity.jsx +++ b/config-ui/src/pages/pipelines/activity.jsx @@ -61,8 +61,9 @@ const PipelineActivity = (props) => { // isRunning, isFetching, errors: pipelineErrors, - // setSettings: setPipelineSettings, - // lastRunId + setSettings: setPipelineSettings, + // setAutoStart: setPipelineAutoStart, + lastRunId, } = usePipelineManager(pipelineName) const pipelineHasProvider = (providerId) => { @@ -86,9 +87,34 @@ const PipelineActivity = (props) => { return activeTask?.pipelineRow || 1 } + const restartPipeline = useCallback((tasks = []) => { + const existingTasksConfiguration = tasks.map(t => { + return { + plugin: t.plugin, + options: t.options + } + }) + console.log('>>> RESTARTING PIPELINE WITH EXISTING CONFIGURATION!!', existingTasksConfiguration) + // setPipelineAutoStart(true) + // setPipelineSettings({ + // autoStart: true, + // name: `RETRY | ${activePipeline.name}`, + // tasks: [ + // [...existingTasksConfiguration] + // ] + // }) + history.push({ + pathname: '/pipelines/create', + state: { + existingTasks: existingTasksConfiguration + } + }) + }, [activePipeline.name, setPipelineSettings]) + useEffect(() => { setPipelineId(pId) console.log('>>> REQUESTED PIPELINE ID ===', pId) + // return () => setPipelineAutoStart(false) }, [pId]) useEffect(() => { @@ -128,6 +154,10 @@ const PipelineActivity = (props) => { }, [stages]) + useEffect(() => { + console.log('>>> GOT LAST RUN ID!', lastRunId) + }, [lastRunId]) + return ( <>
@@ -344,15 +374,19 @@ const PipelineActivity = (props) => { icon='reset' text='RESTART' intent='warning' + onClick={() => restartPipeline(activePipeline.tasks)} disabled={activePipeline.status !== 'TASK_FAILED'} /> )} -
diff --git a/config-ui/src/pages/pipelines/create.jsx b/config-ui/src/pages/pipelines/create.jsx index dc828578312..1fc26d8e333 100644 --- a/config-ui/src/pages/pipelines/create.jsx +++ b/config-ui/src/pages/pipelines/create.jsx @@ -2,6 +2,7 @@ import React, { Fragment, useEffect, useCallback, useState, useRef } from 'react import { CSSTransition } from 'react-transition-group' import { useHistory, + useLocation, Link, // useParams, } from 'react-router-dom' @@ -48,6 +49,7 @@ import '@/styles/pipelines.scss' const CreatePipeline = (props) => { const history = useHistory() + const location = useLocation() // const { providerId } = useParams() // const [activeProvider, setActiveProvider] = useState(integrationsData[0]) const [integrations, setIntegrations] = useState(integrationsData) @@ -71,6 +73,7 @@ const CreatePipeline = (props) => { const [enabledProviders, setEnabledProviders] = useState([]) const [runTasks, setRunTasks] = useState([]) + const [existingTasks, setExistingTasks] = useState([]) const [namePrefix, setNamePrefix] = useState(pipelinePrefixes[0]) const [nameSuffix, setNameSuffix] = useState(pipelineSuffixes[0]) @@ -84,6 +87,7 @@ const CreatePipeline = (props) => { const [owner, setOwner] = useState('') const [autoRedirect, setAutoRedirect] = useState(true) + const [restartDetected, setRestartDetected] = useState(false) const { runPipeline, @@ -180,6 +184,16 @@ const CreatePipeline = (props) => { setPipelineName(`${namePrefix} ${nameSuffix}`) } + const resetConfiguration = () => { + setExistingTasks([]) + setEnabledProviders([]) + setProjectId(null) + setBoardId(null) + setSelectedSource(null) + setRepositoryName(null) + setOwner(null) + } + useEffect(() => { }, [pipelineName]) @@ -235,7 +249,59 @@ const CreatePipeline = (props) => { useEffect(() => { console.log('>> BUILT JIRA INSTANCE SELECT MENU... ', sources) - }, [sources]) + if (sources.length > 0 && restartDetected) { + const JiraTask = existingTasks.find(t => t.plugin === Providers.JIRA) + if (JiraTask) { + console.log('>>>>>HERE!!!', sources.find(s => s.id === parseInt(JiraTask.options?.sourceId, 10))) + setSelectedSource(sources.find(s => s.id === parseInt(JiraTask.options?.sourceId, 10))) + } + } + }, [sources, existingTasks, restartDetected]) + + useEffect(() => { + if (location.state?.existingTasks) { + console.log('>> RESTART ATTEMPT: DETECTED EXISTING PIPELINE CONFIGURATION... ', location.state.existingTasks) + const tasks = location.state.existingTasks + setRestartDetected(true) + setExistingTasks(tasks) + window.history.replaceState(null, '') + // !WARNING! This logic will only handle ONE STAGE (Stage 1) + // @todo: refactor later for multi-stage + const GitLabTask = tasks.find(t => t.plugin === Providers.GITLAB) + const GitHubTask = tasks.find(t => t.plugin === Providers.GITHUB) + const JiraTask = tasks.find(t => t.plugin === Providers.JIRA) + const JenkinsTask = tasks.find(t => t.plugin === Providers.JENKINS) + if (GitLabTask) { + setEnabledProviders(eP => [...eP, Providers.GITLAB]) + // console.log('>>>> GL TASK OBJECT = ', GitLabTask) + setProjectId(GitLabTask.options?.projectId) + } + if (GitHubTask) { + setEnabledProviders(eP => [...eP, Providers.GITHUB]) + // console.log('>>>> GH TASK OBJECT = ', GitHubTask) + setRepositoryName(GitHubTask.options?.repositoryName) + setOwner(GitHubTask.options?.owner) + } + if (JiraTask) { + setEnabledProviders(eP => [...eP, Providers.JIRA]) + // console.log('>>>> JIRA TASK OBJECT = ', JiraTask) + setBoardId(JiraTask.options?.boardId) + // setSourceId(JiraTask.options?.sourceId) + // setSelectedSource(sources.find(s => s.id === parseInt(JiraTask.options?.sourceId, 10))) + } + if (JenkinsTask) { + setEnabledProviders(eP => [...eP, Providers.JENKINS]) + } + } else { + setRestartDetected(false) + setExistingTasks([]) + } + + return () => { + setRestartDetected(false) + setExistingTasks([]) + } + }, [location]) return ( <> @@ -523,6 +589,7 @@ const CreatePipeline = (props) => { >Run Pipeline + {/*
Date: Thu, 23 Dec 2021 19:08:39 -0500 Subject: [PATCH 16/24] fix: change pipeline name for manual run --- config-ui/src/pages/triggers/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-ui/src/pages/triggers/index.jsx b/config-ui/src/pages/triggers/index.jsx index 22430cbcf87..b86dfa6e192 100644 --- a/config-ui/src/pages/triggers/index.jsx +++ b/config-ui/src/pages/triggers/index.jsx @@ -92,7 +92,7 @@ export default function Triggers () { const res = await request.post( `${DEVLAKE_ENDPOINT}/pipelines`, JSON.stringify({ - name: `config-ui trigger ${new Date()}`, + name: `(m)RUN ${new Date()}`, tasks: JSON.parse(textAreaBody) }) ) From 9e09812c4cc944654ac3477be5947773a8481421 Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Thu, 23 Dec 2021 19:13:44 -0500 Subject: [PATCH 17/24] chore: cleanup unused code blocks --- config-ui/src/pages/pipelines/activity.jsx | 15 +++------------ config-ui/src/pages/pipelines/create.jsx | 6 ------ 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/config-ui/src/pages/pipelines/activity.jsx b/config-ui/src/pages/pipelines/activity.jsx index 426d2b9d9df..201e63271a6 100644 --- a/config-ui/src/pages/pipelines/activity.jsx +++ b/config-ui/src/pages/pipelines/activity.jsx @@ -11,8 +11,8 @@ import { Position, Spinner, Colors, - Drawer, - DrawerSize, + // Drawer, + // DrawerSize, Classes, // ButtonGroup, InputGroup, Input, Tag,H2, TextArea,Link } from '@blueprintjs/core' @@ -26,7 +26,7 @@ import Nav from '@/components/Nav' import Sidebar from '@/components/Sidebar' import AppCrumbs from '@/components/Breadcrumbs' import Content from '@/components/Content' -import ContentLoader from '@/components/loaders/ContentLoader' +// import ContentLoader from '@/components/loaders/ContentLoader' import StagePanel from '@/components/pipelines/StagePanel' import TaskActivity from '@/components/pipelines/TaskActivity' import CodeInspector from '@/components/pipelines/CodeInspector' @@ -95,14 +95,6 @@ const PipelineActivity = (props) => { } }) console.log('>>> RESTARTING PIPELINE WITH EXISTING CONFIGURATION!!', existingTasksConfiguration) - // setPipelineAutoStart(true) - // setPipelineSettings({ - // autoStart: true, - // name: `RETRY | ${activePipeline.name}`, - // tasks: [ - // [...existingTasksConfiguration] - // ] - // }) history.push({ pathname: '/pipelines/create', state: { @@ -114,7 +106,6 @@ const PipelineActivity = (props) => { useEffect(() => { setPipelineId(pId) console.log('>>> REQUESTED PIPELINE ID ===', pId) - // return () => setPipelineAutoStart(false) }, [pId]) useEffect(() => { diff --git a/config-ui/src/pages/pipelines/create.jsx b/config-ui/src/pages/pipelines/create.jsx index 1fc26d8e333..115bc00d7b7 100644 --- a/config-ui/src/pages/pipelines/create.jsx +++ b/config-ui/src/pages/pipelines/create.jsx @@ -252,7 +252,6 @@ const CreatePipeline = (props) => { if (sources.length > 0 && restartDetected) { const JiraTask = existingTasks.find(t => t.plugin === Providers.JIRA) if (JiraTask) { - console.log('>>>>>HERE!!!', sources.find(s => s.id === parseInt(JiraTask.options?.sourceId, 10))) setSelectedSource(sources.find(s => s.id === parseInt(JiraTask.options?.sourceId, 10))) } } @@ -273,21 +272,16 @@ const CreatePipeline = (props) => { const JenkinsTask = tasks.find(t => t.plugin === Providers.JENKINS) if (GitLabTask) { setEnabledProviders(eP => [...eP, Providers.GITLAB]) - // console.log('>>>> GL TASK OBJECT = ', GitLabTask) setProjectId(GitLabTask.options?.projectId) } if (GitHubTask) { setEnabledProviders(eP => [...eP, Providers.GITHUB]) - // console.log('>>>> GH TASK OBJECT = ', GitHubTask) setRepositoryName(GitHubTask.options?.repositoryName) setOwner(GitHubTask.options?.owner) } if (JiraTask) { setEnabledProviders(eP => [...eP, Providers.JIRA]) - // console.log('>>>> JIRA TASK OBJECT = ', JiraTask) setBoardId(JiraTask.options?.boardId) - // setSourceId(JiraTask.options?.sourceId) - // setSelectedSource(sources.find(s => s.id === parseInt(JiraTask.options?.sourceId, 10))) } if (JenkinsTask) { setEnabledProviders(eP => [...eP, Providers.JENKINS]) From bccd877512e0f666b5c142c06e9a3b69ada0f529 Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Thu, 23 Dec 2021 19:36:53 -0500 Subject: [PATCH 18/24] fix: cleanup jira selected source initial state --- config-ui/src/pages/pipelines/create.jsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/config-ui/src/pages/pipelines/create.jsx b/config-ui/src/pages/pipelines/create.jsx index 115bc00d7b7..2c68d046afa 100644 --- a/config-ui/src/pages/pipelines/create.jsx +++ b/config-ui/src/pages/pipelines/create.jsx @@ -185,13 +185,14 @@ const CreatePipeline = (props) => { } const resetConfiguration = () => { + window.history.replaceState(null, '') setExistingTasks([]) setEnabledProviders([]) setProjectId(null) setBoardId(null) setSelectedSource(null) - setRepositoryName(null) - setOwner(null) + setRepositoryName('') + setOwner('') } useEffect(() => { @@ -249,13 +250,7 @@ const CreatePipeline = (props) => { useEffect(() => { console.log('>> BUILT JIRA INSTANCE SELECT MENU... ', sources) - if (sources.length > 0 && restartDetected) { - const JiraTask = existingTasks.find(t => t.plugin === Providers.JIRA) - if (JiraTask) { - setSelectedSource(sources.find(s => s.id === parseInt(JiraTask.options?.sourceId, 10))) - } - } - }, [sources, existingTasks, restartDetected]) + }, [sources]) useEffect(() => { if (location.state?.existingTasks) { @@ -280,8 +275,14 @@ const CreatePipeline = (props) => { setOwner(GitHubTask.options?.owner) } if (JiraTask) { + // const selSource = sources.find(s => s.ID === parseInt(JiraTask.options?.sourceId, 10)) setEnabledProviders(eP => [...eP, Providers.JIRA]) setBoardId(JiraTask.options?.boardId) + setSelectedSource({ + id: parseInt(JiraTask.options?.sourceId, 10), + title: '(Instance)', + value: parseInt(JiraTask.options?.sourceId, 10) + }) } if (JenkinsTask) { setEnabledProviders(eP => [...eP, Providers.JENKINS]) From 85f36bb4fd879cf3e93c091f86ff88b412f2788e Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Thu, 23 Dec 2021 19:40:16 -0500 Subject: [PATCH 19/24] fix: dismiss popover on cancel action --- config-ui/src/pages/pipelines/activity.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/config-ui/src/pages/pipelines/activity.jsx b/config-ui/src/pages/pipelines/activity.jsx index 201e63271a6..de5e778d0b7 100644 --- a/config-ui/src/pages/pipelines/activity.jsx +++ b/config-ui/src/pages/pipelines/activity.jsx @@ -351,6 +351,7 @@ const PipelineActivity = (props) => { stlye={{ marginLeft: 'auto', marginRight: '3px' }} /> - - + + + + {/*
Date: Thu, 23 Dec 2021 21:04:20 -0500 Subject: [PATCH 22/24] fix: cleanup effect dependencies --- config-ui/src/pages/pipelines/activity.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config-ui/src/pages/pipelines/activity.jsx b/config-ui/src/pages/pipelines/activity.jsx index 8f5166e27cd..eba07d0a3ef 100644 --- a/config-ui/src/pages/pipelines/activity.jsx +++ b/config-ui/src/pages/pipelines/activity.jsx @@ -11,12 +11,12 @@ import { Position, Spinner, Colors, + Classes, // Drawer, // DrawerSize, - Classes, // ButtonGroup, InputGroup, Input, Tag,H2, TextArea,Link } from '@blueprintjs/core' -import { integrationsData } from '@/data/integrations' +// import { integrationsData } from '@/data/integrations' import { Providers, ProviderLabels @@ -101,7 +101,7 @@ const PipelineActivity = (props) => { existingTasks: existingTasksConfiguration } }) - }, [activePipeline.name, setPipelineSettings]) + }, [history]) useEffect(() => { setPipelineId(pId) From 37a94a0200c25aa23696170b5eb9c2e711cbcfa5 Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Thu, 23 Dec 2021 21:09:59 -0500 Subject: [PATCH 23/24] fix: resolve improper child descendant error --- config-ui/src/components/pipelines/StagePanel.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config-ui/src/components/pipelines/StagePanel.jsx b/config-ui/src/components/pipelines/StagePanel.jsx index db5e200cd48..79460298de3 100644 --- a/config-ui/src/components/pipelines/StagePanel.jsx +++ b/config-ui/src/components/pipelines/StagePanel.jsx @@ -144,9 +144,9 @@ const StagePanel = (props) => { rightIcon={ sIdx !== (Object.keys(stages).length - 1) ? ( - + ) : null } From 52c2c2960bc510b797e76225c551d0f313f47e97 Mon Sep 17 00:00:00 2001 From: Julien Chinapen Date: Thu, 23 Dec 2021 21:13:52 -0500 Subject: [PATCH 24/24] chore: cleanup pipelines scss --- config-ui/src/styles/pipelines.scss | 97 +++++++++++++---------------- 1 file changed, 42 insertions(+), 55 deletions(-) diff --git a/config-ui/src/styles/pipelines.scss b/config-ui/src/styles/pipelines.scss index bf987aee0ec..77b9dcf3bc5 100644 --- a/config-ui/src/styles/pipelines.scss +++ b/config-ui/src/styles/pipelines.scss @@ -1,4 +1,3 @@ - .data-providers { min-width: 514px; } @@ -9,7 +8,7 @@ width: 100%; padding: 24px 12px; transition: background-color 0.3s ease; - border-bottom: 1px solid rgba(0,0,0,0.08); + border-bottom: 1px solid rgba(0, 0, 0, 0.08); border-radius: 8px; -webkit-user-select: none; -moz-user-select: none; @@ -29,13 +28,12 @@ opacity: 0; visibility: hidden; content: '(Turn ON to Configure)'; - color: rgba(100,100,100,0.25); + color: rgba(100, 100, 100, 0.25); transition: all 0.4s ease-in; } &:hover { - background-color: rgba(0,0,0,0.03); - // box-shadow: 0 0 0 0 rgba(232, 71, 28, 0), 0 0 0 0 rgba(232, 71, 28, 0), inset 0 0 0 1px rgba(16, 22, 26, 0.15), inset 0 1px 1px rgba(16, 22, 26, 0.2); + background-color: rgba(0, 0, 0, 0.03); } &.on { @@ -48,27 +46,18 @@ .provider-name { opacity: 0.7; } + .provider-icon { opacity: 0.7; transform: scale(0.9); } + &:hover { &:after { top: 5px; right: 5px; opacity: 1; - visibility: visible; - // display: inline-block; - // width: 150px; - // height: 24px; - // line-height: 24px; - // font-size: 11px; - // position: absolute; - // top: 5px; - // right: 10px; - // content: '(Turn ON to Configure)'; - // color: rgba(100,100,100,0.25); - // transition: all 0.4s ease-in; + visibility: visible; } } } @@ -82,10 +71,12 @@ .provider-icon { transition: all 0.3s ease; - > svg { + + >svg { transition: all 0.3s ease; } } + .provider-name { font-family: 'Montserrat', sans-serif; font-weight: 900; @@ -93,10 +84,12 @@ font-size: 14px; margin-bottom: 3px; transition: all 0.3s ease; + &:hover { color: #007cff; - } + } } + .bp3-popover-wrapper { width: auto; } @@ -107,7 +100,7 @@ padding: 0 20px; align-items: flex-end; display: flex; - + .bp3-form-group { margin-bottom: 0; } @@ -131,9 +124,6 @@ } .btn-pipeline { - // font-family: 'Montserrat', sans-serif; - // text-transform: uppercase; - // letter-spacing: 2px; font-weight: 800; transition: all 0.4s ease; white-space: nowrap; @@ -146,18 +136,20 @@ .bp3-switch { &.provider-toggle-switch { margin-bottom: 0; + &:not(.bp3-align-right) { padding-left: 43px } - + } } .pipeline-action-btn { transition: all 0.4s ease; + &:hover { svg { - fill: #007cff!important + fill: #007cff !important } } } @@ -207,7 +199,6 @@ } .activity-panel-enter { - // transform: rotateX(-50deg); transform: scale(1.01); background-color: #f0f0f0; opacity: 1; @@ -215,7 +206,6 @@ } .activity-panel-enter-done { - // transform: rotateX(0deg); transform: scale(1); background-color: #ffffff; opacity: 1; @@ -223,16 +213,14 @@ } .activity-panel-exit { - // transform: rotateX(20deg); background-color: #f7f7f7; opacity: 1; transition: opacity 300ms, transform 300ms, background-color 800ms; } .activity-panel-exit-active { - // transform: rotateX(40deg); background-color: #eeeeee; - opacity: 1; + opacity: 1; transition: opacity 300ms, transform 300ms, background-color 800ms; } @@ -247,7 +235,6 @@ .bp3-popover { &.popover-lastrun { - // margin-left: -8px; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; @@ -261,81 +248,80 @@ } } -.trigger-module-lastrun { - -} +.trigger-module-lastrun {} .bp3-button { - &.btn-cancel-pipeline { + &.btn-cancel-pipeline { transition: all 0.4s ease; background-color: darken(#FFA8A8, 5%); border: 1px solid darken(#FF6D6D, 5%); box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.35); border-radius: 6px; - // font-family: 'Montserrat', sans-serif; font-style: normal; font-weight: 900; - // font-size: 11px; color: #ffffff; - &:hover,:active,&.bp3-active { - background-color: darken(#FFA8A8, 10%)!important; - border: 1px solid darken(#FF6D6D, 10%)!important; - box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.40)!important; + &:hover, + :active, + &.bp3-active { + background-color: darken(#FFA8A8, 10%) !important; + border: 1px solid darken(#FF6D6D, 10%) !important; + box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.40) !important; } } &.btn-retry-pipeline { transition: all 0.4s ease; - // background-color: darken(#a8d8ff, 5%); - // border: 1px solid darken(#6dd6ff, 5%); box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.35); border-radius: 6px; - // font-family: 'Montserrat', sans-serif; font-style: normal; font-weight: 900; - // font-size: 11px; color: #ffffff; - &:hover,:active,&.bp3-active { - // background-color: darken(#a8d8ff, 15%); - // border: 1px solid darken(#6dd6ff, 15%); + &:hover, + :active, + &.bp3-active { box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.40); } - } + } } .bp3-input-group { .bp3-input { transition: all 0.3s ease; } + &.is-invalid { .bp3-input { background-color: lighten(#FFA8A8, 13%); color: darken(#FF6D6D, 20%); border: 1px solid darken(#FF6D6D, 10%); + &::placeholder { color: lighten(#FF6D6D, 10%); } } - } + } + &.is-valid { .bp3-input { background-color: lighten(#b5ffe0, 11%); color: darken(#00cf8a, 5%); border: 1px solid darken(#6dffce, 15%); - // font-weight: 800; + &::placeholder { color: lighten(#6dffce, 10%); } + &:focus { box-shadow: 0 0 0 1px #1ce878, 0 0 0 3px rgba(28, 232, 188, 0.3), inset 0 1px 1px rgba(16, 26, 23, 0.2) } } - } + } } -.bp3-popover-wrapper, .bp3-popover-target { +.bp3-popover-wrapper, +.bp3-popover-target { width: auto; } @@ -348,12 +334,13 @@ } .bp3-menu { - &.pipeline-presets-menu { + &.pipeline-presets-menu { .bp3-menu-item { - &.bp3-active { + &.bp3-active { background-color: transparent; color: #007cff; font-weight: 800; + &:hover { background-color: rgba(66, 66, 66, 0.08); color: darken(#007cff, 5%);