fix(): several ui improvements (#10556)

Close #10531

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
Antoine Moreaux
2025-03-03 17:06:16 +01:00
committed by GitHub
parent a5d60919a7
commit e8b6b1b941
15 changed files with 88 additions and 101 deletions

View File

@ -56,8 +56,11 @@ export const SettingsWorkspace = () => {
title={t`Customize Domain`}
Icon={<IconWorld />}
Status={
currentWorkspace?.customDomain ? (
currentWorkspace?.customDomain &&
currentWorkspace?.isCustomDomainEnabled ? (
<Status text={'Active'} color={'turquoise'} />
) : currentWorkspace?.customDomain ? (
<Status text={'Inactive'} color={'orange'} />
) : undefined
}
/>

View File

@ -3,16 +3,21 @@ import { TextInputV2 } from '@/ui/input/components/TextInputV2';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { Controller, useFormContext } from 'react-hook-form';
import { H2Title, Section } from 'twenty-ui';
import { Button, H2Title, IconReload, Section } from 'twenty-ui';
import { SettingsCustomDomainRecords } from '~/pages/settings/workspace/SettingsCustomDomainRecords';
import { SettingsCustomDomainRecordsStatus } from '~/pages/settings/workspace/SettingsCustomDomainRecordsStatus';
import { customDomainRecordsState } from '~/pages/settings/workspace/states/customDomainRecordsState';
import { useRecoilValue } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useCheckCustomDomainValidRecords } from '~/pages/settings/workspace/hooks/useCheckCustomDomainValidRecords';
const StyledDomainFormWrapper = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
`;
const StyledButton = styled(Button)`
align-self: flex-start;
`;
const StyledRecordsWrapper = styled.div`
@ -28,6 +33,12 @@ export const SettingsCustomDomain = () => {
customDomainRecordsState,
);
const { checkCustomDomainRecords } = useCheckCustomDomainValidRecords();
if (!customDomainRecords && !loading) {
checkCustomDomainRecords();
}
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const { t } = useLingui();
@ -53,11 +64,18 @@ export const SettingsCustomDomain = () => {
onChange={onChange}
placeholder="crm.yourdomain.com"
error={error?.message}
loading={!!loading}
fullWidth
/>
)}
/>
<StyledButton
loading={loading}
Icon={IconReload}
title={t`Reload`}
variant="primary"
onClick={checkCustomDomainRecords}
type="button"
/>
</StyledDomainFormWrapper>
{currentWorkspace?.customDomain && (
<StyledRecordsWrapper>

View File

@ -1,48 +0,0 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useEffect, useCallback } from 'react';
import { useSetRecoilState, useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
import { useCheckCustomDomainValidRecordsMutation } from '~/generated/graphql';
import { customDomainRecordsState } from '~/pages/settings/workspace/states/customDomainRecordsState';
export const SettingsCustomDomainEffect = () => {
const [checkCustomDomainValidRecords] =
useCheckCustomDomainValidRecordsMutation();
const setCustomDomainRecords = useSetRecoilState(customDomainRecordsState);
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const checkCustomDomainValidRecordsPolling = useCallback(async () => {
setCustomDomainRecords((currentState) => ({
...currentState,
loading: true,
}));
checkCustomDomainValidRecords({
onCompleted: (data) => {
if (isDefined(data.checkCustomDomainValidRecords)) {
setCustomDomainRecords({
loading: false,
customDomainRecords: data.checkCustomDomainValidRecords,
});
}
},
});
}, [checkCustomDomainValidRecords, setCustomDomainRecords]);
useEffect(() => {
let pollIntervalFn: null | ReturnType<typeof setInterval> = null;
if (isDefined(currentWorkspace?.customDomain)) {
checkCustomDomainValidRecordsPolling();
pollIntervalFn = setInterval(checkCustomDomainValidRecordsPolling, 6000);
}
return () => {
if (isDefined(pollIntervalFn)) {
clearInterval(pollIntervalFn);
}
};
}, [checkCustomDomainValidRecordsPolling, currentWorkspace?.customDomain]);
return <></>;
};

View File

@ -18,17 +18,21 @@ const StyledTable = styled(Table)`
const StyledTableCell = styled(TableCell)`
overflow: hidden;
padding: 0 ${({ theme }) => theme.spacing(3)} 0 0;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
`;
const StyledButton = styled(Button)`
-moz-user-select: text;
-ms-user-select: text;
-webkit-user-select: text;
background-color: ${({ theme }) => theme.background.transparent.lighter};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
color: ${({ theme }) => theme.font.color.tertiary};
font-family: ${({ theme }) => theme.font.family};
font-weight: ${({ theme }) => theme.font.weight.regular};
height: ${({ theme }) => theme.spacing(6)};
overflow: hidden;

View File

@ -24,7 +24,6 @@ import { zodResolver } from '@hookform/resolvers/zod';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
import { SettingsPath } from '@/types/SettingsPath';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsCustomDomainEffect } from '~/pages/settings/workspace/SettingsCustomDomainEffect';
import { isDefined } from 'twenty-shared';
export const SettingsDomain = () => {
@ -229,12 +228,7 @@ export const SettingsDomain = () => {
>
<SettingsPageContainer>
<SettingsSubdomain />
{isCustomDomainEnabled && (
<>
<SettingsCustomDomainEffect />
<SettingsCustomDomain />
</>
)}
{isCustomDomainEnabled && <SettingsCustomDomain />}
</SettingsPageContainer>
</SubMenuTopBarContainer>
</FormProvider>

View File

@ -14,15 +14,6 @@ const StyledDomainFormWrapper = styled.div`
display: flex;
`;
const StyledDomain = styled.h2`
align-self: flex-start;
color: ${({ theme }) => theme.font.color.secondary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.medium};
margin: ${({ theme }) => theme.spacing(2)};
white-space: nowrap;
`;
export const SettingsSubdomain = () => {
const domainConfiguration = useRecoilValue(domainConfigurationState);
const { t } = useLingui();
@ -51,13 +42,13 @@ export const SettingsSubdomain = () => {
onChange={onChange}
error={error?.message}
disabled={!!currentWorkspace?.customDomain}
rightAdornment={
isDefined(domainConfiguration.frontDomain)
? `.${domainConfiguration.frontDomain}`
: undefined
}
fullWidth
/>
{isDefined(domainConfiguration.frontDomain) && (
<StyledDomain>
{`.${domainConfiguration.frontDomain}`}
</StyledDomain>
)}
</>
)}
/>

View File

@ -0,0 +1,32 @@
import { customDomainRecordsState } from '~/pages/settings/workspace/states/customDomainRecordsState';
import { useCheckCustomDomainValidRecordsMutation } from '~/generated/graphql';
import { isDefined } from 'twenty-shared';
import { useSetRecoilState } from 'recoil';
export const useCheckCustomDomainValidRecords = () => {
const [checkCustomDomainValidRecords] =
useCheckCustomDomainValidRecordsMutation();
const setCustomDomainRecords = useSetRecoilState(customDomainRecordsState);
const checkCustomDomainRecords = () => {
setCustomDomainRecords((currentState) => ({
...currentState,
loading: true,
}));
checkCustomDomainValidRecords({
onCompleted: (data) => {
if (isDefined(data.checkCustomDomainValidRecords)) {
setCustomDomainRecords({
loading: false,
customDomainRecords: data.checkCustomDomainValidRecords,
});
}
},
});
};
return {
checkCustomDomainRecords,
};
};