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

Simplify export flow; improve form state #284

Merged
merged 7 commits into from
Aug 15, 2024
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
2 changes: 2 additions & 0 deletions common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ export const ML_CHOOSE_MODEL_LINK =
'https://opensearch.org/docs/latest/ml-commons-plugin/integrating-ml-models/#choosing-a-model';
export const TEXT_CHUNKING_PROCESSOR_LINK =
'https://opensearch.org/docs/latest/ingest-pipelines/processors/text-chunking/';
export const CREATE_WORKFLOW_LINK =
'https://opensearch.org/docs/latest/automating-configurations/api/create-workflow/';

/**
* Text chunking algorithm constants
Expand Down
10 changes: 4 additions & 6 deletions common/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,14 @@ export type CreateIngestPipelineNode = TemplateNode & {
model_id?: string;
input_field?: string;
output_field?: string;
configurations: IngestPipelineConfig;
configurations: string;
};
};

export type CreateSearchPipelineNode = TemplateNode & {
user_inputs: {
pipeline_id: string;
configurations: SearchPipelineConfig;
configurations: string;
};
};

Expand All @@ -277,10 +277,7 @@ export type CreateIndexNode = TemplateNode & {
};
user_inputs: {
index_name: string;
configurations: {
settings: {};
mappings: {};
};
configurations: string;
};
};

Expand All @@ -292,6 +289,7 @@ export type TemplateEdge = {
export type TemplateFlow = {
nodes: TemplateNode[];
edges?: TemplateEdge[];
user_params?: {};
};

export type TemplateFlows = {
Expand Down
6 changes: 3 additions & 3 deletions public/component_types/indexer/base_indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import { BaseComponent } from '../base_component';
/**
* A base indexer UI component
*/
export abstract class BaseIndexer extends BaseComponent {
export class BaseIndexer extends BaseComponent {
constructor() {
super();
this.type = COMPONENT_CLASS.INDEXER;
this.label = 'Indexer';
this.description = 'A general indexer';
this.label = 'Index';
this.description = 'An OpenSearch index';
this.inputs = [
{
id: 'input',
Expand Down
1 change: 1 addition & 0 deletions public/component_types/indexer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
* SPDX-License-Identifier: Apache-2.0
*/

export * from './base_indexer';
export * from './knn_indexer';
114 changes: 114 additions & 0 deletions public/pages/workflow_detail/components/export_modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useEffect, useState } from 'react';
import yaml from 'js-yaml';
import {
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiCompressedRadioGroup,
EuiText,
EuiLink,
EuiModal,
EuiModalHeader,
EuiModalHeaderTitle,
EuiModalBody,
EuiModalFooter,
EuiSmallButtonEmpty,
} from '@elastic/eui';
import { CREATE_WORKFLOW_LINK, Workflow } from '../../../../common';
import { reduceToTemplate } from '../../../utils';

interface ExportModalProps {
workflow?: Workflow;
setIsExportModalOpen(isOpen: boolean): void;
}

enum EXPORT_OPTION {
JSON = 'json',
YAML = 'yaml',
}

const exportOptions = [
{
id: EXPORT_OPTION.JSON,
label: 'JSON',
},
{
id: EXPORT_OPTION.YAML,
label: 'YAML',
},
];

/**
* Modal containing all of the export options
*/
export function ExportModal(props: ExportModalProps) {
// format type state
const [selectedOption, setSelectedOption] = useState<EXPORT_OPTION>(
EXPORT_OPTION.JSON
);

// formatted string state
const [formattedConfig, setFormattedConfig] = useState<string>('');
useEffect(() => {
if (props.workflow) {
const workflowTemplate = reduceToTemplate(props.workflow);
if (selectedOption === EXPORT_OPTION.JSON) {
setFormattedConfig(JSON.stringify(workflowTemplate, undefined, 2));
} else if (selectedOption === EXPORT_OPTION.YAML) {
setFormattedConfig(yaml.dump(workflowTemplate));
}
}
}, [props.workflow, selectedOption]);

return (
<EuiModal onClose={() => props.setIsExportModalOpen(false)}>
<EuiModalHeader>
<EuiModalHeaderTitle>
<p>{`Export ${props.workflow?.name}`}</p>
</EuiModalHeaderTitle>
</EuiModalHeader>
<EuiModalBody>
<EuiFlexGroup direction="column">
<EuiFlexItem grow={false}>
<EuiText>
Copy the below workflow templates to use in other clusters.
</EuiText>
<EuiLink href={CREATE_WORKFLOW_LINK} target="_blank">
Learn more
</EuiLink>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiCompressedRadioGroup
options={exportOptions}
idSelected={selectedOption}
onChange={(option) => {
setSelectedOption(option as EXPORT_OPTION);
}}
/>
</EuiFlexItem>
{props.workflow !== undefined && (
<EuiFlexItem grow={false}>
<EuiCodeBlock
language={selectedOption}
fontSize="m"
isCopyable={true}
>
{formattedConfig}
</EuiCodeBlock>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiModalBody>
<EuiModalFooter>
<EuiSmallButtonEmpty onClick={() => props.setIsExportModalOpen(false)}>
Close
</EuiSmallButtonEmpty>
</EuiModalFooter>
</EuiModal>
);
}
73 changes: 47 additions & 26 deletions public/pages/workflow_detail/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
EuiFlexItem,
EuiText,
EuiSmallButtonEmpty,
EuiSmallButton,
} from '@elastic/eui';
import {
DEFAULT_NEW_WORKFLOW_STATE,
Expand All @@ -19,6 +20,7 @@ import {
toFormattedDate,
} from '../../../../common';
import { APP_PATH } from '../../../utils';
import { ExportModal } from './export_modal';

interface WorkflowDetailHeaderProps {
workflow?: Workflow;
Expand All @@ -31,6 +33,9 @@ export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
const [workflowState, setWorkflowState] = useState<WORKFLOW_STATE>('');
const [workflowLastUpdated, setWorkflowLastUpdated] = useState<string>('');

// export modal state
const [isExportModalOpen, setIsExportModalOpen] = useState<boolean>(false);

useEffect(() => {
if (props.workflow) {
setWorkflowName(props.workflow.name);
Expand All @@ -48,31 +53,47 @@ export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
}, [props.workflow]);

return (
<EuiPageHeader
style={{ marginTop: '-8px' }}
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={[
<EuiSmallButtonEmpty
style={{ marginTop: '8px' }}
onClick={() => {
// TODO: add lightweight save here when available
history.replace(APP_PATH.WORKFLOWS);
}}
>
Close
</EuiSmallButtonEmpty>,
<EuiText style={{ marginTop: '16px' }} color="subdued" size="s">
{`Last updated: ${workflowLastUpdated}`}
</EuiText>,
]}
bottomBorder={false}
/>
<>
{isExportModalOpen && (
<ExportModal
workflow={props.workflow}
setIsExportModalOpen={setIsExportModalOpen}
/>
)}
<EuiPageHeader
style={{ marginTop: '-8px' }}
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={[
<EuiSmallButton
style={{ marginTop: '8px' }}
fill={true}
onClick={() => {
setIsExportModalOpen(true);
}}
>
Export
</EuiSmallButton>,
<EuiSmallButtonEmpty
style={{ marginTop: '8px' }}
onClick={() => {
history.replace(APP_PATH.WORKFLOWS);
}}
>
Close
</EuiSmallButtonEmpty>,
<EuiText style={{ marginTop: '16px' }} color="subdued" size="s">
{`Last updated: ${workflowLastUpdated}`}
</EuiText>,
]}
bottomBorder={false}
/>
</>
);
}

This file was deleted.

This file was deleted.

Loading
Loading