You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by pp...@apache.org on 2025/09/25 07:09:03 UTC
(atlas) branch ATLAS-5132 created (now b36d70586)
This is an automated email from the ASF dual-hosted git repository.
ppawar pushed a change to branch ATLAS-5132
in repository https://gitbox.apache.org/repos/asf/atlas.git
at b36d70586 ATLAS-5132: [REACT UI] Unique Advanced/Search queries do not work as expected
This branch includes the following new commits:
new b36d70586 ATLAS-5132: [REACT UI] Unique Advanced/Search queries do not work as expected
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(atlas) 01/01: ATLAS-5132: [REACT UI] Unique Advanced/Search queries do not work as expected
Posted by pp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ppawar pushed a commit to branch ATLAS-5132
in repository https://gitbox.apache.org/repos/asf/atlas.git
commit b36d705866e68b733c05795d6e2e0702dbeca0ec
Author: Prasad Pawar <pr...@freestoneinfotech.com>
AuthorDate: Thu Sep 25 12:36:02 2025 +0530
ATLAS-5132: [REACT UI] Unique Advanced/Search queries do not work as expected
---
dashboard/src/components/Table/TableLayout.tsx | 50 +++++++-
dashboard/src/components/muiComponents.tsx | 26 ++--
dashboard/src/views/SearchResult/SearchResult.tsx | 134 +++++++++++++++++----
.../public/js/views/graph/LineageLayoutView.js | 4 +-
.../public/js/views/graph/TypeSystemTreeView.js | 7 +-
.../public/js/views/graph/LineageLayoutView.js | 4 +-
.../public/js/views/graph/TypeSystemTreeView.js | 7 +-
7 files changed, 186 insertions(+), 46 deletions(-)
diff --git a/dashboard/src/components/Table/TableLayout.tsx b/dashboard/src/components/Table/TableLayout.tsx
index f58d150b0..931bda7ac 100644
--- a/dashboard/src/components/Table/TableLayout.tsx
+++ b/dashboard/src/components/Table/TableLayout.tsx
@@ -374,14 +374,40 @@ const TableLayout: FC<TableProps> = ({
const [goToPageVal, setGoToPageVal] = useState<any>("");
const [rowSelection, setRowSelection] = useState({});
- const [sorting, setSorting] = useState<SortingState>(
- !isEmpty(defaultSortCol) ? defaultSortCol : []
+ const existingColumnIds = useMemo(
+ () =>
+ (!isEmpty(memoizedColumns)
+ ? memoizedColumns.map((c: any) => c.id || c.accessorKey)
+ : []) as string[],
+ [memoizedColumns]
);
+
+ const sanitizeSorting = (sortingState: SortingState) => {
+ if (isEmpty(sortingState)) return [] as SortingState;
+ return sortingState.filter(
+ (s: any) => s && existingColumnIds.includes(s.id)
+ );
+ };
+
+ const [sorting, setSorting] = useState<SortingState>(() => []);
+
const [columnOrder, setColumnOrder] = useState<any>(() =>
!isEmpty(memoizedColumns)
- ? memoizedColumns.map((c: any) => c.accessorKey)
+ ? memoizedColumns
+ .map((c: any) => c.id || c.accessorKey)
+ .filter(Boolean)
: []
);
+
+ useEffect(() => {
+ setColumnOrder(
+ !isEmpty(memoizedColumns)
+ ? memoizedColumns
+ .map((c: any) => c.id || c.accessorKey)
+ .filter(Boolean)
+ : []
+ )
+ }, [memoizedColumns])
const [columnVisibility, setColumnVisibility] = useState(defaultHideColumns);
const [tagModal, setTagModal] = useState<boolean>(false);
let currentParams = searchParams;
@@ -426,7 +452,7 @@ const TableLayout: FC<TableProps> = ({
columnVisibility: columnVisibilityParams
? defaultHideColumns
: columnVisibility,
- sorting,
+ sorting: sanitizeSorting(sorting),
pagination,
rowSelection,
columnOrder
@@ -437,6 +463,17 @@ const TableLayout: FC<TableProps> = ({
autoResetPageIndex: false
});
+ useEffect(() => {
+ setSorting((prev) => sanitizeSorting(prev));
+ setColumnOrder(
+ !isEmpty(memoizedColumns)
+ ? memoizedColumns
+ .map((c: any) => c.id || c.accessorKey)
+ .filter(Boolean)
+ : []
+ );
+ }, [existingColumnIds]);
+
useEffect(() => {
if (typeof fetchData === "function") {
fetchData({
@@ -474,7 +511,8 @@ const TableLayout: FC<TableProps> = ({
resetSorting(true);
resetRowSelection(true);
setRowSelection({});
- setSorting(!isEmpty(defaultSortCol) ? defaultSortCol : []);
+ const candidate = !isEmpty(defaultSortCol) ? defaultSortCol : []
+ setSorting(sanitizeSorting(candidate));
}, [typeParam, defaultSortCol, setSearchParams]);
const handleCloseTagModal = () => {
@@ -619,7 +657,7 @@ const TableLayout: FC<TableProps> = ({
items={columnOrder}
strategy={horizontalListSortingStrategy}
>
- {" "}
+
{headerGroup.headers.map((header) =>
header.isPlaceholder ? null : (
<DraggableTableHeader
diff --git a/dashboard/src/components/muiComponents.tsx b/dashboard/src/components/muiComponents.tsx
index fc4492ef1..cf96d2c6d 100644
--- a/dashboard/src/components/muiComponents.tsx
+++ b/dashboard/src/components/muiComponents.tsx
@@ -104,18 +104,20 @@ const CustomButton = ({
let mergedStyle = { ...defaultStyles, ...customStyles };
return (
- <Button
- variant={variant}
- color={color}
- sx={mergedStyle}
- onClick={onClick}
- size={size}
- endIcon={endIcon}
- startIcon={startIcon}
- disabled={disabled}
- >
- {children}
- </Button>
+ <Box component="span" sx={{ display: 'inline-flex' }}>
+ <Button
+ variant={variant}
+ color={color}
+ sx={mergedStyle}
+ onClick={onClick}
+ size={size}
+ endIcon={endIcon}
+ startIcon={startIcon}
+ disabled={disabled}
+ >
+ {children}
+ </Button>
+ </Box>
);
};
diff --git a/dashboard/src/views/SearchResult/SearchResult.tsx b/dashboard/src/views/SearchResult/SearchResult.tsx
index aa1cd0921..c181aa877 100644
--- a/dashboard/src/views/SearchResult/SearchResult.tsx
+++ b/dashboard/src/views/SearchResult/SearchResult.tsx
@@ -207,8 +207,17 @@ const SearchResult = ({ classificationParams, glossaryTypeParams }: any) => {
globalSearchParams.basicParams = params;
globalSearchParams.dslParams = dslParams;
- let searchTypeParams =
- searchParams.get("searchType") == "dsl" ? dslParams : params;
+
+ const qParam = searchParams.get("query");
+ if (qParam) {
+ try {
+ (globalSearchParams as any).basicParams.query = qParam;
+ (globalSearchParams as any).dslParams.query = qParam;
+ } catch (_e) {}
+ }
+
+ const isDslSearch = searchParams.get("searchType") == "dsl";
+ let searchTypeParams = isDslSearch ? dslParams : params;
try {
const searchResp = await getBasicSearchResult(
{
@@ -221,21 +230,43 @@ const SearchResult = ({ classificationParams, glossaryTypeParams }: any) => {
searchParams.get("searchType") || "basic"
);
const { data = {} } = searchResp || {};
- const { approximateCount, entities } = data || {};
- let totalCount = approximateCount;
- let dataLength;
- if (entities) {
- dataLength = entities?.length;
+
+ const hasEntities = Array.isArray((data as any)?.entities);
+ const hasDslAttributes =
+ Array.isArray((data as any)?.attributes) ||
+ Array.isArray((data as any)?.attributes?.name);
+ const hasDslValues =
+ Array.isArray((data as any)?.attributes?.values) ||
+ Array.isArray((data as any)?.values);
+
+ if (isDslSearch && !hasEntities && !hasDslAttributes) {
+ setSearchData({ entities: [] });
+ setIsEmptyData(true);
+ setLoader(false);
+ return;
+ }
+
+ let dataLength = 0;
+ let totalCountLocal = 0;
+ if (isDslSearch && !hasEntities && hasDslAttributes && hasDslValues) {
+ const vals = (data as any).attributes?.values || (data as any).values;
+ dataLength = (vals as any[])?.length || 0;
+ totalCountLocal = dataLength;
} else {
- dataLength = searchResp?.data?.length;
+ const { approximateCount, entities } = data as any;
+ dataLength = Array.isArray(entities) ? entities.length : 0;
+ totalCountLocal = approximateCount ?? dataLength;
}
+
if (!dataLength) {
setIsEmptyData(true);
setLoader(false);
} else {
setSearchData(searchResp.data);
- setTotalCount(totalCount || 0);
- setPageCount(Math.ceil(totalCount / pagination.pageSize));
+ setTotalCount(totalCountLocal || 0);
+ setPageCount(
+ Math.ceil((totalCountLocal || dataLength) / (pagination.pageSize || pageSize))
+ );
setLoader(false);
}
} catch (error: any) {
@@ -745,10 +776,40 @@ const SearchResult = ({ classificationParams, glossaryTypeParams }: any) => {
}
);
+ const isDslSearchMode = searchParams.get("searchType") === "dsl";
+ const getDslAttributeNames = () => {
+ const src: any = Array.isArray(searchData) ? searchData[0] : searchData;
+ if (!src) return [] as string[];
+ if (Array.isArray(src?.attributes)) {
+ return src.attributes
+ .map((a: any) => (typeof a === 'string' ? a : a?.name))
+ .filter(Boolean);
+ }
+ if (src?.attributes && Array.isArray(src?.attributes?.name)) {
+ return src.attributes.name as string[];
+ }
+ return [] as string[];
+ };
+ const sanitize = (name: string) =>
+ String(name).replace(/[^A-Za-z0-9_]/g, "_").replace(/_{2,}/g, "_");
+ const dslAttrNames = isDslSearchMode ? getDslAttributeNames() : [];
+ const dslColumns = dslAttrNames.map((label: string, idx: number) => {
+ const key = `dsl_${sanitize(label)}` || `dsl_${idx}`
+ return {
+ id: key,
+ accessorKey: key,
+ header: label,
+ cell: (info: any) => <span>{info.getValue()}</span>,
+ show: true
+ }
+ });
+
let allColumns =
- isEmpty(searchParams.get("type")) &&
- isEmpty(searchParams.get("tag")) &&
- !isEmpty(searchParams.get("term"))
+ isDslSearchMode && dslColumns.length > 0
+ ? dslColumns
+ : isEmpty(searchParams.get("type")) &&
+ isEmpty(searchParams.get("tag")) &&
+ !isEmpty(searchParams.get("term"))
? removeDuplicateObjects([...defaultColumns])
: removeDuplicateObjects([
...defaultColumns,
@@ -756,6 +817,8 @@ const SearchResult = ({ classificationParams, glossaryTypeParams }: any) => {
...defaultHideColumns
]);
+ const isDslAggregate = isDslSearchMode && dslColumns.length > 0;
+
const defaultColumnVisibility: any = (columns: any) => {
let columnsParams: any = searchParams.get("attributes");
let hideColumns: any = {};
@@ -778,7 +841,12 @@ const SearchResult = ({ classificationParams, glossaryTypeParams }: any) => {
return hideColumns;
};
- const getDefaultSort = useMemo(() => [{ id: "name", asc: true }], []);
+ const getDefaultSort = useMemo(() => {
+ if (isDslAggregate) {
+ return [] as any[]; // no default sorting for DSL aggregates
+ }
+ return [{ id: "name", asc: true }];
+ }, [isDslAggregate]);
return (
<Stack position="relative" gap={"1rem"}>
@@ -833,27 +901,49 @@ const SearchResult = ({ classificationParams, glossaryTypeParams }: any) => {
<TableLayout
fetchData={fetchSearchResult}
- data={searchData.entities || []}
+ data={
+ isDslSearchMode && dslColumns.length > 0
+ ? (() => {
+ const src: any = Array.isArray(searchData)
+ ? searchData[0]
+ : searchData;
+ const values: any[] = Array.isArray(src?.values)
+ ? src.values
+ : Array.isArray(src?.attributes?.values)
+ ? src.attributes.values
+ : [];
+ return values.map((row: any[], idx: number) => {
+ const obj: any = { id: `dsl-row-${idx}` };
+ dslAttrNames.forEach((n: string, i: number) => {
+ const colKey = `dsl_${sanitize(n)}`
+ obj[colKey] = Array.isArray(row) ? row[i] : row
+ });
+ return obj;
+ });
+ })()
+ : searchData.entities || []
+ }
columns={allColumns.filter(
(value: {}) => Object.keys(value).length !== 0
)}
emptyText="No Records found!"
isFetching={loader}
pageCount={pageCount}
- columnVisibilityParams={true}
- defaultColumnVisibility={defaultColumnVisibility(allColumns)}
+ // columnVisibilityParams={true}
+ columnVisibilityParams={!isDslAggregate}
+ defaultColumnVisibility={isDslAggregate ? {} : defaultColumnVisibility(allColumns)}
defaultColumnParams={defaultColumnsName.join(",")}
- columnVisibility={true}
+ columnVisibility={!isDslAggregate}
+ // columnVisibility={true}
refreshTable={refreshTable}
defaultSortCol={getDefaultSort}
clientSideSorting={true}
isClientSidePagination={false}
columnSort={true}
showPagination={true}
- showRowSelection={true}
- tableFilters={
- isEmpty(classificationParams || glossaryTypeParams) ? true : false
- }
+ showRowSelection={!isDslAggregate}
+ // showRowSelection={true}
+ tableFilters={true}
assignFilters={
!isEmpty(classificationParams || glossaryTypeParams)
? {
diff --git a/dashboardv2/public/js/views/graph/LineageLayoutView.js b/dashboardv2/public/js/views/graph/LineageLayoutView.js
index ce7692535..15f7d775f 100644
--- a/dashboardv2/public/js/views/graph/LineageLayoutView.js
+++ b/dashboardv2/public/js/views/graph/LineageLayoutView.js
@@ -576,7 +576,9 @@ define(['require',
if ((that.filterObj.isProcessHideCheck && obj && obj.isProcess) || (that.filterObj.isDeletedEntityHideCheck && obj && obj.isDeleted) || (Globals.isLineageOnDemandEnabled && obj && _.contains(["Input", "Output"], obj.btnType))) {
return;
}
- typeStr += '<option value="' + obj.guid + '">' + obj.displayText + '</option>';
+ var label = _.escape(obj.displayText);
+ var value = _.escape(obj.guid);
+ typeStr += '<option value="' + value + '">' + label + '</option>';
});
}
that.ui.lineageTypeSearch.html(typeStr);
diff --git a/dashboardv2/public/js/views/graph/TypeSystemTreeView.js b/dashboardv2/public/js/views/graph/TypeSystemTreeView.js
index 935cae001..a75139443 100644
--- a/dashboardv2/public/js/views/graph/TypeSystemTreeView.js
+++ b/dashboardv2/public/js/views/graph/TypeSystemTreeView.js
@@ -460,10 +460,13 @@ define([
var nodes = that.LineageHelperRef.getNodes();
if (!_.isEmpty(nodes)) {
_.each(nodes, function(obj) {
- searchStr += '<option value="' + obj.guid + '">' + obj.name + "</option>";
+ var label = _.escape(obj.name)
+ var value = _.escape(obj.guid)
+ searchStr += '<option value="' + value + '">' + label + "</option>";
if (obj.serviceType && !tempFilteMap[obj.serviceType]) {
tempFilteMap[obj.serviceType] = obj.serviceType;
- filterStr += '<option value="' + obj.serviceType + '">' + obj.serviceType + "</option>";
+ var svc = _.escape(obj.serviceType)
+ filterStr += '<option value="' + svc + '">' + svc + "</option>";
}
});
}
diff --git a/dashboardv3/public/js/views/graph/LineageLayoutView.js b/dashboardv3/public/js/views/graph/LineageLayoutView.js
index ce7692535..15f7d775f 100644
--- a/dashboardv3/public/js/views/graph/LineageLayoutView.js
+++ b/dashboardv3/public/js/views/graph/LineageLayoutView.js
@@ -576,7 +576,9 @@ define(['require',
if ((that.filterObj.isProcessHideCheck && obj && obj.isProcess) || (that.filterObj.isDeletedEntityHideCheck && obj && obj.isDeleted) || (Globals.isLineageOnDemandEnabled && obj && _.contains(["Input", "Output"], obj.btnType))) {
return;
}
- typeStr += '<option value="' + obj.guid + '">' + obj.displayText + '</option>';
+ var label = _.escape(obj.displayText);
+ var value = _.escape(obj.guid);
+ typeStr += '<option value="' + value + '">' + label + '</option>';
});
}
that.ui.lineageTypeSearch.html(typeStr);
diff --git a/dashboardv3/public/js/views/graph/TypeSystemTreeView.js b/dashboardv3/public/js/views/graph/TypeSystemTreeView.js
index 935cae001..a75139443 100644
--- a/dashboardv3/public/js/views/graph/TypeSystemTreeView.js
+++ b/dashboardv3/public/js/views/graph/TypeSystemTreeView.js
@@ -460,10 +460,13 @@ define([
var nodes = that.LineageHelperRef.getNodes();
if (!_.isEmpty(nodes)) {
_.each(nodes, function(obj) {
- searchStr += '<option value="' + obj.guid + '">' + obj.name + "</option>";
+ var label = _.escape(obj.name)
+ var value = _.escape(obj.guid)
+ searchStr += '<option value="' + value + '">' + label + "</option>";
if (obj.serviceType && !tempFilteMap[obj.serviceType]) {
tempFilteMap[obj.serviceType] = obj.serviceType;
- filterStr += '<option value="' + obj.serviceType + '">' + obj.serviceType + "</option>";
+ var svc = _.escape(obj.serviceType)
+ filterStr += '<option value="' + svc + '">' + svc + "</option>";
}
});
}