mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-11 00:35:22 +00:00

* Fix #1356: Add new entities to ES index from OpenMetadata server Co-authored-by: Sachin-chaurasiya <sachinchaurasiyachotey87@gmail.com>
318 lines
8.6 KiB
TypeScript
318 lines
8.6 KiB
TypeScript
/*
|
|
* Copyright 2021 Collate
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import { AxiosResponse } from 'axios';
|
|
import React, { useEffect, useRef, useState } from 'react';
|
|
import { Link } from 'react-router-dom';
|
|
import { getSuggestions } from '../../axiosAPIs/miscAPI';
|
|
import { SearchIndex } from '../../enums/search.enum';
|
|
import { serviceTypeLogo } from '../../utils/ServiceUtils';
|
|
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
|
import { getEntityLink } from '../../utils/TableUtils';
|
|
|
|
type SuggestionProp = {
|
|
searchText: string;
|
|
isOpen: boolean;
|
|
setIsOpen: (value: boolean) => void;
|
|
};
|
|
|
|
type CommonSource = {
|
|
fqdn: string;
|
|
service_type: string;
|
|
name: string;
|
|
};
|
|
|
|
type TableSource = {
|
|
table_id: string;
|
|
table_name: string;
|
|
} & CommonSource;
|
|
|
|
type DashboardSource = {
|
|
dashboard_id: string;
|
|
dashboard_name: string;
|
|
} & CommonSource;
|
|
|
|
type TopicSource = {
|
|
topic_id: string;
|
|
topic_name: string;
|
|
} & CommonSource;
|
|
|
|
type PipelineSource = {
|
|
pipeline_id: string;
|
|
pipeline_name: string;
|
|
} & CommonSource;
|
|
|
|
type DBTModelSource = {
|
|
dbt_model_id: string;
|
|
dbt_model_name: string;
|
|
} & CommonSource;
|
|
|
|
type Option = {
|
|
_index: string;
|
|
_source: TableSource &
|
|
DashboardSource &
|
|
TopicSource &
|
|
PipelineSource &
|
|
DBTModelSource;
|
|
};
|
|
|
|
const Suggestions = ({ searchText, isOpen, setIsOpen }: SuggestionProp) => {
|
|
const [options, setOptions] = useState<Array<Option>>([]);
|
|
const [tableSuggestions, setTableSuggestions] = useState<TableSource[]>([]);
|
|
const [topicSuggestions, setTopicSuggestions] = useState<TopicSource[]>([]);
|
|
const [dashboardSuggestions, setDashboardSuggestions] = useState<
|
|
DashboardSource[]
|
|
>([]);
|
|
|
|
const [pipelineSuggestions, setPipelineSuggestions] = useState<
|
|
PipelineSource[]
|
|
>([]);
|
|
const [DBTModelSuggestions, setDBTModelSuggestions] = useState<
|
|
DBTModelSource[]
|
|
>([]);
|
|
const isMounting = useRef(true);
|
|
|
|
const setSuggestions = (options: Array<Option>) => {
|
|
setTableSuggestions(
|
|
options
|
|
.filter((option) => option._index === SearchIndex.TABLE)
|
|
.map((option) => option._source)
|
|
);
|
|
setTopicSuggestions(
|
|
options
|
|
.filter((option) => option._index === SearchIndex.TOPIC)
|
|
.map((option) => option._source)
|
|
);
|
|
setDashboardSuggestions(
|
|
options
|
|
.filter((option) => option._index === SearchIndex.DASHBOARD)
|
|
.map((option) => option._source)
|
|
);
|
|
setPipelineSuggestions(
|
|
options
|
|
.filter((option) => option._index === SearchIndex.PIPELINE)
|
|
.map((option) => option._source)
|
|
);
|
|
setDBTModelSuggestions(
|
|
options
|
|
.filter((option) => option._index === SearchIndex.DBT_MODEL)
|
|
.map((option) => option._source)
|
|
);
|
|
};
|
|
|
|
const getGroupLabel = (index: string) => {
|
|
let label = '';
|
|
let icon = '';
|
|
switch (index) {
|
|
case SearchIndex.TOPIC:
|
|
label = 'Topics';
|
|
icon = Icons.TOPIC_GREY;
|
|
|
|
break;
|
|
case SearchIndex.DASHBOARD:
|
|
label = 'Dashboards';
|
|
icon = Icons.DASHBOARD_GREY;
|
|
|
|
break;
|
|
case SearchIndex.PIPELINE:
|
|
label = 'Pipelines';
|
|
icon = Icons.PIPELINE_GREY;
|
|
|
|
break;
|
|
case SearchIndex.DBT_MODEL:
|
|
label = 'DBT Models';
|
|
icon = Icons.DBTMODEL_GREY;
|
|
|
|
break;
|
|
case SearchIndex.TABLE:
|
|
default:
|
|
label = 'Tables';
|
|
icon = Icons.TABLE_GREY;
|
|
|
|
break;
|
|
}
|
|
|
|
return (
|
|
<div className="tw-flex tw-items-center">
|
|
<SVGIcons alt="icon" className="tw-h-4 tw-w-4 tw-ml-2" icon={icon} />
|
|
<p className="tw-px-2 tw-py-2 tw-text-grey-muted tw-text-xs">{label}</p>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const getSuggestionElement = (
|
|
fqdn: string,
|
|
serviceType: string,
|
|
name: string,
|
|
index: string
|
|
) => {
|
|
return (
|
|
<div
|
|
className="tw-flex tw-items-center hover:tw-bg-body-hover"
|
|
key={fqdn}>
|
|
<img
|
|
alt={serviceType}
|
|
className="tw-inline tw-h-4 tw-w-4 tw-ml-2"
|
|
src={serviceTypeLogo(serviceType)}
|
|
/>
|
|
<Link
|
|
className="tw-block tw-px-4 tw-py-2 tw-text-sm"
|
|
data-testid="data-name"
|
|
id={fqdn.replace(/\./g, '')}
|
|
to={getEntityLink(index, fqdn)}
|
|
onClick={() => setIsOpen(false)}>
|
|
{name}
|
|
</Link>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const getEntitiesSuggestions = () => {
|
|
return (
|
|
<div className="py-1" role="none">
|
|
{tableSuggestions.length > 0 && (
|
|
<>
|
|
{getGroupLabel(SearchIndex.TABLE)}
|
|
|
|
{tableSuggestions.map((suggestion: TableSource) => {
|
|
const fqdn = suggestion.fqdn;
|
|
const name = suggestion.name;
|
|
const serviceType = suggestion.service_type;
|
|
|
|
return getSuggestionElement(
|
|
fqdn,
|
|
serviceType,
|
|
name,
|
|
SearchIndex.TABLE
|
|
);
|
|
})}
|
|
</>
|
|
)}
|
|
{topicSuggestions.length > 0 && (
|
|
<>
|
|
{getGroupLabel(SearchIndex.TOPIC)}
|
|
|
|
{topicSuggestions.map((suggestion: TopicSource) => {
|
|
const fqdn = suggestion.fqdn;
|
|
const name = suggestion.name;
|
|
const serviceType = suggestion.service_type;
|
|
|
|
return getSuggestionElement(
|
|
fqdn,
|
|
serviceType,
|
|
name,
|
|
SearchIndex.TOPIC
|
|
);
|
|
})}
|
|
</>
|
|
)}
|
|
{dashboardSuggestions.length > 0 && (
|
|
<>
|
|
{getGroupLabel(SearchIndex.DASHBOARD)}
|
|
|
|
{dashboardSuggestions.map((suggestion: DashboardSource) => {
|
|
const fqdn = suggestion.fqdn;
|
|
const name = suggestion.name;
|
|
const serviceType = suggestion.service_type;
|
|
|
|
return getSuggestionElement(
|
|
fqdn,
|
|
serviceType,
|
|
name,
|
|
SearchIndex.DASHBOARD
|
|
);
|
|
})}
|
|
</>
|
|
)}
|
|
{pipelineSuggestions.length > 0 && (
|
|
<>
|
|
{getGroupLabel(SearchIndex.PIPELINE)}
|
|
|
|
{pipelineSuggestions.map((suggestion: PipelineSource) => {
|
|
const fqdn = suggestion.fqdn;
|
|
const name = suggestion.name;
|
|
const serviceType = suggestion.service_type;
|
|
|
|
return getSuggestionElement(
|
|
fqdn,
|
|
serviceType,
|
|
name,
|
|
SearchIndex.PIPELINE
|
|
);
|
|
})}
|
|
</>
|
|
)}
|
|
{DBTModelSuggestions.length > 0 && (
|
|
<>
|
|
{getGroupLabel(SearchIndex.DBT_MODEL)}
|
|
|
|
{DBTModelSuggestions.map((suggestion: DBTModelSource) => {
|
|
const fqdn = suggestion.fqdn;
|
|
const name = suggestion.name;
|
|
const serviceType = suggestion.service_type;
|
|
|
|
return getSuggestionElement(
|
|
fqdn,
|
|
serviceType,
|
|
name,
|
|
SearchIndex.DBT_MODEL
|
|
);
|
|
})}
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (!isMounting.current) {
|
|
getSuggestions(searchText).then((res: AxiosResponse) => {
|
|
if (res.data) {
|
|
setOptions(res.data.suggest['table-suggest'][0].options);
|
|
setSuggestions(res.data.suggest['table-suggest'][0].options);
|
|
setIsOpen(true);
|
|
}
|
|
});
|
|
}
|
|
}, [searchText]);
|
|
|
|
// alwyas Keep this useEffect at the end...
|
|
useEffect(() => {
|
|
isMounting.current = false;
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
{options.length > 0 && isOpen ? (
|
|
<>
|
|
<button
|
|
className="tw-z-10 tw-fixed tw-inset-0 tw-h-full tw-w-full tw-bg-black tw-opacity-0"
|
|
onClick={() => setIsOpen(false)}
|
|
/>
|
|
<div
|
|
aria-labelledby="menu-button"
|
|
aria-orientation="vertical"
|
|
className="tw-origin-top-right tw-absolute tw-z-10
|
|
tw-w-full tw-mt-1 tw-rounded-md tw-shadow-lg
|
|
tw-bg-white tw-ring-1 tw-ring-black tw-ring-opacity-5 focus:tw-outline-none"
|
|
role="menu">
|
|
{getEntitiesSuggestions()}
|
|
</div>
|
|
</>
|
|
) : null}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default Suggestions;
|