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

Set up plugin boilerplate & placeholder pages #3

Merged
merged 3 commits into from
Sep 5, 2023
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
7 changes: 7 additions & 0 deletions common/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
export const PLUGIN_ID = 'aiFlowDashboards';

export const BASE_NODE_API_PATH = '/api/ai_flow';
6 changes: 6 additions & 0 deletions common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export * from './constants';
9 changes: 9 additions & 0 deletions opensearch_dashboards.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"id": "aiFlowDashboards",
"version": "3.0.0.0",
"opensearchDashboardsVersion": "3.0.0",
"server": true,
"ui": true,
"requiredPlugins": ["navigation"],
"optionalPlugins": []
}
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "ai-flow-dashboards",
joshpalis marked this conversation as resolved.
Show resolved Hide resolved
"version": "3.0.0.0",
"description": "OpenSearch AI Flow Dashboards Plugin",
"main": "index.js",
"config": {
"plugin_version": "3.0.0.0",
"plugin_name": "aiFlowDashboards",
"plugin_zip_name": "ai-flow-dashboards"
joshpalis marked this conversation as resolved.
Show resolved Hide resolved
},
"private": true,
"scripts": {
"plugin-helpers": "../../scripts/use_node ../../scripts/plugin_helpers",
"osd": "../../scripts/use_node ../../scripts/osd",
"opensearch": "node ../../scripts/opensearch",
"lint": "node ../../scripts/eslint .",
Comment on lines +13 to +16
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do some of these use use_node and others don't?

Also, plugins should also have a lint:style script, that calls ../../scripts/use_node ../../scripts/stylelint (which should be part of the CI workflow, along with lint:es)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll clean up the use_node vs. node differences, I referenced some of this from different existing plugins.

Thanks for the suggestions on the lint scripts - I'll work on that + adding a github workflow for them

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BSFishy I've updated and added a lint script in latest commit. For some reason there is an issue with that commit showing up as part of this PR, checking on if that is a newly-public-repo config that needs updated or related to the list of incidents that've happened today

"build": "yarn plugin-helpers build && echo Renaming artifact to $npm_package_config_plugin_zip_name-$npm_package_config_plugin_version.zip && mv ./build/$npm_package_config_plugin_name*.zip ./build/$npm_package_config_plugin_zip_name-$npm_package_config_plugin_version.zip"
},
"lint-staged": {
"*.{ts,tsx,js,jsx,json,css,md}": [
"prettier --write",
"git add"
]
},
"devDependencies": {},
"dependencies": {},
"resolutions": {}
}
80 changes: 80 additions & 0 deletions public/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

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';

interface Props extends RouteComponentProps {}

export const AiFlowDashboardsApp = (props: Props) => {
const sidebar = (
<EuiPageSideBar style={{ minWidth: 190 }} hidden={false}>
owaiskazi19 marked this conversation as resolved.
Show resolved Hide resolved
<EuiSideNav
style={{ width: 190 }}
items={[
{
name: Navigation.AiApplicationBuilder,
id: 0,
items: [
{
name: Navigation.UseCases,
id: 1,
href: `#${APP_PATH.USE_CASES}`,
isSelected: props.location.pathname === APP_PATH.USE_CASES,
},
{
name: Navigation.Workflows,
id: 2,
href: `#${APP_PATH.WORKFLOWS}`,
isSelected: props.location.pathname === APP_PATH.WORKFLOWS,
},
],
},
]}
/>
</EuiPageSideBar>
);

// 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={(props: RouteComponentProps) => <UseCases />}
/>
<Route
path={APP_PATH.WORKFLOWS}
render={(props: RouteComponentProps) => <Workflows />}
/>
{/* Defaulting to Overview page */}
<Route
path={`${APP_PATH.HOME}`}
render={(props: RouteComponentProps) => <Overview />}
/>
</Switch>
</EuiPageTemplate>
</>
</I18nProvider>
)
}
</CoreServicesConsumer>
);
};
13 changes: 13 additions & 0 deletions public/core_services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { createContext } from 'react';
import { CoreStart } from '../../../src/core/public';

const CoreServicesContext = createContext<CoreStart | null>(null);

const CoreServicesConsumer = CoreServicesContext.Consumer;

export { CoreServicesContext, CoreServicesConsumer };
1 change: 1 addition & 0 deletions public/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* stylelint-disable no-empty-source */
20 changes: 20 additions & 0 deletions public/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import './index.scss';

import { AiFlowDashboardsPlugin } from './plugin';

// This exports static code and TypeScript types,
// as well as, OpenSearch Dashboards Platform `plugin()` initializer.
export function plugin() {
owaiskazi19 marked this conversation as resolved.
Show resolved Hide resolved
return new AiFlowDashboardsPlugin();
}
export {
AiFlowDashboardsPluginSetup,
AiFlowDashboardsPluginStart,
} from './types';

export * from './core_services';
8 changes: 8 additions & 0 deletions public/pages/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export * from './use_cases';
export * from './workflows';
export * from './overview';
6 changes: 6 additions & 0 deletions public/pages/overview/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { Overview } from './overview';
23 changes: 23 additions & 0 deletions public/pages/overview/overview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

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';

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

return (
<EuiPageHeader>
<EuiText>Welcome to the AI Application Builder!</EuiText>
</EuiPageHeader>
);
}
6 changes: 6 additions & 0 deletions public/pages/use_cases/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { UseCases } from './use_cases';
26 changes: 26 additions & 0 deletions public/pages/use_cases/use_cases.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

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';

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

return (
<EuiPageHeader>
<EuiText>Use cases page placeholder...</EuiText>
</EuiPageHeader>
);
}
6 changes: 6 additions & 0 deletions public/pages/workflows/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { Workflows } from './workflows';
26 changes: 26 additions & 0 deletions public/pages/workflows/workflows.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

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';

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

return (
<EuiPageHeader>
<EuiText>Workflows page placeholder...</EuiText>
</EuiPageHeader>
);
}
46 changes: 46 additions & 0 deletions public/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
AppMountParameters,
CoreSetup,
CoreStart,
Plugin,
} from '../../../src/core/public';
import {
AiFlowDashboardsPluginSetup,
AiFlowDashboardsPluginStart,
} from './types';
import { PLUGIN_ID } from '../common';

export class AiFlowDashboardsPlugin
implements Plugin<AiFlowDashboardsPluginSetup, AiFlowDashboardsPluginStart> {
public setup(core: CoreSetup): AiFlowDashboardsPluginSetup {
// Register the plugin in the side navigation
core.application.register({
id: PLUGIN_ID,
title: 'AI Application Builder',
category: {
id: 'opensearch',
label: 'OpenSearch plugins',
order: 2000,
},
// TODO: can i remove this below order
order: 5000,
owaiskazi19 marked this conversation as resolved.
Show resolved Hide resolved
async mount(params: AppMountParameters) {
const { renderApp } = await import('./render_app');
const [coreStart] = await core.getStartServices();
return renderApp(coreStart, params);
},
});
return {};
}

public start(core: CoreStart): AiFlowDashboardsPluginStart {
return {};
}

public stop() {}
}
31 changes: 31 additions & 0 deletions public/render_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
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>
</Router>,
element
);

return () => ReactDOM.unmountComponentAtNode(element);
};
15 changes: 15 additions & 0 deletions public/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { NavigationPublicPluginStart } from '../../../src/plugins/navigation/public';

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface AiFlowDashboardsPluginSetup {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface AiFlowDashboardsPluginStart {}

export interface AppPluginStartDependencies {
navigation: NavigationPublicPluginStart;
}
24 changes: 24 additions & 0 deletions public/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export enum Navigation {
AiApplicationBuilder = 'AI Application Builder',
UseCases = 'Use Cases',
Workflows = 'Workflows',
}

export enum APP_PATH {
HOME = '/',
USE_CASES = '/use-cases',
WORKSPACE = '/workspace',
WORKFLOWS = '/workflows',
WORKFLOW_DETAIL = '/workflows/:workflowId/',
}

export const BREADCRUMBS = Object.freeze({
AI_APPLICATION_BUILDER: { text: 'AI application builder', href: '#/' },
USE_CASES: { text: 'Use cases', href: `#${APP_PATH.USE_CASES}` },
WORKFLOWS: { text: 'Workflows', href: `#${APP_PATH.WORKFLOWS}` },
});
Loading
Loading