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

Add-Create-Experiment-button-when-selecting-experiement-final #11332

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 98 additions & 69 deletions frontend/src/pages/NewRunV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ import {
convertExperimentToResource,
convertPipelineVersionToResource,
} from 'src/lib/ResourceConverter';
import AddIcon from '@material-ui/icons/Add';
import { ToolbarActionMap } from '../components/Toolbar';
import { NewExperimentFC } from './functional_components/NewExperimentFC';

const css = stylesheet({
nonEditableInput: {
Expand Down Expand Up @@ -182,6 +185,7 @@ function NewRunV2(props: NewRunV2Props) {
const [isStartingNewRun, setIsStartingNewRun] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
const [isParameterValid, setIsParameterValid] = useState(false);
const [openNewExperiment, setOpenNewExperiment] = useState(false);
const [isRecurringRun, setIsRecurringRun] = useState(
urlParser.get(QUERY_PARAMS.isRecurring) === '1' || cloneOrigin.isRecurring,
);
Expand Down Expand Up @@ -225,6 +229,18 @@ function NewRunV2(props: NewRunV2Props) {
? cloneOrigin.recurringRun?.pipeline_version_reference
: cloneOrigin.run?.pipeline_version_reference;

// Creat new experiment option
const createNewExperiment = {
action1: {
action: () => setOpenNewExperiment(true),
disabledTitle: 'create experiment to new run disabled title',
icon: AddIcon,
id: 'create experiment to new run id',
title: 'Create new experiment',
tooltip: 'Create new experiment',
},
};

// Title and list of actions on the top of page.
useEffect(() => {
props.updateToolbar({
Expand Down Expand Up @@ -531,6 +547,9 @@ function NewRunV2(props: NewRunV2Props) {
<div>This run will be associated with the following experiment</div>
<ExperimentSelector
{...props}
isOpenNewExperiment={openNewExperiment}
onCancelNewExperiment={() => setOpenNewExperiment(false)}
toolbarActionMap={createNewExperiment}
experimentName={experimentName}
handleExperimentChange={experiment => {
setExperiment(experiment);
Expand Down Expand Up @@ -890,6 +909,9 @@ interface ExperimentSelectorSpecificProps {
namespace?: string;
experimentName: string | undefined;
handleExperimentChange: (experiment: V2beta1Experiment) => void;
toolbarActionMap?: ToolbarActionMap;
isOpenNewExperiment: boolean;
onCancelNewExperiment: () => void;
}
type ExperimentSelectorProps = PageProps & ExperimentSelectorSpecificProps;

Expand Down Expand Up @@ -930,75 +952,82 @@ function ExperimentSelector(props: ExperimentSelectorProps) {
onClose={() => setExperimentSelectorOpen(false)}
PaperProps={{ id: 'experimentSelectorDialog' }}
>
<DialogContent>
<ResourceSelector
{...props}
title='Choose an experiment'
filterLabel='Filter experiments'
listApi={async (
page_token?: string,
page_size?: number,
sort_by?: string,
filter?: string,
) => {
// A new run can only be created in an unarchived experiment.
// Therefore, when listing experiments here for selection, we
// only list unarchived experiments.
const new_filter = JSON.parse(
decodeURIComponent(filter || '{"predicates": []}'),
) as V2beta1Filter;
new_filter.predicates = (new_filter.predicates || []).concat([
{
key: 'storage_state',
operation: V2beta1PredicateOperation.NOTEQUALS,
string_value: V2beta1ExperimentStorageState.ARCHIVED.toString(),
},
]);
const response = await Apis.experimentServiceApiV2.listExperiments(
page_token,
page_size,
sort_by,
encodeURIComponent(JSON.stringify(new_filter)),
props.namespace,
);
return {
nextPageToken: response.next_page_token || '',
resources: response.experiments?.map(e => convertExperimentToResource(e)) || [],
};
}}
columns={EXPERIMENT_SELECTOR_COLUMNS}
emptyMessage='No experiments found. Create an experiment and then try again.'
initialSortColumn={ExperimentSortKeys.CREATED_AT}
selectionChanged={async (selectedExperimentId: string) => {
const selectedExperiment = await Apis.experimentServiceApiV2.getExperiment(
selectedExperimentId,
);
setPendingExperiment(selectedExperiment);
}}
/>
</DialogContent>
<DialogActions>
<Button
id='cancelExperimentSelectionBtn'
onClick={() => setExperimentSelectorOpen(false)}
color='secondary'
>
Cancel
</Button>
<Button
id='useExperimentBtn'
onClick={() => {
if (pendingExperiment) {
props.handleExperimentChange(pendingExperiment);
}
setExperimentSelectorOpen(false);
}}
color='secondary'
disabled={!pendingExperiment}
>
Use this experiment
</Button>
</DialogActions>
{props.isOpenNewExperiment ? (
<NewExperimentFC onCancel={props.onCancelNewExperiment} {...props} />
) : (
<>
<DialogContent>
<ResourceSelector
{...props}
toolbarActionMap={props.toolbarActionMap}
title='Choose an experiment'
filterLabel='Filter experiments'
listApi={async (
page_token?: string,
page_size?: number,
sort_by?: string,
filter?: string,
) => {
// A new run can only be created in an unarchived experiment.
// Therefore, when listing experiments here for selection, we
// only list unarchived experiments.
const new_filter = JSON.parse(
decodeURIComponent(filter || '{"predicates": []}'),
) as V2beta1Filter;
new_filter.predicates = (new_filter.predicates || []).concat([
{
key: 'storage_state',
operation: V2beta1PredicateOperation.NOTEQUALS,
string_value: V2beta1ExperimentStorageState.ARCHIVED.toString(),
},
]);
const response = await Apis.experimentServiceApiV2.listExperiments(
page_token,
page_size,
sort_by,
encodeURIComponent(JSON.stringify(new_filter)),
props.namespace,
);
return {
nextPageToken: response.next_page_token || '',
resources: response.experiments?.map(e => convertExperimentToResource(e)) || [],
};
}}
columns={EXPERIMENT_SELECTOR_COLUMNS}
emptyMessage='No experiments found. Create an experiment and then try again.'
initialSortColumn={ExperimentSortKeys.CREATED_AT}
selectionChanged={async (selectedExperimentId: string) => {
const selectedExperiment = await Apis.experimentServiceApiV2.getExperiment(
selectedExperimentId,
);
setPendingExperiment(selectedExperiment);
}}
/>
</DialogContent>
<DialogActions>
<Button
id='cancelExperimentSelectionBtn'
onClick={() => setExperimentSelectorOpen(false)}
color='secondary'
>
Cancel
</Button>
<Button
id='useExperimentBtn'
onClick={() => {
if (pendingExperiment) {
props.handleExperimentChange(pendingExperiment);
}
setExperimentSelectorOpen(false);
}}
color='secondary'
disabled={!pendingExperiment}
>
Use this experiment
</Button>
</DialogActions>
</>
)}
</Dialog>
</>
);
Expand Down
9 changes: 5 additions & 4 deletions frontend/src/pages/functional_components/NewExperimentFC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const css = stylesheet({

interface ExperimentProps {
namespace?: string;
onCancel?: () => void;
}

type NewExperimentFCProps = ExperimentProps & PageProps;
Expand Down Expand Up @@ -136,6 +137,9 @@ export function NewExperimentFC(props: NewExperimentFCProps) {
});
};

const onCancel = () =>
props.onCancel ? props.onCancel() : props.history.push(RoutePage.EXPERIMENTS);

return (
<div className={classes(commonCss.page, padding(20, 'lr'))}>
<div className={classes(commonCss.scrollContainer, padding(20, 'lr'))}>
Expand Down Expand Up @@ -173,10 +177,7 @@ export function NewExperimentFC(props: NewExperimentFCProps) {
title={'Next'}
onClick={createExperiment}
/>
<Button
id='cancelNewExperimentBtn'
onClick={() => props.history.push(RoutePage.EXPERIMENTS)}
>
<Button id='cancelNewExperimentBtn' onClick={onCancel}>
Cancel
</Button>
<div className={css.errorMessage}>
Expand Down
Loading