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 styled from '@emotion/styled';
|
||||||
import { IconArchive, IconDotsVertical, IconPencil } from 'twenty-ui';
|
import { IconArchive, IconDotsVertical, IconPencil } from 'twenty-ui';
|
||||||
|
|
||||||
|
import { SettingsSummaryCard } from '@/settings/components/SettingsSummaryCard';
|
||||||
import { SettingsDataModelIsCustomTag } from '@/settings/data-model/objects/SettingsDataModelIsCustomTag';
|
import { SettingsDataModelIsCustomTag } from '@/settings/data-model/objects/SettingsDataModelIsCustomTag';
|
||||||
import { useIcons } from '@/ui/display/icon/hooks/useIcons';
|
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 { 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 { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
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';
|
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||||
|
|
||||||
type SettingsAboutSectionProps = {
|
type SettingsObjectSummaryCardProps = {
|
||||||
iconKey?: string;
|
iconKey?: string;
|
||||||
isCustom: boolean;
|
isCustom: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
@ -23,21 +20,6 @@ type SettingsAboutSectionProps = {
|
|||||||
onEdit: () => void;
|
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)`
|
const StyledIsCustomTag = styled(SettingsDataModelIsCustomTag)`
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
height: ${({ theme }) => theme.spacing(6)};
|
height: ${({ theme }) => theme.spacing(6)};
|
||||||
@ -45,13 +27,13 @@ const StyledIsCustomTag = styled(SettingsDataModelIsCustomTag)`
|
|||||||
|
|
||||||
const dropdownId = 'settings-object-edit-about-menu-dropdown';
|
const dropdownId = 'settings-object-edit-about-menu-dropdown';
|
||||||
|
|
||||||
export const SettingsAboutSection = ({
|
export const SettingsObjectSummaryCard = ({
|
||||||
iconKey = '',
|
iconKey = '',
|
||||||
isCustom,
|
isCustom,
|
||||||
name,
|
name,
|
||||||
onDeactivate,
|
onDeactivate,
|
||||||
onEdit,
|
onEdit,
|
||||||
}: SettingsAboutSectionProps) => {
|
}: SettingsObjectSummaryCardProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { getIcon } = useIcons();
|
const { getIcon } = useIcons();
|
||||||
const Icon = getIcon(iconKey);
|
const Icon = getIcon(iconKey);
|
||||||
@ -69,14 +51,15 @@ export const SettingsAboutSection = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Section>
|
<SettingsSummaryCard
|
||||||
<H2Title title="About" description="Manage your object" />
|
title={
|
||||||
<Card>
|
<>
|
||||||
<StyledCardContent>
|
{!!Icon && <Icon size={theme.icon.size.md} />}
|
||||||
<StyledName>
|
{name}
|
||||||
{!!Icon && <Icon size={theme.icon.size.md} />}
|
</>
|
||||||
{name}
|
}
|
||||||
</StyledName>
|
rightComponent={
|
||||||
|
<>
|
||||||
<StyledIsCustomTag isCustom={isCustom} />
|
<StyledIsCustomTag isCustom={isCustom} />
|
||||||
<Dropdown
|
<Dropdown
|
||||||
dropdownId={dropdownId}
|
dropdownId={dropdownId}
|
||||||
@ -103,8 +86,8 @@ export const SettingsAboutSection = ({
|
|||||||
scope: dropdownId,
|
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 { IconChevronRight } from 'twenty-ui';
|
||||||
|
|
||||||
import { SettingsListCard } from '@/settings/components/SettingsListCard';
|
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';
|
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||||
|
|
||||||
type SettingsIntegrationDatabaseConnectionsListCardProps = {
|
type SettingsIntegrationDatabaseConnectionsListCardProps = {
|
||||||
@ -52,13 +52,8 @@ export const SettingsIntegrationDatabaseConnectionsListCard = ({
|
|||||||
)}
|
)}
|
||||||
RowRightComponent={({ item: connection }) => (
|
RowRightComponent={({ item: connection }) => (
|
||||||
<StyledRowRightContainer>
|
<StyledRowRightContainer>
|
||||||
<Status
|
<SettingsIntegrationDatabaseConnectedTablesStatus
|
||||||
color="green"
|
connectedTablesCount={connection.tables.length}
|
||||||
text={
|
|
||||||
connection.tables.length === 1
|
|
||||||
? `1 tracked table`
|
|
||||||
: `${connection.tables.length} tracked tables`
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<LightIconButton Icon={IconChevronRight} accent="tertiary" />
|
<LightIconButton Icon={IconChevronRight} accent="tertiary" />
|
||||||
</StyledRowRightContainer>
|
</StyledRowRightContainer>
|
||||||
|
@ -13,13 +13,13 @@ import { getDisabledFieldMetadataItems } from '@/object-metadata/utils/getDisabl
|
|||||||
import { getFieldSlug } from '@/object-metadata/utils/getFieldSlug';
|
import { getFieldSlug } from '@/object-metadata/utils/getFieldSlug';
|
||||||
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
|
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
|
||||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
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 { SettingsObjectFieldActiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldActiveActionDropdown';
|
||||||
import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown';
|
import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown';
|
||||||
import {
|
import {
|
||||||
SettingsObjectFieldItemTableRow,
|
SettingsObjectFieldItemTableRow,
|
||||||
StyledObjectFieldTableRow,
|
StyledObjectFieldTableRow,
|
||||||
} from '@/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow';
|
} 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 { getFieldIdentifierType } from '@/settings/data-model/utils/getFieldIdentifierType';
|
||||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||||
import { AppPath } from '@/types/AppPath';
|
import { AppPath } from '@/types/AppPath';
|
||||||
@ -98,13 +98,16 @@ export const SettingsObjectDetail = () => {
|
|||||||
{ children: activeObjectMetadataItem.labelPlural },
|
{ children: activeObjectMetadataItem.labelPlural },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<SettingsAboutSection
|
<Section>
|
||||||
iconKey={activeObjectMetadataItem.icon ?? undefined}
|
<H2Title title="About" description="Manage your object" />
|
||||||
name={activeObjectMetadataItem.labelPlural || ''}
|
<SettingsObjectSummaryCard
|
||||||
isCustom={activeObjectMetadataItem.isCustom}
|
iconKey={activeObjectMetadataItem.icon ?? undefined}
|
||||||
onDeactivate={handleDisableObject}
|
name={activeObjectMetadataItem.labelPlural || ''}
|
||||||
onEdit={() => navigate('./edit')}
|
isCustom={activeObjectMetadataItem.isCustom}
|
||||||
/>
|
onDeactivate={handleDisableObject}
|
||||||
|
onEdit={() => navigate('./edit')}
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
<Section>
|
<Section>
|
||||||
<H2Title
|
<H2Title
|
||||||
title="Fields"
|
title="Fields"
|
||||||
|
@ -7,9 +7,12 @@ import { useSettingsIntegrationCategories } from '@/settings/integrations/hooks/
|
|||||||
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
||||||
import { AppPath } from '@/types/AppPath';
|
import { AppPath } from '@/types/AppPath';
|
||||||
import { SettingsPath } from '@/types/SettingsPath';
|
import { SettingsPath } from '@/types/SettingsPath';
|
||||||
|
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
|
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 { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||||
|
import { SettingsIntegrationDatabaseConnectionSummaryCard } from '~/pages/settings/integrations/SettingsIntegrationDatabaseConnectionSummaryCard';
|
||||||
import { mockedRemoteObjectIntegrations } from '~/testing/mock-data/remoteObjectDatabases';
|
import { mockedRemoteObjectIntegrations } from '~/testing/mock-data/remoteObjectDatabases';
|
||||||
|
|
||||||
export const SettingsIntegrationDatabaseConnection = () => {
|
export const SettingsIntegrationDatabaseConnection = () => {
|
||||||
@ -66,6 +69,14 @@ export const SettingsIntegrationDatabaseConnection = () => {
|
|||||||
{ children: connection.name },
|
{ 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>
|
</SettingsPageContainer>
|
||||||
</SubMenuTopBarContainer>
|
</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