Skip to content

Commit

Permalink
Refine logic actions for runs on an archived experiment page
Browse files Browse the repository at this point in the history
  • Loading branch information
DaoDaoNoCode committed Jun 3, 2024
1 parent 3bee930 commit ce61bac
Show file tree
Hide file tree
Showing 27 changed files with 421 additions and 174 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ import {
buildMockPipelines,
mockProjectK8sResource,
mockRouteK8sResource,
buildMockRunKF,
buildMockJobKF,
} from '~/__mocks__';
import {
archivedRunsTable,
archiveExperimentModal,
bulkArchiveExperimentModal,
bulkRestoreExperimentModal,
pipelineRunJobTable,
pipelineRunsGlobal,
restoreExperimentModal,
} from '~/__tests__/cypress/cypress/pages/pipelines';
Expand All @@ -23,6 +27,7 @@ import {
ProjectModel,
RouteModel,
} from '~/__tests__/cypress/cypress/utils/models';
import { RecurringRunStatus, StorageStateKF } from '~/concepts/pipelines/kfTypes';

const projectName = 'test-project-name';
const initialMockPipeline = buildMockPipelineV2({ display_name: 'Test pipeline' });
Expand Down Expand Up @@ -199,7 +204,7 @@ describe('Experiments', () => {
});
});

describe('Runs page', () => {
describe('Runs page for active experiment', () => {
const activeExperimentsTable = experimentsTabs.getActiveExperimentsTable();
const [mockExperiment] = mockExperiments;

Expand Down Expand Up @@ -240,6 +245,67 @@ describe('Experiments', () => {
});
});

describe('Runs page for archived experiment', () => {
const archivedExperimentsTable = experimentsTabs.getArchivedExperimentsTable();
const mockExperiment = { ...mockExperiments[0], storage_state: StorageStateKF.ARCHIVED };

beforeEach(() => {
initIntercepts();
cy.interceptOdh(
'GET /api/service/pipelines/:namespace/:serviceName/apis/v2beta1/experiments/:experimentId',
{
path: {
namespace: projectName,
serviceName: 'dspa',
experimentId: mockExperiment.experiment_id,
},
},
mockExperiment,
);
cy.interceptOdh(
'GET /api/service/pipelines/:namespace/:serviceName/apis/v2beta1/runs',
{
path: { namespace: projectName, serviceName: 'dspa' },
},
{ runs: [buildMockRunKF({ storage_state: StorageStateKF.ARCHIVED })] },
);

cy.interceptOdh(
'GET /api/service/pipelines/:namespace/:serviceName/apis/v2beta1/recurringruns',
{
path: { namespace: projectName, serviceName: 'dspa' },
},
{ recurringRuns: [buildMockJobKF({ status: RecurringRunStatus.DISABLED })] },
);
experimentsTabs.mockGetExperiments(projectName, [], mockExperiments);
experimentsTabs.visit(projectName);
experimentsTabs.findArchivedTab().click();
archivedExperimentsTable.getRowByName(mockExperiment.display_name).find().find('a').click();
});

it('navigates to the runs page when clicking an experiment name', () => {
verifyRelativeURL(`/experiments/${projectName}/${mockExperiment.experiment_id}/runs`);
cy.findByLabelText('Breadcrumb').findByText('Experiments');
});

it('has empty state on active runs tab', () => {
pipelineRunsGlobal.findActiveRunsTab().click();
cy.findByTestId('experiment-archived-empty-state').should('be.visible');
});

it('has restore button disabled on archived runs tab', () => {
pipelineRunsGlobal.findArchivedRunsTab().click();
archivedRunsTable.getRowByName('Test run').findCheckbox().click();
pipelineRunsGlobal.findRestoreRunButton().should('have.class', 'pf-m-aria-disabled');
});

it('has create schedule button disabled on schedules tab', () => {
pipelineRunsGlobal.findSchedulesTab().click();
pipelineRunJobTable.getRowByName('Test job').findCheckbox().click();
pipelineRunsGlobal.findScheduleRunButton().should('have.class', 'pf-m-aria-disabled');
});
});

const initIntercepts = () => {
cy.interceptOdh('GET /api/config', mockDashboardConfig({ disablePipelineExperiments: false }));
cy.interceptK8sList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -959,7 +959,7 @@ describe('Pipelines', () => {
pipelineRow.findExpandButton().click();
pipelineRow
.getPipelineVersionRowById(initialMockPipelineVersion.pipeline_version_id)
.findKebabAction('Schedule run')
.findKebabAction('Create schedule')
.click();

verifyRelativeURL(`/pipelines/${projectName}/pipelineRun/create?runType=scheduled`);
Expand Down Expand Up @@ -1176,7 +1176,7 @@ export const runScheduleRunPageNavTest = (visitPipelineProjects: () => void): vo
pipelinesTable.find();
pipelinesTable
.getRowById(initialMockPipeline.pipeline_id)
.findKebabAction('Schedule run')
.findKebabAction('Create schedule')
.click();

verifyRelativeURL(`/pipelines/${projectName}/pipelineRun/create?runType=scheduled`);
Expand All @@ -1196,10 +1196,10 @@ export const viewPipelineServerDetailsTest = (visitPipelineProjects: () => void)
}),
);
visitPipelineProjects();
viewPipelinelineDetails();
viewPipelineDetails();
};

const viewPipelinelineDetails = (
const viewPipelineDetails = (
accessKey = 'sdsd',
secretKey = 'sdsd',
endpoint = 'https://s3.amazonaws.com',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ describe('Pipeline topology', () => {
});

it('navigates to "Schedule run" page on "Schedule run" click', () => {
pipelineDetails.selectActionDropdownItem('Schedule run');
pipelineDetails.selectActionDropdownItem('Create schedule');
verifyRelativeURL(`/pipelineRuns/${projectId}/pipelineRun/create?runType=scheduled`);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const RunForm: React.FC<RunFormProps> = ({ data, runType, onValueChange }) => {
projectName={getProjectDisplayName(data.project)}
value={data.experiment}
onChange={(experiment) => onValueChange('experiment', experiment)}
isSchedule={isSchedule}
/>

<FormSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,25 @@ import {
CreateRunPageSections,
runPageSectionTitles,
} from '~/concepts/pipelines/content/createRun/const';
import ExperimentSelector from '~/concepts/pipelines/content/experiment/ExperimentSelector';
import {
ActiveExperimentSelector,
AllExperimentSelector,
} from '~/concepts/pipelines/content/experiment/ExperimentSelector';
import CreateExperimentButton from '~/concepts/pipelines/content/experiment/CreateExperimentButton';
import { SupportedArea, useIsAreaAvailable } from '~/concepts/areas';

type ExperimentSectionProps = {
type ProjectAndExperimentSectionProps = {
projectName: string;
value: ExperimentKFv2 | null;
onChange: (experiment: ExperimentKFv2) => void;
isSchedule: boolean;
};

const ProjectAndExperimentSection: React.FC<ExperimentSectionProps> = ({
const ProjectAndExperimentSection: React.FC<ProjectAndExperimentSectionProps> = ({
projectName,
value,
onChange,
isSchedule,
}) => {
const isExperimentsAvailable = useIsAreaAvailable(SupportedArea.PIPELINE_EXPERIMENTS).status;

Expand All @@ -39,7 +44,11 @@ const ProjectAndExperimentSection: React.FC<ExperimentSectionProps> = ({
<FormGroup label="Experiment" aria-label="Experiment" isRequired>
<Stack hasGutter>
<StackItem>
<ExperimentSelector selection={value?.display_name} onSelect={onChange} />
{isSchedule ? (
<AllExperimentSelector selection={value?.display_name} onSelect={onChange} />
) : (
<ActiveExperimentSelector selection={value?.display_name} onSelect={onChange} />
)}
</StackItem>
<StackItem>
<CreateExperimentButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
PipelineVersionKFv2,
RecurringRunMode,
RuntimeConfigParameters,
StorageStateKF,
} from '~/concepts/pipelines/kfTypes';
import { PipelineAPIs } from '~/concepts/pipelines/types';
import {
Expand Down Expand Up @@ -97,7 +98,10 @@ const createJob = async (
: undefined,
},
max_concurrency: String(formData.runType.data.maxConcurrency),
mode: RecurringRunMode.ENABLE,
mode:
formData.experiment?.storage_state === StorageStateKF.ARCHIVED
? RecurringRunMode.DISABLE
: RecurringRunMode.ENABLE,
no_catchup: !formData.runType.data.catchUp,
service_account: '',
experiment_id: formData.experiment?.experiment_id || '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
PipelineRunJobKFv2,
PipelineRunKFv2,
PipelineVersionKFv2,
StorageStateKF,
} from '~/concepts/pipelines/kfTypes';

import { UpdateObjectAtPropAndValue } from '~/pages/projects/types';
Expand Down Expand Up @@ -98,10 +99,25 @@ const useUpdateExperimentFormData = (
const [formData, setFormValue] = formState;

React.useEffect(() => {
if (!formData.experiment && experiment) {
// on create run page, we always check the experiment archived state
// no matter it's duplicated or carried from the create schedules pages
if (formData.runType.type === RunTypeOption.ONE_TRIGGER) {
if (formData.experiment) {
if (formData.experiment.storage_state === StorageStateKF.ARCHIVED) {
setFormValue('experiment', null);
}
} else if (experiment) {
if (experiment.storage_state === StorageStateKF.ARCHIVED) {
setFormValue('experiment', null);
} else {
setFormValue('experiment', experiment);
}
}
} else if (!formData.experiment && experiment) {
// else, on create schedules page, we do what we did before
setFormValue('experiment', experiment);
}
}, [formData.experiment, setFormValue, experiment]);
}, [formData.experiment, setFormValue, experiment, formData.runType.type]);
};

const useUpdatePipelineFormData = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,34 @@ import { TableBase, getTableColumnSort } from '~/components/table';
import { ExperimentKFv2 } from '~/concepts/pipelines/kfTypes';
import PipelineViewMoreFooterRow from '~/concepts/pipelines/content/tables/PipelineViewMoreFooterRow';
import DashboardEmptyTableView from '~/concepts/dashboard/DashboardEmptyTableView';
import { useExperimentSelector } from '~/concepts/pipelines/content/pipelineSelector/useCreateSelectors';
import {
useActiveExperimentSelector,
useAllExperimentSelector,
} from '~/concepts/pipelines/content/pipelineSelector/useCreateSelectors';
import { experimentSelectorColumns } from '~/concepts/pipelines/content/experiment/columns';

type ExperimentSelectorProps = {
selection?: string;
onSelect: (experiment: ExperimentKFv2) => void;
};

const ExperimentSelector: React.FC<ExperimentSelectorProps> = ({ selection, onSelect }) => {
const InnerExperimentSelector: React.FC<
ReturnType<typeof useAllExperimentSelector> & ExperimentSelectorProps
> = ({
fetchedSize,
totalSize,
searchProps,
onSearchClear,
onLoadMore,
sortProps,
loaded,
initialLoaded,
data: experiments,
selection,
onSelect,
}) => {
const [isOpen, setOpen] = React.useState(false);

const {
fetchedSize,
totalSize,
searchProps,
onSearchClear,
onLoadMore,
sortProps,
loaded,
initialLoaded,
data: experiments,
} = useExperimentSelector();

const toggleRef = React.useRef(null);
const menuRef = React.useRef(null);

Expand Down Expand Up @@ -140,4 +145,12 @@ const ExperimentSelector: React.FC<ExperimentSelectorProps> = ({ selection, onSe
);
};

export default ExperimentSelector;
export const AllExperimentSelector: React.FC<ExperimentSelectorProps> = (props) => {
const selectorProps = useAllExperimentSelector();
return <InnerExperimentSelector {...props} {...selectorProps} />;
};

export const ActiveExperimentSelector: React.FC<ExperimentSelectorProps> = (props) => {
const selectorProps = useActiveExperimentSelector();
return <InnerExperimentSelector {...props} {...selectorProps} />;
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as React from 'react';
import { useSelectorSearch } from '~/concepts/pipelines/content/pipelineSelector/utils';
import useExperimentTable from '~/concepts/pipelines/content/tables/experiment/useExperimentTable';
import useExperimentTable, {
useActiveExperimentTable,
} from '~/concepts/pipelines/content/tables/experiment/useExperimentTable';
import usePipelinesTable from '~/concepts/pipelines/content/tables/pipeline/usePipelinesTable';
import usePipelineVersionsTable from '~/concepts/pipelines/content/tables/pipelineVersion/usePipelineVersionsTable';
import {
Expand Down Expand Up @@ -38,14 +40,19 @@ type UsePipelineSelectorData<DataType> = {
};
};

export const useExperimentSelector = (): UsePipelineSelectorData<ExperimentKFv2> => {
const experimentsTable = useExperimentTable();
const [[{ items: initialData, nextPageToken: initialPageToken }, loaded]] = experimentsTable;
return useCreateSelector<ExperimentKFv2>(
experimentsTable,
useExperimentLoadMore({ initialData, initialPageToken, loaded }),
);
};
export const getExperimentSelector =
(useTable: typeof useExperimentTable) => (): UsePipelineSelectorData<ExperimentKFv2> => {
const experimentsTable = useTable();
const [[{ items: initialData, nextPageToken: initialPageToken }, loaded]] = experimentsTable;
return useCreateSelector<ExperimentKFv2>(
experimentsTable,
useExperimentLoadMore({ initialData, initialPageToken, loaded }),
);
};

export const useAllExperimentSelector = getExperimentSelector(useExperimentTable);

export const useActiveExperimentSelector = getExperimentSelector(useActiveExperimentTable);

export const usePipelineSelector = (): UsePipelineSelectorData<PipelineKFv2> => {
const pipelinesTable = usePipelinesTable();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const PipelineDetailsActions: React.FC<PipelineDetailsActionsProps> = ({
)
}
>
Schedule run
Create schedule
</DropdownItem>,
<DropdownSeparator key="separator-view" />,
<DropdownItem
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import useExperiments from '~/concepts/pipelines/apiHooks/useExperiments';
import useExperiments, { useActiveExperiments } from '~/concepts/pipelines/apiHooks/useExperiments';
import createUsePipelineTable from '~/concepts/pipelines/content/tables/usePipelineTable';

export const useActiveExperimentTable = createUsePipelineTable(useActiveExperiments);

export default createUsePipelineTable(useExperiments);
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ const PipelinesTableRow: React.FC<PipelinesTableRowProps> = ({
},
},
{
title: 'Schedule run',
title: 'Create schedule',
onClick: () => {
navigate(
{
Expand Down
Loading

0 comments on commit ce61bac

Please sign in to comment.