Skip to content

Commit

Permalink
Misc bug fixes and minor UX improvements II (opensearch-project#432) (o…
Browse files Browse the repository at this point in the history
…pensearch-project#439)

* Change readonly fields into codeblock



* Change which panel is collapsible; various wording changes



* Move edit buttons of ingest/search in header; spacing cleanup



* Update wording and layout of input/output transform form components



* update tests



* remove gutter entirely on query buttons



---------

Signed-off-by: Tyler Ohlsen <[email protected]>
  • Loading branch information
ohltyler authored Oct 29, 2024
1 parent 373a528 commit fb47cca
Show file tree
Hide file tree
Showing 14 changed files with 325 additions and 225 deletions.
1 change: 0 additions & 1 deletion common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,6 @@ export enum PROCESSOR_CONTEXT {
export const START_FROM_SCRATCH_WORKFLOW_NAME = 'Start From Scratch';
export const DEFAULT_NEW_WORKFLOW_NAME = 'new_workflow';
export const DEFAULT_NEW_WORKFLOW_DESCRIPTION = 'My new workflow';
export const DEFAULT_NEW_WORKFLOW_STATE = WORKFLOW_STATE.NOT_STARTED;
export const DEFAULT_NEW_WORKFLOW_STATE_TYPE = ('NOT_STARTED' as any) as typeof WORKFLOW_STATE;
export const DATE_FORMAT_PATTERN = 'MM/DD/YY hh:mm A';
export const EMPTY_FIELD_STRING = '--';
Expand Down
9 changes: 6 additions & 3 deletions public/general_components/processors_title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@ interface ProcessorsTitleProps {
*/
export function ProcessorsTitle(props: ProcessorsTitleProps) {
return (
<EuiFlexItem grow={false}>
<EuiFlexItem
grow={false}
style={{ marginTop: '-24px', marginBottom: '-8px' }}
>
<EuiText size="s">
<div>
<>
<h3
style={{ display: 'inline-block' }}
>{`${props.title} (${props.processorCount}) -`}</h3>
&nbsp;
<h3 style={{ display: 'inline-block', fontStyle: 'italic' }}>
optional
</h3>
</div>
</>
</EuiText>
</EuiFlexItem>
);
Expand Down
7 changes: 0 additions & 7 deletions public/pages/workflow_detail/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ import {
EuiSmallButton,
} from '@elastic/eui';
import {
DEFAULT_NEW_WORKFLOW_STATE,
PLUGIN_ID,
MAX_WORKFLOW_NAME_TO_DISPLAY,
WORKFLOW_STATE,
Workflow,
getCharacterLimitedString,
toFormattedDate,
Expand Down Expand Up @@ -58,7 +56,6 @@ export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
const history = useHistory();
// workflow state
const [workflowName, setWorkflowName] = useState<string>('');
const [workflowState, setWorkflowState] = useState<WORKFLOW_STATE>('');
const [workflowLastUpdated, setWorkflowLastUpdated] = useState<string>('');

// export modal state
Expand All @@ -80,7 +77,6 @@ export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
MAX_WORKFLOW_NAME_TO_DISPLAY
)
);
setWorkflowState(props.workflow.state || DEFAULT_NEW_WORKFLOW_STATE);
try {
const formattedDate = toFormattedDate(
// @ts-ignore
Expand Down Expand Up @@ -206,9 +202,6 @@ export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
pageTitle={
<EuiFlexGroup direction="row" alignItems="flexEnd" gutterSize="m">
<EuiFlexItem grow={false}>{workflowName}</EuiFlexItem>
<EuiFlexItem grow={false} style={{ marginBottom: '10px' }}>
<EuiText size="m">{workflowState}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
}
rightSideItems={[
Expand Down
30 changes: 14 additions & 16 deletions public/pages/workflow_detail/resizable_workspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ interface ResizableWorkspaceProps {
}

const WORKFLOW_INPUTS_PANEL_ID = 'workflow_inputs_panel_id';
const PREVIEW_PANEL_ID = 'preview_panel_id';
const TOOLS_PANEL_ID = 'tools_panel_id';

/**
Expand Down Expand Up @@ -69,18 +70,16 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
undefined
);

// Workflow inputs side panel state
const [isWorkflowInputsPanelOpen, setIsWorkflowInputsPanelOpen] = useState<
boolean
>(true);
// Preview side panel state. This panel encapsulates the tools panel as a child resizable panel.
const [isPreviewPanelOpen, setIsPreviewPanelOpen] = useState<boolean>(true);
const collapseFnHorizontal = useRef(
(id: string, options: { direction: 'left' | 'right' }) => {}
);
const onToggleWorkflowInputsChange = () => {
collapseFnHorizontal.current(WORKFLOW_INPUTS_PANEL_ID, {
direction: 'left',
const onTogglePreviewChange = () => {
collapseFnHorizontal.current(PREVIEW_PANEL_ID, {
direction: 'right',
});
setIsWorkflowInputsPanelOpen(!isWorkflowInputsPanelOpen);
setIsPreviewPanelOpen(!isPreviewPanelOpen);
};

// ingest state
Expand Down Expand Up @@ -143,7 +142,7 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
direction="horizontal"
className="stretch-absolute"
style={{
marginLeft: isWorkflowInputsPanelOpen ? '-8px' : '0px',
marginLeft: '-8px',
marginTop: '-8px',
}}
>
Expand All @@ -159,13 +158,10 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
<>
<EuiResizablePanel
id={WORKFLOW_INPUTS_PANEL_ID}
mode="collapsible"
initialSize={50}
mode="main"
initialSize={60}
minSize="25%"
paddingSize="s"
onToggleCollapsedInternal={() =>
onToggleWorkflowInputsChange()
}
>
<WorkflowInputs
workflow={props.workflow}
Expand All @@ -181,14 +177,16 @@ export function ResizableWorkspace(props: ResizableWorkspaceProps) {
</EuiResizablePanel>
<EuiResizableButton />
<EuiResizablePanel
id={PREVIEW_PANEL_ID}
style={{
marginRight: '-32px',
marginRight: isPreviewPanelOpen ? '-32px' : '0px',
marginBottom: isToolsPanelOpen ? '0px' : '24px',
}}
mode="main"
mode="collapsible"
initialSize={60}
minSize="25%"
paddingSize="s"
onToggleCollapsedInternal={() => onTogglePreviewChange()}
>
<EuiResizableContainer
className="workspace-panel"
Expand Down
7 changes: 5 additions & 2 deletions public/pages/workflow_detail/tools/tools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ const inputTabs = [
},
];

// TODO: this may change in the future
const PANEL_TITLE = 'Inspector';

/**
* The base Tools component for performing ingest and search, viewing resources, and debugging.
*/
Expand Down Expand Up @@ -116,9 +119,9 @@ export function Tools(props: ToolsProps) {
height: '100%',
}}
>
<EuiFlexItem grow={false}>
<EuiFlexItem grow={false} style={{ marginBottom: '0px' }}>
<EuiText size="s">
<h2>Tools</h2>
<h2>{PANEL_TITLE}</h2>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
Expand Down
7 changes: 3 additions & 4 deletions public/pages/workflow_detail/workflow_detail.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,8 @@ describe('WorkflowDetail Page with create ingestion option', () => {
);
expect(getAllByText('Skip ingestion pipeline').length).toBeGreaterThan(0);
expect(getAllByText('Define ingest pipeline').length).toBeGreaterThan(0);
expect(getAllByText('Tools').length).toBeGreaterThan(0);
expect(getAllByText('Inspector').length).toBeGreaterThan(0);
expect(getAllByText('Preview').length).toBeGreaterThan(0);
expect(getAllByText('Not started').length).toBeGreaterThan(0);
expect(
getAllByText((content) => content.startsWith('Last updated:')).length
).toBeGreaterThan(0);
Expand Down Expand Up @@ -240,14 +239,14 @@ describe('WorkflowDetail Page with skip ingestion option (Hybrid Search Workflow
);
userEvent.click(addRequestProcessorButton);
await waitFor(() => {
expect(getAllByText('Processors').length).toBeGreaterThan(0);
expect(getAllByText('PROCESSORS').length).toBeGreaterThan(0);
});

// Add response processor
const addResponseProcessorButton = getAllByTestId('addProcessorButton')[1];
userEvent.click(addResponseProcessorButton);
await waitFor(() => {
expect(getAllByText('Processors').length).toBeGreaterThan(0);
expect(getAllByText('PROCESSORS').length).toBeGreaterThan(0);
});

// Save, Build and Run query, Back buttons
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
EuiSmallFilterButton,
EuiSuperSelectOption,
EuiCompressedSuperSelect,
EuiCodeBlock,
EuiSmallButtonEmpty,
} from '@elastic/eui';
import { JsonField } from '../input_fields';
import {
Expand Down Expand Up @@ -293,9 +295,25 @@ export function SourceData(props: SourceDataProps) {
)}
<EuiFlexGroup direction="column" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiText size="s">
<h3>Source data</h3>
</EuiText>
<EuiFlexGroup direction="row" justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiText size="s">
<h3>Import data</h3>
</EuiText>
</EuiFlexItem>
{docsPopulated && (
<EuiFlexItem grow={false}>
<EuiSmallButtonEmpty
onClick={() => setIsEditModalOpen(true)}
data-testid="editSourceDataButton"
iconType="pencil"
iconSide="left"
>
Edit
</EuiSmallButtonEmpty>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiFlexItem>
{props.lastIngested !== undefined && (
<EuiFlexItem grow={false}>
Expand All @@ -305,27 +323,36 @@ export function SourceData(props: SourceDataProps) {
</EuiFlexItem>
)}

<EuiFlexItem grow={false}>
<EuiSmallButton
fill={false}
style={{ width: '100px' }}
onClick={() => setIsEditModalOpen(true)}
data-testid="editSourceDataButton"
>
{docsPopulated ? `Edit` : `Select data`}
</EuiSmallButton>
</EuiFlexItem>
{docsPopulated && (
{!docsPopulated && (
<EuiFlexItem grow={false}>
<JsonField
label="Documents to be imported"
fieldPath={'ingest.docs'}
helpText="Documents should be formatted as a valid JSON array."
editorHeight="25vh"
readOnly={true}
/>
<EuiSmallButton
fill={false}
style={{ width: '100px' }}
onClick={() => setIsEditModalOpen(true)}
data-testid="selectDataToImportButton"
>
{`Select data`}
</EuiSmallButton>
</EuiFlexItem>
)}

{docsPopulated && (
<>
<EuiSpacer size="s" />
<EuiFlexItem grow={true}>
<EuiCodeBlock
fontSize="s"
language="json"
overflowHeight={300}
isCopyable={false}
whiteSpace="pre"
paddingSize="none"
>
{getIn(values, 'ingest.docs')}
</EuiCodeBlock>
</EuiFlexItem>
</>
)}
</EuiFlexGroup>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiCompressedFormRow,
EuiLink,
EuiPanel,
EuiSmallButton,
EuiSmallButtonEmpty,
EuiSpacer,
EuiText,
} from '@elastic/eui';
import { Field, FieldProps, getIn, useFormikContext } from 'formik';
import {
Expand All @@ -30,15 +28,17 @@ import { MapField } from './map_field';
interface MapArrayFieldProps {
field: IConfigField;
fieldPath: string; // the full path in string-form to the field (e.g., 'ingest.enrich.processors.text_embedding_processor.inputField')
label?: string;
helpLink?: string;
helpText?: string;
keyTitle?: string;
keyPlaceholder?: string;
valueTitle?: string;
valuePlaceholder?: string;
onMapAdd?: (curArray: MapArrayFormValue) => void;
onMapDelete?: (idxToDelete: number) => void;
keyOptions?: { label: string }[];
valueOptions?: { label: string }[];
addMapEntryButtonText?: string;
addMapButtonText?: string;
}

/**
Expand Down Expand Up @@ -90,17 +90,6 @@ export function MapArrayField(props: MapArrayFieldProps) {
<EuiCompressedFormRow
fullWidth={true}
key={props.fieldPath}
label={props.label}
labelAppend={
props.helpLink ? (
<EuiText size="xs">
<EuiLink href={props.helpLink} target="_blank">
Learn more
</EuiLink>
</EuiText>
) : undefined
}
helpText={props.helpText || undefined}
isInvalid={
getIn(errors, field.name) !== undefined &&
getIn(errors, field.name).length > 0 &&
Expand Down Expand Up @@ -135,10 +124,14 @@ export function MapArrayField(props: MapArrayFieldProps) {
<EuiPanel grow={true}>
<MapField
fieldPath={`${props.fieldPath}.${idx}`}
helpText={props.helpText}
keyTitle={props.keyTitle}
keyPlaceholder={props.keyPlaceholder}
valueTitle={props.valueTitle}
valuePlaceholder={props.valuePlaceholder}
keyOptions={props.keyOptions}
valueOptions={props.valueOptions}
addEntryButtonText={props.addMapEntryButtonText}
/>
</EuiPanel>
</EuiAccordion>
Expand All @@ -151,10 +144,14 @@ export function MapArrayField(props: MapArrayFieldProps) {
<EuiPanel grow={true}>
<MapField
fieldPath={`${props.fieldPath}.0`}
helpText={props.helpText}
keyTitle={props.keyTitle}
keyPlaceholder={props.keyPlaceholder}
valueTitle={props.valueTitle}
valuePlaceholder={props.valuePlaceholder}
keyOptions={props.keyOptions}
valueOptions={props.valueOptions}
addEntryButtonText={props.addMapEntryButtonText}
/>
</EuiPanel>
<EuiSpacer size="s" />
Expand Down Expand Up @@ -182,7 +179,9 @@ export function MapArrayField(props: MapArrayFieldProps) {
onClick={() => {
addMap(field.value);
}}
>{`(Advanced) Add another prediction`}</EuiSmallButtonEmpty>
>
{props.addMapButtonText || `(Advanced) Add another map`}
</EuiSmallButtonEmpty>
)}
</>
</div>
Expand Down
Loading

0 comments on commit fb47cca

Please sign in to comment.