Skip to content

Commit

Permalink
[BUG]fix add sample notebooks (#2108)
Browse files Browse the repository at this point in the history
* fix add sample notebooks

Signed-off-by: sumukhswamy <[email protected]>

* changes for label

Signed-off-by: sumukhswamy <[email protected]>

* updated apis when MDS is disabled

Signed-off-by: sumukhswamy <[email protected]>

* asddressed comments

Signed-off-by: sumukhswamy <[email protected]>

* addressed comments

Signed-off-by: sumukhswamy <[email protected]>

* updated the comments

Signed-off-by: sumukhswamy <[email protected]>

---------

Signed-off-by: sumukhswamy <[email protected]>
  • Loading branch information
sumukhswamy authored Sep 4, 2024
1 parent 2ba055f commit 0550228
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 38 deletions.
65 changes: 51 additions & 14 deletions public/components/notebooks/components/helpers/modal_containers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,27 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useState } from 'react';
import {
EuiOverlayMask,
EuiConfirmModal,
EuiSmallButton,
EuiSmallButtonEmpty,
EuiCompressedFieldText,
EuiForm,
EuiCompressedFormRow,
EuiConfirmModal,
EuiForm,
EuiModal,
EuiModalBody,
EuiModalFooter,
EuiModalHeader,
EuiModalHeaderTitle,
EuiText,
EuiOverlayMask,
EuiSmallButton,
EuiSmallButtonEmpty,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import React, { useState } from 'react';
import { CoreStart, SavedObjectsStart } from '../../../../../../../src/core/public';
import { DataSourceManagementPluginSetup } from '../../../../../../../src/plugins/data_source_management/public/plugin';
import { dataSourceFilterFn } from '../../../../../common/utils/shared';
import { CustomInputModal } from './custom_modals/custom_input_modal';

/* The file contains helper functions for modal layouts
Expand Down Expand Up @@ -80,8 +84,26 @@ export const getSampleNotebooksModal = (
onCancel: (
event?: React.KeyboardEvent<HTMLDivElement> | React.MouseEvent<HTMLButtonElement, MouseEvent>
) => void,
onConfirm: (event?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
onConfirm: (event?: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void,
dataSourceEnabled: boolean,
dataSourceManagement: DataSourceManagementPluginSetup,
savedObjectsMDSClient: SavedObjectsStart,
notifications: CoreStart['notifications'],
handleSelectedDataSourceChange: (
dataSourceMDSId: string | undefined,
dataSourceMDSLabel: string | undefined
) => void
) => {
let DataSourceSelector;
const onSelectedDataSource = (e) => {
const dataConnectionId = e[0] ? e[0].id : undefined;
const dataConnectionLabel = e[0] ? e[0].label : undefined;
handleSelectedDataSourceChange(dataConnectionId, dataConnectionLabel);
};

if (dataSourceEnabled) {
DataSourceSelector = dataSourceManagement.ui.DataSourceSelector;
}
return (
<EuiOverlayMask>
<EuiConfirmModal
Expand All @@ -92,12 +114,27 @@ export const getSampleNotebooksModal = (
confirmButtonText="Yes"
defaultFocusedButton="confirm"
>
<EuiText size="s">
<p>
Do you want to add sample notebooks? This will also add Dashboards sample flights and
logs data if they have not been added.
</p>
</EuiText>
{dataSourceEnabled && (
<>
<EuiTitle size="s">
<h4>Select a Data source</h4>
</EuiTitle>
<DataSourceSelector
savedObjectsClient={savedObjectsMDSClient.client}
notifications={notifications}
onSelectedDataSource={onSelectedDataSource}
disabled={false}
fullWidth={false}
removePrepend={false}
dataSourceFilter={dataSourceFilterFn}
/>
</>
)}
<EuiSpacer />
<p>
Do you want to add sample notebooks? This will also add Dashboards sample flights and logs
data if they have not been added.
</p>
</EuiConfirmModal>
</EuiOverlayMask>
);
Expand Down
113 changes: 99 additions & 14 deletions public/components/notebooks/components/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ export class Main extends React.Component<MainProps, MainState> {

// Fetches path and id for all stored notebooks
fetchNotebooks = () => {
if (this.props.dataSourceEnabled) {
// If `MDS` is enabled, only fetch from the first endpoint.
return this.props.http
.get(`${NOTEBOOKS_API_PREFIX}/savedNotebook/`)
.then((savedNotebooksResponse) => {
this.setState({ data: savedNotebooksResponse.data });
})
.catch((err) => {
console.error('Issue in fetching the notebooks', err.body.message);
});
}
// If `MDS` is not enabled /savedNotebook/ API returns notebooks stored as saved objects, and the other one returns notebooks stored as observability objects.
return Promise.all([
this.props.http.get(`${NOTEBOOKS_API_PREFIX}/savedNotebook/`),
this.props.http.get(`${NOTEBOOKS_API_PREFIX}/`),
Expand Down Expand Up @@ -285,7 +297,7 @@ export class Main extends React.Component<MainProps, MainState> {
console.error(err.body.message);
});
};
addSampleNotebooks = async () => {
addSampleNotebooks = async (dataSourceMDSId?: string, dataSourceMDSLabel?: string) => {
try {
this.setState({ loading: true });
const flights = await this.props.http
Expand All @@ -296,7 +308,17 @@ export class Main extends React.Component<MainProps, MainState> {
search: 'opensearch_dashboards_sample_data_flights',
},
})
.then((resp) => resp.total === 0);
.then((resp) => {
if (resp.total === 0) {
return true;
}
const hasDataSourceMDSId = resp.saved_objects.some((obj) =>
obj.references.some((ref) => ref.type === 'data-source' && ref.id === dataSourceMDSId)
);

// Return true if dataSourceMDSId is not found in any references
return !hasDataSourceMDSId;
});
const logs = await this.props.http
.get('../api/saved_objects/_find', {
query: {
Expand All @@ -305,40 +327,99 @@ export class Main extends React.Component<MainProps, MainState> {
search: 'opensearch_dashboards_sample_data_logs',
},
})
.then((resp) => resp.total === 0);
if (flights || logs) this.setToast('Adding sample data. This can take some time.');
await Promise.all([
flights ? this.props.http.post('../api/sample_data/flights') : Promise.resolve(),
logs ? this.props.http.post('../api/sample_data/logs') : Promise.resolve(),
]);
.then((resp) => {
if (resp.total === 0) {
return true;
}
const hasDataSourceMDSId = resp.saved_objects.some((obj) =>
obj.references.some((ref) => ref.type === 'data-source' && ref.id === dataSourceMDSId)
);

// Return true if dataSourceMDSId is not found in any references
return !hasDataSourceMDSId;
});
if (flights) {
this.setToast('Adding sample data for flights. This can take some time.');
await this.props.http.post('../api/sample_data/flights', {
query: { data_source_id: dataSourceMDSId },
});
}
if (logs) {
this.setToast('Adding sample data for logs. This can take some time.');
await this.props.http.post('../api/sample_data/logs', {
query: { data_source_id: dataSourceMDSId },
});
}
const visIds: string[] = [];
await this.props.http
.get('../api/saved_objects/_find', {
query: {
type: 'visualization',
search_fields: 'title',
search: '[Logs] Response Codes Over Time + Annotations',
search:
`[Logs] Response Codes Over Time + Annotations` +
(dataSourceMDSLabel ? `_${dataSourceMDSLabel}` : ''),
},
})
.then((resp) => visIds.push(resp.saved_objects[0].id));
.then((resp) => {
if (this.props.dataSourceEnabled) {
const searchTitle = `[Logs] Response Codes Over Time + Annotations_${dataSourceMDSLabel}`;
const savedObjects = resp.saved_objects;

const foundObject = savedObjects.find((obj) => obj.attributes.title === searchTitle);
if (foundObject) {
visIds.push(foundObject.id);
}
} else {
visIds.push(resp.saved_objects[0].id);
}
});
await this.props.http
.get('../api/saved_objects/_find', {
query: {
type: 'visualization',
search_fields: 'title',
search: '[Logs] Unique Visitors vs. Average Bytes',
search:
`[Logs] Unique Visitors vs. Average Bytes` +
(dataSourceMDSLabel ? `_${dataSourceMDSLabel}` : ''),
},
})
.then((resp) => visIds.push(resp.saved_objects[0].id));
.then((resp) => {
if (this.props.dataSourceEnabled) {
const searchTitle = `[Logs] Unique Visitors vs. Average Bytes_${dataSourceMDSLabel}`;
const savedObjects = resp.saved_objects;

const foundObject = savedObjects.find((obj) => obj.attributes.title === searchTitle);
if (foundObject) {
visIds.push(foundObject.id);
}
} else {
visIds.push(resp.saved_objects[0].id);
}
});
await this.props.http
.get('../api/saved_objects/_find', {
query: {
type: 'visualization',
search_fields: 'title',
search: '[Flights] Flight Count and Average Ticket Price',
search:
`[Flights] Flight Count and Average Ticket Price` +
(dataSourceMDSLabel ? `_${dataSourceMDSLabel}` : ''),
},
})
.then((resp) => visIds.push(resp.saved_objects[0].id));
.then((resp) => {
if (this.props.dataSourceEnabled) {
const searchTitle = `[Flights] Flight Count and Average Ticket Price_${dataSourceMDSLabel}`;
const savedObjects = resp.saved_objects;

const foundObject = savedObjects.find((obj) => obj.attributes.title === searchTitle);
if (foundObject) {
visIds.push(foundObject.id);
}
} else {
visIds.push(resp.saved_objects[0].id);
}
});
await this.props.http
.post(`${NOTEBOOKS_API_PREFIX}/note/savedNotebook/addSampleNotebooks`, {
body: JSON.stringify({ visIds }),
Expand Down Expand Up @@ -393,6 +474,10 @@ export class Main extends React.Component<MainProps, MainState> {
parentBreadcrumb={this.props.parentBreadcrumb}
setBreadcrumbs={this.props.setBreadcrumbs}
setToast={this.setToast}
dataSourceManagement={this.props.dataSourceManagement}
notifications={this.props.notifications}
dataSourceEnabled={this.props.dataSourceEnabled}
savedObjectsMDSClient={this.props.savedObjectsMDSClient}
/>
)}
/>
Expand Down
52 changes: 42 additions & 10 deletions public/components/notebooks/components/note_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*/

import {
EuiSmallButton,
EuiCompressedFieldSearch,
EuiFlexGroup,
EuiFlexItem,
Expand All @@ -19,6 +18,7 @@ import {
EuiPageContentHeaderSection,
EuiPageHeader,
EuiPageHeaderSection,
EuiSmallButton,
EuiSpacer,
EuiTableFieldDataColumnType,
EuiText,
Expand All @@ -28,35 +28,49 @@ import truncate from 'lodash/truncate';
import moment from 'moment';
import React, { useEffect, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import { ChromeBreadcrumb } from '../../../../../../src/core/public';
import {
ChromeBreadcrumb,
CoreStart,
MountPoint,
SavedObjectsStart,
} from '../../../../../../src/core/public';
import { DataSourceManagementPluginSetup } from '../../../../../../src/plugins/data_source_management/public';
import {
CREATE_NOTE_MESSAGE,
NOTEBOOKS_DOCUMENTATION_URL,
} from '../../../../common/constants/notebooks';
import { UI_DATE_FORMAT } from '../../../../common/constants/shared';
import { setNavBreadCrumbs } from '../../../../common/utils/set_nav_bread_crumbs';
import { HeaderControlledComponentsWrapper } from '../../../../public/plugin_helpers/plugin_headerControl';
import { coreRefs } from '../../../framework/core_refs';
import {
DeleteNotebookModal,
getCustomModal,
getSampleNotebooksModal,
} from './helpers/modal_containers';
import { NotebookType } from './main';
import { setNavBreadCrumbs } from '../../../../common/utils/set_nav_bread_crumbs';
import { HeaderControlledComponentsWrapper } from '../../../../public/plugin_helpers/plugin_headerControl';
import { coreRefs } from '../../../framework/core_refs';

const newNavigation = coreRefs.chrome?.navGroup.getNavGroupEnabled();

interface NoteTableProps {
loading: boolean;
fetchNotebooks: () => void;
addSampleNotebooks: () => void;
addSampleNotebooks: (
dataSourceMDSId: string | undefined,
dataSourceLabel: string | undefined
) => void;
notebooks: NotebookType[];
createNotebook: (newNoteName: string) => void;
renameNotebook: (newNoteName: string, noteId: string) => void;
cloneNotebook: (newNoteName: string, noteId: string) => void;
deleteNotebook: (noteList: string[], toastMessage?: string) => void;
parentBreadcrumb: ChromeBreadcrumb;
setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => void;
dataSourceEnabled: boolean;
dataSourceManagement: DataSourceManagementPluginSetup;
setActionMenu: (menuMount: MountPoint | undefined) => void;
savedObjectsMDSClient: SavedObjectsStart;
notifications: CoreStart['notifications'];
// setToast: (title: string, color?: string, text?: string) => void;
}

Expand All @@ -69,6 +83,10 @@ export function NoteTable({
deleteNotebook,
parentBreadcrumb,
setBreadcrumbs,
dataSourceEnabled,
dataSourceManagement,
savedObjectsMDSClient,
notifications,
}: NoteTableProps) {
const [isModalVisible, setIsModalVisible] = useState(false); // Modal Toggle
const [modalLayout, setModalLayout] = useState(<EuiOverlayMask />); // Modal Layout
Expand Down Expand Up @@ -154,11 +172,25 @@ export function NoteTable({
};

const addSampleNotebooksModal = async () => {
let selectedDataSourceId: string | undefined;
let selectedDataSourceLabel: string | undefined;
const handleSelectedDataSourceChange = (id?: string, label?: string) => {
selectedDataSourceId = id;
selectedDataSourceLabel = label;
};
setModalLayout(
getSampleNotebooksModal(closeModal, async () => {
closeModal();
await addSampleNotebooks();
})
getSampleNotebooksModal(
closeModal,
async () => {
closeModal();
await addSampleNotebooks(selectedDataSourceId, selectedDataSourceLabel);
},
dataSourceEnabled,
dataSourceManagement,
savedObjectsMDSClient,
notifications,
handleSelectedDataSourceChange
)
);
showModal();
};
Expand Down

0 comments on commit 0550228

Please sign in to comment.