Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve gui for pipeline job creation #1141

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
12 changes: 3 additions & 9 deletions src/components/alert/dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ const testData: Array<ComponentType> = [
),
() => (
<Alert type="danger">
<Typography variant="h4">
That didn't work <image aria-label="Sad">😞</image>
</Typography>
<Typography variant="h4">That didn't work 😞</Typography>
<div>
The error message was <samp>error_msg</samp>
</div>
Expand All @@ -72,9 +70,7 @@ const testData: Array<ComponentType> = [
),
() => (
<Alert type="danger">
<Typography variant="h4">
That didn't work <image aria-label="Sad">😞</image>
</Typography>
<Typography variant="h4">That didn't work 😞</Typography>
<div>
Error subscribing to resource <code>some resource</code> with parameter{' '}
<code>some parameter</code>
Expand Down Expand Up @@ -118,9 +114,7 @@ const testData: Array<ComponentType> = [
),
() => (
<Alert type="danger">
<Typography variant="h4">
That didn't work <image aria-label="Sad">😞</image>
</Typography>
<Typography variant="h4">That didn't work 😞</Typography>
<div>
Error subscribing to resource <code>some_resource</code> with parameters{' '}
<code>some_parameter</code>, <code>some_other_parameter</code>,{' '}
Expand Down
23 changes: 4 additions & 19 deletions src/components/app-overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,7 @@ export function AppOverview({ appName }: { appName: string }) {
{ skip: !appName, pollingInterval }
);

const {
appAlias,
dnsAliases,
dnsExternalAliases,
environments,
jobs,
registration,
} = application ?? {};
const { appAlias, dnsAliases, dnsExternalAliases, jobs } = application ?? {};

return (
<main className="grid grid--gap-medium">
Expand Down Expand Up @@ -69,18 +62,10 @@ export function AppOverview({ appName }: { appName: string }) {
title={'DNS external aliases'}
/>
)}
{environments?.length > 0 && (
<span className="grid grid--gap-small">
<Typography variant="h4">Environments</Typography>
)}
<EnvironmentsSummary
appName={appName}
envs={environments}
repository={registration?.repository}
/>

{jobs?.length > 0 && (
<Typography variant="h4">Latest pipeline jobs</Typography>
)}
{application && <EnvironmentsSummary application={application} />}
</span>
<JobsList appName={appName} jobs={jobs} limit={LATEST_JOBS_LIMIT} />
</AsyncResource>
</main>
Expand Down
9 changes: 4 additions & 5 deletions src/components/async-resource/async-resource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ export default function AsyncResource({
}

if (
asyncState.isError &&
!nonErrorCodes?.includes(getFetchErrorCode(asyncState.error))
asyncState.isError ||
(asyncState.error &&
!nonErrorCodes?.includes(getFetchErrorCode(asyncState.error)))
) {
const { code, message } = getFetchErrorData(asyncState.error);

Expand All @@ -45,9 +46,7 @@ export default function AsyncResource({
content={errorContent}
defaultContent={
<Alert type="danger">
<Typography variant="h4">
That didn't work <image aria-label="Sad">😞</image>
</Typography>
<Typography variant="h4">That didn't work 😞</Typography>
<div className="grid grid--gap-small">
<div>
<Typography variant="caption">Error message:</Typography>
Expand Down
20 changes: 8 additions & 12 deletions src/components/component/dns-aliases.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export const DNSAliases: FunctionComponent<DefaultAppAliasProps> = ({
title,
}) => (
<>
{dnsAliases?.length > 0 &&
(dnsAliases.length == 1 ? (
<div className="grid grid--gap-x-small">
<Typography variant="h4">{title}</Typography>
{dnsAliases?.length > 0 && (
<div className="grid grid--gap-small">
<Typography variant="h4">{title}</Typography>
{dnsAliases.length == 1 ? (
<Typography as="span">
<DNSAlias
appName={appName}
Expand All @@ -29,12 +29,7 @@ export const DNSAliases: FunctionComponent<DefaultAppAliasProps> = ({
environmentName={dnsAliases[0].environmentName}
/>
</Typography>
</div>
) : (
<>
<Typography className="whitespace-nowrap" variant="h4" as="span">
{title}
</Typography>
) : (
<Accordion className="accordion elevated" chevronPosition="right">
<Accordion.Item isExpanded={false}>
<Accordion.Header>
Expand All @@ -60,7 +55,8 @@ export const DNSAliases: FunctionComponent<DefaultAppAliasProps> = ({
</Accordion.Panel>
</Accordion.Item>
</Accordion>
</>
))}
)}
</div>
)}
</>
);
75 changes: 53 additions & 22 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,46 @@ 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 = application?.environments?.length;
const buildBranches = useGetApplicationBranches(application);
const hasBuildBranches = Object.keys(buildBranches).length > 0;
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,9 +96,9 @@ 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="">
<option hidden value="">
— Please select —
</option>
{Object.keys(Pipelines).map((pipeline) => (
Expand All @@ -83,7 +107,14 @@ export default function CreateJobForm({
</option>
))}
</NativeSelect>
</PipelineForm>
{PipelineForm && (
<PipelineForm
onSuccess={onSuccess}
application={application}
pipelineName={pipeline}
/>
)}
</AsyncResource>
);
}
CreateJobForm.propTypes = {
Expand Down
27 changes: 27 additions & 0 deletions src/components/create-job-form/missing-radix-config-alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Icon, Typography } from '@equinor/eds-core-react';
import { info_circle } from '@equinor/eds-icons';
import type { Application } from '../../store/radix-api';
import { Alert } from '../alert';
import { NewApplyConfigPipelineLink } from '../link/apply-config-pipeline-link';
import { RadixConfigFileLink } from '../link/radix-config-file-link';

type Props = { application: Application };

export const MissingRadixConfigAlert = ({ application }: Props) => (
<Alert className="icon">
<Icon data={info_circle} color="primary" />
<span className="grid grid--gap-small">
<Typography>
The <RadixConfigFileLink registration={application?.registration} />{' '}
file must be read by Radix before using this pipeline job.
</Typography>
<Typography>
Run the{' '}
<NewApplyConfigPipelineLink appName={application.name}>
apply-config
</NewApplyConfigPipelineLink>{' '}
pipeline job to read the file from the application's GitHub repository.
</Typography>
</span>
</Alert>
);
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
Loading