Skip to content

Commit

Permalink
Merge pull request #1517 from uidoyen/odh-1242
Browse files Browse the repository at this point in the history
Fix Pipeline Job titles are partially handled
  • Loading branch information
openshift-merge-robot authored Sep 15, 2023
2 parents 0b0c94b + a464556 commit f88283c
Show file tree
Hide file tree
Showing 18 changed files with 416 additions and 92 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 @@ -9,6 +9,7 @@ import {
RunType,
RunTypeOption,
ScheduledType,
RunParam,
} from '~/concepts/pipelines/content/createRun/types';
import {
DateTimeKF,
Expand All @@ -18,6 +19,7 @@ import {
PipelineRunKF,
ResourceReferenceKF,
} from '~/concepts/pipelines/kfTypes';

import { getPipelineCoreResourcePipelineReference } from '~/concepts/pipelines/content/tables/utils';
import usePipelineById from '~/concepts/pipelines/apiHooks/usePipelineById';
import { UpdateObjectAtPropAndValue } from '~/pages/projects/types';
Expand All @@ -34,6 +36,9 @@ const isPipelineRunJob = (
runOrJob?: PipelineRunJobKF | PipelineRunKF,
): runOrJob is PipelineRunJobKF => !!(runOrJob as PipelineRunJobKF)?.trigger;

const isPipeline = (pipeline?: unknown): pipeline is PipelineKF =>
!!(pipeline as PipelineKF)?.default_version;

const useUpdateData = <T extends PipelineCoreResourceKF>(
setFunction: UpdateObjectAtPropAndValue<RunFormData>,
run: T | null = null,
Expand All @@ -45,6 +50,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 +61,37 @@ const useUpdateData = <T extends PipelineCoreResourceKF>(
}, [setData]);
};

const useUpdatePipelineRun = (
setFunction: UpdateObjectAtPropAndValue<RunFormData>,
initialData?: PipelineRunKF | PipelineRunJobKF,
) => {
const { getJobInformation } = usePipelinesAPI();
const { data: pipelineRunJob, loading } = getJobInformation(initialData);

const updatedSetFunction = React.useCallback<UpdateObjectAtPropAndValue<RunFormData>>(
(key, pipeline) => {
if (!loading && isPipeline(pipeline)) {
setFunction(key, pipeline);
setFunction('params', getParams(pipeline));
const nameDesc: ValueOf<RunFormData> = {
name: initialData?.name ? `Duplicate of ${initialData.name}` : '',
description: pipelineRunJob?.description ?? initialData?.description ?? '',
};
setFunction('nameDesc', nameDesc);
}
},
[setFunction, initialData, pipelineRunJob, loading],
);

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

const useUpdatePipeline = (
setFunction: UpdateObjectAtPropAndValue<RunFormData>,
initialData?: PipelineRunKF | PipelineRunJobKF,
Expand All @@ -72,13 +109,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 @@ -160,6 +200,11 @@ export const useUpdateRunType = (
}, [setFunction, initialData]);
};

const getParams = (pipeline?: PipelineKF): RunParam[] | undefined =>
pipeline
? (pipeline.parameters || []).map((p) => ({ label: p.name, value: p.value ?? '' }))
: undefined;

const useRunFormData = (
initialData?: PipelineRunKF | PipelineRunJobKF,
lastPipeline?: PipelineKF,
Expand All @@ -176,13 +221,11 @@ const useRunFormData = (
pipeline: lastPipeline ?? null,
// experiment: null,
runType: { type: RunTypeOption.ONE_TRIGGER },
params: lastPipeline
? (lastPipeline.parameters || []).map((p) => ({ label: p.name, value: p.value ?? '' }))
: undefined,
params: getParams(lastPipeline),
});

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

Expand Down
Loading

0 comments on commit f88283c

Please sign in to comment.