Skip to content

Commit

Permalink
poc for maps data source support (#18)
Browse files Browse the repository at this point in the history
poc for maps data source support
  • Loading branch information
junqiu-lei authored Mar 27, 2024
1 parent 4f413a7 commit d1c28a0
Show file tree
Hide file tree
Showing 12 changed files with 249 additions and 74 deletions.
2 changes: 1 addition & 1 deletion opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
"server": true,
"ui": true,
"requiredPlugins": ["regionMap", "opensearchDashboardsReact", "opensearchDashboardsUtils", "navigation", "savedObjects", "data", "embeddable", "visualizations"],
"optionalPlugins": ["home"]
"optionalPlugins": ["home", "dataSource", "dataSourceManagement"]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
},
"devDependencies": {
"@types/react-test-renderer": "^18.0.7",
"cypress": "^13.6.3",
"cypress": "9.5.4",
"cypress-multi-reporters": "^1.5.0",
"prettier": "^2.1.1"
}
Expand Down
6 changes: 5 additions & 1 deletion public/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import { MapServices } from './types';
import { MapsDashboardsApp } from './components/app';
import { OpenSearchDashboardsContextProvider } from '../../../src/plugins/opensearch_dashboards_react/public';

export const renderApp = ({ element }: AppMountParameters, services: MapServices) => {
export const renderApp = (
{ element }: AppMountParameters,
services: MapServices,
dataSourceManagementEnabled: boolean
) => {
ReactDOM.render(
<OpenSearchDashboardsContextProvider services={services}>
<MapsDashboardsApp />
Expand Down
6 changes: 5 additions & 1 deletion public/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ export const MapsDashboardsApp = () => {
<I18nProvider>
<Switch>
<Route path={[APP_PATH.CREATE_MAP, APP_PATH.EDIT_MAP]} render={() => <MapPage />} />
<Route exact path={APP_PATH.LANDING_PAGE_PATH} render={() => <MapsList />} />
<Route
exact
path={APP_PATH.LANDING_PAGE_PATH}
render={() => <MapsList />}
/>
</Switch>
</I18nProvider>
</Router>
Expand Down
28 changes: 27 additions & 1 deletion public/components/layer_control_panel/layer_control_panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { IndexPattern } from '../../../../../src/plugins/data/public';
import { AddLayerPanel } from '../add_layer_panel';
import { LayerConfigPanel } from '../layer_config';
import { MapLayerSpecification } from '../../model/mapLayerType';
import { LAYER_ICON_TYPE_MAP } from '../../../common';
import { DASHBOARDS_MAPS_LAYER_TYPE, LAYER_ICON_TYPE_MAP } from '../../../common';
import { useOpenSearchDashboards } from '../../../../../src/plugins/opensearch_dashboards_react/public';
import { MapServices } from '../../types';
import { MapState } from '../../model/mapState';
Expand All @@ -49,18 +49,22 @@ interface Props {
selectedLayerConfig: MapLayerSpecification | undefined;
setSelectedLayerConfig: (layerConfig: MapLayerSpecification | undefined) => void;
setIsUpdatingLayerRender: (isUpdatingLayerRender: boolean) => void;
setDataSourceRefIds: (dataSourceRefIds: string[]) => void;
}

export const LayerControlPanel = memo(
({
maplibreRef,
setLayers,
layers,
layersIndexPatterns,
setLayersIndexPatterns,
zoom,
isReadOnlyMode,
selectedLayerConfig,
setSelectedLayerConfig,
setIsUpdatingLayerRender,
setDataSourceRefIds,
}: Props) => {
const { services } = useOpenSearchDashboards<MapServices>();

Expand Down Expand Up @@ -205,12 +209,34 @@ export const LayerControlPanel = memo(
setIsDeleteLayerModalVisible(true);
};

const removeDataLayerDataSource = (layer: MapLayerSpecification) => {
console.log('removeDataLayerDataSource is called');
if (layer.type === DASHBOARDS_MAPS_LAYER_TYPE.DOCUMENTS) {
const indexPatternId = layer.source.indexPatternId;
const indexPattern = layersIndexPatterns.find((idp) => idp.id === indexPatternId);
if (indexPattern) {
const indexPatternClone = [...layersIndexPatterns];
const index = indexPatternClone.findIndex((idp) => idp.id === indexPatternId);
if (index > -1) {
indexPatternClone.splice(index, 1);
setLayersIndexPatterns(indexPatternClone);
}
setDataSourceRefIds(
indexPatternClone
.filter((i) => i.dataSourceRef !== undefined)
.map((i) => indexPattern.dataSourceRef!.id)
);
}
}
};

const onDeleteLayerConfirm = () => {
if (selectedDeleteLayer) {
removeLayers(maplibreRef.current!, selectedDeleteLayer.id, true);
removeLayer(selectedDeleteLayer.id);
setIsDeleteLayerModalVisible(false);
setSelectedDeleteLayer(undefined);
removeDataLayerDataSource(selectedDeleteLayer);
}
};

Expand Down
10 changes: 10 additions & 0 deletions public/components/map_container/map_container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ interface MapContainerProps {
isUpdatingLayerRender: boolean;
setIsUpdatingLayerRender: (isUpdatingLayerRender: boolean) => void;
addSpatialFilter: (shape: ShapeFilter, label: string | null, relation: GeoShapeRelation) => void;
dataSourceRefIds: string[];
setDataSourceRefIds: (refIds: string[]) => void;
}

export class MapsServiceError extends Error {
Expand All @@ -67,6 +69,7 @@ export const MapContainer = ({
isUpdatingLayerRender,
setIsUpdatingLayerRender,
addSpatialFilter,
setDataSourceRefIds,
}: MapContainerProps) => {
const { services } = useOpenSearchDashboards<MapServices>();

Expand Down Expand Up @@ -245,6 +248,12 @@ export const MapContainer = ({
);
const cloneLayersIndexPatterns = [...layersIndexPatterns, newIndexPattern];
setLayersIndexPatterns(cloneLayersIndexPatterns);
console.log('Print-------updateIndexPatterns');
setDataSourceRefIds(
cloneLayersIndexPatterns
.filter((indexPattern) => indexPattern.dataSourceRef !== undefined)
.map((indexPattern) => indexPattern.dataSourceRef!.id)
);
}
};

Expand All @@ -271,6 +280,7 @@ export const MapContainer = ({
selectedLayerConfig={selectedLayerConfig}
setSelectedLayerConfig={setSelectedLayerConfig}
setIsUpdatingLayerRender={setIsUpdatingLayerRender}
setDataSourceRefIds={setDataSourceRefIds}
/>
)}
{mounted && tooltipState === TOOLTIP_STATE.DISPLAY_FEATURES && maplibreRef.current && (
Expand Down
52 changes: 50 additions & 2 deletions public/components/map_page/map_page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { MapState } from '../../model/mapState';
import { GeoShapeFilterMeta, ShapeFilter } from '../../../../../src/plugins/data/common';
import { buildGeoShapeFilterMeta } from '../../model/geo/filter';
import { FilterBar } from '../filter_bar/filter_bar';
import { getDataLayers } from '../../model/layersFunctions';

export interface DashboardProps {
timeRange?: TimeRange;
Expand All @@ -51,13 +52,15 @@ export const MapComponent = ({ mapIdFromSavedObject, dashboardProps }: MapCompon
savedObjects: { client: savedObjectsClient },
} = services;
const [layers, setLayers] = useState<MapLayerSpecification[]>([]);
const [savedMapObject, setSavedMapObject] =
useState<SimpleSavedObject<MapSavedObjectAttributes> | null>();
const [savedMapObject, setSavedMapObject] = useState<SimpleSavedObject<
MapSavedObjectAttributes
> | null>();
const [layersIndexPatterns, setLayersIndexPatterns] = useState<IndexPattern[]>([]);
const maplibreRef = useRef<Maplibre | null>(null);
const [mapState, setMapState] = useState<MapState>(getInitialMapState());
const [isUpdatingLayerRender, setIsUpdatingLayerRender] = useState(true);
const isReadOnlyMode = !!dashboardProps;
const [dataSourceRefIds, setDataSourceRefIds] = useState<string[]>([]);

useEffect(() => {
if (mapIdFromSavedObject) {
Expand All @@ -68,14 +71,20 @@ export const MapComponent = ({ mapIdFromSavedObject, dashboardProps }: MapCompon
setMapState(savedMapState);
setLayers(layerList);
const savedIndexPatterns: IndexPattern[] = [];
const remoteDataSourceIds: string[] = [];
layerList.forEach(async (layer: MapLayerSpecification) => {
if (layer.type === DASHBOARDS_MAPS_LAYER_TYPE.DOCUMENTS) {
const indexPatternId = layer.source.indexPatternId;
const indexPattern = await services.data.indexPatterns.get(indexPatternId);
savedIndexPatterns.push(indexPattern);
if (indexPattern.dataSourceRef) {
remoteDataSourceIds.push(indexPattern.dataSourceRef.id);
}
}
});
console.log(remoteDataSourceIds, 'Print-----remoteDataSourceIds-----');
setLayersIndexPatterns(savedIndexPatterns);
setDataSourceRefIds(remoteDataSourceIds);
});
} else {
const initialDefaultLayer: MapLayerSpecification = getLayerConfigMap()[
Expand All @@ -87,6 +96,42 @@ export const MapComponent = ({ mapIdFromSavedObject, dashboardProps }: MapCompon
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

// useEffect(() => {
// const remoteDataSourceIds: string[] = [];
// console.log(layersIndexPatterns, 'xxxPrint--useEffect---layersIndexPatterns-----');
// // layersIndexPatterns.forEach((indexPattern: IndexPattern) => {
// // console.log('should print', indexPattern);
// // console.log(layersIndexPatterns, 'Print-----layersIndexPatterns-----');
// // if (indexPattern.dataSourceRef) {
// // remoteDataSourceIds.push(indexPattern.dataSourceRef.id);
// // } else {
// // remoteDataSourceIds.push('');
// // }
// // });
// console.log(layersIndexPatterns.length, 'Print-----layersIndexPatterns.length-----');
// // for (let i = 0; i < layersIndexPatterns.length; i++) {
// // console.log('should print', layersIndexPatterns[i]);
// // if (layersIndexPatterns[i].dataSourceRef) {
// // remoteDataSourceIds.push(layersIndexPatterns[i].dataSourceRef.id);
// // } else {
// // remoteDataSourceIds.push('');
// // }
// // }
// // layersIndexPatterns.map((indexPattern) => console.log(indexPattern.dataSourceRef?.id));
//
// for await (const indexPattern of layersIndexPatterns) {
// console.log('should print', indexPattern);
// if (indexPattern.dataSourceRef) {
// remoteDataSourceIds.push(indexPattern.dataSourceRef.id);
// } else {
// remoteDataSourceIds.push('');
// }
// }
//
// setDataSourceRefIds(remoteDataSourceIds);
// console.log(remoteDataSourceIds, 'useEffect remoteDataSourceIds');
// }, [layersIndexPatterns]);

const addSpatialFilter = (
shape: ShapeFilter,
label: string | null,
Expand Down Expand Up @@ -124,6 +169,7 @@ export const MapComponent = ({ mapIdFromSavedObject, dashboardProps }: MapCompon
mapState={mapState}
setMapState={setMapState}
setIsUpdatingLayerRender={setIsUpdatingLayerRender}
dataSourceRefIds={dataSourceRefIds}
/>
)}
{!isReadOnlyMode && !!mapState.spatialMetaFilters?.length && (
Expand All @@ -149,6 +195,8 @@ export const MapComponent = ({ mapIdFromSavedObject, dashboardProps }: MapCompon
isUpdatingLayerRender={isUpdatingLayerRender}
setIsUpdatingLayerRender={setIsUpdatingLayerRender}
addSpatialFilter={addSpatialFilter}
dataSourceRefIds={dataSourceRefIds}
setDataSourceRefIds={setDataSourceRefIds}
/>
</div>
);
Expand Down
102 changes: 82 additions & 20 deletions public/components/map_top_nav/top_nav_menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ interface MapTopNavMenuProps {
setMapState: (mapState: MapState) => void;
originatingApp?: string;
setIsUpdatingLayerRender: (isUpdatingLayerRender: boolean) => void;
dataSourceRefIds: string[];
}

export const MapTopNavMenu = ({
Expand All @@ -37,6 +38,7 @@ export const MapTopNavMenu = ({
mapState,
setMapState,
setIsUpdatingLayerRender,
dataSourceRefIds,
}: MapTopNavMenuProps) => {
const { services } = useOpenSearchDashboards<MapServices>();
const {
Expand All @@ -48,6 +50,9 @@ export const MapTopNavMenu = ({
application: { navigateToApp },
embeddable,
scopedHistory,
dataSourceManagement,
savedObjects: { client: savedObjectsClient },
notifications,
} = services;

const [title, setTitle] = useState<string>('');
Expand Down Expand Up @@ -132,27 +137,84 @@ export const MapTopNavMenu = ({
});
}, [services, mapIdFromUrl, layers, title, description, mapState, originatingApp]);

const dataSourceManagementEnabled: boolean = !!dataSourceManagement;
// const remoteDataSourceIds: (string | undefined)[] = Array.from(
// new Set(layersIndexPatterns.map((indexPattern) => indexPattern.dataSourceRef?.id))
// );

// useEffect(() => {
// console.log(layersIndexPatterns, 'Print-----layersIndexPatterns-----');
// console.log(layersIndexPatterns.length, 'Print-----layersIndexPatterns.length-----');
// const remoteDataSourceIds: string[] = layersIndexPatterns
// .filter((indexPattern) => indexPattern.dataSourceRef !== undefined)
// .map((indexPattern) => indexPattern.dataSourceRef!.id);
// console.log(remoteDataSourceIds, 'Print-----remoteDataSourceIds-----');
// setDataSourceRefIds(remoteDataSourceIds);
// }, [layersIndexPatterns]);
//
// const dataSourceRefIds1: string[] = layersIndexPatterns
// .filter((indexPattern) => indexPattern.dataSourceRef !== undefined)
// .map((indexPattern) => indexPattern.dataSourceRef!.id);
//
// console.log(
// layersIndexPatterns.length,
// 'Print-----layersIndexPatterns.length-out-of-effect-----MapTopNavMenu'
// );
// console.log(layersIndexPatterns, 'Print-----layersIndexPatterns--out-of-effect---MapTopNavMenu');
// console.log(dataSourceRefIds1, 'Print-----dataSourceRefIds1--out-of-effect---MapTopNavMenu');

// const remoteDataSourceIds: string[] = layersIndexPatterns.map(
// (indexPattern) => indexPattern.dataSourceRef!.id
// );
// console.log(remoteDataSourceIds, 'remoteDataSourceIds');

// for (const indexPattern of layersIndexPatterns) {
// console.log(indexPattern, 'indexPattern');
// console.log(indexPattern.dataSourceRef, 'indexPattern.dataSourceRef');
// console.log(indexPattern.dataSourceRef?.id, 'indexPattern.dataSourceRef?.id');
// }

console.log(dataSourceRefIds, 'Print-----dataSourceRefIds-----MapTopNavMenu');

return (
// @ts-ignore
<TopNavMenu
appName={MAPS_APP_ID}
config={config}
setMenuMountPoint={setHeaderActionMenu}
indexPatterns={layersIndexPatterns || []}
showSearchBar={true}
showFilterBar={false}
showDatePicker={true}
showQueryBar={true}
showSaveQuery={true}
showQueryInput={true}
onQuerySubmit={handleQuerySubmit}
dateRangeFrom={dateFrom}
dateRangeTo={dateTo}
query={queryConfig}
isRefreshPaused={isRefreshPaused}
refreshInterval={refreshIntervalValue}
onRefresh={refreshDataLayerRender}
onRefreshChange={onRefreshChange}
/>
<>
<TopNavMenu
appName={MAPS_APP_ID}
config={config}
setMenuMountPoint={setHeaderActionMenu}
indexPatterns={layersIndexPatterns || []}
showSearchBar={true}
showFilterBar={false}
showDatePicker={true}
showQueryBar={true}
showSaveQuery={true}
showQueryInput={true}
onQuerySubmit={handleQuerySubmit}
dateRangeFrom={dateFrom}
dateRangeTo={dateTo}
query={queryConfig}
isRefreshPaused={isRefreshPaused}
refreshInterval={refreshIntervalValue}
onRefresh={refreshDataLayerRender}
onRefreshChange={onRefreshChange}
/>
{dataSourceManagementEnabled && (
// @ts-ignore
<dataSourceManagement.ui.DataSourceMenu
setMenuMountPoint={setHeaderActionMenu}
showDataSourceAggregatedView={true}
activeDatasourceIds={dataSourceRefIds}
savedObjects={savedObjectsClient}
notifications={notifications}
appName={'mapsPageDataSourceMenu'}
hideLocalCluster={false}
fullWidth={true}
displayAllCompatibleDataSources={false}
showTopNavMenuItems={true}
config={config}
/>
)}
</>
);
};
Loading

0 comments on commit d1c28a0

Please sign in to comment.