Skip to content

Commit

Permalink
improve gui for pipeline job creation
Browse files Browse the repository at this point in the history
  • Loading branch information
nilsgstrabo committed Nov 22, 2024
1 parent 390e051 commit 52ae2a6
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 178 deletions.
80 changes: 59 additions & 21 deletions src/components/create-job-form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@ import * as PropTypes from 'prop-types';
import {
type ComponentProps,
type FunctionComponent,
type PropsWithChildren,
useState,
useCallback,
useMemo,
} from 'react';

import { PipelineFormPromote } from './pipeline-form-promote';

import './style.css';
import { useSearchParams } from 'react-router-dom';
import { pollingInterval } from '../../store/defaults';
import {
type Application,
useGetApplicationQuery,
} from '../../store/radix-api';
import { PipelineFormApplyConfig } from './pipeline-form-apply-config';
import { PipelineFormBuildBranches } from './pipeline-form-build-branches';
import { PipelineFormDeploy } from './pipeline-form-deploy';
import { PipelineFormPromote } from './pipeline-form-promote';
import { useGetApplicationBranches } from './use-get-application-branches';
import './style.css';
import AsyncResource from '../async-resource/async-resource';

export interface CreateJobFormProps {
appName: string;
Expand All @@ -25,11 +31,11 @@ type SupportedPipelineNames =
| ComponentProps<typeof PipelineFormPromote>['pipelineName']
| ComponentProps<typeof PipelineFormApplyConfig>['pipelineName'];

export type FormProp = PropsWithChildren<{
appName: string;
export type FormProp = {
application: Application;
onSuccess: (jobName: string) => void;
pipelineName: string;
}>;
};

const Pipelines = {
build: PipelineFormBuildBranches,
Expand All @@ -39,28 +45,53 @@ const Pipelines = {
'apply-config': PipelineFormApplyConfig,
} satisfies Record<SupportedPipelineNames, FunctionComponent<FormProp>>;

const pipelineSearchParam = 'pipeline';

export default function CreateJobForm({
appName,
onSuccess,
}: CreateJobFormProps) {
const [searchParams] = useSearchParams();
const [pipeline, setPipeline] = useState<SupportedPipelineNames>(() => {
const urlPipeline = searchParams.get('pipeline');
const { data: application, ...appState } = useGetApplicationQuery(
{ appName },
{ pollingInterval }
);

const hasEnvironments = useMemo(
() => application?.environments?.length > 0,
[application]
);
const buildBranches = useGetApplicationBranches(application);
const hasBuildBranches = useMemo(
() => Object.keys(buildBranches).length > 0,
[buildBranches]
);
const [searchParams, setSearchParams] = useSearchParams();
const setPipelineType = useCallback(
(pipeline: string) => {
setSearchParams((prev) => {
prev.set(pipelineSearchParam, pipeline);
return prev;
});
},
[setSearchParams]
);
const pipeline = useMemo(() => {
const urlPipeline = searchParams.get(pipelineSearchParam);
if (Object.keys(Pipelines).includes(urlPipeline)) {
return urlPipeline as SupportedPipelineNames;
return urlPipeline;
}

return 'build-deploy';
});
return !hasEnvironments
? 'apply-config'
: hasBuildBranches
? 'build-deploy'
: '';
}, [searchParams, hasEnvironments, hasBuildBranches]);

const PipelineForm = Pipelines[pipeline];

return (
<PipelineForm
onSuccess={onSuccess}
appName={appName}
pipelineName={pipeline}
>
<AsyncResource asyncState={appState}>
<Typography
group="input"
variant="text"
Expand All @@ -72,7 +103,7 @@ export default function CreateJobForm({
id="PipelineNameSelect"
label=""
value={pipeline}
onChange={(e) => setPipeline(e.target.value as SupportedPipelineNames)}
onChange={(e) => setPipelineType(e.target.value)}
>
<option disabled value="">
— Please select —
Expand All @@ -83,7 +114,14 @@ export default function CreateJobForm({
</option>
))}
</NativeSelect>
</PipelineForm>
{PipelineForm && (
<PipelineForm
onSuccess={onSuccess}
application={application}
pipelineName={pipeline}
/>
)}
</AsyncResource>
);
}
CreateJobForm.propTypes = {
Expand Down
10 changes: 3 additions & 7 deletions src/components/create-job-form/pipeline-form-apply-config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,16 @@ import { Alert } from '../alert';
import { handlePromiseWithToast } from '../global-top-nav/styled-toaster';
import type { FormProp } from './index';

export function PipelineFormApplyConfig({
children,
appName,
onSuccess,
}: FormProp) {
export function PipelineFormApplyConfig({ application, onSuccess }: FormProp) {
const [trigger, state] = useTriggerPipelineApplyConfigMutation();
const [deployExternalDNS, setDeployExternalDNS] = useState(false);

const handleSubmit = handlePromiseWithToast(
async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();

const response = await trigger({
appName,
appName: application.name,
pipelineParametersApplyConfig: {
deployExternalDNS: deployExternalDNS,
},
Expand All @@ -37,7 +34,6 @@ export function PipelineFormApplyConfig({
<form onSubmit={handleSubmit}>
<fieldset disabled={state.isLoading} className="grid grid--gap-medium">
<div className="grid grid--gap-small input">
{children}
<Typography
className="input-label"
as="span"
Expand Down
57 changes: 33 additions & 24 deletions src/components/create-job-form/pipeline-form-build-branches.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,20 @@ import { TargetEnvs } from './target-envs';
import { useGetApplicationBranches } from './use-get-application-branches';

export function PipelineFormBuildBranches({
children,
onSuccess,
appName,
application,
pipelineName,
}: FormProp) {
const isBuildDeployPipeline = pipelineName === 'build-deploy';
const [triggerBuild, buildState] = useTriggerPipelineBuildMutation();
const [triggerBuildDeploy, buildDeployState] =
useTriggerPipelineBuildDeployMutation();

const state = pipelineName === 'build-deploy' ? buildDeployState : buildState;

const createJobState = isBuildDeployPipeline ? buildDeployState : buildState;
const [branch, setBranch] = useState('');
const [selectedBranch, setSelectedBranch] = useState('');
const [branchFullName, setBranchFullName] = useState('');
const [toEnvironment, setToEnvironment] = useState('');
const branches = useGetApplicationBranches(appName);
const branches = useGetApplicationBranches(application);
const [filteredBranches, setFilteredBranches] = useState([]);

const handleOnTextChange = ({
Expand Down Expand Up @@ -73,11 +71,11 @@ export function PipelineFormBuildBranches({
e.preventDefault();

const body = {
appName,
appName: application.name,
pipelineParametersBuild: { branch, toEnvironment },
};
let jobName: string;
if (pipelineName === 'build-deploy') {
if (isBuildDeployPipeline) {
jobName = (await triggerBuildDeploy(body).unwrap()).name;
} else {
jobName = (await triggerBuild(body).unwrap()).name;
Expand All @@ -94,17 +92,23 @@ export function PipelineFormBuildBranches({
};
return (
<form onSubmit={handleSubmit}>
<fieldset disabled={state.isLoading} className="grid grid--gap-medium">
<fieldset
disabled={createJobState.isLoading}
className="grid grid--gap-medium"
>
<div className="grid grid--gap-small input">
{children}
<Typography
className="input-label"
as="span"
group="navigation"
variant="label"
token={{ color: 'currentColor' }}
>
Build (but do not deploy) a git branch
{isBuildDeployPipeline ? (
<>Build and deploy a git branch</>
) : (
<>Build (but do not deploy) a git branch</>
)}
</Typography>
<Typography
group="input"
Expand All @@ -113,8 +117,15 @@ export function PipelineFormBuildBranches({
>
Git branch to build
</Typography>
<NativeSelect id="BranchSelect" label="" onChange={handleChange}>
<option value="">— Please select —</option>
<NativeSelect
value={branch}
id="BranchSelect"
label=""
onChange={handleChange}
>
<option hidden value="">
— Please select —
</option>
{Object.keys(branches ?? {}).map((branch, i) => (
<option key={i} value={branch}>
{branch}
Expand Down Expand Up @@ -170,25 +181,23 @@ export function PipelineFormBuildBranches({
</NativeSelect>
</div>
)}
{pipelineName === 'build-deploy' &&
branch &&
!isAnyValidRegex(branch) && (
<TargetEnvs
targetEnvs={toEnvironment ? [toEnvironment] : filteredBranches}
branch={branch}
/>
)}
{isBuildDeployPipeline && branch && !isAnyValidRegex(branch) && (
<TargetEnvs
targetEnvs={toEnvironment ? [toEnvironment] : filteredBranches}
branch={branch}
/>
)}
</div>

<div className="o-action-bar">
{state.isLoading && (
{createJobState.isLoading && (
<div>
<CircularProgress size={16} /> Creating…
</div>
)}
{state.isError && (
{createJobState.isError && (
<Alert type="danger">
Failed to create job. {getFetchErrorMessage(state.error)}
Failed to create job. {getFetchErrorMessage(createJobState.error)}
</Alert>
)}
<div>
Expand Down
22 changes: 7 additions & 15 deletions src/components/create-job-form/pipeline-form-deploy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,22 @@ import {
Typography,
} from '@equinor/eds-core-react';
import { type FormEvent, useState } from 'react';
import { pollingInterval } from '../../store/defaults';
import {
useGetEnvironmentSummaryQuery,
useTriggerPipelineDeployMutation,
} from '../../store/radix-api';
import { useTriggerPipelineDeployMutation } from '../../store/radix-api';

import { getFetchErrorMessage } from '../../store/utils';
import { Alert } from '../alert';
import { handlePromiseWithToast } from '../global-top-nav/styled-toaster';
import type { FormProp } from './index';

export function PipelineFormDeploy({ children, appName, onSuccess }: FormProp) {
export function PipelineFormDeploy({ application, onSuccess }: FormProp) {
const [trigger, state] = useTriggerPipelineDeployMutation();
const { data: environments } = useGetEnvironmentSummaryQuery(
{ appName },
{ pollingInterval }
);
const [toEnvironment, setToEnvironment] = useState('');

const handleSubmit = handlePromiseWithToast(
async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();

const response = await trigger({
appName,
appName: application.name,
pipelineParametersDeploy: {
toEnvironment,
},
Expand All @@ -45,7 +36,6 @@ export function PipelineFormDeploy({ children, appName, onSuccess }: FormProp) {
<form onSubmit={handleSubmit}>
<fieldset disabled={state.isLoading} className="grid grid--gap-medium">
<div className="grid grid--gap-small input">
{children}
<Typography
className="input-label"
as="span"
Expand All @@ -70,8 +60,10 @@ export function PipelineFormDeploy({ children, appName, onSuccess }: FormProp) {
onChange={(e) => setToEnvironment(e.target.value)}
value={toEnvironment}
>
<option value="">— Please select —</option>
{environments?.map(({ name }, i) => (
<option hidden value="">
— Please select —
</option>
{application.environments?.map(({ name }, i) => (
<option key={i} value={name}>
{name}
</option>
Expand Down
Loading

0 comments on commit 52ae2a6

Please sign in to comment.