mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-26 13:31:45 +03:00
feat: add Database Connection Summary Card to Settings/Integrations/D… (#4791)
…atabase/Connection page Closes #4558 <img width="542" alt="image" src="https://github.com/twentyhq/twenty/assets/3098428/16d7d8ce-57db-4e48-ba72-a2318a2d34a4"> --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
parent
9d45f7811e
commit
f184541293
@ -0,0 +1,38 @@
|
||||
import { ReactNode } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
|
||||
type SettingsSummaryCardProps = {
|
||||
title: ReactNode;
|
||||
rightComponent: ReactNode;
|
||||
};
|
||||
|
||||
const StyledCardContent = styled(CardContent)`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
min-height: ${({ theme }) => theme.spacing(6)};
|
||||
`;
|
||||
|
||||
const StyledTitle = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
display: flex;
|
||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
margin-right: auto;
|
||||
`;
|
||||
|
||||
export const SettingsSummaryCard = ({
|
||||
title,
|
||||
rightComponent,
|
||||
}: SettingsSummaryCardProps) => (
|
||||
<Card>
|
||||
<StyledCardContent>
|
||||
<StyledTitle>{title}</StyledTitle>
|
||||
{rightComponent}
|
||||
</StyledCardContent>
|
||||
</Card>
|
||||
);
|
@ -2,20 +2,17 @@ import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconArchive, IconDotsVertical, IconPencil } from 'twenty-ui';
|
||||
|
||||
import { SettingsSummaryCard } from '@/settings/components/SettingsSummaryCard';
|
||||
import { SettingsDataModelIsCustomTag } from '@/settings/data-model/objects/SettingsDataModelIsCustomTag';
|
||||
import { useIcons } from '@/ui/display/icon/hooks/useIcons';
|
||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
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 { Section } from '@/ui/layout/section/components/Section';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
|
||||
type SettingsAboutSectionProps = {
|
||||
type SettingsObjectSummaryCardProps = {
|
||||
iconKey?: string;
|
||||
isCustom: boolean;
|
||||
name: string;
|
||||
@ -23,21 +20,6 @@ type SettingsAboutSectionProps = {
|
||||
onEdit: () => void;
|
||||
};
|
||||
|
||||
const StyledCardContent = styled(CardContent)`
|
||||
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;
|
||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
margin-right: auto;
|
||||
`;
|
||||
|
||||
const StyledIsCustomTag = styled(SettingsDataModelIsCustomTag)`
|
||||
box-sizing: border-box;
|
||||
height: ${({ theme }) => theme.spacing(6)};
|
||||
@ -45,13 +27,13 @@ const StyledIsCustomTag = styled(SettingsDataModelIsCustomTag)`
|
||||
|
||||
const dropdownId = 'settings-object-edit-about-menu-dropdown';
|
||||
|
||||
export const SettingsAboutSection = ({
|
||||
export const SettingsObjectSummaryCard = ({
|
||||
iconKey = '',
|
||||
isCustom,
|
||||
name,
|
||||
onDeactivate,
|
||||
onEdit,
|
||||
}: SettingsAboutSectionProps) => {
|
||||
}: SettingsObjectSummaryCardProps) => {
|
||||
const theme = useTheme();
|
||||
const { getIcon } = useIcons();
|
||||
const Icon = getIcon(iconKey);
|
||||
@ -69,14 +51,15 @@ export const SettingsAboutSection = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<H2Title title="About" description="Manage your object" />
|
||||
<Card>
|
||||
<StyledCardContent>
|
||||
<StyledName>
|
||||
{!!Icon && <Icon size={theme.icon.size.md} />}
|
||||
{name}
|
||||
</StyledName>
|
||||
<SettingsSummaryCard
|
||||
title={
|
||||
<>
|
||||
{!!Icon && <Icon size={theme.icon.size.md} />}
|
||||
{name}
|
||||
</>
|
||||
}
|
||||
rightComponent={
|
||||
<>
|
||||
<StyledIsCustomTag isCustom={isCustom} />
|
||||
<Dropdown
|
||||
dropdownId={dropdownId}
|
||||
@ -103,8 +86,8 @@ export const SettingsAboutSection = ({
|
||||
scope: dropdownId,
|
||||
}}
|
||||
/>
|
||||
</StyledCardContent>
|
||||
</Card>
|
||||
</Section>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
import { Status } from '@/ui/display/status/components/Status';
|
||||
|
||||
type SettingsIntegrationDatabaseConnectedTablesStatusProps = {
|
||||
connectedTablesCount: number;
|
||||
};
|
||||
|
||||
export const SettingsIntegrationDatabaseConnectedTablesStatus = ({
|
||||
connectedTablesCount,
|
||||
}: SettingsIntegrationDatabaseConnectedTablesStatusProps) => (
|
||||
<Status
|
||||
color="green"
|
||||
text={
|
||||
connectedTablesCount === 1
|
||||
? `1 tracked table`
|
||||
: `${connectedTablesCount} tracked tables`
|
||||
}
|
||||
/>
|
||||
);
|
@ -3,7 +3,7 @@ import styled from '@emotion/styled';
|
||||
import { IconChevronRight } from 'twenty-ui';
|
||||
|
||||
import { SettingsListCard } from '@/settings/components/SettingsListCard';
|
||||
import { Status } from '@/ui/display/status/components/Status';
|
||||
import { SettingsIntegrationDatabaseConnectedTablesStatus } from '@/settings/integrations/components/SettingsIntegrationDatabaseConnectedTablesStatus';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
|
||||
type SettingsIntegrationDatabaseConnectionsListCardProps = {
|
||||
@ -52,13 +52,8 @@ export const SettingsIntegrationDatabaseConnectionsListCard = ({
|
||||
)}
|
||||
RowRightComponent={({ item: connection }) => (
|
||||
<StyledRowRightContainer>
|
||||
<Status
|
||||
color="green"
|
||||
text={
|
||||
connection.tables.length === 1
|
||||
? `1 tracked table`
|
||||
: `${connection.tables.length} tracked tables`
|
||||
}
|
||||
<SettingsIntegrationDatabaseConnectedTablesStatus
|
||||
connectedTablesCount={connection.tables.length}
|
||||
/>
|
||||
<LightIconButton Icon={IconChevronRight} accent="tertiary" />
|
||||
</StyledRowRightContainer>
|
||||
|
@ -13,13 +13,13 @@ import { getDisabledFieldMetadataItems } from '@/object-metadata/utils/getDisabl
|
||||
import { getFieldSlug } from '@/object-metadata/utils/getFieldSlug';
|
||||
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SettingsAboutSection } from '@/settings/data-model/object-details/components/SettingsObjectAboutSection';
|
||||
import { SettingsObjectFieldActiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldActiveActionDropdown';
|
||||
import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown';
|
||||
import {
|
||||
SettingsObjectFieldItemTableRow,
|
||||
StyledObjectFieldTableRow,
|
||||
} from '@/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow';
|
||||
import { SettingsObjectSummaryCard } from '@/settings/data-model/object-details/components/SettingsObjectSummaryCard';
|
||||
import { getFieldIdentifierType } from '@/settings/data-model/utils/getFieldIdentifierType';
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
@ -98,13 +98,16 @@ export const SettingsObjectDetail = () => {
|
||||
{ children: activeObjectMetadataItem.labelPlural },
|
||||
]}
|
||||
/>
|
||||
<SettingsAboutSection
|
||||
iconKey={activeObjectMetadataItem.icon ?? undefined}
|
||||
name={activeObjectMetadataItem.labelPlural || ''}
|
||||
isCustom={activeObjectMetadataItem.isCustom}
|
||||
onDeactivate={handleDisableObject}
|
||||
onEdit={() => navigate('./edit')}
|
||||
/>
|
||||
<Section>
|
||||
<H2Title title="About" description="Manage your object" />
|
||||
<SettingsObjectSummaryCard
|
||||
iconKey={activeObjectMetadataItem.icon ?? undefined}
|
||||
name={activeObjectMetadataItem.labelPlural || ''}
|
||||
isCustom={activeObjectMetadataItem.isCustom}
|
||||
onDeactivate={handleDisableObject}
|
||||
onEdit={() => navigate('./edit')}
|
||||
/>
|
||||
</Section>
|
||||
<Section>
|
||||
<H2Title
|
||||
title="Fields"
|
||||
|
@ -7,9 +7,12 @@ import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/
|
||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { SettingsIntegrationDatabaseConnectionSummaryCard } from '~/pages/settings/integrations/SettingsIntegrationDatabaseConnectionSummaryCard';
|
||||
import { mockedRemoteObjectIntegrations } from '~/testing/mock-data/remoteObjectDatabases';
|
||||
|
||||
export const SettingsIntegrationDatabaseConnection = () => {
|
||||
@ -66,6 +69,14 @@ export const SettingsIntegrationDatabaseConnection = () => {
|
||||
{ children: connection.name },
|
||||
]}
|
||||
/>
|
||||
<Section>
|
||||
<H2Title title="About" description="About this remote object" />
|
||||
<SettingsIntegrationDatabaseConnectionSummaryCard
|
||||
databaseLogoUrl={integration.from.image}
|
||||
connectionName={connection.name}
|
||||
connectedTablesNb={connection.tables.length}
|
||||
/>
|
||||
</Section>
|
||||
</SettingsPageContainer>
|
||||
</SubMenuTopBarContainer>
|
||||
);
|
||||
|
@ -0,0 +1,44 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { SettingsSummaryCard } from '@/settings/components/SettingsSummaryCard';
|
||||
import { SettingsIntegrationDatabaseConnectedTablesStatus } from '@/settings/integrations/components/SettingsIntegrationDatabaseConnectedTablesStatus';
|
||||
|
||||
type SettingsIntegrationDatabaseConnectionSummaryCardProps = {
|
||||
databaseLogoUrl: string;
|
||||
connectionName: string;
|
||||
connectedTablesNb: number;
|
||||
};
|
||||
|
||||
const StyledDatabaseLogoContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: ${({ theme }) => theme.spacing(4)};
|
||||
justify-content: center;
|
||||
width: ${({ theme }) => theme.spacing(4)};
|
||||
`;
|
||||
|
||||
const StyledDatabaseLogo = styled.img`
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
export const SettingsIntegrationDatabaseConnectionSummaryCard = ({
|
||||
databaseLogoUrl,
|
||||
connectionName,
|
||||
connectedTablesNb,
|
||||
}: SettingsIntegrationDatabaseConnectionSummaryCardProps) => (
|
||||
<SettingsSummaryCard
|
||||
title={
|
||||
<>
|
||||
<StyledDatabaseLogoContainer>
|
||||
<StyledDatabaseLogo alt="" src={databaseLogoUrl} />
|
||||
</StyledDatabaseLogoContainer>
|
||||
{connectionName}
|
||||
</>
|
||||
}
|
||||
rightComponent={
|
||||
<SettingsIntegrationDatabaseConnectedTablesStatus
|
||||
connectedTablesCount={connectedTablesNb}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
Loading…
Reference in New Issue
Block a user