Skip to content

Commit 64fb41f

Browse files
author
Daniel Duong
committed
feat(automl/configure, autorag/configure): empty state when no s3 conn
1 parent 9762fa8 commit 64fb41f

2 files changed

Lines changed: 272 additions & 235 deletions

File tree

packages/automl/frontend/src/app/components/configure/AutomlConfigure.tsx

Lines changed: 122 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
CardHeader,
1414
CardTitle,
1515
Content,
16+
EmptyState,
17+
EmptyStateBody,
1618
FormHelperText,
1719
Gallery,
1820
Grid,
@@ -25,6 +27,7 @@ import {
2527
Stack,
2628
StackItem,
2729
} from '@patternfly/react-core';
30+
import { CubesIcon } from '@patternfly/react-icons';
2831
import { useQueryClient } from '@tanstack/react-query';
2932
import { findKey } from 'es-toolkit';
3033
import React, { useEffect, useRef, useState } from 'react';
@@ -321,114 +324,128 @@ function AutomlConfigure(): React.JSX.Element {
321324
<Content component="h3">Configure details</Content>
322325
</CardHeader>
323326
<CardBody>
324-
<Stack hasGutter style={{ gap: 'var(--pf-t--global--spacer--xl)' }}>
325-
<StackItem>
326-
<ConfigureFormGroup label="Prediction type" isRequired>
327-
<Controller
328-
control={form.control}
329-
name="task_type"
330-
render={({ field }) => (
331-
<Gallery hasGutter minWidths={{ default: '200px' }}>
332-
{PREDICTION_TYPES.map((type) => (
333-
<Card
334-
key={type.value}
335-
isSelectable
336-
isDisabled={!canSelectLearningType}
337-
isSelected={field.value === type.value}
338-
onClick={() => field.onChange(type.value)}
339-
data-testid={`task-type-card-${type.value}`}
340-
>
341-
<CardHeader
342-
selectableActions={{
343-
selectableActionId: `task-type-${type.value}`,
344-
selectableActionAriaLabelledby: `task-type-label-${type.value}`,
345-
name: 'task_type',
346-
variant: 'single',
347-
isChecked: field.value === type.value,
348-
onChange: () => field.onChange(type.value),
349-
isHidden: true,
350-
}}
327+
{!selectedSecret ? (
328+
<EmptyState
329+
variant="xs"
330+
titleText="Select an S3 connection or upload a file to get started"
331+
headingLevel="h4"
332+
icon={CubesIcon}
333+
>
334+
<EmptyStateBody>
335+
In order to configure details and run an experiment, add a document or
336+
connection in the widget on the left.
337+
</EmptyStateBody>
338+
</EmptyState>
339+
) : (
340+
<Stack hasGutter style={{ gap: 'var(--pf-t--global--spacer--xl)' }}>
341+
<StackItem>
342+
<ConfigureFormGroup label="Prediction type" isRequired>
343+
<Controller
344+
control={form.control}
345+
name="task_type"
346+
render={({ field }) => (
347+
<Gallery hasGutter minWidths={{ default: '200px' }}>
348+
{PREDICTION_TYPES.map((type) => (
349+
<Card
350+
key={type.value}
351+
isSelectable
352+
isDisabled={!canSelectLearningType}
353+
isSelected={field.value === type.value}
354+
onClick={() => field.onChange(type.value)}
355+
data-testid={`task-type-card-${type.value}`}
351356
>
352-
<CardTitle id={`task-type-label-${type.value}`}>
353-
{type.label}
354-
</CardTitle>
355-
</CardHeader>
356-
<CardBody>
357-
<Content component="small">{type.description}</Content>
358-
</CardBody>
359-
</Card>
360-
))}
361-
</Gallery>
362-
)}
363-
/>
364-
</ConfigureFormGroup>
365-
</StackItem>
366-
367-
{isTimeseries ? (
368-
<ConfigureTimeseriesForm
369-
columns={columns}
370-
isLoadingColumns={isLoadingColumns}
371-
isFetchingColumns={isFetchingColumns}
372-
columnsError={columnsError}
373-
isFileSelected={isFileSelected}
374-
formIsSubmitting={formIsSubmitting}
375-
/>
376-
) : (
377-
<ConfigureTabularForm
378-
columns={columns}
379-
isLoadingColumns={isLoadingColumns}
380-
isFetchingColumns={isFetchingColumns}
381-
columnsError={columnsError}
382-
isFileSelected={isFileSelected}
383-
formIsSubmitting={formIsSubmitting}
384-
/>
385-
)}
357+
<CardHeader
358+
selectableActions={{
359+
selectableActionId: `task-type-${type.value}`,
360+
selectableActionAriaLabelledby: `task-type-label-${type.value}`,
361+
name: 'task_type',
362+
variant: 'single',
363+
isChecked: field.value === type.value,
364+
onChange: () => field.onChange(type.value),
365+
isHidden: true,
366+
}}
367+
>
368+
<CardTitle id={`task-type-label-${type.value}`}>
369+
{type.label}
370+
</CardTitle>
371+
</CardHeader>
372+
<CardBody>
373+
<Content component="small">{type.description}</Content>
374+
</CardBody>
375+
</Card>
376+
))}
377+
</Gallery>
378+
)}
379+
/>
380+
</ConfigureFormGroup>
381+
</StackItem>
386382

387-
<StackItem>
388-
<ConfigureFormGroup
389-
label="Top models to consider"
390-
labelHelp={{
391-
header: 'Top models to consider',
392-
body: 'Number of top models to select and refit. The pipeline will train multiple models and select the best performing ones for final training.',
393-
}}
394-
>
395-
<Controller
396-
control={form.control}
397-
name="top_n"
398-
render={({ field, fieldState }) => (
399-
<>
400-
<NumberInput
401-
id="top-n-input"
402-
value={field.value}
403-
min={MIN_TOP_N}
404-
max={MAX_TOP_N}
405-
isDisabled={formIsSubmitting}
406-
validated={fieldState.error ? 'error' : 'default'}
407-
onMinus={() => field.onChange(Number(field.value) - 1)}
408-
onPlus={() => field.onChange(Number(field.value) + 1)}
409-
onChange={(event: React.FormEvent<HTMLInputElement>) => {
410-
const value = parseInt(event.currentTarget.value, 10);
411-
if (!Number.isNaN(value)) {
412-
field.onChange(value);
413-
}
414-
}}
415-
data-testid="top-n-input"
416-
/>
417-
{fieldState.error && (
418-
<FormHelperText>
419-
<HelperText>
420-
<HelperTextItem variant="error">
421-
{fieldState.error.message}
422-
</HelperTextItem>
423-
</HelperText>
424-
</FormHelperText>
425-
)}
426-
</>
427-
)}
383+
{isTimeseries ? (
384+
<ConfigureTimeseriesForm
385+
columns={columns}
386+
isLoadingColumns={isLoadingColumns}
387+
isFetchingColumns={isFetchingColumns}
388+
columnsError={columnsError}
389+
isFileSelected={isFileSelected}
390+
formIsSubmitting={formIsSubmitting}
428391
/>
429-
</ConfigureFormGroup>
430-
</StackItem>
431-
</Stack>
392+
) : (
393+
<ConfigureTabularForm
394+
columns={columns}
395+
isLoadingColumns={isLoadingColumns}
396+
isFetchingColumns={isFetchingColumns}
397+
columnsError={columnsError}
398+
isFileSelected={isFileSelected}
399+
formIsSubmitting={formIsSubmitting}
400+
/>
401+
)}
402+
403+
<StackItem>
404+
<ConfigureFormGroup
405+
label="Top models to consider"
406+
labelHelp={{
407+
header: 'Top models to consider',
408+
body: 'Number of top models to select and refit. The pipeline will train multiple models and select the best performing ones for final training.',
409+
}}
410+
>
411+
<Controller
412+
control={form.control}
413+
name="top_n"
414+
render={({ field, fieldState }) => (
415+
<>
416+
<NumberInput
417+
id="top-n-input"
418+
value={field.value}
419+
min={MIN_TOP_N}
420+
max={MAX_TOP_N}
421+
isDisabled={formIsSubmitting}
422+
validated={fieldState.error ? 'error' : 'default'}
423+
onMinus={() => field.onChange(Number(field.value) - 1)}
424+
onPlus={() => field.onChange(Number(field.value) + 1)}
425+
onChange={(event: React.FormEvent<HTMLInputElement>) => {
426+
const value = parseInt(event.currentTarget.value, 10);
427+
if (!Number.isNaN(value)) {
428+
field.onChange(value);
429+
}
430+
}}
431+
data-testid="top-n-input"
432+
/>
433+
{fieldState.error && (
434+
<FormHelperText>
435+
<HelperText>
436+
<HelperTextItem variant="error">
437+
{fieldState.error.message}
438+
</HelperTextItem>
439+
</HelperText>
440+
</FormHelperText>
441+
)}
442+
</>
443+
)}
444+
/>
445+
</ConfigureFormGroup>
446+
</StackItem>
447+
</Stack>
448+
)}
432449
</CardBody>
433450
</div>
434451
</Card>

0 commit comments

Comments
 (0)