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

[Manual Backport 2.x] Combined backport of Discover 2.0 commits #4872

Merged
  •  
  •  
  •  
6 changes: 3 additions & 3 deletions packages/osd-stylelint-config/config/global_selectors.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"src/plugins/vis_builder/public/application/components/searchable_dropdown.scss",
"src/plugins/vis_builder/public/application/components/side_nav.scss",
"packages/osd-ui-framework/src/components/button/button_group/_button_group.scss",
"src/plugins/discover/public/application/components/sidebar/discover_sidebar.scss",
"src/plugins/discover/public/application/angular/doc_table/components/table_row/_open.scss"
"src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.scss",
"src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/_open.scss"
]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"font-family": {
"explanation": "All \"font-family\" styles should be inherited from OUI themes and components. Remove the rule.",
"approved": [
"src/plugins/discover/public/application/_discover.scss",
"src/plugins/discover_legacy/public/application/_discover.scss",
"src/plugins/maps_legacy/public/map/_leaflet_overrides.scss",
"src/plugins/maps_legacy/public/map/_legend.scss",
"src/plugins/opensearch_dashboards_legacy/public/font_awesome/font_awesome.scss",
Expand All @@ -12,7 +12,8 @@
"src/plugins/data/public/ui/typeahead/_suggestion.scss",
"src/plugins/vis_type_timeseries/public/application/components/_error.scss",
"packages/osd-ui-framework/src/components/form/check_box/_check_box.scss",
"src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss"
"src/plugins/discover/public/application/components/doc_viewer/doc_viewer.scss",
"src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.scss"
]
}
}
}
7 changes: 7 additions & 0 deletions src/plugins/data_explorer/.i18nrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"prefix": "dataExplorer",
"paths": {
"dataExplorer": "."
},
"translations": ["translations/ja-JP.json"]
}
11 changes: 11 additions & 0 deletions src/plugins/data_explorer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# dataExplorer

A OpenSearch Dashboards plugin

---

## Development

See the [OpenSearch Dashboards contributing
guide](https://github.com/opensearch-project/OpenSearch-Dashboards/blob/main/CONTRIBUTING.md) for instructions
setting up your development environment.
7 changes: 7 additions & 0 deletions src/plugins/data_explorer/common/index.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 = 'data-explorer';
export const PLUGIN_NAME = 'Data Explorer';
18 changes: 18 additions & 0 deletions src/plugins/data_explorer/opensearch_dashboards.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"id": "dataExplorer",
"version": "1.0.0",
"opensearchDashboardsVersion": "opensearchDashboards",
"server": true,
"ui": true,
"requiredPlugins": [
"data",
"navigation",
"embeddable",
"expressions"
],
"optionalPlugins": [],
"requiredBundles": [
"opensearchDashboardsReact",
"opensearchDashboardsUtils"
]
}
41 changes: 41 additions & 0 deletions src/plugins/data_explorer/public/application.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider as ReduxProvider } from 'react-redux';
import { Router, Route, Switch } from 'react-router-dom';
import { AppMountParameters, CoreStart } from '../../../core/public';
import { OpenSearchDashboardsContextProvider } from '../../opensearch_dashboards_react/public';
import { DataExplorerServices } from './types';
import { DataExplorerApp } from './components/app';
import { Store } from './utils/state_management';

export const renderApp = (
core: CoreStart,
services: DataExplorerServices,
params: AppMountParameters,
store: Store
) => {
const { history, element } = params;
ReactDOM.render(
<Router history={history}>
<OpenSearchDashboardsContextProvider services={services}>
<ReduxProvider store={store}>
<services.i18n.Context>
<Switch>
<Route path={[`/:appId`, '/']} exact={false}>
<DataExplorerApp params={params} />
</Route>
</Switch>
</services.i18n.Context>
</ReduxProvider>
</OpenSearchDashboardsContextProvider>
</Router>,
element
);

return () => ReactDOM.unmountComponentAtNode(element);
};

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions src/plugins/data_explorer/public/components/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { AppMountParameters } from '../../../../core/public';
import { useView } from '../utils/use';
import { AppContainer } from './app_container';
import { useOpenSearchDashboards } from '../../../opensearch_dashboards_react/public';
import { DataExplorerServices } from '../types';
import { syncQueryStateWithUrl } from '../../../data/public';

export const DataExplorerApp = ({ params }: { params: AppMountParameters }) => {
const { view } = useView();
const {
services: {
data: { query },
osdUrlStateStorage,
},
} = useOpenSearchDashboards<DataExplorerServices>();
const { pathname } = useLocation();

useEffect(() => {
// syncs `_g` portion of url with query services
const { stop } = syncQueryStateWithUrl(query, osdUrlStateStorage);

return () => stop();

// this effect should re-run when pathname is changed to preserve querystring part,
// so the global state is always preserved
}, [query, osdUrlStateStorage, pathname]);

return <AppContainer view={view} params={params} />;
};
18 changes: 18 additions & 0 deletions src/plugins/data_explorer/public/components/app_container.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
$osdHeaderOffset: $euiHeaderHeightCompensation;

.deSidebar {
max-width: 462px;
min-width: 400px;
}

.deLayout {
height: calc(100vh - #{$osdHeaderOffset});

&__canvas {
height: 100%;
}
}

.headerIsExpanded .deLayout {
height: calc(100vh - #{$osdHeaderOffset * 2});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { AppContainer } from './app_container';
import { View } from '../services/view_service/view';
import { AppMountParameters } from '../../../../core/public';
import { render } from 'test_utils/testing_lib_helpers';

describe('DataExplorerApp', () => {
const createView = () => {
return new View({
id: 'test-view',
title: 'Test View',
defaultPath: '/test-path',
appExtentions: {} as any,
Canvas: (() => <div>canvas</div>) as any,
Panel: (() => <div>panel</div>) as any,
Context: (() => <div>Context</div>) as any,
});
};

const params: AppMountParameters = {
element: document.createElement('div'),
history: {} as any,
onAppLeave: jest.fn(),
setHeaderActionMenu: jest.fn(),
appBasePath: '',
};

it('should render NoView when a non existent view is selected', () => {
const { container } = render(<AppContainer params={params} />);

expect(container).toContainHTML('View not found');
});

it('should render the canvas and panel when selected', () => {
const view = createView();
const { container } = render(<AppContainer view={view} params={params} />);

expect(container).toMatchSnapshot();
});
});
39 changes: 39 additions & 0 deletions src/plugins/data_explorer/public/components/app_container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { EuiPage, EuiPageBody } from '@elastic/eui';
import { Suspense } from 'react';
import { AppMountParameters } from '../../../../core/public';
import { Sidebar } from './sidebar';
import { NoView } from './no_view';
import { View } from '../services/view_service/view';
import './app_container.scss';

export const AppContainer = ({ view, params }: { view?: View; params: AppMountParameters }) => {
// TODO: Make this more robust.
if (!view) {
return <NoView />;
}

const { Canvas, Panel, Context } = view;

// Render the application DOM.
return (
<EuiPage className="deLayout" paddingSize="none">
{/* TODO: improve fallback state */}
<Suspense fallback={<div>Loading...</div>}>
<Context {...params}>
<Sidebar>
<Panel {...params} />
</Sidebar>
<EuiPageBody className="deLayout__canvas">
<Canvas {...params} />
</EuiPageBody>
</Context>
</Suspense>
</EuiPage>
);
};
40 changes: 40 additions & 0 deletions src/plugins/data_explorer/public/components/no_view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { EuiPageTemplate, EuiEmptyPrompt } from '@elastic/eui';
import { FormattedMessage } from '@osd/i18n/react';

export const NoView = () => {
return (
<EuiPageTemplate
template="centeredContent"
className="dePageTemplate"
pageContentProps={{
role: 'alertdialog',
color: 'plain',
hasBorder: false,
}}
>
<EuiEmptyPrompt
iconType="alert"
iconColor="danger"
title={
<h2>
<FormattedMessage id="dataExplorer.noView.title" defaultMessage="View not found" />
</h2>
}
body={
<p>
<FormattedMessage
id="dataExplorer.noView.body"
defaultMessage="The view you are trying to access does not exist. Please check the URL and try again."
/>
</p>
}
/>
</EuiPageTemplate>
);
};
Loading
Loading