- {totalDatasetRows === 0 ? (
- "No records to display"
+ {memoizedData.length === 0 ? (
+ 'No records to display'
+ ) : showAuditPaginationSummary ? (
+ <>
+ Showing {memoizedData.length.toLocaleString()}{' '}
+ {memoizedData.length === 1 ? 'record' : 'records'} From{' '}
+ {auditRangeStart.toLocaleString()} -{' '}
+ {auditRangeEnd.toLocaleString()}
+ >
) : (
<>
Showing {footerRangeStart.toLocaleString()}-
- {footerRangeEnd.toLocaleString()} of{" "}
- {totalDatasetRows.toLocaleString()}{" "}
- {totalDatasetRows === 1 ? "record" : "records"}
+ {footerRangeEnd.toLocaleString()} of{' '}
+ {totalDatasetRows.toLocaleString()}{' '}
+ {totalDatasetRows === 1 ? 'record' : 'records'}
>
)}
diff --git a/dashboard/src/components/muiComponents.tsx b/dashboard/src/components/muiComponents.tsx
index cf96d2c6d23..12ee53af455 100644
--- a/dashboard/src/components/muiComponents.tsx
+++ b/dashboard/src/components/muiComponents.tsx
@@ -90,7 +90,8 @@ const CustomButton = ({
size,
endIcon,
startIcon,
- disabled
+ disabled,
+ ...rest
}: ButtonProps | any) => {
let defaultStyles = {
fontWeight: "600 !important",
@@ -114,6 +115,7 @@ const CustomButton = ({
endIcon={endIcon}
startIcon={startIcon}
disabled={disabled}
+ {...rest}
>
{children}
diff --git a/dashboard/src/models/tableLayoutType.ts b/dashboard/src/models/tableLayoutType.ts
index 4fa240f6f2d..84b13a95d19 100644
--- a/dashboard/src/models/tableLayoutType.ts
+++ b/dashboard/src/models/tableLayoutType.ts
@@ -61,4 +61,9 @@ export interface TableProps {
defaultPageSize?: number;
/** Client pagination: invoked when the user changes page size (e.g. sync schema relationship chunk limit). */
onClientPageSizeChange?: (pageSize: number) => void;
+ /**
+ * Admin audit table: API does not return a total count. Footer shows
+ * "Showing {n} records From {start} - {end}" instead of "… of {total}".
+ */
+ paginationSummaryVariant?: 'default' | 'audit';
}
diff --git a/dashboard/src/redux/slice/sessionSlice.ts b/dashboard/src/redux/slice/sessionSlice.ts
index cf91a555060..82e49757191 100644
--- a/dashboard/src/redux/slice/sessionSlice.ts
+++ b/dashboard/src/redux/slice/sessionSlice.ts
@@ -75,7 +75,7 @@ const sessionSlice = createSlice({
state.sessionObj = {
loading: false,
data: null,
- error: action.payload as string
+ error: (action.payload as string) || action.error?.message || 'An error occurred'
};
});
}
diff --git a/dashboard/src/utils/Global.ts b/dashboard/src/utils/Global.ts
index bdbff111a73..5d20cb123c1 100644
--- a/dashboard/src/utils/Global.ts
+++ b/dashboard/src/utils/Global.ts
@@ -23,27 +23,27 @@ const dateFormat = "MM/DD/YYYY";
const globalSession = (sessionData: any) => {
globalSessionData.restCrsfHeader =
- sessionData["atlas.rest-csrf.custom-header"] || "";
+ sessionData["atlas.rest-csrf.custom-header"] ?? "";
globalSessionData.crsfToken = sessionData["_csrfToken"];
globalSessionData.debugMetrics = sessionData["atlas.debug.metrics.enabled"];
globalSessionData.entityCreate =
- sessionData["atlas.entity.create.allowed"] || true;
+ sessionData["atlas.entity.create.allowed"] ?? true;
globalSessionData.entityUpdate =
- sessionData["atlas.entity.update.allowed"] || true;
+ sessionData["atlas.entity.update.allowed"] ?? true;
globalSessionData.taskTabEnabled =
- sessionData["atlas.tasks.enabled"] || false;
+ sessionData["atlas.tasks.enabled"] ?? false;
globalSessionData.sessionTimeout =
- sessionData["atlas.session.timeout.secs"] || 900;
+ sessionData["atlas.session.timeout.secs"] ?? 900;
globalSessionData.uiTaskTabEnabled =
sessionData["atlas.tasks.ui.tab.enabled"];
globalSessionData.relationshipSearch =
- sessionData["atlas.relationship.search.enabled"] || false;
+ sessionData["atlas.relationship.search.enabled"] ?? false;
globalSessionData.isLineageOnDemandEnabled =
- sessionData["atlas.lineage.on.demand.enabled"] || false;
+ sessionData["atlas.lineage.on.demand.enabled"] ?? false;
globalSessionData.lineageNodeCount =
- sessionData["atlas.lineage.on.demand.default.node.count"] || 3;
+ sessionData["atlas.lineage.on.demand.default.node.count"] ?? 3;
globalSessionData.isTimezoneFormatEnabled =
- sessionData["atlas.ui.date.timezone.format.enabled"] || true;
+ sessionData["atlas.ui.date.timezone.format.enabled"] ?? true;
};
export { globalSession, entityImgPath, dateTimeFormat, dateFormat };
diff --git a/dashboard/src/utils/Utils.ts b/dashboard/src/utils/Utils.ts
index b404c9d040f..38556b9b543 100644
--- a/dashboard/src/utils/Utils.ts
+++ b/dashboard/src/utils/Utils.ts
@@ -340,7 +340,7 @@ const getEntityIconPath = (options: any) => {
};
const serverError = (error: any, toastId: any) => {
- // fetchApi already surfaces 403 via serverErrorHandler (toast); avoid duplicate.
+ // fetchApi already surfaces 403 via deferred toast.error; avoid duplicate.
if (error?.response?.status === 403) {
return;
}
diff --git a/dashboard/src/views/Administrator/Audits/AdminAuditTable.tsx b/dashboard/src/views/Administrator/Audits/AdminAuditTable.tsx
index 379dbbb6c33..e8e72bd4455 100644
--- a/dashboard/src/views/Administrator/Audits/AdminAuditTable.tsx
+++ b/dashboard/src/views/Administrator/Audits/AdminAuditTable.tsx
@@ -252,6 +252,7 @@ const AdminAuditTable = () => {
}
}}
queryBuilder={false}
+ paginationSummaryVariant="audit"
/>
diff --git a/dashboard/src/views/Administrator/Audits/AuditsFilter/AuditFiltersFields.tsx b/dashboard/src/views/Administrator/Audits/AuditsFilter/AuditFiltersFields.tsx
index 70bc8cd0be0..5cba22c6a1d 100644
--- a/dashboard/src/views/Administrator/Audits/AuditsFilter/AuditFiltersFields.tsx
+++ b/dashboard/src/views/Administrator/Audits/AuditsFilter/AuditFiltersFields.tsx
@@ -25,7 +25,8 @@ import moment from "moment";
import type { Field, RuleType } from "react-querybuilder";
import { toFullOption } from "react-querybuilder";
-export const validator = (r: RuleType) => !!r.value;
+export const validator = (r: RuleType) =>
+ r.value !== undefined && r.value !== null && r.value !== "";
let defaultRange = "Last 7 Days";
const getDateConfig = (ruleObj, name, operator) => {
let valueObj = ruleObj
@@ -160,6 +161,10 @@ export const getObjDef = (
groupType?: any,
isSystemAttr?: any
): any => {
+ if (!allDataObj || !attrObj) {
+ return;
+ }
+
const { enums } = allDataObj;
let getLableWithType = function (label: string, name: string) {
if (
diff --git a/dashboard/src/views/BusinessMetadata/BusinessMetadataAtrributeForm.tsx b/dashboard/src/views/BusinessMetadata/BusinessMetadataAtrributeForm.tsx
index d32eb70176e..cf3a0d8c3e9 100644
--- a/dashboard/src/views/BusinessMetadata/BusinessMetadataAtrributeForm.tsx
+++ b/dashboard/src/views/BusinessMetadata/BusinessMetadataAtrributeForm.tsx
@@ -38,7 +38,6 @@ import {
tooltipClasses,
TooltipProps,
styled,
- FilterOptionsState,
ToggleButton,
ToggleButtonGroup
} from "@mui/material";
@@ -74,15 +73,42 @@ const HtmlTooltip = styled(({ className, ...props }: TooltipProps) => (
}
}));
+export const filterAttributeEnumOptions = (
+ options: { value: string }[],
+ inputValue: string,
+ selectedValues: { value: string }[]
+) => {
+ const lowerInputValue = inputValue ? inputValue.toLowerCase() : '';
+ const filteredOptions: { value: string }[] = [];
+
+ let selectedEnumValues = !isEmpty(selectedValues)
+ ? selectedValues.map((obj: { value: string }) => {
+ return obj.value.toLowerCase()
+ })
+ : [];
+
+ options.forEach((option: { value: string }) => {
+ const labelLower = option.value.toLowerCase();
+ if (
+ labelLower.includes(lowerInputValue) &&
+ !selectedEnumValues.includes(labelLower)
+ ) {
+ filteredOptions.push(option)
+ }
+ });
+
+ return filteredOptions
+}
+
const BusinessMetadataAttributeForm = ({
- fields,
+ fields = [],
control,
remove,
- watched,
- dataTypeOptions,
- enumTypes,
- watch: attributeDefsWatch,
- setValue: attributeDefsSetValue
+ watched = [],
+ dataTypeOptions = [],
+ enumTypes = [],
+ watch: attributeDefsWatch = () => undefined,
+ setValue: attributeDefsSetValue = () => undefined
}: any) => {
const { enumObj }: any = useAppSelector((state: any) => state.enum);
const { enumDefs } = enumObj?.data || {};
@@ -99,7 +125,7 @@ const BusinessMetadataAttributeForm = ({
} = useForm();
const toastId: any = useRef(null);
- const onSubmit = async (values: any) => {
+ const onSubmit = async (values: any = {}) => {
let formData = { ...values };
let isPutCall = false;
let isPostCallEnum = false;
@@ -129,7 +155,7 @@ const BusinessMetadataAttributeForm = ({
isPostCallEnum = true;
}
let elementValues: { ordinal: number; value: any }[] = [];
- selectedEnumValues?.forEach((inputEnumVal: any, index: number) => {
+ selectedEnumValues.forEach((inputEnumVal: any, index: number) => {
elementValues?.push({
ordinal: index + 1,
value: inputEnumVal
@@ -163,9 +189,8 @@ const BusinessMetadataAttributeForm = ({
toast.dismiss(toastId.current);
toastId.current = toast.success("No updated values");
}
- fields?.forEach((fieldItem: any, idx: number) => {
+ fields.forEach((fieldItem: any, idx: number) => {
const fieldEnumType =
- attributeDefsWatch &&
attributeDefsWatch(`attributeDefs.${idx}.enumType`);
if (fieldEnumType === enumType) {
attributeDefsSetValue(
@@ -186,33 +211,6 @@ const BusinessMetadataAttributeForm = ({
setEnumModal(false);
};
- const filterOptions = (
- options: any[],
- { inputValue }: FilterOptionsState
,
- selectedValues: { value: string }[]
- ) => {
- const lowerInputValue = inputValue ? inputValue.toLowerCase() : "";
- const filteredOptions: any[] = [];
-
- let selectedEnumValues = !isEmpty(selectedValues)
- ? selectedValues.map((obj: { value: string }) => {
- return obj.value.toLowerCase();
- })
- : [];
-
- options.forEach((option: { value: string }) => {
- const labelLower = option.value.toLowerCase();
- if (
- labelLower.includes(lowerInputValue) &&
- !selectedEnumValues.includes(labelLower)
- ) {
- filteredOptions.push(option);
- }
- });
-
- return filteredOptions;
- };
-
return fields.map(
(
field: {
diff --git a/dashboard/src/views/BusinessMetadata/BusinessMetadataForm.tsx b/dashboard/src/views/BusinessMetadata/BusinessMetadataForm.tsx
index 9d31691e539..239e4ae4326 100644
--- a/dashboard/src/views/BusinessMetadata/BusinessMetadataForm.tsx
+++ b/dashboard/src/views/BusinessMetadata/BusinessMetadataForm.tsx
@@ -238,7 +238,7 @@ const BusinessMetaDataForm = ({
};
const toastMssg = (bmName: string) => {
- if (isEmpty(bmAttribute && isEmpty(editbmAttribute))) {
+ if (isEmpty(bmAttribute) && isEmpty(editbmAttribute)) {
toast.success(`Business Metadata ${bmName} was created successfully`);
} else {
toast.success(
diff --git a/dashboard/src/views/Classification/AddTagAttributes.tsx b/dashboard/src/views/Classification/AddTagAttributes.tsx
index 34d4392e884..013deff8117 100644
--- a/dashboard/src/views/Classification/AddTagAttributes.tsx
+++ b/dashboard/src/views/Classification/AddTagAttributes.tsx
@@ -167,8 +167,13 @@ const AddTagAttributes = ({ open, onClose }: any) => {
Add New Attributes
- {fields.map((field: any, index) => (
-
+ {fields.map((field: any, index) => {
+ /* istanbul ignore next */
+ const shouldShowToggle =
+ watched?.[index] &&
+ watched?.[index]?.typeName == "array";
+ return (
+
{
))}
- {watched?.[index] &&
- watched?.[index]?.typeName == "array" && (
- (
- <>
-
-
-
- >
- )}
- />
- )}
+ {shouldShowToggle && (
+ (
+ <>
+
+
+
+ >
+ )}
+ />
+ )}