Skip to content

Commit

Permalink
Fix Pipeline Job titles are partially handled
Browse files Browse the repository at this point in the history
  • Loading branch information
uidoyen committed Sep 14, 2023
1 parent 0b0c94b commit cf7548e
Show file tree
Hide file tree
Showing 18 changed files with 410 additions and 89 deletions.
6 changes: 6 additions & 0 deletions frontend/src/components/table/TableRowTitleDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ import ResourceNameTooltip from '~/components/ResourceNameTooltip';
type TableRowTitleDescriptionProps = {
title: React.ReactNode;
resource?: K8sResourceCommon;
subtitle?: React.ReactNode;
description?: string;
descriptionAsMarkdown?: boolean;
label?: React.ReactNode;
};

const TableRowTitleDescription: React.FC<TableRowTitleDescriptionProps> = ({
title,
description,
resource,
subtitle,
descriptionAsMarkdown,
label,
}) => {
let descriptionNode: React.ReactNode;
if (description) {
Expand All @@ -31,7 +35,9 @@ const TableRowTitleDescription: React.FC<TableRowTitleDescriptionProps> = ({
<Title headingLevel="h3" size="md">
{resource ? <ResourceNameTooltip resource={resource}>{title}</ResourceNameTooltip> : title}
</Title>
{subtitle && <Text>{subtitle}</Text>}
{descriptionNode}
{label}
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import * as React from 'react';
import { Icon, List, ListItem, Stack, StackItem, Text, Tooltip } from '@patternfly/react-core';
import {
Icon,
List,
ListItem,
Stack,
StackItem,
TextContent,
Text,
TextVariants,
Tooltip,
ExpandableSection,
Badge,
} from '@patternfly/react-core';
import { CheckCircleIcon, ExclamationCircleIcon, PendingIcon } from '@patternfly/react-icons';
import DeleteModal from '~/pages/projects/components/DeleteModal';
import { usePipelinesAPI } from '~/concepts/pipelines/context';
import { PipelineCoreResourceKF } from '~/concepts/pipelines/kfTypes';
import { K8sAPIOptions } from '~/k8sTypes';
import useNotification from '~/utilities/useNotification';
import { PipelineType } from '~/concepts/pipelines/content/tables/utils';
import PipelineJobReferenceName from './PipelineJobReferenceName';
import PipelineRunTypeLabel from './PipelineRunTypeLabel';

type DeletePipelineCoreResourceModalProps = {
type: 'triggered run' | 'scheduled run' | 'pipeline';
Expand All @@ -24,7 +39,7 @@ const DeletePipelineCoreResourceModal: React.FC<DeletePipelineCoreResourceModalP
const [deleteStatuses, setDeleteStatus] = React.useState<(true | Error | undefined)[]>([]);
const abortControllerRef = React.useRef(new AbortController());
const notification = useNotification();

const [isExpanded, setIsExpanded] = React.useState(true);
const resourceCount = toDeleteResources.length;

const onBeforeCloseRef = React.useRef<(v: boolean) => void>(() => undefined);
Expand Down Expand Up @@ -54,10 +69,14 @@ const DeletePipelineCoreResourceModal: React.FC<DeletePipelineCoreResourceModalP
setDeleteStatus([]);
abortControllerRef.current = new AbortController();
};

const onToggle = (isExpanded: boolean) => {
setIsExpanded(isExpanded);
};
return (
<DeleteModal
title={`Delete ${type}${resourceCount > 1 ? 's' : ''}`}
title={`Delete ${resourceCount > 1 ? resourceCount : ''} ${type}${
resourceCount > 1 ? 's' : ''
}?`}
isOpen={resourceCount !== 0}
onClose={() => onBeforeCloseRef.current(false)}
deleting={deleting}
Expand Down Expand Up @@ -118,7 +137,7 @@ const DeletePipelineCoreResourceModal: React.FC<DeletePipelineCoreResourceModalP
});
}
}}
submitButtonLabel={`Delete ${type}${resourceCount > 1 ? 's' : ''}`}
submitButtonLabel="Delete"
deleteName={
resourceCount === 1 ? toDeleteResources[0].name : `Delete ${resourceCount} ${type}s`
}
Expand All @@ -133,39 +152,61 @@ const DeletePipelineCoreResourceModal: React.FC<DeletePipelineCoreResourceModalP
</Text>
</StackItem>
<StackItem>
<List>
{toDeleteResources.map((resource, i) => {
let icon: React.ReactNode;
if (!deleting) {
icon = null;
} else {
const state = deleteStatuses[i];
if (state === undefined) {
icon = <PendingIcon />;
} else if (state === true) {
icon = (
<Icon status="success">
<CheckCircleIcon />
</Icon>
);
<ExpandableSection
toggleContent={
<>
<span>Selected {resourceCount > 1 ? 'runs' : 'run'}</span>
{resourceCount > 0 && <Badge isRead={true}>{resourceCount}</Badge>}
</>
}
onToggle={onToggle}
isExpanded={isExpanded}
>
<List>
{toDeleteResources.map((resource, i) => {
let icon: React.ReactNode;
if (!deleting) {
icon = null;
} else {
icon = (
<Tooltip content={state.message}>
<Icon status="danger">
<ExclamationCircleIcon />
const state = deleteStatuses[i];
if (state === undefined) {
icon = <PendingIcon />;
} else if (state === true) {
icon = (
<Icon status="success">
<CheckCircleIcon />
</Icon>
</Tooltip>
);
);
} else {
icon = (
<Tooltip content={state.message}>
<Icon status="danger">
<ExclamationCircleIcon />
</Icon>
</Tooltip>
);
}
}
}

return (
<ListItem key={resource.id} icon={icon}>
{resource.name}
</ListItem>
);
})}
</List>
return (
<ListItem key={resource.id} icon={icon}>
<TextContent>
<Text component={TextVariants.h6}>
{resource.name}{' '}
{type === PipelineType.TRIGGERED_RUN && (
<PipelineRunTypeLabel resource={resource} />
)}
</Text>

{type === PipelineType.TRIGGERED_RUN && (
<PipelineJobReferenceName resource={resource} />
)}
</TextContent>
</ListItem>
);
})}
</List>
</ExpandableSection>
</StackItem>
</Stack>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { Text, TextVariants } from '@patternfly/react-core';
import { getPipelineJobExecutionCount } from '~/concepts/pipelines/content/tables/utils';
import { PipelineCoreResourceKF } from '~/concepts/pipelines/kfTypes';
import { usePipelinesAPI } from '~/concepts/pipelines/context';

type PipelineJobReferenceNameProps = {
resource: PipelineCoreResourceKF;
};

const PipelineJobReferenceName: React.FC<PipelineJobReferenceNameProps> = ({ resource }) => {
const { getJobInformation } = usePipelinesAPI();
const { data, loading } = getJobInformation(resource);

return (
<>
{loading ? (
'loading...'
) : data ? (
<Text component={TextVariants.p} className="pf-u-pb-sm">
Run {getPipelineJobExecutionCount(resource.name)} of {data?.name}
</Text>
) : (
''
)}
</>
);
};
export default PipelineJobReferenceName;
41 changes: 41 additions & 0 deletions frontend/src/concepts/pipelines/content/PipelineRunTypeLabel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { Label, Tooltip } from '@patternfly/react-core';
import {
PipelineRunLabels,
getPipelineCoreResourceJobReference,
getPipelineCoreResourcePipelineReference,
} from '~/concepts/pipelines/content/tables/utils';
import { PipelineCoreResourceKF } from '~/concepts/pipelines/kfTypes';

type PipelineRunTypeLabelProps = {
resource: PipelineCoreResourceKF;
};
const PipelineRunTypeLabel: React.FC<PipelineRunTypeLabelProps> = ({ resource }) => {
const jobReference = getPipelineCoreResourceJobReference(resource);
const pipelineReference = getPipelineCoreResourcePipelineReference(resource);

return (
<>
{jobReference ? (
<>
<Tooltip content={'Created by a scheduled run'}>
<Label color="blue">{PipelineRunLabels.RECURRING}</Label>
</Tooltip>
</>
) : !pipelineReference ? (
<>
<Tooltip content={<div>Created by a scheduled run that was deleted</div>}>
<Label color="blue">{PipelineRunLabels.RECURRING}</Label>
</Tooltip>
</>
) : (
<>
<Tooltip content={<div>Run once immediately after creation</div>}>
<Label color="blue">{PipelineRunLabels.ONEOFF}</Label>
</Tooltip>
</>
)}
</>
);
};
export default PipelineRunTypeLabel;
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ import {
PipelineRunKF,
ResourceReferenceKF,
} from '~/concepts/pipelines/kfTypes';
import { getPipelineCoreResourcePipelineReference } from '~/concepts/pipelines/content/tables/utils';
import {
getPipelineCoreResourcePipelineReference,
getPipelineCoreResourceJobReference,
} from '~/concepts/pipelines/content/tables/utils';
import usePipelineById from '~/concepts/pipelines/apiHooks/usePipelineById';
import usePipelineRunJobById from '~/concepts/pipelines/apiHooks/usePipelineRunJobById';
import { UpdateObjectAtPropAndValue } from '~/pages/projects/types';
import { FetchState } from '~/utilities/useFetchState';
import { ValueOf } from '~/typeHelpers';
Expand All @@ -45,6 +49,7 @@ const useUpdateData = <T extends PipelineCoreResourceKF>(
const [resource, loaded] = useFetchHookFnc(reference?.key.id);
const resourceRef = React.useRef<ValueOf<RunFormData>>(resource);
resourceRef.current = resource;

const setData = React.useCallback(() => {
if (loaded && resourceRef.current) {
setFunction(fieldId, resourceRef.current);
Expand All @@ -55,6 +60,33 @@ const useUpdateData = <T extends PipelineCoreResourceKF>(
}, [setData]);
};

const useUpdatePipelineRun = (
setFunction: UpdateObjectAtPropAndValue<RunFormData>,
initialData?: PipelineRunKF | PipelineRunJobKF,
) => {
const reference = getPipelineCoreResourceJobReference(initialData);
const [pipelineRunJob] = usePipelineRunJobById(reference?.key.id);
const updatedSetFunction = React.useCallback<UpdateObjectAtPropAndValue<RunFormData>>(
(key, resource) => {
setFunction(key, resource);
const nameDesc: ValueOf<RunFormData> = {
name: initialData?.name ? `Duplicate of ${initialData.name}` : '',
description: pipelineRunJob?.description ?? initialData?.description ?? '',
};
setFunction('nameDesc', nameDesc);
},
[setFunction, initialData, pipelineRunJob],
);

return useUpdateData(
updatedSetFunction,
pipelineRunJob,
'pipeline',
getPipelineCoreResourcePipelineReference,
usePipelineById,
);
};

const useUpdatePipeline = (
setFunction: UpdateObjectAtPropAndValue<RunFormData>,
initialData?: PipelineRunKF | PipelineRunJobKF,
Expand All @@ -72,13 +104,16 @@ const useUpdatePipeline = (
},
[setFunction, initialData?.pipeline_spec.parameters],
);
return useUpdateData(

const updatedData = useUpdateData(
updatedSetFunction,
initialData,
'pipeline',
getPipelineCoreResourcePipelineReference,
usePipelineById,
);

return updatedData;
};

// const useUpdateExperiment = (
Expand Down Expand Up @@ -180,9 +215,9 @@ const useRunFormData = (
? (lastPipeline.parameters || []).map((p) => ({ label: p.name, value: p.value ?? '' }))
: undefined,
});

const setFunction = objState[1];
useUpdatePipeline(setFunction, initialData);
useUpdatePipelineRun(setFunction, initialData);
// useUpdateExperiment(setFunction, initialData);
useUpdateRunType(setFunction, initialData);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { Label, Split, SplitItem } from '@patternfly/react-core';
import { PipelineRunKF } from '~/concepts/pipelines/kfTypes';
import { computeRunStatus } from '~/concepts/pipelines/content/utils';
import PipelineRunTypeLabel from '~/concepts/pipelines/content/PipelineRunTypeLabel';

type RunJobTitleProps = {
run: PipelineRunKF;
statusIcon?: boolean;
hasJobReference?: boolean;
pipelineRunLabel?: boolean;
};

const PipelineDetailsTitle: React.FC<RunJobTitleProps> = ({
run,
statusIcon,
pipelineRunLabel,
}) => {
const { icon, label } = computeRunStatus(run);

return (
<>
<Split hasGutter>
<SplitItem>{run.name}</SplitItem>
{pipelineRunLabel && (
<SplitItem>
<PipelineRunTypeLabel resource={run} />
</SplitItem>
)}
{statusIcon && (
<SplitItem>
<Label icon={icon}>{label}</Label>
</SplitItem>
)}
</Split>
</>
);
};
export default PipelineDetailsTitle;
Loading

0 comments on commit cf7548e

Please sign in to comment.