- "No xxx" removed for empty relations - All(0) removed --------- Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
This commit is contained in:
@ -1,35 +0,0 @@
|
|||||||
import { useTheme } from '@emotion/react';
|
|
||||||
import styled from '@emotion/styled';
|
|
||||||
import { useIcons } from 'twenty-ui';
|
|
||||||
|
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
|
||||||
|
|
||||||
type RecordDetailRelationRecordsListEmptyStateProps = {
|
|
||||||
relationObjectMetadataItem: ObjectMetadataItem;
|
|
||||||
};
|
|
||||||
|
|
||||||
const StyledRelationRecordsListEmptyState = styled.div`
|
|
||||||
color: ${({ theme }) => theme.font.color.light};
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: ${({ theme }) => theme.spacing(2)};
|
|
||||||
display: flex;
|
|
||||||
height: ${({ theme }) => theme.spacing(10)};
|
|
||||||
text-transform: capitalize;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const RecordDetailRelationRecordsListEmptyState = ({
|
|
||||||
relationObjectMetadataItem,
|
|
||||||
}: RecordDetailRelationRecordsListEmptyStateProps) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
const { getIcon } = useIcons();
|
|
||||||
const Icon = getIcon(relationObjectMetadataItem.icon);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StyledRelationRecordsListEmptyState>
|
|
||||||
<Icon size={theme.icon.size.sm} />
|
|
||||||
<div>No {relationObjectMetadataItem.labelSingular}</div>
|
|
||||||
</StyledRelationRecordsListEmptyState>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -13,8 +13,6 @@ import { RelationFromManyFieldInputMultiRecordsEffect } from '@/object-record/re
|
|||||||
import { useUpdateRelationFromManyFieldInput } from '@/object-record/record-field/meta-types/input/hooks/useUpdateRelationFromManyFieldInput';
|
import { useUpdateRelationFromManyFieldInput } from '@/object-record/record-field/meta-types/input/hooks/useUpdateRelationFromManyFieldInput';
|
||||||
import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||||
import { RecordDetailRelationRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsList';
|
import { RecordDetailRelationRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsList';
|
||||||
import { RecordDetailRelationRecordsListEmptyState } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListEmptyState';
|
|
||||||
import { RecordDetailRelationSectionSkeletonLoader } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationSectionSkeletonLoader';
|
|
||||||
import { RecordDetailSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailSection';
|
import { RecordDetailSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailSection';
|
||||||
import { RecordDetailSectionHeader } from '@/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader';
|
import { RecordDetailSectionHeader } from '@/object-record/record-show/record-detail-section/components/RecordDetailSectionHeader';
|
||||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||||
@ -133,20 +131,10 @@ export const RecordDetailRelationSection = ({
|
|||||||
}?${qs.stringify(filterQueryParams)}`;
|
}?${qs.stringify(filterQueryParams)}`;
|
||||||
|
|
||||||
const showContent = () => {
|
const showContent = () => {
|
||||||
if (loading) {
|
return (
|
||||||
return (
|
relationRecords.length > 0 && (
|
||||||
<RecordDetailRelationSectionSkeletonLoader
|
<RecordDetailRelationRecordsList relationRecords={relationRecords} />
|
||||||
numSkeletons={fieldName === 'people' ? 2 : 1}
|
)
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return relationRecords.length ? (
|
|
||||||
<RecordDetailRelationRecordsList relationRecords={relationRecords} />
|
|
||||||
) : (
|
|
||||||
<RecordDetailRelationRecordsListEmptyState
|
|
||||||
relationObjectMetadataItem={relationObjectMetadataItem}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -158,6 +146,8 @@ export const RecordDetailRelationSection = ({
|
|||||||
recordId,
|
recordId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (loading) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RecordDetailSection>
|
<RecordDetailSection>
|
||||||
<RecordDetailSectionHeader
|
<RecordDetailSectionHeader
|
||||||
@ -166,11 +156,15 @@ export const RecordDetailRelationSection = ({
|
|||||||
isToManyObjects
|
isToManyObjects
|
||||||
? {
|
? {
|
||||||
to: filterLinkHref,
|
to: filterLinkHref,
|
||||||
label: `All (${relationRecords.length})`,
|
label:
|
||||||
|
relationRecords.length > 0
|
||||||
|
? `All (${relationRecords.length})`
|
||||||
|
: '',
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
hideRightAdornmentOnMouseLeave={!isDropdownOpen && !isMobile}
|
hideRightAdornmentOnMouseLeave={!isDropdownOpen && !isMobile}
|
||||||
|
areRecordsAvailable={relationRecords.length > 0}
|
||||||
rightAdornment={
|
rightAdornment={
|
||||||
<DropdownScope dropdownScopeId={dropdownId}>
|
<DropdownScope dropdownScopeId={dropdownId}>
|
||||||
<StyledAddDropdown
|
<StyledAddDropdown
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
|
||||||
import { useTheme } from '@emotion/react';
|
|
||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
const StyledSkeletonDiv = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: ${({ theme }) => theme.spacing(4)};
|
|
||||||
height: 40px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const RecordDetailRelationSectionSkeletonLoader = ({
|
|
||||||
numSkeletons = 1,
|
|
||||||
}: {
|
|
||||||
numSkeletons?: number;
|
|
||||||
}) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
return (
|
|
||||||
<SkeletonTheme
|
|
||||||
baseColor={theme.background.tertiary}
|
|
||||||
highlightColor={theme.background.transparent.lighter}
|
|
||||||
borderRadius={4}
|
|
||||||
>
|
|
||||||
<StyledSkeletonDiv>
|
|
||||||
{Array.from({ length: numSkeletons }).map((_, index) => (
|
|
||||||
<Skeleton key={index} width={129} height={16} />
|
|
||||||
))}
|
|
||||||
</StyledSkeletonDiv>
|
|
||||||
</SkeletonTheme>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -1,12 +1,16 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
const StyledHeader = styled.header<{ isDropdownOpen?: boolean }>`
|
const StyledHeader = styled.header<{
|
||||||
|
isDropdownOpen?: boolean;
|
||||||
|
areRecordsAvailable?: boolean;
|
||||||
|
}>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
margin-bottom: ${({ theme, areRecordsAvailable }) =>
|
||||||
|
areRecordsAvailable && theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTitle = styled.div`
|
const StyledTitle = styled.div`
|
||||||
@ -34,6 +38,7 @@ type RecordDetailSectionHeaderProps = {
|
|||||||
link?: { to: string; label: string };
|
link?: { to: string; label: string };
|
||||||
rightAdornment?: React.ReactNode;
|
rightAdornment?: React.ReactNode;
|
||||||
hideRightAdornmentOnMouseLeave?: boolean;
|
hideRightAdornmentOnMouseLeave?: boolean;
|
||||||
|
areRecordsAvailable?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RecordDetailSectionHeader = ({
|
export const RecordDetailSectionHeader = ({
|
||||||
@ -41,11 +46,13 @@ export const RecordDetailSectionHeader = ({
|
|||||||
link,
|
link,
|
||||||
rightAdornment,
|
rightAdornment,
|
||||||
hideRightAdornmentOnMouseLeave = true,
|
hideRightAdornmentOnMouseLeave = true,
|
||||||
|
areRecordsAvailable = false,
|
||||||
}: RecordDetailSectionHeaderProps) => {
|
}: RecordDetailSectionHeaderProps) => {
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledHeader
|
<StyledHeader
|
||||||
|
areRecordsAvailable={areRecordsAvailable}
|
||||||
onMouseEnter={() => setIsHovered(true)}
|
onMouseEnter={() => setIsHovered(true)}
|
||||||
onMouseLeave={() => setIsHovered(false)}
|
onMouseLeave={() => setIsHovered(false)}
|
||||||
>
|
>
|
||||||
@ -53,7 +60,9 @@ export const RecordDetailSectionHeader = ({
|
|||||||
<StyledTitleLabel>{title}</StyledTitleLabel>
|
<StyledTitleLabel>{title}</StyledTitleLabel>
|
||||||
{link && <StyledLink to={link.to}>{link.label}</StyledLink>}
|
{link && <StyledLink to={link.to}>{link.label}</StyledLink>}
|
||||||
</StyledTitle>
|
</StyledTitle>
|
||||||
{hideRightAdornmentOnMouseLeave && !isHovered ? null : rightAdornment}
|
{hideRightAdornmentOnMouseLeave && !isHovered && areRecordsAvailable
|
||||||
|
? null
|
||||||
|
: rightAdornment}
|
||||||
</StyledHeader>
|
</StyledHeader>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user