Skip to content

Commit

Permalink
Header Redesign (#293) (#298)
Browse files Browse the repository at this point in the history
Signed-off-by: saimedhi <saimedhi@amazon.com>
Signed-off-by: Sai Medhini Reddy Maryada <117196660+saimedhi@users.noreply.github.com>
(cherry picked from commit 60de152)

Co-authored-by: Sai Medhini Reddy Maryada <117196660+saimedhi@users.noreply.github.com>
  • Loading branch information
opensearch-trigger-bot[bot] and saimedhi authored Aug 19, 2024
1 parent 65c2c18 commit 0068e87
Show file tree
Hide file tree
Showing 12 changed files with 339 additions and 117 deletions.
1 change: 1 addition & 0 deletions common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { WORKFLOW_STATE } from './interfaces';

export const PLUGIN_ID = 'flow-framework';
export const SEARCH_STUDIO = 'Search Studio';

/**
* BACKEND FLOW FRAMEWORK APIs
Expand Down
212 changes: 176 additions & 36 deletions public/pages/workflow_detail/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, ReactElement } from 'react';
import { useHistory } from 'react-router-dom';
import {
EuiPageHeader,
Expand All @@ -15,17 +15,42 @@ import {
} from '@elastic/eui';
import {
DEFAULT_NEW_WORKFLOW_STATE,
PLUGIN_ID,
MAX_WORKFLOW_NAME_TO_DISPLAY,
WORKFLOW_STATE,
Workflow,
getCharacterLimitedString,
toFormattedDate,
} from '../../../../common';
import { APP_PATH } from '../../../utils';
import {
APP_PATH,
SHOW_ACTIONS_IN_HEADER,
constructUrlWithParams,
getDataSourceId,
} from '../../../utils';
import { ExportModal } from './export_modal';
import {
getApplication,
getCore,
getDataSourceEnabled,
getHeaderActionMenu,
getNavigationUI,
getNotifications,
getSavedObjectsClient,
getDataSourceManagementPlugin,
} from '../../../services';
import { DataSourceViewConfig } from '../../../../../../src/plugins/data_source_management/public';
import { HeaderVariant } from '../../../../../../src/core/public';
import {
TopNavControlTextData,
TopNavMenuData,
TopNavMenuIconData,
} from '../../../../../../src/plugins/navigation/public';
import { MountPoint } from '../../../../../../src/core/public';

interface WorkflowDetailHeaderProps {
workflow?: Workflow;
setActionMenu: (menuMount?: MountPoint) => void;
}

export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
Expand All @@ -38,6 +63,14 @@ export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
// export modal state
const [isExportModalOpen, setIsExportModalOpen] = useState<boolean>(false);

const dataSourceEnabled = getDataSourceEnabled().enabled;
const dataSourceId = getDataSourceId();
const { TopNavMenu, HeaderControl } = getNavigationUI();
const { setAppRightControls } = getApplication();
const {
chrome: { setHeaderVariant },
} = getCore();

useEffect(() => {
if (props.workflow) {
setWorkflowName(
Expand All @@ -59,6 +92,62 @@ export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
}
}, [props.workflow]);

// When NewHomePage is enabled, use 'application' HeaderVariant; otherwise, use 'page' HeaderVariant (default).
useEffect(() => {
if (SHOW_ACTIONS_IN_HEADER) {
setHeaderVariant?.(HeaderVariant.APPLICATION);
}
return () => {
setHeaderVariant?.();
};
}, [setHeaderVariant, SHOW_ACTIONS_IN_HEADER]);

const onExportButtonClick = () => {
setIsExportModalOpen(true);
};

const onExitButtonClick = () => {
history.replace(
constructUrlWithParams(APP_PATH.WORKFLOWS, undefined, dataSourceId)
);
};

const topNavConfig: TopNavMenuData[] = [
{
iconType: 'exportAction',
tooltip: 'Export',
ariaLabel: 'Export',
run: onExportButtonClick,
controlType: 'icon',
} as TopNavMenuIconData,
{
iconType: 'exit',
tooltip: 'Return to projects',
ariaLabel: 'Exit',
run: onExitButtonClick,
controlType: 'icon',
} as TopNavMenuIconData,
];

let renderDataSourceComponent: ReactElement | null = null;
if (dataSourceEnabled && getDataSourceManagementPlugin()) {
const DataSourceMenu = getDataSourceManagementPlugin().ui.getDataSourceMenu<
DataSourceViewConfig
>();
renderDataSourceComponent = (
<DataSourceMenu
setMenuMountPoint={props.setActionMenu}
componentType={'DataSourceView'}
componentConfig={{
activeOption: [{ id: dataSourceId }],
fullWidth: false,
savedObjects: getSavedObjectsClient(),
notifications: getNotifications(),
}}
/>
);
}

return (
<>
{isExportModalOpen && (
Expand All @@ -67,40 +156,91 @@ export function WorkflowDetailHeader(props: WorkflowDetailHeaderProps) {
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}
/>
{SHOW_ACTIONS_IN_HEADER ? (
<>
<TopNavMenu
appName={PLUGIN_ID}
config={topNavConfig}
screenTitle={workflowName}
showDataSourceMenu={dataSourceEnabled}
dataSourceMenuConfig={
dataSourceEnabled
? {
componentType: 'DataSourceView',
componentConfig: {
activeOption: [{ id: dataSourceId }],
fullWidth: false,
savedObjects: getSavedObjectsClient(),
notifications: getNotifications(),
},
}
: undefined
}
showSearchBar={false}
showQueryBar={false}
showQueryInput={false}
showDatePicker={false}
showFilterBar={false}
useDefaultBehaviors={true}
setMenuMountPoint={getHeaderActionMenu()}
groupActions={SHOW_ACTIONS_IN_HEADER}
/>
<HeaderControl
setMountPoint={setAppRightControls}
controls={[
{
text: `Last updated: ${workflowLastUpdated}`,
color: 'subdued',
className: 'workflow-detail-last-updated',
} as TopNavControlTextData,
]}
/>
</>
) : (
<>
{dataSourceEnabled && renderDataSourceComponent}
<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(
constructUrlWithParams(
APP_PATH.WORKFLOWS,
undefined,
dataSourceId
)
);
}}
>
Close
</EuiSmallButtonEmpty>,
<EuiText style={{ marginTop: '16px' }} color="subdued" size="s">
{`Last updated: ${workflowLastUpdated}`}
</EuiText>,
]}
bottomBorder={false}
/>
</>
)}
</>
);
}
7 changes: 7 additions & 0 deletions public/pages/workflow_detail/workflow-detail-styles.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
.workflow-detail {
overflow: hidden;
}

.workflow-detail-last-updated {
line-height: $euiFormControlCompressedHeight;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
70 changes: 26 additions & 44 deletions public/pages/workflow_detail/workflow_detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useEffect, ReactElement } from 'react';
import React, { useEffect } from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { ReactFlowProvider } from 'reactflow';
Expand All @@ -16,7 +16,7 @@ import {
EuiPage,
EuiPageBody,
} from '@elastic/eui';
import { APP_PATH, BREADCRUMBS } from '../../utils';
import { APP_PATH, BREADCRUMBS, SHOW_ACTIONS_IN_HEADER} from '../../utils';
import { getCore } from '../../services';
import { WorkflowDetailHeader } from './components';
import {
Expand All @@ -43,13 +43,7 @@ import {
getDataSourceId,
} from '../../utils/utils';

import {
getDataSourceManagementPlugin,
getDataSourceEnabled,
getNotifications,
getSavedObjectsClient,
} from '../../services';
import { DataSourceViewConfig } from '../../../../../src/plugins/data_source_management/public';
import { getDataSourceEnabled } from '../../services';

export interface WorkflowDetailRouterProps {
workflowId: string;
Expand Down Expand Up @@ -82,21 +76,26 @@ export function WorkflowDetail(props: WorkflowDetailProps) {
MAX_WORKFLOW_NAME_TO_DISPLAY
);

const {
chrome: { setBreadcrumbs },
} = getCore();
useEffect(() => {
if (dataSourceEnabled) {
getCore().chrome.setBreadcrumbs([
BREADCRUMBS.FLOW_FRAMEWORK,
BREADCRUMBS.WORKFLOWS(dataSourceId),
{ text: workflowName },
]);
} else {
getCore().chrome.setBreadcrumbs([
BREADCRUMBS.FLOW_FRAMEWORK,
BREADCRUMBS.WORKFLOWS(),
{ text: workflowName },
]);
}
}, [workflowName]);
setBreadcrumbs(
SHOW_ACTIONS_IN_HEADER
? [
BREADCRUMBS.TITLE_WITH_REF(
dataSourceEnabled ? dataSourceId : undefined
),
BREADCRUMBS.WORKFLOW_NAME(workflowName),
{ text: '' },
]
: [
BREADCRUMBS.FLOW_FRAMEWORK,
BREADCRUMBS.WORKFLOWS(dataSourceEnabled ? dataSourceId : undefined),
{ text: workflowName },
]
);
}, [SHOW_ACTIONS_IN_HEADER, dataSourceEnabled, dataSourceId, workflowName]);

// On initial load:
// - fetch workflow
Expand All @@ -106,25 +105,6 @@ export function WorkflowDetail(props: WorkflowDetailProps) {
dispatch(searchModels({ apiBody: FETCH_ALL_QUERY_BODY, dataSourceId }));
}, []);

let renderDataSourceComponent: ReactElement | null = null;
if (dataSourceEnabled && getDataSourceManagementPlugin()) {
const DataSourceMenu = getDataSourceManagementPlugin().ui.getDataSourceMenu<
DataSourceViewConfig
>();
renderDataSourceComponent = (
<DataSourceMenu
setMenuMountPoint={props.setActionMenu}
componentType={'DataSourceView'}
componentConfig={{
activeOption: [{ id: dataSourceId }],
fullWidth: false,
savedObjects: getSavedObjectsClient(),
notifications: getNotifications(),
}}
/>
);
}

return errorMessage.includes(ERROR_GETTING_WORKFLOW_MSG) ? (
<EuiFlexGroup direction="column" alignItems="center">
<EuiFlexItem grow={3}>
Expand All @@ -146,10 +126,12 @@ export function WorkflowDetail(props: WorkflowDetailProps) {
</EuiFlexGroup>
) : (
<ReactFlowProvider>
{dataSourceEnabled && renderDataSourceComponent}
<EuiPage>
<EuiPageBody className="workflow-detail stretch-relative">
<WorkflowDetailHeader workflow={workflow} />
<WorkflowDetailHeader
workflow={workflow}
setActionMenu={props.setActionMenu}
/>
<ReactFlowProvider>
<ResizableWorkspace workflow={workflow} />
</ReactFlowProvider>
Expand Down
Loading

0 comments on commit 0068e87

Please sign in to comment.