feat: add Fields table to Object Detail page (#1988)

* feat: add Fields table to Object Detail page

Closes #1815

* refactor: add ObjectFieldDataType
This commit is contained in:
Thaïs
2023-10-13 11:51:11 +02:00
committed by GitHub
parent bd9a6c56fe
commit 818efd72d0
14 changed files with 342 additions and 58 deletions

View File

@ -0,0 +1,61 @@
import { css, useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import {
IconCheck,
IconLink,
IconNumbers,
IconPlug,
IconSocial,
IconUserCircle,
} from '@/ui/icon';
import { IconComponent } from '@/ui/icon/types/IconComponent';
import { ObjectFieldItem } from '../types/ObjectFieldItem';
type ObjectFieldDataTypeProps = {
value: ObjectFieldItem['dataType'];
};
const StyledDataType = styled.div<{ value: ObjectFieldItem['dataType'] }>`
align-items: center;
border: 1px solid transparent;
border-radius: ${({ theme }) => theme.border.radius.sm};
display: flex;
font-size: ${({ theme }) => theme.font.size.sm};
gap: ${({ theme }) => theme.spacing(1)};
height: 20px;
padding: 0 ${({ theme }) => theme.spacing(2)};
${({ theme, value }) =>
value === 'relation'
? css`
border-color: ${theme.color.purple20};
color: ${theme.color.purple};
`
: ''}
`;
const dataTypes: Record<
ObjectFieldItem['dataType'],
{ label: string; Icon: IconComponent }
> = {
boolean: { label: 'True/False', Icon: IconCheck },
number: { label: 'Number', Icon: IconNumbers },
relation: { label: 'Relation', Icon: IconPlug },
social: { label: 'Social', Icon: IconSocial },
teammate: { label: 'Teammate', Icon: IconUserCircle },
text: { label: 'Text', Icon: IconLink },
};
export const ObjectFieldDataType = ({ value }: ObjectFieldDataTypeProps) => {
const theme = useTheme();
const { label, Icon } = dataTypes[value];
return (
<StyledDataType value={value}>
<Icon size={theme.icon.size.sm} />
{label}
</StyledDataType>
);
};

View File

@ -0,0 +1,57 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { IconDotsVertical } from '@/ui/icon';
import { TableCell } from '@/ui/table/components/TableCell';
import { TableRow } from '@/ui/table/components/TableRow';
import { ObjectFieldItem } from '../types/ObjectFieldItem';
import { ObjectFieldDataType } from './ObjectFieldDataType';
export const StyledObjectFieldTableRow = styled(TableRow)`
grid-template-columns: 180px 148px 148px 36px;
`;
const StyledNameTableCell = styled(TableCell)`
color: ${({ theme }) => theme.font.color.primary};
gap: ${({ theme }) => theme.spacing(2)};
`;
const StyledIconTableCell = styled(TableCell)`
justify-content: center;
padding-right: ${({ theme }) => theme.spacing(1)};
`;
const StyledIconDotsVertical = styled(IconDotsVertical)`
color: ${({ theme }) => theme.font.color.tertiary};
`;
export const ObjectFieldItemTableRow = ({
fieldItem,
}: {
fieldItem: ObjectFieldItem;
}) => {
const theme = useTheme();
return (
<StyledObjectFieldTableRow>
<StyledNameTableCell>
<fieldItem.Icon size={theme.icon.size.md} />
{fieldItem.name}
</StyledNameTableCell>
<TableCell>
{fieldItem.type === 'standard' ? 'Standard' : 'Custom'}
</TableCell>
<TableCell>
<ObjectFieldDataType value={fieldItem.dataType} />
</TableCell>
<StyledIconTableCell>
<StyledIconDotsVertical
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
/>
</StyledIconTableCell>
</StyledObjectFieldTableRow>
);
};

View File

@ -0,0 +1,125 @@
import { ObjectFieldItem } from '@/settings/objects/types/ObjectFieldItem';
import {
IconBrandLinkedin,
IconBrandTwitter,
IconBuildingSkyscraper,
IconCurrencyDollar,
IconFreeRights,
IconGraph,
IconHeadphones,
IconLink,
IconLuggage,
IconPlane,
IconTarget,
IconUser,
IconUserCircle,
IconUsers,
} from '@/ui/icon';
export const activeObjectItems = [
{
name: 'Companies',
singularName: 'company',
Icon: IconBuildingSkyscraper,
type: 'standard',
fields: 23,
instances: 165,
},
{
name: 'People',
singularName: 'person',
Icon: IconUser,
type: 'standard',
fields: 16,
instances: 462,
},
];
export const disabledObjectItems = [
{
name: 'Travels',
Icon: IconLuggage,
type: 'custom',
fields: 23,
instances: 165,
},
{
name: 'Flights',
Icon: IconPlane,
type: 'custom',
fields: 23,
instances: 165,
},
];
export const activeFieldItems: ObjectFieldItem[] = [
{
name: 'People',
Icon: IconUser,
type: 'standard',
dataType: 'relation',
},
{
name: 'URL',
Icon: IconLink,
type: 'standard',
dataType: 'text',
},
{
name: 'Linkedin',
Icon: IconBrandLinkedin,
type: 'standard',
dataType: 'social',
},
{
name: 'Account Owner',
Icon: IconUserCircle,
type: 'standard',
dataType: 'teammate',
},
{
name: 'Employees',
Icon: IconUsers,
type: 'custom',
dataType: 'number',
},
];
export const disabledFieldItems: ObjectFieldItem[] = [
{
name: 'ICP',
Icon: IconTarget,
type: 'standard',
dataType: 'boolean',
},
{
name: 'Twitter',
Icon: IconBrandTwitter,
type: 'standard',
dataType: 'social',
},
{
name: 'Annual revenue',
Icon: IconCurrencyDollar,
type: 'standard',
dataType: 'number',
},
{
name: 'Is public',
Icon: IconGraph,
type: 'standard',
dataType: 'boolean',
},
{
name: 'Free tier?',
Icon: IconFreeRights,
type: 'custom',
dataType: 'boolean',
},
{
name: 'Priority support',
Icon: IconHeadphones,
type: 'custom',
dataType: 'boolean',
},
];

View File

@ -0,0 +1 @@
export const objectSettingsWidth = '512px';

View File

@ -0,0 +1,8 @@
import { IconComponent } from '@/ui/icon/types/IconComponent';
export type ObjectFieldItem = {
name: string;
Icon: IconComponent;
type: 'standard' | 'custom';
dataType: 'boolean' | 'number' | 'relation' | 'social' | 'teammate' | 'text';
};

View File

@ -40,7 +40,10 @@ export {
IconFileImport,
IconFileUpload,
IconForbid,
IconFreeRights,
IconGraph,
IconGripVertical,
IconHeadphones,
IconHeart,
IconHeartOff,
IconHelpCircle,
@ -60,13 +63,16 @@ export {
IconMinus,
IconMoneybag,
IconNotes,
IconNumbers,
IconPencil,
IconPhone,
IconPlane,
IconPlug,
IconPlus,
IconProgressCheck,
IconSearch,
IconSettings,
IconSocial,
IconTag,
IconTarget,
IconTargetArrow,

View File

@ -8,6 +8,7 @@ const StyledPanel = styled.div`
display: flex;
flex-direction: row;
height: 100%;
overflow: auto;
width: 100%;
`;

View File

@ -6,6 +6,7 @@ import { IconChevronDown, IconChevronUp } from '@/ui/icon';
type TableSectionProps = {
children: ReactNode;
isInitiallyExpanded?: boolean;
title: string;
};
@ -38,9 +39,13 @@ const StyledSectionContent = styled.div`
padding: ${({ theme }) => theme.spacing(2)} 0;
`;
export const TableSection = ({ children, title }: TableSectionProps) => {
export const TableSection = ({
children,
isInitiallyExpanded = true,
title,
}: TableSectionProps) => {
const theme = useTheme();
const [isExpanded, setIsExpanded] = useState(true);
const [isExpanded, setIsExpanded] = useState(isInitiallyExpanded);
const handleToggleSection = () =>
setIsExpanded((previousIsExpanded) => !previousIsExpanded);