Skip to content

Commit

Permalink
Add initial server route; add core & route services (#27)
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Ohlsen <[email protected]>
  • Loading branch information
ohltyler committed Sep 12, 2023
1 parent e9a3116 commit 9991af8
Show file tree
Hide file tree
Showing 15 changed files with 133 additions and 90 deletions.
2 changes: 1 addition & 1 deletion common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export const PLUGIN_ID = 'aiFlowDashboards';

export const BASE_NODE_API_PATH = '/api/ai_flow';
export const SEARCH_PATH = `${BASE_NODE_API_PATH}/search`;
1 change: 1 addition & 0 deletions opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"opensearchDashboardsVersion": "3.0.0",
"server": true,
"ui": true,
"requiredBundles": ["opensearchDashboardsUtils"],
"requiredPlugins": ["navigation"],
"optionalPlugins": []
}
55 changes: 21 additions & 34 deletions public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
*/

import React from 'react';
import { I18nProvider } from '@osd/i18n/react';
import { Route, RouteComponentProps, Switch } from 'react-router-dom';
import { EuiPageSideBar, EuiSideNav, EuiPageTemplate } from '@elastic/eui';
import { CoreStart } from '../../../src/core/public';
import { Navigation, APP_PATH } from './utils';
import { Overview, UseCases, Workflows } from './pages';
import { CoreServicesConsumer } from './core_services';

// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface Props extends RouteComponentProps {}
Expand Down Expand Up @@ -46,36 +43,26 @@ export const AiFlowDashboardsApp = (props: Props) => {

// Render the application DOM.
return (
<CoreServicesConsumer>
{(core: CoreStart | null) =>
core && (
<I18nProvider>
<>
<EuiPageTemplate
template="empty"
pageContentProps={{ paddingSize: 'm' }}
pageSideBar={sidebar}
>
<Switch>
<Route
path={APP_PATH.USE_CASES}
render={(routeProps: RouteComponentProps) => <UseCases />}
/>
<Route
path={APP_PATH.WORKFLOWS}
render={(routeProps: RouteComponentProps) => <Workflows />}
/>
{/* Defaulting to Overview page */}
<Route
path={`${APP_PATH.HOME}`}
render={(routeProps: RouteComponentProps) => <Overview />}
/>
</Switch>
</EuiPageTemplate>
</>
</I18nProvider>
)
}
</CoreServicesConsumer>
<EuiPageTemplate
template="empty"
pageContentProps={{ paddingSize: 'm' }}
pageSideBar={sidebar}
>
<Switch>
<Route
path={APP_PATH.USE_CASES}
render={(routeProps: RouteComponentProps) => <UseCases />}
/>
<Route
path={APP_PATH.WORKFLOWS}
render={(routeProps: RouteComponentProps) => <Workflows />}
/>
{/* Defaulting to Overview page */}
<Route
path={`${APP_PATH.HOME}`}
render={(routeProps: RouteComponentProps) => <Overview />}
/>
</Switch>
</EuiPageTemplate>
);
};
13 changes: 0 additions & 13 deletions public/core_services.ts

This file was deleted.

2 changes: 0 additions & 2 deletions public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,3 @@ export {
AiFlowDashboardsPluginSetup,
AiFlowDashboardsPluginStart,
} from './types';

export * from './core_services';
6 changes: 2 additions & 4 deletions public/pages/overview/overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@

import React, { useEffect } from 'react';
import { EuiPageHeader, EuiText } from '@elastic/eui';
import { CoreServicesContext } from '../../core_services';
import { CoreStart } from '../../../../../src/core/public';
import { BREADCRUMBS } from '../../utils';
import { getCore } from '../../services';

export function Overview() {
const core = React.useContext(CoreServicesContext) as CoreStart;
useEffect(() => {
core.chrome.setBreadcrumbs([BREADCRUMBS.AI_APPLICATION_BUILDER]);
getCore().chrome.setBreadcrumbs([BREADCRUMBS.AI_APPLICATION_BUILDER]);
});

return (
Expand Down
6 changes: 2 additions & 4 deletions public/pages/use_cases/use_cases.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@

import React, { useEffect } from 'react';
import { EuiPageHeader, EuiText } from '@elastic/eui';
import { CoreServicesContext } from '../../core_services';
import { CoreStart } from '../../../../../src/core/public';
import { BREADCRUMBS } from '../../utils';
import { getCore } from '../../services';

export function UseCases() {
const core = React.useContext(CoreServicesContext) as CoreStart;
useEffect(() => {
core.chrome.setBreadcrumbs([
getCore().chrome.setBreadcrumbs([
BREADCRUMBS.AI_APPLICATION_BUILDER,
BREADCRUMBS.USE_CASES,
]);
Expand Down
6 changes: 2 additions & 4 deletions public/pages/workflows/workflows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@

import React, { useEffect } from 'react';
import { EuiPageHeader, EuiText } from '@elastic/eui';
import { CoreServicesContext } from '../../core_services';
import { CoreStart } from '../../../../../src/core/public';
import { BREADCRUMBS } from '../../utils';
import { getCore } from '../../services';

export function Workflows() {
const core = React.useContext(CoreServicesContext) as CoreStart;
useEffect(() => {
core.chrome.setBreadcrumbs([
getCore().chrome.setBreadcrumbs([
BREADCRUMBS.AI_APPLICATION_BUILDER,
BREADCRUMBS.WORKFLOWS,
]);
Expand Down
5 changes: 5 additions & 0 deletions public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
AiFlowDashboardsPluginStart,
} from './types';
import { PLUGIN_ID } from '../common';
import { setCore, setRouteService } from './services';
import { configureRoutes } from './route_service';

export class AiFlowDashboardsPlugin
implements Plugin<AiFlowDashboardsPluginSetup, AiFlowDashboardsPluginStart> {
Expand All @@ -33,6 +35,9 @@ export class AiFlowDashboardsPlugin
async mount(params: AppMountParameters) {
const { renderApp } = await import('./render_app');
const [coreStart] = await core.getStartServices();
const routeServices = configureRoutes(coreStart);
setCore(coreStart);
setRouteService(routeServices);
return renderApp(coreStart, params);
},
});
Expand Down
9 changes: 1 addition & 8 deletions public/render_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,14 @@ import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import { AppMountParameters, CoreStart } from '../../../src/core/public';
import { AiFlowDashboardsApp } from './app';
import { CoreServicesContext } from './core_services';

export const renderApp = (
coreStart: CoreStart,
{ appBasePath, element }: AppMountParameters
) => {
ReactDOM.render(
<Router basename={appBasePath + '#/'}>
<Route
render={(props) => (
<CoreServicesContext.Provider value={coreStart}>
<AiFlowDashboardsApp {...props} />
</CoreServicesContext.Provider>
)}
/>
<Route render={(props) => <AiFlowDashboardsApp {...props} />} />
</Router>,
element
);
Expand Down
29 changes: 29 additions & 0 deletions public/route_service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { CoreStart, HttpFetchError } from '../../../src/core/public';
import { SEARCH_PATH } from '../common';

export interface RouteService {
searchIndex: (indexName: string, body: {}) => Promise<any | HttpFetchError>;
}

export function configureRoutes(core: CoreStart): RouteService {
return {
searchIndex: async (indexName: string, body: {}) => {
try {
const response = await core.http.post<{ respString: string }>(
`${SEARCH_PATH}/${indexName}`,
{
body: JSON.stringify(body),
}
);
return response;
} catch (e: any) {
return e as HttpFetchError;
}
},
};
}
14 changes: 14 additions & 0 deletions public/services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { createGetterSetter } from '../../../src/plugins/opensearch_dashboards_utils/public';
import { CoreStart } from '../../../src/core/public';
import { RouteService } from './route_service';

export const [getCore, setCore] = createGetterSetter<CoreStart>('Core');

export const [getRouteService, setRouteService] = createGetterSetter<
RouteService
>('');
4 changes: 2 additions & 2 deletions server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
AiFlowDashboardsPluginSetup,
AiFlowDashboardsPluginStart,
} from './types';
import { defineRoutes } from './routes';
import { registerOpenSearchRoutes } from './routes';

export class AiFlowDashboardsPlugin
implements Plugin<AiFlowDashboardsPluginSetup, AiFlowDashboardsPluginStart> {
Expand All @@ -30,7 +30,7 @@ export class AiFlowDashboardsPlugin
const router = core.http.createRouter();

// Register server side APIs
defineRoutes(router);
registerOpenSearchRoutes(router);

return {};
}
Expand Down
19 changes: 1 addition & 18 deletions server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,4 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { IRouter } from '../../../../src/core/server';
import { BASE_NODE_API_PATH } from '../../common';

export function defineRoutes(router: IRouter) {
router.get(
{
path: BASE_NODE_API_PATH,
validate: false,
},
async (context, request, response) => {
return response.ok({
body: {
time: new Date().toISOString(),
},
});
}
);
}
export * from './opensearch_routes';
52 changes: 52 additions & 0 deletions server/routes/opensearch_routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { schema } from '@osd/config-schema';
import { SearchRequest } from '@opensearch-project/opensearch/api/types';
import {
IRouter,
IOpenSearchDashboardsResponse,
} from '../../../../src/core/server';
import { SEARCH_PATH } from '../../common';

export function registerOpenSearchRoutes(router: IRouter): void {
router.post(
{
path: `${SEARCH_PATH}/{index_name}`,
validate: {
params: schema.object({
index_name: schema.string(),
}),
body: schema.any(),
},
},
async (context, req, res): Promise<IOpenSearchDashboardsResponse<any>> => {
const client = context.core.opensearch.client.asCurrentUser;
// eslint-disable-next-line @typescript-eslint/naming-convention
const { index_name } = req.params;
const body = req.body;

const params = {
index: index_name,
body,
} as SearchRequest;

try {
const response = await client.search(params);
return res.ok({ body: response });
} catch (err: any) {
return res.customError({
statusCode: err.statusCode || 500,
body: {
message: err.message,
attributes: {
error: err.body?.error || err.message,
},
},
});
}
}
);
}

0 comments on commit 9991af8

Please sign in to comment.