fix(ui): null deref (#12659)

This commit is contained in:
Aseem Bansal 2025-02-17 22:15:47 +05:30 committed by GitHub
parent 3e7c896aab
commit fc69c34167
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
76 changed files with 92 additions and 92 deletions

View File

@ -142,7 +142,7 @@ export default function DomainNode({
const isInSelectMode = !!selectDomainOverride;
const isDomainNodeSelected = !!isOnEntityPage && !isInSelectMode;
const shouldAutoOpen = useMemo(
() => !isInSelectMode && entityData?.parentDomains?.domains.some((parent) => parent.urn === domain.urn),
() => !isInSelectMode && entityData?.parentDomains?.domains?.some((parent) => parent.urn === domain.urn),
[isInSelectMode, entityData, domain.urn],
);
const paddingLeft = $paddingLeft + 16;

View File

@ -241,9 +241,9 @@ export const CreateERModelRelationModal = ({
};
const table1NameBusiness = getDatasetName(table1Dataset);
const table1NameTech = table1Dataset?.name || table1Dataset?.urn?.split(',').at(1) || '';
const table1NameTech = table1Dataset?.name || table1Dataset?.urn?.split(',')?.at(1) || '';
const table2NameBusiness = getDatasetName(table2Dataset);
const table2NameTech = table2Dataset?.name || table2Dataset?.urn?.split(',').at(1) || '';
const table2NameTech = table2Dataset?.name || table2Dataset?.urn?.split(',')?.at(1) || '';
const handleAdd = () => {
const newData: ERModelRelationDataType = {

View File

@ -474,7 +474,7 @@ export function combineSiblingsForEntity(entity: Entity, visitedSiblingUrns: Set
const combinedEntity: CombinedEntity = { entity: combineEntityWithSiblings({ ...entity }) };
const siblings =
(combinedEntity.entity as GenericEntityProperties).siblingsSearch?.searchResults.map((r) => r.entity) ?? [];
(combinedEntity.entity as GenericEntityProperties).siblingsSearch?.searchResults?.map((r) => r.entity) ?? [];
const isPrimary = (combinedEntity.entity as GenericEntityProperties).siblings?.isPrimary;
const siblingUrns = siblings.map((sibling) => sibling?.urn);

View File

@ -12,7 +12,7 @@ function matchesTagsOrTermsOrDescription(field: SchemaField, filterText: string,
.toLocaleLowerCase()
.includes(filterText),
) ||
field.description?.toLocaleLowerCase()?.includes(filterText)
field.description?.toLocaleLowerCase().includes(filterText)
);
}

View File

@ -257,7 +257,7 @@ export default class EntityRegistry {
getLineageAssets(type: EntityType, data: EntityLineageV2Fragment): Map<string, LineageAsset> | undefined {
// TODO: Fold into entity registry?
if (data?.__typename === 'Domain') {
return data?.dataProducts?.searchResults.reduce((obj, r) => {
return data?.dataProducts?.searchResults?.reduce((obj, r) => {
if (r.entity.__typename === 'DataProduct') {
const name = this.getDisplayName(r.entity.type, r.entity);
obj.set(name, { name, type: LineageAssetType.DataProduct, size: r.entity.entities?.total });

View File

@ -132,7 +132,7 @@ export class ChartEntity implements Entity<Chart> {
visible: (_, chart: GetChartQuery) =>
!!chart?.chart?.subTypes?.typeNames?.includes(SubType.TableauWorksheet) ||
!!chart?.chart?.subTypes?.typeNames?.includes(SubType.Looker) ||
chart?.chart?.platform.name === MODE,
chart?.chart?.platform?.name === MODE,
enabled: () => true,
},
},

View File

@ -35,7 +35,7 @@ export default function TableauDataSourcesSection() {
fetchPolicy: 'cache-first',
});
const dataSources = searchData?.searchAcrossEntities?.searchResults.map((r) => r.entity);
const dataSources = searchData?.searchAcrossEntities?.searchResults?.map((r) => r.entity);
if (!dataSources?.length) {
return null;

View File

@ -132,8 +132,8 @@ export const RunsTab = () => {
name: run?.name,
status: run?.state?.[0]?.status,
resultType: run?.state?.[0]?.result?.resultType,
inputs: run?.inputs?.relationships.map((relationship) => relationship.entity),
outputs: run?.outputs?.relationships.map((relationship) => relationship.entity),
inputs: run?.inputs?.relationships?.map((relationship) => relationship.entity),
outputs: run?.outputs?.relationships?.map((relationship) => relationship.entity),
externalUrl: run?.externalUrl,
}));
if (loading) {

View File

@ -63,7 +63,7 @@ export const AssetsSection = () => {
<HorizontalList>
{!loading &&
contentsSummary?.types.map((summary) => {
contentsSummary?.types?.map((summary) => {
const { type, count, entityType: summaryEntityType } = summary;
const typeName = (
type ||

View File

@ -199,8 +199,8 @@ export const OperationsTab = () => {
status: run?.state?.[0]?.status,
resultType: run?.state?.[0]?.result?.resultType,
duration: run?.state?.[0]?.durationMillis,
inputs: run?.inputs?.relationships.map((relationship) => relationship.entity),
outputs: run?.outputs?.relationships.map((relationship) => relationship.entity),
inputs: run?.inputs?.relationships?.map((relationship) => relationship.entity),
outputs: run?.outputs?.relationships?.map((relationship) => relationship.entity),
externalUrl: run?.externalUrl,
parentTemplate: run?.parentTemplate?.relationships?.[0]?.entity,
}));

View File

@ -119,7 +119,7 @@ export const InteriorTitleContent = ({
?.filter(
(constraint) =>
(constraint?.sourceFields?.filter(
(sourceField) => sourceField?.fieldPath.trim() === fieldPath.trim(),
(sourceField) => sourceField?.fieldPath?.trim() === fieldPath.trim(),
).length || 0) > 0,
)
.map((constraint) => (

View File

@ -28,7 +28,7 @@ const StructuredPropValues = ({ schemaFieldEntity, propColumn }: Props) => {
);
const propRow = property ? mapStructuredPropertyToPropertyRow(property) : undefined;
const values = propRow?.values;
const isRichText = propRow?.dataType?.info.type === StdDataType.RichText;
const isRichText = propRow?.dataType?.info?.type === StdDataType.RichText;
const hasMoreValues = values && values.length > 2;
const displayedValues = hasMoreValues ? values.slice(0, 1) : values;

View File

@ -38,7 +38,7 @@ export function convertEditableSchemaMetadataForUpdate(
): EditableSchemaMetadataUpdate {
return {
editableSchemaFieldInfo:
editableSchemaMetadata?.editableSchemaFieldInfo.map((editableSchemaFieldInfo) => ({
editableSchemaMetadata?.editableSchemaFieldInfo?.map((editableSchemaFieldInfo) => ({
fieldPath: editableSchemaFieldInfo?.fieldPath,
description: editableSchemaFieldInfo?.description,
globalTags: { tags: convertTagsForUpdate(editableSchemaFieldInfo?.globalTags?.tags || []) },

View File

@ -78,7 +78,7 @@ export default function DataProductsTab() {
fetchPolicy: 'no-cache',
});
const totalResults = data?.searchAcrossEntities?.total || 0;
const searchResults = data?.searchAcrossEntities?.searchResults.map((r) => r.entity) || [];
const searchResults = data?.searchAcrossEntities?.searchResults?.map((r) => r.entity) || [];
const dataProducts = [...createdDataProducts, ...searchResults];
const displayedDataProducts = dataProducts
.map(

View File

@ -70,7 +70,7 @@ export const ContentsSection = () => {
{loading && <ContentSectionLoading />}
<Carousel>
{!loading &&
contentsSummary?.types.map((summary) => {
contentsSummary?.types?.map((summary) => {
const { type, count, entityType: summaryEntityType } = summary;
const typeName = (
type ||

View File

@ -56,7 +56,7 @@ export const DataProductsSection = () => {
},
});
const dataProducts = data?.searchAcrossEntities?.searchResults.map((r) => r.entity) || [];
const dataProducts = data?.searchAcrossEntities?.searchResults?.map((r) => r.entity) || [];
const numDataProducts = data?.searchAcrossEntities?.total || 0;
if (!numDataProducts) {

View File

@ -23,7 +23,7 @@ export default function GlossaryRelatedEntity() {
]) ||
[];
entityData?.isAChildren?.relationships.forEach((term) => {
entityData?.isAChildren?.relationships?.forEach((term) => {
const childUrn = term.entity?.urn;
if (childUrn) {

View File

@ -35,14 +35,14 @@ export default function SourcesView() {
features?.reduce((accumulator: Array<Dataset>, feature) => {
if (feature.__typename === 'MLFeature' && feature.properties?.sources) {
// eslint-disable-next-line array-callback-return
feature.properties?.sources.map((source: Dataset | null) => {
feature.properties?.sources?.map((source: Dataset | null) => {
if (source && accumulator.findIndex((dataset) => dataset.urn === source?.urn) === -1) {
accumulator.push(source);
}
});
} else if (feature.__typename === 'MLPrimaryKey' && feature.properties?.sources) {
// eslint-disable-next-line array-callback-return
feature.properties?.sources.map((source: Dataset | null) => {
feature.properties?.sources?.map((source: Dataset | null) => {
if (source && accumulator.findIndex((dataset) => dataset.urn === source?.urn) === -1) {
accumulator.push(source);
}

View File

@ -9,7 +9,7 @@ export default function MlModelFeaturesTab() {
const entity = useBaseEntity() as GetMlModelQuery;
const model = entity && entity.mlModel;
const features = model?.features?.relationships.map((relationship) => relationship.entity) as Array<
const features = model?.features?.relationships?.map((relationship) => relationship.entity) as Array<
MlFeature | MlPrimaryKey
>;

View File

@ -64,7 +64,7 @@ export const OwnershipList = () => {
});
const totalOwnershipTypes = data?.listOwnershipTypes?.total || 0;
const ownershipTypes =
data?.listOwnershipTypes?.ownershipTypes.filter((type) => type.urn !== 'urn:li:ownershipType:none') || [];
data?.listOwnershipTypes?.ownershipTypes?.filter((type) => type.urn !== 'urn:li:ownershipType:none') || [];
const onClickCreateOwnershipType = () => {
setShowOwnershipBuilder(true);

View File

@ -16,7 +16,7 @@ export function filterResultsForMove(entity: Domain, entityUrn: string) {
return (
entity.urn !== entityUrn &&
entity.__typename === 'Domain' &&
!entity.parentDomains?.domains.some((node) => node.urn === entityUrn)
!entity.parentDomains?.domains?.some((node) => node.urn === entityUrn)
);
}

View File

@ -13,7 +13,7 @@ export function filterResultsForMove(entity: GlossaryNode, entityUrn: string) {
return (
entity.urn !== entityUrn &&
entity.__typename === 'GlossaryNode' &&
!entity.parentNodes?.nodes.some((node) => node.urn === entityUrn)
!entity.parentNodes?.nodes?.some((node) => node.urn === entityUrn)
);
}

View File

@ -29,7 +29,7 @@ const GlossaryItemRibbon = styled.span<GlossaryItemRibbonProps>`
export const GlossaryPreviewCardDecoration = ({ urn, entityData, displayProperties }: Props) => {
const parentNodeCount = entityData?.parentNodes?.count || 0;
const urnText = parentNodeCount === 0 ? urn : entityData?.parentNodes?.nodes[parentNodeCount - 1].urn || '';
const urnText = parentNodeCount === 0 ? urn : entityData?.parentNodes?.nodes[parentNodeCount - 1]?.urn || '';
const glossaryColor = displayProperties?.colorHex || generateColorFromPalette(urnText);
return <GlossaryItemRibbon color={glossaryColor} />;

View File

@ -43,7 +43,7 @@ const StructuredPropertyBadge = ({ structuredProperties }: Props) => {
if (!badgeStructuredProperty) return null;
const propertyValue = propRow?.values[0]?.value;
const relatedDescription = propRow?.structuredProperty.definition.allowedValues?.find(
const relatedDescription = propRow?.structuredProperty?.definition?.allowedValues?.find(
(v) => getStructuredPropertyValue(v.value) === propertyValue,
)?.description;

View File

@ -31,7 +31,7 @@ export default function DataProductSection({ readOnly }: Props) {
const [dataProduct, setDataProduct] = useState<DataProduct | null>(null);
const dataProductRelationships = entityData?.dataProduct?.relationships;
const siblingUrns: string[] =
entityData?.siblingsSearch?.searchResults.map((sibling) => sibling.entity.urn || '') || [];
entityData?.siblingsSearch?.searchResults?.map((sibling) => sibling.entity.urn || '') || [];
const canEditDataProducts = !!entityData?.privileges?.canEditDataProducts;

View File

@ -62,7 +62,7 @@ export default function SetDataProductModal({
const displayedDataProducts: Entity[] =
!showRecommendations && data?.autoCompleteForMultiple?.suggestions
? data?.autoCompleteForMultiple?.suggestions.flatMap((suggestion) => suggestion.entities)
? data?.autoCompleteForMultiple?.suggestions?.flatMap((suggestion) => suggestion.entities)
: recommendedDataProducts;
const handleSearch = useMemo(() => {

View File

@ -123,7 +123,7 @@ export default function UpstreamHealth() {
);
useEffect(() => {
if (directUpstreamData?.searchAcrossLineage?.searchResults.length && !directUpstreamEntities.length) {
if (directUpstreamData?.searchAcrossLineage?.searchResults?.length && !directUpstreamEntities.length) {
setDirectUpstreamEntities(
directUpstreamData.searchAcrossLineage.searchResults.map((result) => result.entity as Dataset),
);
@ -136,7 +136,7 @@ export default function UpstreamHealth() {
]);
useEffect(() => {
if (indirectUpstreamData?.searchAcrossLineage?.searchResults.length && !indirectUpstreamEntities.length) {
if (indirectUpstreamData?.searchAcrossLineage?.searchResults?.length && !indirectUpstreamEntities.length) {
setIndirectUpstreamEntities(
indirectUpstreamData.searchAcrossLineage.searchResults.map((result) => result.entity as Dataset),
);

View File

@ -3,7 +3,7 @@ import { Dataset, EntityType, FilterOperator, LineageDirection } from '../../../
export function getNumAssertionsFailing(dataset: Dataset) {
let numFailing = 0;
dataset.assertions?.assertions.forEach((assertion) => {
dataset.assertions?.assertions?.forEach((assertion) => {
if (assertion.runEvents?.failed) {
numFailing += 1;
}

View File

@ -95,7 +95,7 @@ const SidebarStructuredProperties = ({ properties }: Props) => {
<>
{entityTypeProperties?.map((property) => {
const propertyRow: PropertyRow | undefined = getPropertyRowFromSearchResult(property, allProperties);
const isRichText = propertyRow?.dataType?.info.type === StdDataType.RichText;
const isRichText = propertyRow?.dataType?.info?.type === StdDataType.RichText;
const values = propertyRow?.values;
const propertyName = getDisplayName(property.entity as StructuredPropertyEntity);

View File

@ -2,8 +2,8 @@ export function handleAccessRoles(externalRoles, loggedInUser) {
const accessRoles = new Array<any>();
if (
externalRoles?.dataset?.access &&
externalRoles?.dataset?.access.roles &&
externalRoles?.dataset?.access.roles.length > 0
externalRoles?.dataset?.access?.roles &&
externalRoles?.dataset?.access?.roles.length > 0
) {
externalRoles?.dataset?.access?.roles?.forEach((userRoles) => {
const role = {
@ -12,7 +12,7 @@ export function handleAccessRoles(externalRoles, loggedInUser) {
accessType: userRoles?.role?.properties?.type || ' ',
hasAccess:
(userRoles?.role?.actors?.users &&
userRoles?.role?.actors?.users.length > 0 &&
userRoles?.role?.actors?.users?.length > 0 &&
userRoles?.role?.actors?.users?.some(
(user) => user.user.urn === loggedInUser?.me?.corpUser?.urn,
)) ||

View File

@ -52,7 +52,7 @@ export default function useDownstreamQueries(filterText: string) {
const [downstreamQueryEntities, setDownstreamQueryEntities] = useState<[QueryEntity, Entity][]>([]);
useEffect(() => {
lineageData?.searchAcrossLineage?.searchResults.forEach((result) => {
lineageData?.searchAcrossLineage?.searchResults?.forEach((result) => {
result.paths?.forEach((path) => {
if (!path) return;
const parent = path.path[path.path.length - 2];

View File

@ -166,7 +166,7 @@ export default function CompactSchemaTable({
function getCount(fieldPath: any) {
const data: any =
usageStats?.aggregations?.fields &&
usageStats?.aggregations?.fields.find((field) => {
usageStats?.aggregations?.fields?.find((field) => {
return field?.fieldName === fieldPath;
});
return (data && data.count) ?? 0;

View File

@ -284,7 +284,7 @@ export default function SchemaTable({
function getCount(fieldPath: any) {
const data: any =
usageStats?.aggregations?.fields &&
usageStats?.aggregations?.fields.find((field) => {
usageStats?.aggregations?.fields?.find((field) => {
return field?.fieldName === fieldPath;
});
return (data && data.count) ?? 0;

View File

@ -53,7 +53,7 @@ export function AboutFieldTab({ properties }: AboutFieldTabProps) {
expandedFieldIndex !== undefined && expandedFieldIndex !== -1
? properties.schemaFields[expandedFieldIndex]
: undefined;
const editableFieldInfo = properties.editableSchemaMetadata?.editableSchemaFieldInfo.find(
const editableFieldInfo = properties.editableSchemaMetadata?.editableSchemaFieldInfo?.find(
(candidateEditableFieldInfo) =>
pathMatchesExact(candidateEditableFieldInfo.fieldPath, expandedField?.fieldPath),
);

View File

@ -84,10 +84,10 @@ const HistorySidebar = ({ open, onClose, urn, siblingUrn, versionList, hideSeman
const { entityPlatform, siblingPlatform } = useGetSiblingPlatforms();
const transactionEntries: ChangeTransactionEntry[] = [
...(entityTimelineData?.getTimeline?.changeTransactions.map((transaction) =>
...(entityTimelineData?.getTimeline?.changeTransactions?.map((transaction) =>
makeTransactionEntry(transaction, hideSemanticVersions ? [] : versionList, entityPlatform ?? undefined),
) || []),
...(siblingTimelineData?.getTimeline?.changeTransactions.map((transaction) =>
...(siblingTimelineData?.getTimeline?.changeTransactions?.map((transaction) =>
makeTransactionEntry(transaction, [], siblingPlatform ?? undefined),
) || []),
].sort((a, b) => a.transaction.timestampMillis - b.transaction.timestampMillis);

View File

@ -8,7 +8,7 @@ interface Props {
export function getFieldDescriptionDetails({ schemaFieldEntity, editableFieldInfo, defaultDescription }: Props) {
// get most recent documentation
const sortedDocumentations = schemaFieldEntity?.documentation?.documentations.sort(
const sortedDocumentations = schemaFieldEntity?.documentation?.documentations?.sort(
(doc1, doc2) => (doc2.attribution?.time || 0) - (doc1.attribution?.time || 0),
);
const documentation = sortedDocumentations?.[0];

View File

@ -30,7 +30,7 @@ export default function useDescriptionRenderer(
};
return (description: string | undefined, record: SchemaField, index: number): JSX.Element => {
const editableFieldInfo = editableSchemaMetadata?.editableSchemaFieldInfo.find((candidateEditableFieldInfo) =>
const editableFieldInfo = editableSchemaMetadata?.editableSchemaFieldInfo?.find((candidateEditableFieldInfo) =>
pathMatchesExact(candidateEditableFieldInfo.fieldPath, record.fieldPath),
);
const { schemaFieldEntity } = record;

View File

@ -7,7 +7,7 @@ export default function useExtractFieldDescriptionInfo(
editableSchemaMetadata: EditableSchemaMetadata | null | undefined,
) {
return (record: SchemaField, description: string | undefined | null = null) => {
const editableFieldInfoB = editableSchemaMetadata?.editableSchemaFieldInfo.find((candidateEditableFieldInfo) =>
const editableFieldInfoB = editableSchemaMetadata?.editableSchemaFieldInfo?.find((candidateEditableFieldInfo) =>
pathMatchesExact(candidateEditableFieldInfo.fieldPath, record.fieldPath),
);
const { displayedDescription, isPropagated, sourceDetail } = getFieldDescriptionDetails({

View File

@ -5,7 +5,7 @@ export default function useExtractFieldGlossaryTermsInfo(
editableSchemaMetadata: EditableSchemaMetadata | null | undefined,
) {
return (record: SchemaField, defaultUneditableTerms: GlossaryTerms | null = null) => {
const editableTerms = editableSchemaMetadata?.editableSchemaFieldInfo.find((candidateEditableFieldInfo) =>
const editableTerms = editableSchemaMetadata?.editableSchemaFieldInfo?.find((candidateEditableFieldInfo) =>
pathMatchesExact(candidateEditableFieldInfo.fieldPath, record.fieldPath),
)?.glossaryTerms;

View File

@ -3,7 +3,7 @@ import { EditableSchemaMetadata, GlobalTags, SchemaField } from '@src/types.gene
export default function useExtractFieldTagsInfo(editableSchemaMetadata: EditableSchemaMetadata | null | undefined) {
return (record: SchemaField, defaultUneditableTags: GlobalTags | null = null) => {
const editableTags = editableSchemaMetadata?.editableSchemaFieldInfo.find((candidateEditableFieldInfo) =>
const editableTags = editableSchemaMetadata?.editableSchemaFieldInfo?.find((candidateEditableFieldInfo) =>
pathMatchesExact(candidateEditableFieldInfo.fieldPath, record.fieldPath),
)?.globalTags;

View File

@ -14,7 +14,7 @@ export default function useTagsAndTermsRendererFeatureTable(
const refetch = useRefetch();
const tagAndTermRender = (tags: GlobalTags, record: SchemaField, rowIndex: number | undefined) => {
const relevantEditableFieldInfo = editableSchemaMetadata?.editableSchemaFieldInfo.find(
const relevantEditableFieldInfo = editableSchemaMetadata?.editableSchemaFieldInfo?.find(
(candidateEditableFieldInfo) => pathMatchesExact(candidateEditableFieldInfo.fieldPath, record.fieldPath),
);

View File

@ -45,7 +45,7 @@ type Props = {
export const AcrylAssertionResultsChartTimeline = ({ results, platform, timeRange }: Props) => {
const entityRegistry = useEntityRegistry();
const completedRuns =
results?.runEvents.filter((runEvent) => runEvent.status === AssertionRunStatus.Complete) || [];
results?.runEvents?.filter((runEvent) => runEvent.status === AssertionRunStatus.Complete) || [];
/**
* Data for the timeline of assertion results.

View File

@ -136,7 +136,7 @@ export const useSiblingOptionsForAssertionBuilder = (
urn: sibling.urn,
title:
getPlatformName(sibling) ??
sibling?.dataPlatformInstance?.platform.name ??
sibling?.dataPlatformInstance?.platform?.name ??
sibling?.platform?.urn ??
sibling.urn,
disabled: true,

View File

@ -112,7 +112,7 @@ export const DatasetAssertionDetails = ({ urn, lastEvaluatedAtMillis }: Props) =
};
const completeAssertionRunEvents =
data?.assertion?.runEvents?.runEvents.filter(
data?.assertion?.runEvents?.runEvents?.filter(
(runEvent) => runEvent.status === AssertionRunStatus.Complete && runEvent.result,
) || [];

View File

@ -56,7 +56,7 @@ export const AssertionResultsTimelineViz = ({
}: Props) => {
// Run event data
const completedRuns =
results?.runEvents.filter((runEvent) => runEvent.status === AssertionRunStatus.Complete) || [];
results?.runEvents?.filter((runEvent) => runEvent.status === AssertionRunStatus.Complete) || [];
const assertionResultChartData: AssertionResultChartData = getAssertionResultChartData(assertion, completedRuns);

View File

@ -8,7 +8,7 @@ export function getAssetDescriptionDetails({
defaultDescription?: string | null;
}) {
// get most recent documentation aspect
const sortedDocumentations = entityProperties?.documentation?.documentations.sort(
const sortedDocumentations = entityProperties?.documentation?.documentations?.sort(
(doc1, doc2) => (doc2.attribution?.time || 0) - (doc1.attribution?.time || 0),
);
const documentation = sortedDocumentations?.[0];

View File

@ -7,7 +7,7 @@ import { useEntityRegistry } from '../../../../useEntityRegistry';
export const ChartDashboardsTab = () => {
const entity = useBaseEntity() as any;
const chart = entity && entity.chart;
const dashboards = chart?.dashboards?.relationships.map((relationship) => relationship.entity);
const dashboards = chart?.dashboards?.relationships?.map((relationship) => relationship.entity);
const entityRegistry = useEntityRegistry();
const totalDashboards = chart?.dashboards?.total || 0;
const title = `Found in ${totalDashboards} ${

View File

@ -6,7 +6,7 @@ import { EntityList } from './components/EntityList';
export const DashboardChartsTab = () => {
const entity = useBaseEntity() as any;
const dashboard = entity && entity.dashboard;
const charts = dashboard?.charts?.relationships.map((relationship) => relationship.entity);
const charts = dashboard?.charts?.relationships?.map((relationship) => relationship.entity);
const totalCharts = dashboard?.charts?.total || 0;
const title = `Contains ${totalCharts} assets`;
return <EntityList title={title} type={EntityType.Chart} entities={charts || []} />;

View File

@ -7,7 +7,7 @@ import { useEntityRegistry } from '../../../../useEntityRegistry';
export const DashboardDatasetsTab = () => {
const entity = useBaseEntity() as any;
const dashboard = entity && entity.dashboard;
const datasets = dashboard?.datasets?.relationships.map((relationship) => relationship.entity);
const datasets = dashboard?.datasets?.relationships?.map((relationship) => relationship.entity);
const entityRegistry = useEntityRegistry();
const totalDatasets = dashboard?.datasets?.total || 0;
const title = `Consumes ${totalDatasets} ${

View File

@ -30,7 +30,7 @@ export const DataFlowJobsTab = ({ properties = { urn: '' } }: Props) => {
};
const dataFlow = data && data?.dataFlow;
const dataJobs = dataFlow?.childJobs?.relationships.map((relationship) => relationship.entity);
const dataJobs = dataFlow?.childJobs?.relationships?.map((relationship) => relationship.entity);
const entityRegistry = useEntityRegistry();
const totalJobs = dataFlow?.childJobs?.total || 0;
const pageSize = data?.dataFlow?.childJobs?.count || 0;

View File

@ -25,7 +25,7 @@ export default function DynamicTabularTab({ payload: rawPayload }: Props) {
width: 210,
title: 'Name',
dataIndex: 'key',
sorter: (a, b) => a?.key.localeCompare(b?.key || '') || 0,
sorter: (a, b) => a?.key?.localeCompare(b?.key || '') || 0,
defaultSortOrder: 'ascend',
render: (name: string) => <NameText>{name}</NameText>,
},

View File

@ -238,7 +238,7 @@ export default function IncidentListItem({ incident, refetch }: Props) {
<>
<IncidentDescriptionLabel>Resolution Note</IncidentDescriptionLabel>
<IncidentDescriptionText>
{incident?.status.message || 'No additional details'}
{incident?.status?.message || 'No additional details'}
</IncidentDescriptionText>
</>
) : null}
@ -269,15 +269,15 @@ export default function IncidentListItem({ incident, refetch }: Props) {
placement="left"
title={<Typography.Text strong>Note</Typography.Text>}
content={
incident?.status.message === null ? (
incident?.status?.message === null ? (
<Typography.Text type="secondary">No additional details</Typography.Text>
) : (
<Typography.Text type="secondary">{incident?.status.message}</Typography.Text>
<Typography.Text type="secondary">{incident?.status?.message}</Typography.Text>
)
}
>
<IncidentResolvedText>
{incident?.status.lastUpdated && (
{incident?.status?.lastUpdated && (
<Tooltip showArrow={false} title={toLocalDateTimeString(lastModifiedDate)}>
Resolved {toRelativeTimeString(lastModifiedDate)} by{' '}
</Tooltip>

View File

@ -71,7 +71,7 @@ export default function ColumnsLineageSelect({
allowClear
placeholder="Select column"
>
{entityWithSchema?.schemaMetadata?.fields.map((field) => {
{entityWithSchema?.schemaMetadata?.fields?.map((field) => {
const fieldPath = downgradeV2FieldPath(field.fieldPath);
return (
<Select.Option value={field.fieldPath}>

View File

@ -10,7 +10,7 @@ export const FeatureTableTab = () => {
const entityRegistry = useEntityRegistry();
const feature = entity && entity.mlFeature;
const featureTables = feature?.featureTables?.relationships.map((relationship) => relationship.entity);
const featureTables = feature?.featureTables?.relationships?.map((relationship) => relationship.entity);
const title = `Part of ${entityRegistry.getEntityName(EntityType.MlfeatureTable)}`;
return <EntityList title={title} type={EntityType.MlfeatureTable} entities={featureTables || []} />;

View File

@ -10,7 +10,7 @@ export const FeatureTableTab = () => {
const entityRegistry = useEntityRegistry();
const feature = entity && entity.mlPrimaryKey;
const featureTables = feature?.featureTables?.relationships.map((relationship) => relationship.entity);
const featureTables = feature?.featureTables?.relationships?.map((relationship) => relationship.entity);
const title = `Part of ${entityRegistry.getEntityName(EntityType.MlfeatureTable)}`;
return <EntityList title={title} type={EntityType.MlfeatureTable} entities={featureTables || []} />;

View File

@ -48,7 +48,7 @@ export default function StructuredPropertyTooltip({ propertyRow }: Props) {
) : (
<span />
)}
{structuredProperty?.definition.allowedValues && (
{structuredProperty?.definition?.allowedValues && (
<CardinalityLabel structuredProperty={structuredProperty} />
)}
</NameLabelWrapper>

View File

@ -10,7 +10,7 @@ interface Props {
export default function ValuesColumn({ propertyRow, filterText }: Props) {
const { values } = propertyRow;
const isRichText = propertyRow.dataType?.info.type === StdDataType.RichText;
const isRichText = propertyRow.dataType?.info?.type === StdDataType.RichText;
return (
<>

View File

@ -59,7 +59,7 @@ function getStructuredPropertyRows(entityData?: GenericEntityProperties | null)
function getFieldStructuredPropertyRows(fieldPath: string, entityData?: GenericEntityProperties | null) {
const structuredPropertyRows: PropertyRow[] = [];
const schemaFieldEntity = entityData?.schemaMetadata?.fields.find(
const schemaFieldEntity = entityData?.schemaMetadata?.fields?.find(
(f) => f.fieldPath === fieldPath,
)?.schemaFieldEntity;

View File

@ -153,7 +153,7 @@ export default function VersionsDrawer({ versionSetUrn, open }: Props) {
urn,
label: (
<VersionPill
label={versionProperties?.version.versionTag || '<unlabeled>'}
label={versionProperties?.version?.versionTag || '<unlabeled>'}
isLatest={versionProperties?.isLatest}
/>
),

View File

@ -64,7 +64,7 @@ export default function VersionsPreview({ versionSet }: Props) {
{!!total && <VersionsCount label={total.toString()} size="sm" clickable={false} />}
</Header>
<VersionsWrapper>
{versionSet?.versionsSearch?.searchResults.map((result) => (
{versionSet?.versionsSearch?.searchResults?.map((result) => (
<VersionPreviewRow entity={result.entity} />
))}
</VersionsWrapper>
@ -127,7 +127,7 @@ function VersionPreviewRow({ entity }: VersionPreviewRowProps) {
<VersionPreviewEntry isViewing={isViewing}>
<VersionPreviewHeader>
<VersionPill
label={versionProperties?.version.versionTag ?? '<unlabeled>'}
label={versionProperties?.version?.versionTag ?? '<unlabeled>'}
isLatest={versionProperties?.isLatest}
/>
{!!versionProperties?.isLatest && (

View File

@ -102,9 +102,9 @@ export default function UserProfile({ urn }: Props) {
const castedCorpUser = data?.corpUser as any;
const userGroups: Array<EntityRelationship> =
castedCorpUser?.groups?.relationships.map((relationship) => relationship as EntityRelationship) || [];
castedCorpUser?.groups?.relationships?.map((relationship) => relationship as EntityRelationship) || [];
const userRoles: Array<EntityRelationship> =
castedCorpUser?.roles?.relationships.map((relationship) => relationship as EntityRelationship) || [];
castedCorpUser?.roles?.relationships?.map((relationship) => relationship as EntityRelationship) || [];
const { data: userOwnedAsset } = useGetUserOwnedAssetsQuery({ variables: { urn } });
// Routed Tabs Constants

View File

@ -28,7 +28,7 @@ export const convertStateToUpdateInput = (state: ViewBuilderState) => {
entityTypes: state?.definition?.entityTypes,
filter: {
operator: state?.definition?.filter?.operator,
filters: state?.definition?.filter?.filters.map((filter) => ({
filters: state?.definition?.filter?.filters?.map((filter) => ({
field: filter.field,
condition: filter.condition,
values: filter.values,

View File

@ -29,7 +29,7 @@ export default function GlossaryRoutes() {
const appConfig = useAppConfig();
const authenticatedUser = useGetAuthenticatedUser();
const isThemeV2 = useIsThemeV2();
const canManageGlossary = authenticatedUser?.platformPrivileges.manageGlossaries || false;
const canManageGlossary = authenticatedUser?.platformPrivileges?.manageGlossaries || false;
const hideGlossary = !!appConfig?.config?.visualConfig?.hideGlossary;
const showGlossary = shouldShowGlossary(canManageGlossary, hideGlossary);

View File

@ -53,10 +53,10 @@ const BusinessGlossaryPage = () => {
setEntityData(null);
}, [setEntityData]);
const terms = termsData?.getRootGlossaryTerms?.terms.sort((termA, termB) =>
const terms = termsData?.getRootGlossaryTerms?.terms?.sort((termA, termB) =>
sortGlossaryTerms(entityRegistry, termA, termB),
);
const nodes = nodesData?.getRootGlossaryNodes?.nodes.sort((nodeA, nodeB) =>
const nodes = nodesData?.getRootGlossaryNodes?.nodes?.sort((nodeA, nodeB) =>
sortGlossaryNodes(entityRegistry, nodeA, nodeB),
);

View File

@ -141,7 +141,7 @@ function NodeItem(props: Props) {
});
useEffect(() => {
if (openToEntity && entityData && entityData.parentNodes?.nodes.some((parent) => parent.urn === node.urn)) {
if (openToEntity && entityData && entityData.parentNodes?.nodes?.some((parent) => parent.urn === node.urn)) {
setAreChildrenVisible(true);
}
}, [entityData, node.urn, openToEntity]);

View File

@ -29,7 +29,7 @@ export default function GlossaryRoutes() {
const appConfig = useAppConfig();
const authenticatedUser = useGetAuthenticatedUser();
const canManageGlossary = authenticatedUser?.platformPrivileges.manageGlossaries || false;
const canManageGlossary = authenticatedUser?.platformPrivileges?.manageGlossaries || false;
const hideGlossary = !!appConfig?.config?.visualConfig?.hideGlossary;
const showGlossary = shouldShowGlossary(canManageGlossary, hideGlossary);
const isShowNavBarRedesign = useShowNavBarRedesign();

View File

@ -242,7 +242,7 @@ export function NavLinksMenu(props: Props) {
if (menuItem.isHidden) return null;
// Menu item has sub menu items
const hasSubMenu = menuItem.subMenu?.items && menuItem.subMenu?.items.length > 0;
const hasSubMenu = menuItem.subMenu?.items && menuItem.subMenu?.items?.length > 0;
// Return a menu item with a submenu
if (hasSubMenu) {
@ -250,7 +250,7 @@ export function NavLinksMenu(props: Props) {
<SubMenu>
<SubMenuContent>
<SubMenuTitle>{menuItem.title}</SubMenuTitle>
{menuItem.subMenu?.items.map((subMenuItem) => {
{menuItem.subMenu?.items?.map((subMenuItem) => {
if (subMenuItem.isHidden) return null;
return (
<SubMenuLink>

View File

@ -82,7 +82,7 @@ export const NavSidebar = () => {
const { config } = useAppConfig();
const logout = useGetLogoutHandler();
const showAnalytics = (config?.analyticsConfig.enabled && me && me?.platformPrivileges?.viewAnalytics) || false;
const showAnalytics = (config?.analyticsConfig?.enabled && me && me?.platformPrivileges?.viewAnalytics) || false;
const showStructuredProperties =
config?.featureFlags?.showManageStructuredProperties &&
(me.platformPrivileges?.manageStructuredProperties || me.platformPrivileges?.viewStructuredPropertiesPage);

View File

@ -116,7 +116,7 @@ export function extendColumnLineage(
// if this upstreamEntityUrn is a sibling of one of the already rendered nodes,
// update the fine grained map with the rendered node instead of its sibling
Array.from(fetchedEntities.keys()).forEach((urn) => {
fetchedEntities.get(urn)?.siblingsSearch?.searchResults.forEach((sibling) => {
fetchedEntities.get(urn)?.siblingsSearch?.searchResults?.forEach((sibling) => {
if (sibling && sibling.entity.urn === upstreamEntityUrn) {
updateFineGrainedMap(
fineGrainedMap,

View File

@ -85,7 +85,7 @@ export default function AddEntityEdge({ direction, setEntitiesToAdd, entitiesToA
);
const selectEntity = (urn: string) => {
const resultEntities = autoCompleteResults?.autoCompleteForMultiple?.suggestions.flatMap(
const resultEntities = autoCompleteResults?.autoCompleteForMultiple?.suggestions?.flatMap(
(suggestion) => suggestion.entities || [],
);
const selectedEntity = resultEntities?.find((entity) => entity.urn === urn);

View File

@ -103,7 +103,7 @@ export default function useSearchAcrossLineage(
const smallContext = { nodes, edges, adjacencyList, setDisplayVersion };
let addedNode = false;
data?.searchAcrossLineage?.searchResults.forEach((result) => {
data?.searchAcrossLineage?.searchResults?.forEach((result) => {
addedNode = addedNode || !nodes.has(result.entity.urn);
const node = setEntityNodeDefault(result.entity.urn, result.entity.type, direction, nodes);
if (result.explored || result.ignoredAsHop) {

View File

@ -58,7 +58,7 @@ const Pills = ({ glossaryTerms, tags, owners, entityCapabilities, paths, entityT
label=""
countLabel="term"
onClick={handlePillClick(PreviewSection.GLOSSARY_TERMS, glossaryTerms.terms)}
highlightedText={glossaryTerms.terms?.length ? glossaryTerms?.terms[0].term.properties?.name : ''}
highlightedText={glossaryTerms.terms?.length ? glossaryTerms?.terms[0]?.term?.properties?.name : ''}
/>
)}
{showTagsBadge && tags && (

View File

@ -153,5 +153,5 @@ export function useRemoveDataProductAssets(setShouldRefetchEmbeddedListSearch) {
}
export const isDefaultBrowsePath = (browsePaths: BrowsePathV2) => {
return browsePaths.path?.length === 1 && browsePaths?.path[0].name === 'Default';
return browsePaths.path?.length === 1 && browsePaths?.path[0]?.name === 'Default';
};

View File

@ -258,7 +258,7 @@ export const SearchBar = ({
const emptyQueryOptions = useMemo(() => {
const moduleOptions =
recommendationData?.listRecommendations?.modules.map((module) => ({
recommendationData?.listRecommendations?.modules?.map((module) => ({
label: <EntityTypeLabel>{module.title}</EntityTypeLabel>,
options: [...module.content.map((content) => renderRecommendedQuery(content.value))],
})) || [];

View File

@ -306,7 +306,7 @@ export function getFilterOptions(
) {
const aggregationFilterOptions = aggregations.map((agg) => ({ field: filterField, ...agg }));
const searchResults = autoCompleteResults?.autoCompleteForMultiple?.suggestions.find((suggestion) =>
const searchResults = autoCompleteResults?.autoCompleteForMultiple?.suggestions?.find((suggestion) =>
FACETS_TO_ENTITY_TYPES[filterField]?.includes(suggestion.type),
);
const searchFilterOptions = searchResults?.entities

View File

@ -196,8 +196,8 @@ export const AccessTokens = () => {
return renderSearchResult(result);
});
const totalTokens = tokensData?.listAccessTokens.total || 0;
const tokens = useMemo(() => tokensData?.listAccessTokens.tokens || [], [tokensData]);
const totalTokens = tokensData?.listAccessTokens?.total || 0;
const tokens = useMemo(() => tokensData?.listAccessTokens?.tokens || [], [tokensData]);
const filteredTokens = tokens.filter((token) => !removedTokens.includes(token.id));
const [revokeAccessToken, { error: revokeTokenError }] = useRevokeAccessTokenMutation();