Skip to content

Commit

Permalink
Support multi data source in Region map (opensearch-project#6654)
Browse files Browse the repository at this point in the history
Signed-off-by: Junqiu Lei <[email protected]>
  • Loading branch information
junqiu-lei authored Apr 26, 2024
1 parent 857f8cb commit fea8202
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 38 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [Multiple Datasource] Modify selectable picker to remove group label and close popover after selection ([#6515](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6515))
- [Multiple Datasource] Extract the button component for datasource picker to avoid duplicate code ([#6559](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6559))
- [Workspace] Add workspaces filter to saved objects page. ([#6458](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6458))
- [Multiple Datasource] Support multi data source in Region map ([#6654](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6654))

### 🐛 Bug Fixes

Expand Down
5 changes: 3 additions & 2 deletions src/plugins/region_map/opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
],
"requiredBundles": [
"opensearchDashboardsUtils",
"charts",
"charts",
"visDefaultEditor"
]
],
"optionalPlugins": ["dataSource"]
}
12 changes: 8 additions & 4 deletions src/plugins/region_map/public/choropleth_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ export class ChoroplethLayer extends OpenSearchDashboardsMapLayer {
leaflet,
layerChosenByUser,
http,
uiSettings
uiSettings,
dataSourceRefId
) {
super();
this._serviceSettings = serviceSettings;
Expand All @@ -119,6 +120,7 @@ export class ChoroplethLayer extends OpenSearchDashboardsMapLayer {
this._http = http;
this._visParams = null;
this._uiSettings = uiSettings;
this._dataSourceRefId = dataSourceRefId;

// eslint-disable-next-line no-undef
this._leafletLayer = this._leaflet.geoJson(null, {
Expand Down Expand Up @@ -249,7 +251,7 @@ CORS configuration of the server permits requests from the OpenSearch Dashboards
try {
const services = getServices(this._http);
const indexSize = this._uiSettings.get(CUSTOM_VECTOR_MAP_MAX_SIZE_SETTING);
const result = await services.getIndexData(this._layerName, indexSize);
const result = await services.getIndexData(this._layerName, indexSize, this._dataSourceRefId);

const finalResult = {
type: 'FeatureCollection',
Expand Down Expand Up @@ -346,7 +348,8 @@ CORS configuration of the server permits requests from the OpenSearch Dashboards
leaflet,
layerChosenByUser,
http,
uiSettings
uiSettings,
dataSourceRefId
) {
const clonedLayer = new ChoroplethLayer(
name,
Expand All @@ -359,7 +362,8 @@ CORS configuration of the server permits requests from the OpenSearch Dashboards
leaflet,
layerChosenByUser,
http,
uiSettings
uiSettings,
dataSourceRefId
);
clonedLayer.setJoinField(this._joinField);
clonedLayer.setColorRamp(this._colorRamp);
Expand Down
26 changes: 16 additions & 10 deletions src/plugins/region_map/public/region_map_type.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,18 @@ export function createRegionMapTypeDefinition(dependencies) {
return arr1.concat(arr2).filter((item) => !arr1.includes(item) || !arr2.includes(item));
};

const getCustomIndices = async () => {
const getCustomIndices = async (dataSourceRefId) => {
try {
const result = await services.getCustomIndices();
const result = await services.getCustomIndices(dataSourceRefId);
return result.resp;
} catch (e) {
return false;
}
};

const getJoinFields = async (indexName) => {
const getJoinFields = async (indexName, dataSourceRefId) => {
try {
const result = await services.getIndexMapping(indexName);
const result = await services.getIndexMapping(indexName, dataSourceRefId);
const properties = diffArray(Object.keys(result.resp[indexName].mappings.properties), [
'location',
]);
Expand All @@ -82,17 +82,17 @@ export function createRegionMapTypeDefinition(dependencies) {
}
};

const addSchemaToCustomLayer = async (customlayer) => {
const joinFields = await getJoinFields(customlayer.index);
const addSchemaToCustomLayer = async (customlayer, dataSourceRefId) => {
const joinFields = await getJoinFields(customlayer, dataSourceRefId);
const customLayerWithSchema = {
attribution:
'<a rel="noreferrer noopener" href="http://www.naturalearthdata.com/about/terms-of-use">Made with NaturalEarth</a>',
created_at: '2017-04-26T17:12:15.978370',
format: 'geojson',
fields: joinFields,
id: customlayer.index,
id: customlayer,
meta: undefined,
name: customlayer.index,
name: customlayer,
origin: 'user-upload',
};

Expand Down Expand Up @@ -147,6 +147,7 @@ provided base maps, or add your own. Darker colors represent higher values.',
vectorLayers: [],
customVectorLayers: [],
tmsLayers: [],
dataSourceRefId: '',
},
schemas: new Schemas([
{
Expand Down Expand Up @@ -199,7 +200,12 @@ provided base maps, or add your own. Darker colors represent higher values.',
const customVectorLayers = regionmapsConfig.layers.map(
mapToLayerWithId.bind(null, ORIGIN.OPENSEARCH_DASHBOARDS_YML)
);
const customIndices = await getCustomIndices();

// Read the data source reference id from index pattern if available, empty string means for local clusters
const dataSourceRefId = vis.data.indexPattern?.dataSourceRef?.id || '';
vis.type.editorConfig.collections.dataSourceRefId = dataSourceRefId;

const customIndices = await getCustomIndices(dataSourceRefId);

let selectedLayer = vectorLayers[0];
let selectedJoinField = selectedLayer ? selectedLayer.fields[0] : null;
Expand All @@ -214,7 +220,7 @@ provided base maps, or add your own. Darker colors represent higher values.',
.filter(
(layer) => !vectorLayers.some((vectorLayer) => vectorLayer.layerId === layer.layerId)
);
const promises = customIndices.map(addSchemaToCustomLayer);
const promises = customIndices.map((idx) => addSchemaToCustomLayer(idx, dataSourceRefId));
const newCustomLayers = await Promise.all(promises);

// backfill v1 manifest for now
Expand Down
7 changes: 4 additions & 3 deletions src/plugins/region_map/public/region_map_visualization.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ export function createRegionMapVisualization({
const metricFieldFormatter = getFormatService().deserialize(this._params.metric.format);

this._choroplethLayer.setLayerChosenByUser(this._params.layerChosenByUser);

this._choroplethLayer.setJoinField(this._params.selectedJoinField.name);
this._choroplethLayer.setColorRamp(truncatedColorMaps[this._params.colorSchema].value);
this._choroplethLayer.setLineWeight(this._params.outlineWeight);
Expand Down Expand Up @@ -231,7 +230,8 @@ export function createRegionMapVisualization({
(await lazyLoadMapsLegacyModules()).L,
this._params.layerChosenByUser,
http,
uiSettings
uiSettings,
this.vis.type.editorConfig.collections.dataSourceRefId
);
} else {
const { ChoroplethLayer } = await import('./choropleth_layer');
Expand All @@ -246,7 +246,8 @@ export function createRegionMapVisualization({
(await lazyLoadMapsLegacyModules()).L,
this._params.layerChosenByUser,
http,
uiSettings
uiSettings,
this.vis.type.editorConfig.collections.dataSourceRefId
);
}
this._choroplethLayer.setLayerChosenByUser(this._params.layerChosenByUser);
Expand Down
31 changes: 19 additions & 12 deletions src/plugins/region_map/public/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,53 @@
import { CoreStart, HttpFetchError } from 'opensearch-dashboards/public';

export interface Services {
getCustomIndices: () => Promise<undefined | HttpFetchError>;
getIndexData: (indexName: string, size: number) => Promise<undefined | HttpFetchError>;
getIndexMapping: (indexName: string) => Promise<undefined | HttpFetchError>;
getCustomIndices: (dataSourceRefId: string) => Promise<undefined | HttpFetchError>;
getIndexData: (
indexName: string,
size: number,
dataSourceRefId: string
) => Promise<undefined | HttpFetchError>;
getIndexMapping: (
indexName: string,
dataSourceRefId: string
) => Promise<undefined | HttpFetchError>;
}

export function getServices(http: CoreStart['http']): Services {
return {
getCustomIndices: async () => {
getCustomIndices: async (dataSourceRefId: string) => {
try {
const response = await http.post('../api/geospatial/_indices', {
return await http.post('../api/geospatial/_indices', {
body: JSON.stringify({
index: '*-map',
}),
query: { dataSourceId: dataSourceRefId },
});
return response;
} catch (e) {
return e;
}
},
getIndexData: async (indexName: string, size: number) => {
getIndexData: async (indexName: string, size: number, dataSourceRefId: string) => {
try {
const response = await http.post('../api/geospatial/_search', {
return await http.post('../api/geospatial/_search', {
body: JSON.stringify({
index: indexName,
size,
}),
query: { dataSourceId: dataSourceRefId },
});
return response;
} catch (e) {
return e;
}
},
getIndexMapping: async (indexName: string) => {
getIndexMapping: async (indexName: string, dataSourceRefId: string) => {
try {
const response = await http.post('../api/geospatial/_mappings', {
return await http.post('../api/geospatial/_mappings', {
body: JSON.stringify({
index: indexName,
}),
query: { dataSourceId: dataSourceRefId },
});
return response;
} catch (e) {
return e;
}
Expand Down
38 changes: 31 additions & 7 deletions src/plugins/region_map/server/routes/opensearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,28 @@ export function registerGeospatialRoutes(router: IRouter) {
body: schema.object({
index: schema.string(),
}),
query: schema.maybe(schema.object({}, { unknowns: 'allow' })),
},
},
async (context, req, res) => {
const client = context.core.opensearch.client.asCurrentUser;
try {
const { index } = req.body;
const indices = await client.cat.indices({
index,
let client;
// @ts-ignore
if (!req.query.dataSourceId) {
client = context.core.opensearch.client.asCurrentUser;
} else {
// @ts-ignore
client = await context.dataSource.opensearch.getClient(req.query.dataSourceId);
}
const response = await client.cat.indices({
index: req.body.index,
format: 'json',
});
const indexNames = response.body.map((index: any) => index.index);
return res.ok({
body: {
ok: true,
resp: indices.body,
resp: indexNames,
},
});
} catch (err: any) {
Expand Down Expand Up @@ -59,10 +67,18 @@ export function registerGeospatialRoutes(router: IRouter) {
index: schema.string(),
size: schema.number(),
}),
query: schema.maybe(schema.object({}, { unknowns: 'allow' })),
},
},
async (context, req, res) => {
const client = context.core.opensearch.client.asCurrentUser;
let client;
// @ts-ignore
if (!req.query.dataSourceId) {
client = context.core.opensearch.client.asCurrentUser;
} else {
// @ts-ignore
client = await context.dataSource.opensearch.getClient(req.query.dataSourceId);
}
try {
const { index, size } = req.body;
const params = { index, body: {}, size };
Expand Down Expand Up @@ -91,10 +107,18 @@ export function registerGeospatialRoutes(router: IRouter) {
body: schema.object({
index: schema.string(),
}),
query: schema.maybe(schema.object({}, { unknowns: 'allow' })),
},
},
async (context, req, res) => {
const client = context.core.opensearch.client.asCurrentUser;
let client;
// @ts-ignore
if (!req.query.dataSourceId) {
client = context.core.opensearch.client.asCurrentUser;
} else {
// @ts-ignore
client = await context.dataSource.opensearch.getClient(req.query.dataSourceId);
}
try {
const { index } = req.body;
const mappings = await client.indices.getMapping({ index });
Expand Down

0 comments on commit fea8202

Please sign in to comment.