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

Moving Query Workbench to Dev Tools #349

Merged
merged 10 commits into from
Jul 19, 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
31 changes: 31 additions & 0 deletions common/utils/legacy_route_helper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export const convertLegacyWorkbenchUrl = (location: Location) => {
// Update pathname to new structure
let pathname = location.pathname.replace(
'app/opensearch-query-workbench',
'app/dev_tools#/opensearch-query-workbench'
);

// If the pathname ends with '/', remove it before appending the hash
if (pathname.endsWith('/')) {
pathname = pathname.slice(0, -1);
}

// Adjust the hash part of the URL
let hash = location.hash.replace('#/', '/');

// If hash contains "accelerate" or any random text, handle it properly
if (hash.includes('accelerate/')) {
hash = hash.replace('#/', '/');
} else if (hash.startsWith('#/')) {
hash = hash.replace('#/', '/');
}

const finalUrl = `${pathname}${hash}`;

return finalUrl;
};
2 changes: 1 addition & 1 deletion opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
"ui": true,
"supportedOSDataSourceVersions": ">=1.0.0",
"requiredOSDataSourcePlugins": ["opensearch-sql"],
"requiredPlugins": ["navigation", "opensearchDashboardsReact", "opensearchDashboardsUtils"],
"requiredPlugins": ["devTools", "navigation", "opensearchDashboardsReact", "opensearchDashboardsUtils"],
"optionalPlugins": ["observabilityDashboards", "dataSource", "dataSourceManagement"]
}
4 changes: 2 additions & 2 deletions public/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* SPDX-License-Identifier: Apache-2.0
*/


import React from 'react';
import ReactDOM from 'react-dom';
import { AppMountParameters, CoreStart } from '../../../src/core/public';
Expand All @@ -14,7 +13,7 @@ import { AppPluginStartDependencies } from './types';
export const renderApp = (
{ notifications, http, chrome, savedObjects }: CoreStart,
{ navigation, dataSource }: AppPluginStartDependencies,
{ appBasePath, element, setHeaderActionMenu }: AppMountParameters,
{ appBasePath, element, setHeaderActionMenu, dataSourceId }: AppMountParameters,
Copy link
Member

Choose a reason for hiding this comment

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

@TackAdam Did we test this with and without new nav? cc: @sumukhswamy

Copy link
Member

Choose a reason for hiding this comment

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

Thanks! Sumukh for validating offline that workbench works with MDS with and without new nav.

dataSourceManagement: DataSourceManagementPluginSetup
) => {
ReactDOM.render(
Expand All @@ -28,6 +27,7 @@ export const renderApp = (
dataSourceEnabled={!!dataSource}
dataSourceManagement={dataSourceManagement}
setActionMenu={setHeaderActionMenu}
dataSourceMDSId={dataSourceId}
/>,
element
);
Expand Down
41 changes: 23 additions & 18 deletions public/components/Main/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import { executeAsyncQuery } from '../../../common/utils/async_query_helpers';
import { fetchDataSources } from '../../../common/utils/fetch_datasources';
import * as pluginManifest from '../../../opensearch_dashboards.json';
import { coreRefs } from '../../framework/core_refs';
import { MESSAGE_TAB_LABEL } from '../../utils/constants';
import {
Tree,
Expand All @@ -61,8 +62,8 @@

interface ResponseData {
ok: boolean;
resp: any;

Check warning on line 65 in public/components/Main/main.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
body: any;

Check warning on line 66 in public/components/Main/main.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
}

export interface ResponseDetail<T> {
Expand All @@ -72,11 +73,11 @@
}

export interface TranslateResult {
[key: string]: any;

Check warning on line 76 in public/components/Main/main.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
}

export interface QueryMessage {
text: any;

Check warning on line 80 in public/components/Main/main.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
className: string;
}

Expand All @@ -96,13 +97,13 @@
[key: string]: {
nodes: Tree;
expandedRow?: {};
selectedNodes?: { [key: string]: any };

Check warning on line 100 in public/components/Main/main.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
};
}

export interface DataRow {
rowId: number;
data: { [key: string]: any };

Check warning on line 106 in public/components/Main/main.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
}

interface MainProps {
Expand All @@ -114,6 +115,7 @@
notifications: NotificationsStart;
dataSourceEnabled: boolean;
dataSourceManagement: DataSourceManagementPluginSetup;
dataSourceMDSId: string;
setActionMenu: (menuMount: MountPoint | undefined) => void;
}

Expand Down Expand Up @@ -150,7 +152,7 @@
}

const SUCCESS_MESSAGE = 'Success';
const errorQueryResponse = (queryResultResponseDetail: any) => {

Check warning on line 155 in public/components/Main/main.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
const errorMessage =
queryResultResponseDetail.errorMessage +
', this query is not runnable. \n \n' +
Expand Down Expand Up @@ -178,7 +180,7 @@
const dataRows: DataRow[] = [];

const schema: object[] = _.get(responseObj, 'schema');
const datarows: any[][] = _.get(responseObj, 'datarows');

Check warning on line 183 in public/components/Main/main.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
let queryType = 'default';

for (const column of schema.values()) {
Expand All @@ -203,7 +205,7 @@
}

for (const [id, field] of datarows.entries()) {
const row: { [key: string]: any } = {};

Check warning on line 208 in public/components/Main/main.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
row.TABLE_NAME = field[index];
const dataRow: DataRow = {
rowId: id,
Expand All @@ -216,7 +218,7 @@
case 'describe':
case 'default':
for (const [id, field] of schema.entries()) {
let alias: any = null;

Check warning on line 221 in public/components/Main/main.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected any. Specify a different type
try {
alias = _.get(field, 'alias');
} catch (e) {
Expand Down Expand Up @@ -290,7 +292,7 @@
isCallOutVisible: false,
cluster: 'Indexes',
dataSourceOptions: [],
selectedMDSDataConnectionId: '',
selectedMDSDataConnectionId: this.props.dataSourceMDSId,
mdsClusterName: '',
flintDataConnections: false,
};
Expand All @@ -301,19 +303,22 @@
}

componentDidMount() {
this.props.setBreadcrumbs([
{
text: 'Query Workbench',
href: '#',
},
]);
if (!coreRefs?.chrome?.navGroup.getNavGroupEnabled()) {
this.props.setBreadcrumbs([
{
text: 'Query Workbench',
href: '#',
},
]);
}

this.fetchFlintDataSources();
}

fetchFlintDataSources = () => {
fetchDataSources(
this.httpClient,
this.state.selectedMDSDataConnectionId,
this.props.dataSourceMDSId,
this.props.urlDataSource,
(dataOptions) => {
if (dataOptions.length > 0) {
Expand Down Expand Up @@ -435,7 +440,7 @@
const endpoint = '/api/sql_console/' + (_.isEqual(language, 'SQL') ? 'sqlquery' : 'pplquery');
let query = {};
if (this.props.dataSourceEnabled) {
query = { dataSourceMDSId: this.state.selectedMDSDataConnectionId };
query = { dataSourceMDSId: this.props.dataSourceMDSId };
}
const responsePromise = Promise.all(
queries.map((eachQuery: string) =>
Expand Down Expand Up @@ -570,7 +575,7 @@
});
}
},
this.state.selectedMDSDataConnectionId,
this.props.dataSourceMDSId,
(errorDetails: string) => {
this.setState({
asyncLoading: false,
Expand Down Expand Up @@ -599,7 +604,7 @@
if (queries.length > 0) {
let query = {};
if (this.props.dataSourceEnabled) {
query = { dataSourceMDSId: this.state.selectedMDSDataConnectionId };
query = { dataSourceMDSId: this.props.dataSourceMDSId };
}
const endpoint =
'/api/sql_console/' + (_.isEqual(language, 'SQL') ? 'translatesql' : 'translateppl');
Expand Down Expand Up @@ -651,7 +656,7 @@
if (queries.length > 0) {
let query = {};
if (this.props.dataSourceEnabled) {
query = { dataSourceMDSId: this.state.selectedMDSDataConnectionId };
query = { dataSourceMDSId: this.props.dataSourceMDSId };
}
Promise.all(
queries.map((eachQuery: string) =>
Expand Down Expand Up @@ -688,7 +693,7 @@
if (queries.length > 0) {
let query = {};
if (this.props.dataSourceEnabled) {
query = { dataSourceMDSId: this.state.selectedMDSDataConnectionId };
query = { dataSourceMDSId: this.props.dataSourceMDSId };
}
const endpoint = '/api/sql_console/' + (_.isEqual(language, 'SQL') ? 'sqlquery' : 'pplquery');
Promise.all(
Expand Down Expand Up @@ -726,7 +731,7 @@
if (queries.length > 0) {
let query = {};
if (this.props.dataSourceEnabled) {
query = { dataSourceMDSId: this.state.selectedMDSDataConnectionId };
query = { dataSourceMDSId: this.props.dataSourceMDSId };
}
const endpoint = '/api/sql_console/' + (_.isEqual(language, 'SQL') ? 'sqlcsv' : 'pplcsv');
Promise.all(
Expand Down Expand Up @@ -764,7 +769,7 @@
if (queries.length > 0) {
let query = {};
if (this.props.dataSourceEnabled) {
query = { dataSourceMDSId: this.state.selectedMDSDataConnectionId };
query = { dataSourceMDSId: this.props.dataSourceMDSId };
}
const endpoint = '/api/sql_console/' + (_.isEqual(language, 'SQL') ? 'sqltext' : 'ppltext');
Promise.all(
Expand Down Expand Up @@ -947,7 +952,7 @@
openAccelerationFlyout={
this.props.isAccelerationFlyoutOpen && !this.state.isAccelerationFlyoutOpened
}
dataSourceMDSId={this.state.selectedMDSDataConnectionId}
dataSourceMDSId={this.props.dataSourceMDSId}
setIsAccelerationFlyoutOpened={this.setIsAccelerationFlyoutOpened}
/>
);
Expand Down Expand Up @@ -1086,7 +1091,7 @@
onSelect={this.handleDataSelect}
urlDataSource={this.props.urlDataSource}
asyncLoading={this.state.asyncLoading}
dataSourceMDSId={this.state.selectedMDSDataConnectionId}
dataSourceMDSId={this.props.dataSourceMDSId}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
Expand All @@ -1105,7 +1110,7 @@
updateSQLQueries={this.updateSQLQueries}
refreshTree={this.state.refreshTree}
dataSourceEnabled={this.props.dataSourceEnabled}
dataSourceMDSId={this.state.selectedMDSDataConnectionId}
dataSourceMDSId={this.props.dataSourceMDSId}
clusterTab={this.state.cluster}
language={this.state.language}
updatePPLQueries={this.updatePPLQueries}
Expand Down
15 changes: 12 additions & 3 deletions public/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { DataSourceManagementPluginSetup } from '../../../../src/plugins/data_source_management/public';
import { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public';

import { coreRefs } from '../framework/core_refs';
import { Main } from './Main';

interface WorkbenchAppDeps {
Expand All @@ -24,20 +25,25 @@
savedObjects: CoreStart['savedObjects'];
dataSourceEnabled: boolean;
dataSourceManagement: DataSourceManagementPluginSetup;
dataSourceMDSId: string;
setActionMenu: (menuMount: MountPoint | undefined) => void;
}

export const WorkbenchApp = ({
basename,

Check failure on line 33 in public/components/app.tsx

View workflow job for this annotation

GitHub Actions / Lint

'basename' is defined but never used. Allowed unused args must match /^_/u
notifications,
http,
navigation,

Check failure on line 36 in public/components/app.tsx

View workflow job for this annotation

GitHub Actions / Lint

'navigation' is defined but never used. Allowed unused args must match /^_/u
chrome,
savedObjects,
dataSourceEnabled,
dataSourceManagement,
dataSourceMDSId: dataSourceId,
setActionMenu,
}: WorkbenchAppDeps) => {
const isNavGroupEnabled = coreRefs?.chrome?.navGroup.getNavGroupEnabled();
const basePath = isNavGroupEnabled ? 'opensearch-query-workbench' : '';

return (
<HashRouter>
<I18nProvider>
Expand All @@ -47,7 +53,7 @@
<Switch>
<Route
exact
path="/"
path={`/${basePath}`}
render={(props) => (
<Main
httpClient={http}
Expand All @@ -59,13 +65,14 @@
savedObjects={savedObjects}
dataSourceEnabled={dataSourceEnabled}
dataSourceManagement={dataSourceManagement}
dataSourceMDSId={dataSourceId}
setActionMenu={setActionMenu}
/>
)}
/>
<Route
exact
path="/:dataSource"
path={`/${basePath}/:dataSource`}
render={(props) => (
<Main
httpClient={http}
Expand All @@ -77,13 +84,14 @@
savedObjects={savedObjects}
dataSourceEnabled={dataSourceEnabled}
dataSourceManagement={dataSourceManagement}
dataSourceMDSId={dataSourceId}
setActionMenu={setActionMenu}
/>
)}
/>
<Route
exact
path="/accelerate/:dataSource"
path={`/${basePath}/accelerate/:dataSource`}
render={(props) => (
<Main
httpClient={http}
Expand All @@ -95,6 +103,7 @@
savedObjects={savedObjects}
dataSourceEnabled={dataSourceEnabled}
dataSourceManagement={dataSourceManagement}
dataSourceMDSId={dataSourceId}
setActionMenu={setActionMenu}
/>
)}
Expand Down
86 changes: 64 additions & 22 deletions public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,83 @@
*/

import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '../../../src/core/public';
import { DataSourcePluginSetup, DataSourcePluginStart } from '../../../src/plugins/data_source/public';
import {
DataSourcePluginSetup,
DataSourcePluginStart,
} from '../../../src/plugins/data_source/public';
import { DataSourceManagementPluginSetup } from '../../../src/plugins/data_source_management/public';
import { DevToolsSetup } from '../../../src/plugins/dev_tools/public';
import { PLUGIN_NAME } from '../common/constants';
import { convertLegacyWorkbenchUrl } from '../common/utils/legacy_route_helper';
import { registerObservabilityDependencies } from './dependencies/register_observability_dependencies';
import { coreRefs } from './framework/core_refs';
import { AppPluginStartDependencies, WorkbenchPluginSetup, WorkbenchPluginStart } from './types';
export interface WorkbenchPluginSetupDependencies {
dataSource: DataSourcePluginSetup;
dataSourceManagement: DataSourceManagementPluginSetup
dataSourceManagement: DataSourceManagementPluginSetup;
devTools: DevToolsSetup;
}

export interface WorkbenchPluginStartDependencies {
dataSource: DataSourcePluginStart;
}
export class WorkbenchPlugin implements Plugin<WorkbenchPluginSetup, WorkbenchPluginStart> {
public setup(core: CoreSetup, {dataSource, dataSourceManagement} : WorkbenchPluginSetupDependencies): WorkbenchPluginSetup {
// Register an application into the side navigation menu
core.application.register({
id: 'opensearch-query-workbench',
title: PLUGIN_NAME,
category: {
id: 'opensearch',
label: 'OpenSearch Plugins',
order: 2000,
},
order: 1000,
async mount(params: AppMountParameters) {
// Load application bundle
const { renderApp } = await import('./application');
// Get start services as specified in opensearch_dashboards.json
const [coreStart, depsStart] = await core.getStartServices();
// Render the application
return renderApp(coreStart, depsStart as AppPluginStartDependencies, params, dataSourceManagement);
},
});
public setup(
core: CoreSetup,
{ dataSource, dataSourceManagement, devTools }: WorkbenchPluginSetupDependencies
): WorkbenchPluginSetup {
const isNavGroupEnabled = core.chrome.navGroup.getNavGroupEnabled();

if (isNavGroupEnabled) {
devTools.register({
id: 'opensearch-query-workbench',
title: PLUGIN_NAME,
enableRouting: true,
order: 2,
async mount(params: AppMountParameters) {
// Load application bundle
const { renderApp } = await import('./application');
// Get start services as specified in opensearch_dashboards.json
const [coreStart, depsStart] = await core.getStartServices();
// Render the application
return renderApp(
coreStart,
depsStart as AppPluginStartDependencies,
params,
dataSourceManagement
);
},
});

// redirect legacy workbench URL to current URL under dev-tools
if (window.location.pathname.includes('app/opensearch-query-workbench')) {
window.location.assign(convertLegacyWorkbenchUrl(window.location));
}
} else {
core.application.register({
id: 'opensearch-query-workbench',
title: PLUGIN_NAME,
category: {
id: 'opensearch',
label: 'OpenSearch Plugins',
order: 2000,
},
order: 1000,
async mount(params: AppMountParameters) {
// Load application bundle
const { renderApp } = await import('./application');
// Get start services as specified in opensearch_dashboards.json
const [coreStart, depsStart] = await core.getStartServices();
// Render the application
return renderApp(
coreStart,
depsStart as AppPluginStartDependencies,
params,
dataSourceManagement
);
},
});
}

// Return methods that should be available to other plugins
return {};
Expand Down
Loading