Migrate to a monorepo structure (#2909)
This commit is contained in:
@ -0,0 +1,111 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { IconArchive, IconDotsVertical, IconPencil } from '@/ui/display/icon';
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { useLazyLoadIcon } from '@/ui/input/hooks/useLazyLoadIcon';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
|
||||
type SettingsAboutSectionProps = {
|
||||
iconKey?: string;
|
||||
isCustom: boolean;
|
||||
name: string;
|
||||
onDisable: () => void;
|
||||
onEdit: () => void;
|
||||
};
|
||||
|
||||
const StyledCard = styled(Card)`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledName = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
margin-right: auto;
|
||||
`;
|
||||
|
||||
const StyledTag = styled(Tag)`
|
||||
box-sizing: border-box;
|
||||
height: ${({ theme }) => theme.spacing(6)};
|
||||
`;
|
||||
|
||||
const dropdownScopeId = 'settings-object-edit-about-menu-dropdown';
|
||||
|
||||
export const SettingsAboutSection = ({
|
||||
iconKey = '',
|
||||
isCustom,
|
||||
name,
|
||||
onDisable,
|
||||
onEdit,
|
||||
}: SettingsAboutSectionProps) => {
|
||||
const theme = useTheme();
|
||||
const { Icon } = useLazyLoadIcon(iconKey);
|
||||
|
||||
const { closeDropdown } = useDropdown({ dropdownScopeId });
|
||||
|
||||
const handleEdit = () => {
|
||||
onEdit();
|
||||
closeDropdown();
|
||||
};
|
||||
|
||||
const handleDisable = () => {
|
||||
onDisable();
|
||||
closeDropdown();
|
||||
};
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<H2Title title="About" description="Manage your object" />
|
||||
<StyledCard>
|
||||
<StyledName>
|
||||
{!!Icon && <Icon size={theme.icon.size.md} />}
|
||||
{name}
|
||||
</StyledName>
|
||||
{isCustom ? (
|
||||
<StyledTag color="orange" text="Custom" />
|
||||
) : (
|
||||
<StyledTag color="blue" text="Standard" />
|
||||
)}
|
||||
<DropdownScope dropdownScopeId={dropdownScopeId}>
|
||||
<Dropdown
|
||||
clickableComponent={
|
||||
<LightIconButton Icon={IconDotsVertical} accent="tertiary" />
|
||||
}
|
||||
dropdownComponents={
|
||||
<DropdownMenu width="160px">
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItem
|
||||
text="Edit"
|
||||
LeftIcon={IconPencil}
|
||||
onClick={handleEdit}
|
||||
/>
|
||||
<MenuItem
|
||||
text="Disable"
|
||||
LeftIcon={IconArchive}
|
||||
onClick={handleDisable}
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
</DropdownMenu>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownScopeId,
|
||||
}}
|
||||
/>
|
||||
</DropdownScope>
|
||||
</StyledCard>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,70 @@
|
||||
import {
|
||||
IconArchive,
|
||||
IconDotsVertical,
|
||||
IconEye,
|
||||
IconPencil,
|
||||
} from '@/ui/display/icon';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
|
||||
type SettingsObjectFieldActiveActionDropdownProps = {
|
||||
isCustomField?: boolean;
|
||||
onDisable: () => void;
|
||||
onEdit: () => void;
|
||||
scopeKey: string;
|
||||
};
|
||||
|
||||
export const SettingsObjectFieldActiveActionDropdown = ({
|
||||
isCustomField,
|
||||
onDisable,
|
||||
onEdit,
|
||||
scopeKey,
|
||||
}: SettingsObjectFieldActiveActionDropdownProps) => {
|
||||
const dropdownScopeId = `${scopeKey}-settings-field-active-action-dropdown`;
|
||||
|
||||
const { closeDropdown } = useDropdown({ dropdownScopeId });
|
||||
|
||||
const handleEdit = () => {
|
||||
onEdit();
|
||||
closeDropdown();
|
||||
};
|
||||
|
||||
const handleDisable = () => {
|
||||
onDisable();
|
||||
closeDropdown();
|
||||
};
|
||||
|
||||
return (
|
||||
<DropdownScope dropdownScopeId={dropdownScopeId}>
|
||||
<Dropdown
|
||||
clickableComponent={
|
||||
<LightIconButton Icon={IconDotsVertical} accent="tertiary" />
|
||||
}
|
||||
dropdownComponents={
|
||||
<DropdownMenu width="160px">
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItem
|
||||
text={isCustomField ? 'Edit' : 'View'}
|
||||
LeftIcon={isCustomField ? IconPencil : IconEye}
|
||||
onClick={handleEdit}
|
||||
/>
|
||||
<MenuItem
|
||||
text="Disable"
|
||||
LeftIcon={IconArchive}
|
||||
onClick={handleDisable}
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
</DropdownMenu>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownScopeId,
|
||||
}}
|
||||
/>
|
||||
</DropdownScope>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,68 @@
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { IconTwentyStar } from '@/ui/display/icon/components/IconTwentyStar';
|
||||
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
import { settingsFieldMetadataTypes } from '../../constants/settingsFieldMetadataTypes';
|
||||
|
||||
type SettingsObjectFieldDataTypeProps = {
|
||||
onClick?: () => void;
|
||||
Icon?: IconComponent;
|
||||
label?: string;
|
||||
value: FieldMetadataType;
|
||||
};
|
||||
|
||||
const StyledDataType = styled.div<{ value: FieldMetadataType }>`
|
||||
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;
|
||||
overflow: hidden;
|
||||
padding: 0 ${({ theme }) => theme.spacing(2)};
|
||||
|
||||
${({ onClick }) =>
|
||||
onClick
|
||||
? css`
|
||||
cursor: pointer;
|
||||
`
|
||||
: ''}
|
||||
|
||||
${({ theme, value }) =>
|
||||
value === FieldMetadataType.Relation
|
||||
? css`
|
||||
border-color: ${theme.color.purple20};
|
||||
color: ${theme.color.purple};
|
||||
`
|
||||
: ''}
|
||||
`;
|
||||
|
||||
const StyledLabelContainer = styled.div`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
export const SettingsObjectFieldDataType = ({
|
||||
onClick,
|
||||
value,
|
||||
Icon = settingsFieldMetadataTypes[value]?.Icon ?? IconTwentyStar,
|
||||
label = settingsFieldMetadataTypes[value]?.label,
|
||||
}: SettingsObjectFieldDataTypeProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const StyledIcon = styled(Icon)`
|
||||
flex: 1 0 auto;
|
||||
`;
|
||||
|
||||
return (
|
||||
<StyledDataType onClick={onClick} value={value}>
|
||||
<StyledIcon size={theme.icon.size.sm} />
|
||||
<StyledLabelContainer>{label}</StyledLabelContainer>
|
||||
</StyledDataType>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,66 @@
|
||||
import { IconArchiveOff, IconDotsVertical } from '@/ui/display/icon';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
|
||||
type SettingsObjectFieldDisabledActionDropdownProps = {
|
||||
isCustomField?: boolean;
|
||||
onActivate: () => void;
|
||||
onErase: () => void;
|
||||
scopeKey: string;
|
||||
};
|
||||
|
||||
export const SettingsObjectFieldDisabledActionDropdown = ({
|
||||
onActivate,
|
||||
scopeKey,
|
||||
}: SettingsObjectFieldDisabledActionDropdownProps) => {
|
||||
const dropdownScopeId = `${scopeKey}-settings-field-disabled-action-dropdown`;
|
||||
|
||||
const { closeDropdown } = useDropdown({ dropdownScopeId });
|
||||
|
||||
const handleActivate = () => {
|
||||
onActivate();
|
||||
closeDropdown();
|
||||
};
|
||||
|
||||
// const handleErase = () => {
|
||||
// onErase();
|
||||
// closeDropdown();
|
||||
// };
|
||||
|
||||
return (
|
||||
<DropdownScope dropdownScopeId={dropdownScopeId}>
|
||||
<Dropdown
|
||||
clickableComponent={
|
||||
<LightIconButton Icon={IconDotsVertical} accent="tertiary" />
|
||||
}
|
||||
dropdownComponents={
|
||||
<DropdownMenu width="160px">
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItem
|
||||
text="Activate"
|
||||
LeftIcon={IconArchiveOff}
|
||||
onClick={handleActivate}
|
||||
/>
|
||||
{/* {isCustomField && (
|
||||
<MenuItem
|
||||
text="Erase"
|
||||
accent="danger"
|
||||
LeftIcon={IconTrash}
|
||||
onClick={handleErase}
|
||||
/>
|
||||
)} */}
|
||||
</DropdownMenuItemsContainer>
|
||||
</DropdownMenu>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownScopeId,
|
||||
}}
|
||||
/>
|
||||
</DropdownScope>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,89 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { useRelationMetadata } from '@/object-metadata/hooks/useRelationMetadata';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
|
||||
import { useLazyLoadIcon } from '@/ui/input/hooks/useLazyLoadIcon';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
|
||||
import { relationTypes } from '../../constants/relationTypes';
|
||||
import { settingsFieldMetadataTypes } from '../../constants/settingsFieldMetadataTypes';
|
||||
|
||||
import { SettingsObjectFieldDataType } from './SettingsObjectFieldDataType';
|
||||
|
||||
type SettingsObjectFieldItemTableRowProps = {
|
||||
ActionIcon: ReactNode;
|
||||
fieldMetadataItem: FieldMetadataItem;
|
||||
};
|
||||
|
||||
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)};
|
||||
`;
|
||||
|
||||
export const SettingsObjectFieldItemTableRow = ({
|
||||
ActionIcon,
|
||||
fieldMetadataItem: fieldMetadataItem,
|
||||
}: SettingsObjectFieldItemTableRowProps) => {
|
||||
const theme = useTheme();
|
||||
const { Icon } = useLazyLoadIcon(fieldMetadataItem.icon ?? '');
|
||||
const navigate = useNavigate();
|
||||
|
||||
// TODO: parse with zod and merge types with FieldType (create a subset of FieldType for example)
|
||||
const fieldDataTypeIsSupported =
|
||||
fieldMetadataItem.type in settingsFieldMetadataTypes;
|
||||
|
||||
const { relationObjectMetadataItem, relationType } = useRelationMetadata({
|
||||
fieldMetadataItem,
|
||||
});
|
||||
|
||||
if (!fieldDataTypeIsSupported) return null;
|
||||
|
||||
const RelationIcon = relationType
|
||||
? relationTypes[relationType].Icon
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<StyledObjectFieldTableRow>
|
||||
<StyledNameTableCell>
|
||||
{!!Icon && <Icon size={theme.icon.size.md} />}
|
||||
{fieldMetadataItem.label}
|
||||
</StyledNameTableCell>
|
||||
<TableCell>
|
||||
{fieldMetadataItem.isCustom ? 'Custom' : 'Standard'}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<SettingsObjectFieldDataType
|
||||
Icon={RelationIcon}
|
||||
label={relationObjectMetadataItem?.labelPlural}
|
||||
onClick={
|
||||
relationObjectMetadataItem?.namePlural &&
|
||||
!relationObjectMetadataItem.isSystem
|
||||
? () =>
|
||||
navigate(
|
||||
`/settings/objects/${getObjectSlug(
|
||||
relationObjectMetadataItem,
|
||||
)}`,
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
value={fieldMetadataItem.type}
|
||||
/>
|
||||
</TableCell>
|
||||
<StyledIconTableCell>{ActionIcon}</StyledIconTableCell>
|
||||
</StyledObjectFieldTableRow>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,65 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { useLazyLoadIcon } from '@/ui/input/hooks/useLazyLoadIcon';
|
||||
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
|
||||
type SettingsObjectItemTableRowProps = {
|
||||
action: ReactNode;
|
||||
objectItem: ObjectMetadataItem;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
export const StyledObjectTableRow = styled(TableRow)`
|
||||
grid-template-columns: 180px 98.7px 98.7px 98.7px 36px;
|
||||
`;
|
||||
|
||||
const StyledNameTableCell = styled(TableCell)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledActionTableCell = styled(TableCell)`
|
||||
justify-content: center;
|
||||
padding-right: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
export const SettingsObjectItemTableRow = ({
|
||||
action,
|
||||
objectItem,
|
||||
onClick,
|
||||
}: SettingsObjectItemTableRowProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const { records } = useFindManyRecords({
|
||||
objectNameSingular: objectItem.nameSingular,
|
||||
});
|
||||
|
||||
const { Icon } = useLazyLoadIcon(objectItem.icon ?? '');
|
||||
|
||||
return (
|
||||
<StyledObjectTableRow key={objectItem.namePlural} onClick={onClick}>
|
||||
<StyledNameTableCell>
|
||||
{!!Icon && <Icon size={theme.icon.size.md} />}
|
||||
{objectItem.labelPlural}
|
||||
</StyledNameTableCell>
|
||||
<TableCell>
|
||||
{objectItem.isCustom ? (
|
||||
<Tag color="orange" text="Custom" />
|
||||
) : (
|
||||
<Tag color="blue" text="Standard" />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
{objectItem.fields.filter((field) => !field.isSystem).length}
|
||||
</TableCell>
|
||||
<TableCell align="right">{records.length}</TableCell>
|
||||
<StyledActionTableCell>{action}</StyledActionTableCell>
|
||||
</StyledObjectTableRow>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user