Skip to content

Commit 9afe3e2

Browse files
author
Dan Wilson
authored
kicking off new build manually will push build to build list (#378)
1 parent f1ddc8e commit 9afe3e2

File tree

6 files changed

+103
-59
lines changed

6 files changed

+103
-59
lines changed
Lines changed: 81 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import classNames from 'classnames/bind';
22
import { formatDistanceStrict } from 'date-fns';
3+
import PropTypes from 'prop-types';
34
import React from 'react';
45
import { Link } from 'react-router-dom';
56

@@ -11,59 +12,89 @@ import styles from './build-list.module.scss';
1112

1213
const cx = classNames.bind(styles);
1314

14-
const BuildList = (props) => {
15-
const { url, data } = props;
16-
return (
17-
<ul className={cx('list')}>
18-
{props.data.map((build) => (
19-
<li key={build.id}>
20-
<Link to={`${url}/${build.number}`}>
21-
<div className={cx('list-item')}>
22-
<div className={cx('status')}>
23-
<Status status={build.status} />
24-
<div className={cx('connector')} />
15+
const BuildListItem = ({ build, url }) => (
16+
<li>
17+
<Link to={`${url}/${build.number}`}>
18+
<div className={cx('list-item')}>
19+
<div className={cx('status')}>
20+
<Status status={build.status} />
21+
<div className={cx('connector')} />
22+
</div>
23+
<div className={cx('container')}>
24+
<div className={cx('header')}>
25+
<div className={cx('number')}>{build.number}</div>
26+
<div className={cx('commit')}>{build.title || build.message?.trim()}</div>
27+
</div>
28+
<div className={cx('content')}>
29+
<Activity
30+
className={cx('activity')}
31+
number={build.number}
32+
event={build.event}
33+
action={build.action}
34+
actor={build.sender}
35+
avatar={build.author_avatar}
36+
commit={build.after}
37+
branch={build.target}
38+
target={build.deploy_to}
39+
parent={build.parent}
40+
cron={build.cron}
41+
refs={build.ref}
42+
/>
43+
<div className={cx('timing')}>
44+
<div>
45+
{formatDistanceStrict(new Date(build.created * 1000), new Date(), { addSuffix: true })}
2546
</div>
26-
<div className={cx('container')}>
27-
<div className={cx('header')}>
28-
<div className={cx('number')}>{build.number}</div>
29-
<div className={cx('commit')}>{build.title || build.message?.trim()}</div>
30-
</div>
31-
<div className={cx('content')}>
32-
<Activity
33-
className={cx('activity')}
34-
number={build.number}
35-
event={build.event}
36-
action={build.action}
37-
actor={build.sender}
38-
avatar={build.author_avatar}
39-
commit={build.after}
40-
branch={build.target}
41-
target={build.deploy_to}
42-
parent={build.parent}
43-
cron={build.cron}
44-
refs={build.ref}
45-
/>
46-
<div className={cx('timing')}>
47-
<div>
48-
{formatDistanceStrict(new Date(build.created * 1000), new Date(), { addSuffix: true })}
49-
</div>
50-
<div className={cx('dot')}><span /></div>
51-
<div>
52-
<Elapsed
53-
started={build.started}
54-
finished={build.finished}
55-
className={cx('elapsed')}
56-
/>
57-
</div>
58-
</div>
59-
</div>
47+
<div className={cx('dot')}><span /></div>
48+
<div>
49+
<Elapsed
50+
started={build.started}
51+
finished={build.finished}
52+
className={cx('elapsed')}
53+
/>
6054
</div>
6155
</div>
62-
</Link>
63-
</li>
64-
))}
65-
</ul>
66-
);
56+
</div>
57+
</div>
58+
</div>
59+
</Link>
60+
</li>
61+
);
62+
63+
const BuildList = ({ data, url }) => (
64+
<ul className={cx('list')}>
65+
{data.map((build) => <BuildListItem key={build.number} build={build} url={url} />)}
66+
</ul>
67+
);
68+
69+
const buildPropTypes = PropTypes.shape({
70+
id: PropTypes.number,
71+
number: PropTypes.number,
72+
status: PropTypes.string,
73+
title: PropTypes.number,
74+
message: PropTypes.string,
75+
event: PropTypes.string,
76+
action: PropTypes.string,
77+
sender: PropTypes.string,
78+
author_avatar: PropTypes.string,
79+
after: PropTypes.string,
80+
target: PropTypes.string,
81+
deploy_to: PropTypes.string,
82+
parent: PropTypes.string,
83+
cron: PropTypes.bool,
84+
ref: PropTypes.string,
85+
created: PropTypes.number,
86+
started: PropTypes.number,
87+
finished: PropTypes.number,
88+
});
89+
90+
BuildListItem.propTypes = {
91+
build: buildPropTypes.isRequired,
92+
url: PropTypes.string.isRequired,
93+
};
94+
95+
BuildList.propTypes = {
96+
data: PropTypes.arrayOf(buildPropTypes).isRequired,
97+
url: PropTypes.string.isRequired,
6798
};
6899

69100
export default BuildList;

src/components/pages/repo/new-build-form/new-build-form.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ const NewBuildForm = ({ handleSubmit, handleCancel }) => {
8585
) : null}
8686
<div className={cx('new-build-form-parameters-fields')}>
8787
<Field.Input
88+
name="newKey"
8889
placeholder="key"
8990
value={parameterState.key}
9091
onChange={handleParameterChange('key')}
9192
/>
9293
<Field.Input
94+
name="newVal"
9395
placeholder="value"
9496
value={parameterState.value}
9597
onChange={handleParameterChange('value')}

src/components/shared/bar-chart/bar-chart.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ const BarChart = (props) => {
8282
if (data.length < barsShown) {
8383
const barPlaceholders = Array
8484
.from({ length: barsShown - data.length },
85-
(_, i) => ({ number: data.length + i + 1 }));
85+
(_, i) => ({ number: 0 - i }));
8686
return withHeight.concat(barPlaceholders);
8787
}
8888
return withHeight;
@@ -143,12 +143,14 @@ BarChart.propTypes = {
143143
height: PropTypes.number.isRequired,
144144
onClick: PropTypes.func.isRequired,
145145
minBarWidth: PropTypes.number,
146+
minGapWidth: PropTypes.number,
146147
barsShown: PropTypes.number,
147148
};
148149

149150
BarChart.defaultProps = {
150151
className: '',
151152
minBarWidth: MIN_BAR_WIDTH,
153+
minGapWidth: MIN_GAP_WIDTH,
152154
barsShown: BARS_SHOWN,
153155
};
154156

src/hooks/swr/builds.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ const updateLatestRepos = (repo) => (latest) => {
7777
};
7878

7979
// activity feed updater
80-
const updateBuilds = async (slug, repo) => {
80+
const updateBuilds = async (slug, repo, newBuild = null) => {
8181
if (`/${repo.namespace}/${repo.name}` !== slug) {
8282
// no need to do anything actually since user
8383
// is on the activity feed of another repo
@@ -103,7 +103,7 @@ const updateBuilds = async (slug, repo) => {
103103
*/
104104
const path = `arg@"many"@"/api/repos${slug}/builds?page=1&per_page=${MAX_PAGE_LENGTH}"`;
105105
mutateGlobal(path, async (builds) => {
106-
const { build } = repo;
106+
const build = newBuild ?? repo.build;
107107
/* if no cache or no data,
108108
/ just return an array with received build
109109
*/
@@ -187,5 +187,5 @@ const useStreamBuildEvents = () => {
187187
};
188188

189189
export {
190-
useBuilds, useBuild, useStreamBuildEvents,
190+
useBuilds, useBuild, useStreamBuildEvents, updateBuilds,
191191
};

src/hooks/swr/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
useBuild, useBuilds, useStreamBuildEvents,
2+
useBuild, useBuilds, useStreamBuildEvents, updateBuilds,
33
} from './builds';
44
import { useLogs, useStreamLogs } from './logs';
55
import { useRepo, useLatestRepos } from './repo';
@@ -15,6 +15,7 @@ export {
1515
useSyncAccount,
1616
useBuild,
1717
useBuilds,
18+
updateBuilds,
1819
useBranches,
1920
useDeployments,
2021
useRepo,

src/pages/repo/repo.jsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import classNames from 'classnames/bind';
2+
import PropTypes from 'prop-types';
23
import React, {
34
useCallback, useMemo, useContext,
45
} from 'react';
@@ -13,7 +14,7 @@ import Button from 'components/shared/button';
1314
import Modal, { useModal } from 'components/shared/modal';
1415
import { AppContext } from 'context';
1516
import { useToast } from 'hooks';
16-
import { useRepo } from 'hooks/swr';
17+
import { useRepo, updateBuilds } from 'hooks/swr';
1718
import NotFound from 'pages/not-found';
1819
import { Routes } from 'routes/routes';
1920
import { ReactComponent as DemoIcon } from 'svg/demo.svg';
@@ -57,7 +58,7 @@ const getTabProps = ({
5758
const Repo = ({ user }) => {
5859
const { params } = useRouteMatch();
5960
const {
60-
namespace, name, build, stage = 1, step = 1,
61+
namespace, name,
6162
} = params;
6263
const [context] = useContext(AppContext);
6364
const { isRepoNavDisabled } = context;
@@ -106,16 +107,17 @@ const Repo = ({ user }) => {
106107
}
107108
}
108109
try {
109-
await axiosWrapper(endpoint, {
110+
const newBuild = await axiosWrapper(endpoint, {
110111
method: 'POST',
111112
});
112113
showSuccess('New build has started successfully');
114+
updateBuilds(window.location.pathname, repo, newBuild);
113115
} catch (e) {
114116
showError(`Unable to start a new build: ${e.message}`);
115117
// eslint-disable-next-line no-console
116118
console.warn(e.message);
117119
}
118-
}, [name, namespace, showError, showSuccess]);
120+
}, [name, namespace, showError, showSuccess, repo]);
119121
if (isRepoDataLoading) {
120122
return null;
121123
}
@@ -214,4 +216,10 @@ const Repo = ({ user }) => {
214216
);
215217
};
216218

219+
Repo.propTypes = {
220+
user: PropTypes.shape({
221+
admin: PropTypes.bool,
222+
}).isRequired,
223+
};
224+
217225
export default Repo;

0 commit comments

Comments
 (0)