Translation followup (#9735)
Address PR comments and more progress on translation
This commit is contained in:
@ -39,9 +39,7 @@ export const RecordIndexActionMenuBar = () => {
|
||||
return (
|
||||
<BottomBar
|
||||
bottomBarId={getActionBarIdFromActionMenuId(actionMenuId)}
|
||||
bottomBarHotkeyScopeFromParent={{
|
||||
scope: ActionBarHotkeyScope.ActionBar,
|
||||
}}
|
||||
bottomBarHotkeyScopeFromParent={{ scope: ActionBarHotkeyScope.ActionBar }}
|
||||
>
|
||||
<StyledLabel>{contextStoreNumberOfSelectedRecords} selected:</StyledLabel>
|
||||
{pinnedEntries.map((entry, index) => (
|
||||
|
||||
@ -21,11 +21,7 @@ export const RecordShowRightDrawerActionMenu = () => {
|
||||
return (
|
||||
<>
|
||||
{contextStoreCurrentObjectMetadataId && (
|
||||
<ActionMenuContext.Provider
|
||||
value={{
|
||||
isInRightDrawer: true,
|
||||
}}
|
||||
>
|
||||
<ActionMenuContext.Provider value={{ isInRightDrawer: true }}>
|
||||
<RightDrawerActionMenuDropdown />
|
||||
<ActionMenuConfirmationModals />
|
||||
<RecordActionMenuEntriesSetter />
|
||||
|
||||
@ -72,9 +72,7 @@ export const RightDrawerActionMenuDropdown = () => {
|
||||
<Button title="Actions" hotkeys={[getOsControlSymbol(), 'O']} />
|
||||
}
|
||||
dropdownPlacement="top-end"
|
||||
dropdownOffset={{
|
||||
y: parseInt(theme.spacing(2), 10),
|
||||
}}
|
||||
dropdownOffset={{ y: parseInt(theme.spacing(2), 10) }}
|
||||
dropdownComponents={
|
||||
<DropdownMenuItemsContainer>
|
||||
{actionMenuEntries
|
||||
|
||||
@ -161,9 +161,7 @@ export const CalendarCurrentEventCursor = ({
|
||||
updateCurrentCalendarEvent();
|
||||
}
|
||||
}}
|
||||
transition={{
|
||||
duration: theme.animation.duration.normal,
|
||||
}}
|
||||
transition={{ duration: theme.animation.duration.normal }}
|
||||
>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
|
||||
@ -100,9 +100,7 @@ export const MessageThreadSubscribersDropdownButton = ({
|
||||
)}
|
||||
</DropdownMenu>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: MESSAGE_THREAD_SUBSCRIBER_DROPDOWN_ID,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: MESSAGE_THREAD_SUBSCRIBER_DROPDOWN_ID }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -70,9 +70,7 @@ export const AttachmentDropdown = ({
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownId,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -18,9 +18,7 @@ const meta: Meta<typeof TimelineActivities> = {
|
||||
(Story) => {
|
||||
return (
|
||||
<TimelineActivityContext.Provider
|
||||
value={{
|
||||
labelIdentifierValue: 'Mock',
|
||||
}}
|
||||
value={{ labelIdentifierValue: 'Mock' }}
|
||||
>
|
||||
<Story />
|
||||
</TimelineActivityContext.Provider>
|
||||
|
||||
@ -17,9 +17,7 @@ const meta: Meta<typeof EventCardMessage> = {
|
||||
(Story) => {
|
||||
return (
|
||||
<TimelineActivityContext.Provider
|
||||
value={{
|
||||
labelIdentifierValue: 'Mock',
|
||||
}}
|
||||
value={{ labelIdentifierValue: 'Mock' }}
|
||||
>
|
||||
<Story />
|
||||
</TimelineActivityContext.Provider>
|
||||
|
||||
@ -147,9 +147,7 @@ export const AnalyticsActivityGraph = ({
|
||||
match: '*',
|
||||
},
|
||||
]}
|
||||
yScale={{
|
||||
type: 'linear',
|
||||
}}
|
||||
yScale={{ type: 'linear' }}
|
||||
axisBottom={{
|
||||
format: '%b %d, %I:%M %p', //TODO: add the user prefered time format for the graph
|
||||
tickValues: 2,
|
||||
|
||||
@ -8,11 +8,7 @@ export const AuthProvider = ({ children }: React.PropsWithChildren) => {
|
||||
const currentWorkspaceMembers = useRecoilValue(currentWorkspaceMembersState);
|
||||
|
||||
return (
|
||||
<AuthContext.Provider
|
||||
value={{
|
||||
currentWorkspaceMembers,
|
||||
}}
|
||||
>
|
||||
<AuthContext.Provider value={{ currentWorkspaceMembers }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
|
||||
@ -13,6 +13,7 @@ import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
|
||||
@ -56,6 +57,8 @@ const StyledEmpty = styled.div`
|
||||
`;
|
||||
|
||||
export const CommandMenu = () => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const { onItemClick } = useCommandMenuOnItemClick();
|
||||
|
||||
const commandMenuSearch = useRecoilValue(commandMenuSearchState);
|
||||
@ -99,51 +102,51 @@ export const CommandMenu = () => {
|
||||
|
||||
const commandGroups: CommandGroupConfig[] = [
|
||||
{
|
||||
heading: 'Copilot',
|
||||
heading: t`Copilot`,
|
||||
items: copilotCommands,
|
||||
},
|
||||
{
|
||||
heading: 'Record Selection',
|
||||
heading: t`Record Selection`,
|
||||
items: matchingStandardActionRecordSelectionCommands,
|
||||
},
|
||||
{
|
||||
heading: 'Workflow Record Selection',
|
||||
heading: t`Workflow Record Selection`,
|
||||
items: matchingWorkflowRunRecordSelectionCommands,
|
||||
},
|
||||
{
|
||||
heading: 'View',
|
||||
heading: t`View`,
|
||||
items: matchingStandardActionGlobalCommands,
|
||||
},
|
||||
{
|
||||
heading: 'Workflows',
|
||||
heading: t`Workflows`,
|
||||
items: matchingWorkflowRunGlobalCommands,
|
||||
},
|
||||
{
|
||||
heading: 'Navigate',
|
||||
heading: t`Navigate`,
|
||||
items: matchingNavigateCommand,
|
||||
},
|
||||
{
|
||||
heading: 'People',
|
||||
heading: t`People`,
|
||||
items: peopleCommands,
|
||||
},
|
||||
{
|
||||
heading: 'Companies',
|
||||
heading: t`Companies`,
|
||||
items: companyCommands,
|
||||
},
|
||||
{
|
||||
heading: 'Opportunities',
|
||||
heading: t`Opportunities`,
|
||||
items: opportunityCommands,
|
||||
},
|
||||
{
|
||||
heading: 'Notes',
|
||||
heading: t`Notes`,
|
||||
items: noteCommands,
|
||||
},
|
||||
{
|
||||
heading: 'Tasks',
|
||||
heading: t`Tasks`,
|
||||
items: tasksCommands,
|
||||
},
|
||||
{
|
||||
heading: 'Custom Objects',
|
||||
heading: t`Custom Objects`,
|
||||
items: customObjectCommands,
|
||||
},
|
||||
];
|
||||
|
||||
@ -97,9 +97,7 @@ export const CommandMenuContainer = ({
|
||||
initial="closed"
|
||||
exit="closed"
|
||||
variants={COMMAND_MENU_ANIMATION_VARIANTS}
|
||||
transition={{
|
||||
duration: theme.animation.duration.normal,
|
||||
}}
|
||||
transition={{ duration: theme.animation.duration.normal }}
|
||||
>
|
||||
{children}
|
||||
</StyledCommandMenu>
|
||||
|
||||
@ -19,6 +19,7 @@ import { ActionMenuComponentInstanceContext } from '@/action-menu/states/context
|
||||
import { CommandMenuRouter } from '@/command-menu/components/CommandMenuRouter';
|
||||
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { JestContextStoreSetter } from '~/testing/jest/JestContextStoreSetter';
|
||||
import { CommandMenu } from '../CommandMenu';
|
||||
|
||||
@ -65,6 +66,7 @@ const meta: Meta<typeof CommandMenu> = {
|
||||
ObjectMetadataItemsDecorator,
|
||||
SnackBarDecorator,
|
||||
ComponentWithRouterDecorator,
|
||||
I18nFrontDecorator,
|
||||
],
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -42,9 +42,7 @@ export const PageFavoriteFoldersDropdown = ({
|
||||
/>
|
||||
</>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownId,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||
/>
|
||||
</DropdownScope>
|
||||
</FavoriteFolderPickerComponentInstanceContext>
|
||||
|
||||
@ -33,7 +33,7 @@ export const AppNavigationDrawer = ({
|
||||
|
||||
const drawerProps: NavigationDrawerProps = isSettingsDrawer
|
||||
? {
|
||||
title: t`'Exit Settings'`,
|
||||
title: t`Exit Settings`,
|
||||
children: <SettingsNavigationDrawerItems />,
|
||||
footer: (
|
||||
<AdvancedSettingsToggle
|
||||
|
||||
@ -7,6 +7,7 @@ import { CurrentWorkspaceMemberFavoritesFolders } from '@/favorites/components/C
|
||||
import { WorkspaceFavorites } from '@/favorites/components/WorkspaceFavorites';
|
||||
import { NavigationDrawerOpenedSection } from '@/object-metadata/components/NavigationDrawerOpenedSection';
|
||||
import { RemoteNavigationDrawerSection } from '@/object-metadata/components/RemoteNavigationDrawerSection';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
|
||||
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
@ -15,6 +16,8 @@ import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMe
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
|
||||
const StyledMainSection = styled(NavigationDrawerSection)`
|
||||
min-height: fit-content;
|
||||
@ -37,19 +40,21 @@ export const MainNavigationDrawerItems = () => {
|
||||
navigationDrawerExpandedMemorizedState,
|
||||
);
|
||||
|
||||
const { t } = useLingui();
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isMobile && (
|
||||
<StyledMainSection>
|
||||
<NavigationDrawerItem
|
||||
label="Search"
|
||||
label={t`Search`}
|
||||
Icon={IconSearch}
|
||||
onClick={toggleCommandMenu}
|
||||
keyboard={[getOsControlSymbol(), 'K']}
|
||||
/>
|
||||
<NavigationDrawerItem
|
||||
label="Settings"
|
||||
to={'/settings/profile'}
|
||||
label={t`Settings`}
|
||||
to={getSettingsPath(SettingsPath.ProfilePage)}
|
||||
onClick={() => {
|
||||
setNavigationDrawerExpandedMemorized(isNavigationDrawerExpanded);
|
||||
setIsNavigationDrawerExpanded(true);
|
||||
|
||||
@ -11,7 +11,7 @@ import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { i18nFrontDecorator } from '~/testing/decorators/i18nFrontDecorator';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import {
|
||||
AppNavigationDrawer,
|
||||
AppNavigationDrawerProps,
|
||||
@ -55,7 +55,7 @@ const meta: Meta<StoryArgs> = {
|
||||
decorators: [
|
||||
IconsProviderDecorator,
|
||||
ObjectMetadataItemsDecorator,
|
||||
i18nFrontDecorator,
|
||||
I18nFrontDecorator,
|
||||
(Story, { args }) => (
|
||||
<MemoryRouter initialEntries={[args.routePath]}>
|
||||
<Story />
|
||||
|
||||
@ -44,9 +44,7 @@ export const ObjectFilterDropdownOperandDropdown = ({
|
||||
dropdownHotkeyScope={{
|
||||
scope: FiltersHotkeyScope.ObjectFilterDropdownOperandDropdown,
|
||||
}}
|
||||
dropdownOffset={{
|
||||
x: parseInt(theme.spacing(2), 10),
|
||||
}}
|
||||
dropdownOffset={{ x: parseInt(theme.spacing(2), 10) }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -13,9 +13,7 @@ export const RecordFieldInputScope = ({
|
||||
}: RecordFieldInputScopeProps) => {
|
||||
return (
|
||||
<RecordFieldInputScopeInternalContext.Provider
|
||||
value={{
|
||||
scopeId: recordFieldInputScopeId,
|
||||
}}
|
||||
value={{ scopeId: recordFieldInputScopeId }}
|
||||
>
|
||||
{children}
|
||||
</RecordFieldInputScopeInternalContext.Provider>
|
||||
|
||||
@ -130,7 +130,11 @@ export const useRecordShowPagePagination = (
|
||||
!isFirstRecord || (isFirstRecord && cacheIsAvailableForNavigation);
|
||||
|
||||
const navigateToPreviousRecord = () => {
|
||||
if (isFirstRecord || !recordBefore) {
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isFirstRecord) {
|
||||
if (cacheIsAvailableForNavigation) {
|
||||
const lastRecordIdFromCache =
|
||||
recordIdsInCache[recordIdsInCache.length - 1];
|
||||
@ -164,7 +168,11 @@ export const useRecordShowPagePagination = (
|
||||
!isLastRecord || (isLastRecord && cacheIsAvailableForNavigation);
|
||||
|
||||
const navigateToNextRecord = () => {
|
||||
if (isLastRecord || !recordAfter) {
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isLastRecord) {
|
||||
if (cacheIsAvailableForNavigation) {
|
||||
const firstRecordIdFromCache = recordIdsInCache[0];
|
||||
|
||||
|
||||
@ -229,9 +229,7 @@ export const RecordDetailRelationSection = ({
|
||||
)}
|
||||
</RecordPickerComponentInstanceContext.Provider>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownId,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||
/>
|
||||
</DropdownScope>
|
||||
)
|
||||
|
||||
@ -11,6 +11,7 @@ import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { getCompaniesMock } from '~/testing/mock-data/companies';
|
||||
import { getPeopleMock } from '~/testing/mock-data/people';
|
||||
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
|
||||
import { RecordDetailRelationSection } from '../RecordDetailRelationSection';
|
||||
|
||||
@ -52,6 +53,7 @@ const meta: Meta<typeof RecordDetailRelationSection> = {
|
||||
ObjectMetadataItemsDecorator,
|
||||
SnackBarDecorator,
|
||||
MemoryRouterDecorator,
|
||||
I18nFrontDecorator,
|
||||
],
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { useAggregateRecordsForRecordTableColumnFooter } from '@/object-record/record-table/record-table-footer/hooks/useAggregateRecordsForRecordTableColumnFooter';
|
||||
import styled from '@emotion/styled';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { isDefined, OverflowingTextWithTooltip } from 'twenty-ui';
|
||||
|
||||
const StyledText = styled.span`
|
||||
@ -67,7 +68,9 @@ export const RecordTableColumnAggregateFooterValue = ({
|
||||
)}
|
||||
</StyledValueContainer>
|
||||
) : (
|
||||
<StyledText id={sanitizedId}>Calculate</StyledText>
|
||||
<StyledText id={sanitizedId}>
|
||||
<Trans>Calculate</Trans>
|
||||
</StyledText>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@ -6,6 +6,7 @@ import { Key } from 'ts-key-enum';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Button } from 'twenty-ui';
|
||||
import { isDomain } from '~/utils/is-domain';
|
||||
|
||||
@ -24,28 +25,6 @@ type SettingsAccountsBlocklistInputProps = {
|
||||
blockedEmailOrDomainList: string[];
|
||||
};
|
||||
|
||||
const validationSchema = (blockedEmailOrDomainList: string[]) =>
|
||||
z
|
||||
.object({
|
||||
emailOrDomain: z
|
||||
.string()
|
||||
.trim()
|
||||
.email('Invalid email or domain')
|
||||
.or(
|
||||
z
|
||||
.string()
|
||||
.refine(
|
||||
(value) => value.startsWith('@') && isDomain(value.slice(1)),
|
||||
'Invalid email or domain',
|
||||
),
|
||||
)
|
||||
.refine(
|
||||
(value) => !blockedEmailOrDomainList.includes(value),
|
||||
'Email or domain is already in blocklist',
|
||||
),
|
||||
})
|
||||
.required();
|
||||
|
||||
type FormInput = {
|
||||
emailOrDomain: string;
|
||||
};
|
||||
@ -54,6 +33,30 @@ export const SettingsAccountsBlocklistInput = ({
|
||||
updateBlockedEmailList,
|
||||
blockedEmailOrDomainList,
|
||||
}: SettingsAccountsBlocklistInputProps) => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const validationSchema = (blockedEmailOrDomainList: string[]) =>
|
||||
z
|
||||
.object({
|
||||
emailOrDomain: z
|
||||
.string()
|
||||
.trim()
|
||||
.email(t`Invalid email or domain`)
|
||||
.or(
|
||||
z
|
||||
.string()
|
||||
.refine(
|
||||
(value) => value.startsWith('@') && isDomain(value.slice(1)),
|
||||
t`Invalid email or domain`,
|
||||
),
|
||||
)
|
||||
.refine(
|
||||
(value) => !blockedEmailOrDomainList.includes(value),
|
||||
t`Email or domain is already in blocklist`,
|
||||
),
|
||||
})
|
||||
.required();
|
||||
|
||||
const { reset, handleSubmit, control, formState } = useForm<FormInput>({
|
||||
mode: 'onSubmit',
|
||||
resolver: zodResolver(validationSchema(blockedEmailOrDomainList)),
|
||||
@ -99,7 +102,7 @@ export const SettingsAccountsBlocklistInput = ({
|
||||
)}
|
||||
/>
|
||||
</StyledLinkContainer>
|
||||
<Button title="Add to blocklist" type="submit" />
|
||||
<Button title={t`Add to blocklist`} type="submit" />
|
||||
</StyledContainer>
|
||||
</form>
|
||||
);
|
||||
|
||||
@ -2,6 +2,7 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useTriggerApisOAuth } from '@/settings/accounts/hooks/useTriggerApiOAuth';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import {
|
||||
Button,
|
||||
@ -38,14 +39,16 @@ export const SettingsAccountsListEmptyStateCard = ({
|
||||
FeatureFlagKey.IsMicrosoftSyncEnabled,
|
||||
);
|
||||
|
||||
const { t } = useLingui();
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<StyledHeader>{label || 'No connected account'}</StyledHeader>
|
||||
<StyledHeader>{label || t`No connected account`}</StyledHeader>
|
||||
<StyledBody>
|
||||
{currentWorkspace?.isGoogleAuthEnabled && (
|
||||
<Button
|
||||
Icon={IconGoogle}
|
||||
title="Connect with Google"
|
||||
title={t`Connect with Google`}
|
||||
variant="secondary"
|
||||
onClick={() => triggerApisOAuth('google')}
|
||||
/>
|
||||
@ -53,7 +56,7 @@ export const SettingsAccountsListEmptyStateCard = ({
|
||||
{isMicrosoftSyncEnabled && currentWorkspace?.isMicrosoftAuthEnabled && (
|
||||
<Button
|
||||
Icon={IconMicrosoft}
|
||||
title="Connect with Microsoft"
|
||||
title={t`Connect with Microsoft`}
|
||||
variant="secondary"
|
||||
onClick={() => triggerApisOAuth('microsoft')}
|
||||
/>
|
||||
|
||||
@ -3,6 +3,7 @@ import { expect, fn, userEvent, within } from '@storybook/test';
|
||||
import { ComponentDecorator } from 'twenty-ui';
|
||||
|
||||
import { SettingsAccountsBlocklistInput } from '@/settings/accounts/components/SettingsAccountsBlocklistInput';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
|
||||
const updateBlockedEmailListJestFn = fn();
|
||||
|
||||
@ -16,7 +17,7 @@ const ClearMocksDecorator: Decorator = (Story, context) => {
|
||||
const meta: Meta<typeof SettingsAccountsBlocklistInput> = {
|
||||
title: 'Modules/Settings/Accounts/Blocklist/SettingsAccountsBlocklistInput',
|
||||
component: SettingsAccountsBlocklistInput,
|
||||
decorators: [ComponentDecorator, ClearMocksDecorator],
|
||||
decorators: [ComponentDecorator, ClearMocksDecorator, I18nFrontDecorator],
|
||||
args: {
|
||||
updateBlockedEmailList: updateBlockedEmailListJestFn,
|
||||
blockedEmailOrDomainList: [],
|
||||
|
||||
@ -3,11 +3,12 @@ import { ComponentDecorator } from 'twenty-ui';
|
||||
|
||||
import { SettingsAccountsBlocklistInput } from '@/settings/accounts/components/SettingsAccountsBlocklistInput';
|
||||
import { SettingsAccountsBlocklistSection } from '@/settings/accounts/components/SettingsAccountsBlocklistSection';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
|
||||
const meta: Meta<typeof SettingsAccountsBlocklistSection> = {
|
||||
title: 'Modules/Settings/Accounts/Blocklist/SettingsAccountsBlocklistSection',
|
||||
component: SettingsAccountsBlocklistInput,
|
||||
decorators: [ComponentDecorator],
|
||||
decorators: [ComponentDecorator, I18nFrontDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { LightButton } from 'twenty-ui';
|
||||
|
||||
type CancelButtonProps = {
|
||||
@ -9,9 +10,10 @@ export const CancelButton = ({
|
||||
onCancel,
|
||||
disabled = false,
|
||||
}: CancelButtonProps) => {
|
||||
const { t } = useLingui();
|
||||
return (
|
||||
<LightButton
|
||||
title="Cancel"
|
||||
title={t`Cancel`}
|
||||
accent="tertiary"
|
||||
onClick={onCancel}
|
||||
disabled={disabled}
|
||||
|
||||
@ -34,6 +34,7 @@ import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/compo
|
||||
import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle';
|
||||
import { getNavigationSubItemLeftAdornment } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemLeftAdornment';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { matchPath, resolvePath, useLocation } from 'react-router-dom';
|
||||
import { FeatureFlagKey } from '~/generated/graphql';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
@ -49,6 +50,8 @@ type SettingsNavigationItem = {
|
||||
export const SettingsNavigationDrawerItems = () => {
|
||||
const { signOut } = useAuth();
|
||||
|
||||
const { t } = useLingui();
|
||||
|
||||
const billing = useRecoilValue(billingState);
|
||||
const isFunctionSettingsEnabled = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IsFunctionSettingsEnabled,
|
||||
@ -66,13 +69,13 @@ export const SettingsNavigationDrawerItems = () => {
|
||||
|
||||
const accountSubSettings: SettingsNavigationItem[] = [
|
||||
{
|
||||
label: 'Emails',
|
||||
label: t`Emails`,
|
||||
path: SettingsPath.AccountsEmails,
|
||||
Icon: IconMail,
|
||||
indentationLevel: 2,
|
||||
},
|
||||
{
|
||||
label: 'Calendars',
|
||||
label: t`Calendars`,
|
||||
path: SettingsPath.AccountsCalendars,
|
||||
Icon: IconCalendarEvent,
|
||||
indentationLevel: 2,
|
||||
@ -95,20 +98,20 @@ export const SettingsNavigationDrawerItems = () => {
|
||||
return (
|
||||
<>
|
||||
<NavigationDrawerSection>
|
||||
<NavigationDrawerSectionTitle label="User" />
|
||||
<NavigationDrawerSectionTitle label={t`User`} />
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Profile"
|
||||
label={t`Profile`}
|
||||
path={SettingsPath.ProfilePage}
|
||||
Icon={IconUserCircle}
|
||||
/>
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Experience"
|
||||
label={t`Experience`}
|
||||
path={SettingsPath.Experience}
|
||||
Icon={IconColorSwatch}
|
||||
/>
|
||||
<NavigationDrawerItemGroup>
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Accounts"
|
||||
label={t`Accounts`}
|
||||
path={SettingsPath.Accounts}
|
||||
Icon={IconAt}
|
||||
matchSubPages={false}
|
||||
@ -130,37 +133,37 @@ export const SettingsNavigationDrawerItems = () => {
|
||||
</NavigationDrawerItemGroup>
|
||||
</NavigationDrawerSection>
|
||||
<NavigationDrawerSection>
|
||||
<NavigationDrawerSectionTitle label="Workspace" />
|
||||
<NavigationDrawerSectionTitle label={t`Workspace`} />
|
||||
<SettingsNavigationDrawerItem
|
||||
label="General"
|
||||
label={t`General`}
|
||||
path={SettingsPath.Workspace}
|
||||
Icon={IconSettings}
|
||||
/>
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Members"
|
||||
label={t`Members`}
|
||||
path={SettingsPath.WorkspaceMembersPage}
|
||||
Icon={IconUsers}
|
||||
/>
|
||||
{isBillingPageEnabled && (
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Billing"
|
||||
label={t`Billing`}
|
||||
path={SettingsPath.Billing}
|
||||
Icon={IconCurrencyDollar}
|
||||
/>
|
||||
)}
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Data model"
|
||||
label={t`Data model`}
|
||||
path={SettingsPath.Objects}
|
||||
Icon={IconHierarchy2}
|
||||
/>
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Integrations"
|
||||
label={t`Integrations`}
|
||||
path={SettingsPath.Integrations}
|
||||
Icon={IconApps}
|
||||
/>
|
||||
<AdvancedSettingsWrapper navigationDrawerItem={true}>
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Security"
|
||||
label={t`Security`}
|
||||
path={SettingsPath.Security}
|
||||
Icon={IconKey}
|
||||
/>
|
||||
@ -173,7 +176,7 @@ export const SettingsNavigationDrawerItems = () => {
|
||||
</AdvancedSettingsWrapper>
|
||||
<AdvancedSettingsWrapper navigationDrawerItem={true}>
|
||||
<SettingsNavigationDrawerItem
|
||||
label="API & Webhooks"
|
||||
label={t`API & Webhooks`}
|
||||
path={SettingsPath.Developers}
|
||||
Icon={IconCode}
|
||||
/>
|
||||
@ -181,7 +184,7 @@ export const SettingsNavigationDrawerItems = () => {
|
||||
{isFunctionSettingsEnabled && (
|
||||
<AdvancedSettingsWrapper navigationDrawerItem={true}>
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Functions"
|
||||
label={t`Functions`}
|
||||
path={SettingsPath.ServerlessFunctions}
|
||||
Icon={IconFunction}
|
||||
/>
|
||||
@ -189,21 +192,21 @@ export const SettingsNavigationDrawerItems = () => {
|
||||
)}
|
||||
</NavigationDrawerSection>
|
||||
<NavigationDrawerSection>
|
||||
<NavigationDrawerSectionTitle label="Other" />
|
||||
<NavigationDrawerSectionTitle label={t`Other`} />
|
||||
{isAdminPageEnabled && (
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Server Admin Panel"
|
||||
label={t`Server Admin Panel`}
|
||||
path={SettingsPath.AdminPanel}
|
||||
Icon={IconServer}
|
||||
/>
|
||||
)}
|
||||
<SettingsNavigationDrawerItem
|
||||
label="Releases"
|
||||
label={t`Releases`}
|
||||
path={SettingsPath.Releases}
|
||||
Icon={IconRocket}
|
||||
/>
|
||||
<NavigationDrawerItem
|
||||
label="Logout"
|
||||
label={t`Logout`}
|
||||
onClick={signOut}
|
||||
Icon={IconDoorEnter}
|
||||
/>
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { CancelButton } from '../SaveAndCancelButtons/CancelButton';
|
||||
|
||||
const meta: Meta<typeof CancelButton> = {
|
||||
title: 'Modules/Settings/CancelButton',
|
||||
component: CancelButton,
|
||||
decorators: [I18nFrontDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
@ -126,9 +126,7 @@ export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
|
||||
</DropdownMenuItemsContainer>
|
||||
</DropdownMenu>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownId,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
|
||||
@ -2,6 +2,7 @@ import styled from '@emotion/styled';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { StyledFormCardTitle } from '@/settings/data-model/fields/components/StyledFormCardTitle';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { Card, CardContent } from 'twenty-ui';
|
||||
|
||||
type SettingsDataModelPreviewFormCardProps = {
|
||||
@ -25,7 +26,9 @@ export const SettingsDataModelPreviewFormCard = ({
|
||||
}: SettingsDataModelPreviewFormCardProps) => (
|
||||
<Card className={className} fullWidth rounded>
|
||||
<StyledPreviewContainer divider={!!form}>
|
||||
<StyledFormCardTitle>Preview</StyledFormCardTitle>
|
||||
<StyledFormCardTitle>
|
||||
<Trans>Preview</Trans>
|
||||
</StyledFormCardTitle>
|
||||
{preview}
|
||||
</StyledPreviewContainer>
|
||||
{!!form && <StyledFormContainer>{form}</StyledFormContainer>}
|
||||
|
||||
@ -11,6 +11,7 @@ import { getErrorMessageFromError } from '@/settings/data-model/fields/forms/uti
|
||||
import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import {
|
||||
AppTooltip,
|
||||
Card,
|
||||
@ -91,6 +92,8 @@ export const SettingsDataModelFieldIconLabelForm = ({
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
const { t } = useLingui();
|
||||
|
||||
const isLabelSyncedWithName =
|
||||
watch('isLabelSyncedWithName') ??
|
||||
(isDefined(fieldMetadataItem)
|
||||
@ -99,8 +102,8 @@ export const SettingsDataModelFieldIconLabelForm = ({
|
||||
const label = watch('label');
|
||||
|
||||
const apiNameTooltipText = isLabelSyncedWithName
|
||||
? 'Deactivate "Synchronize Objects Labels and API Names" to set a custom API name'
|
||||
: 'Input must be in camel case and cannot start with a number';
|
||||
? t`Deactivate "Synchronize Objects Labels and API Names" to set a custom API name`
|
||||
: t`Input must be in camel case and cannot start with a number`;
|
||||
|
||||
const fillNameFromLabel = (label: string) => {
|
||||
isDefined(label) &&
|
||||
@ -131,7 +134,7 @@ export const SettingsDataModelFieldIconLabelForm = ({
|
||||
defaultValue={fieldMetadataItem?.label}
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<TextInput
|
||||
placeholder="Employees"
|
||||
placeholder={t`Employees`}
|
||||
value={value}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
@ -160,8 +163,8 @@ export const SettingsDataModelFieldIconLabelForm = ({
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<>
|
||||
<TextInput
|
||||
label="API Name"
|
||||
placeholder="employees"
|
||||
label={t`API Name`}
|
||||
placeholder={t`employees`}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
disabled={
|
||||
@ -205,8 +208,8 @@ export const SettingsDataModelFieldIconLabelForm = ({
|
||||
<Card rounded>
|
||||
<SettingsOptionCardContentToggle
|
||||
Icon={IconRefresh}
|
||||
title="Synchronize Field Label and API Name"
|
||||
description="Should changing a field's label also change the API name?"
|
||||
title={t`Synchronize Field Label and API Name`}
|
||||
description={t`Should changing a field's label also change the API name?`}
|
||||
checked={value ?? true}
|
||||
disabled={
|
||||
isDefined(fieldMetadataItem) &&
|
||||
|
||||
@ -132,12 +132,8 @@ export const SettingsObjectNewFieldSelector = ({
|
||||
<UndecoratedLink
|
||||
to={getSettingsPath(
|
||||
SettingsPath.ObjectNewFieldConfigure,
|
||||
{
|
||||
objectNamePlural,
|
||||
},
|
||||
{
|
||||
fieldType: key,
|
||||
},
|
||||
{ objectNamePlural },
|
||||
{ fieldType: key },
|
||||
)}
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
|
||||
@ -5,6 +5,7 @@ import { ComponentDecorator } from 'twenty-ui';
|
||||
import { FormProviderDecorator } from '~/testing/decorators/FormProviderDecorator';
|
||||
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
|
||||
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
|
||||
import { SettingsDataModelFieldIconLabelForm } from '../SettingsDataModelFieldIconLabelForm';
|
||||
|
||||
@ -24,6 +25,7 @@ const meta: Meta<typeof SettingsDataModelFieldIconLabelForm> = {
|
||||
FormProviderDecorator,
|
||||
IconsProviderDecorator,
|
||||
ComponentDecorator,
|
||||
I18nFrontDecorator,
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadat
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
|
||||
import { SettingsDataModelFieldSettingsFormCard } from '../SettingsDataModelFieldSettingsFormCard';
|
||||
|
||||
@ -33,6 +34,7 @@ const meta: Meta<typeof SettingsDataModelFieldSettingsFormCard> = {
|
||||
ObjectMetadataItemsDecorator,
|
||||
SnackBarDecorator,
|
||||
FormProviderDecorator,
|
||||
I18nFrontDecorator,
|
||||
],
|
||||
args: {
|
||||
fieldMetadataItem,
|
||||
|
||||
@ -4,6 +4,7 @@ import { z } from 'zod';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
|
||||
import { useDateSettingsFormInitialValues } from '@/settings/data-model/fields/forms/date/hooks/useDateSettingsFormInitialValues';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { IconSlash } from 'twenty-ui';
|
||||
|
||||
export const settingsDataModelFieldDateFormSchema = z.object({
|
||||
@ -27,6 +28,8 @@ export const SettingsDataModelFieldDateForm = ({
|
||||
disabled,
|
||||
fieldMetadataItem,
|
||||
}: SettingsDataModelFieldDateFormProps) => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const { control } = useFormContext<SettingsDataModelFieldDateFormValues>();
|
||||
|
||||
const { initialDisplayAsRelativeDateValue } =
|
||||
@ -42,7 +45,7 @@ export const SettingsDataModelFieldDateForm = ({
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<SettingsOptionCardContentToggle
|
||||
Icon={IconSlash}
|
||||
title="Display as relative date"
|
||||
title={t`Display as relative date`}
|
||||
checked={value ?? false}
|
||||
disabled={disabled}
|
||||
onChange={onChange}
|
||||
|
||||
@ -117,9 +117,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
|
||||
<Dropdown
|
||||
dropdownId={SELECT_COLOR_DROPDOWN_ID}
|
||||
dropdownPlacement="bottom-start"
|
||||
dropdownHotkeyScope={{
|
||||
scope: SELECT_COLOR_DROPDOWN_ID,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: SELECT_COLOR_DROPDOWN_ID }}
|
||||
clickableComponent={<StyledColorSample colorName={option.color} />}
|
||||
dropdownComponents={
|
||||
<DropdownMenuItemsContainer>
|
||||
@ -160,9 +158,7 @@ export const SettingsDataModelFieldSelectFormOptionRow = ({
|
||||
<Dropdown
|
||||
dropdownId={SELECT_ACTIONS_DROPDOWN_ID}
|
||||
dropdownPlacement="right-start"
|
||||
dropdownHotkeyScope={{
|
||||
scope: SELECT_ACTIONS_DROPDOWN_ID,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: SELECT_ACTIONS_DROPDOWN_ID }}
|
||||
clickableComponent={
|
||||
<StyledLightIconButton accent="tertiary" Icon={IconDotsVertical} />
|
||||
}
|
||||
|
||||
@ -80,9 +80,7 @@ export const SettingsObjectFieldActiveActionDropdown = ({
|
||||
)}
|
||||
</DropdownMenuItemsContainer>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownId,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -2,6 +2,7 @@ import styled from '@emotion/styled';
|
||||
import { Card, FloatingButton, IconEye } from 'twenty-ui';
|
||||
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import DarkCoverImage from '../../assets/cover-dark.png';
|
||||
import LightCoverImage from '../../assets/cover-light.png';
|
||||
|
||||
@ -25,12 +26,13 @@ const StyledButtonContainer = styled.div`
|
||||
padding-top: ${({ theme }) => theme.spacing(5)};
|
||||
`;
|
||||
export const SettingsObjectCoverImage = () => {
|
||||
const { t } = useLingui();
|
||||
return (
|
||||
<StyledCoverImageContainer>
|
||||
<StyledButtonContainer>
|
||||
<FloatingButton
|
||||
Icon={IconEye}
|
||||
title="Visualize"
|
||||
title={t`Visualize`}
|
||||
size="small"
|
||||
to={'/settings/' + SettingsPath.ObjectOverview}
|
||||
/>
|
||||
|
||||
@ -65,9 +65,7 @@ export const SettingsObjectInactiveMenuDropDown = ({
|
||||
)}
|
||||
</DropdownMenuItemsContainer>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownId,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
SettingsDataModelObjectIdentifiersForm,
|
||||
SettingsDataModelObjectIdentifiersFormValues,
|
||||
} from '@/settings/data-model/objects/forms/components/SettingsDataModelObjectIdentifiersForm';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { Card, CardContent } from 'twenty-ui';
|
||||
|
||||
type SettingsDataModelObjectSettingsFormCardProps = {
|
||||
@ -57,7 +58,9 @@ export const SettingsDataModelObjectSettingsFormCard = ({
|
||||
return (
|
||||
<Card fullWidth>
|
||||
<StyledTopCardContent divider>
|
||||
<SettingsDataModelCardTitle>Preview</SettingsDataModelCardTitle>
|
||||
<SettingsDataModelCardTitle>
|
||||
<Trans>Preview</Trans>
|
||||
</SettingsDataModelCardTitle>
|
||||
{labelIdentifierFieldMetadataItem ? (
|
||||
<StyledFieldPreviewCard
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Button, IconBook2 } from 'twenty-ui';
|
||||
|
||||
export const SettingsReadDocumentationButton = () => {
|
||||
const { t } = useLingui();
|
||||
|
||||
return (
|
||||
<Button
|
||||
title="Read documentation"
|
||||
title={t`Read documentation`}
|
||||
variant="secondary"
|
||||
accent="default"
|
||||
size="small"
|
||||
|
||||
@ -128,9 +128,7 @@ export const SettingsServerlessFunctionTabEnvironmentVariableTableRow = ({
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropDownId,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: dropDownId }}
|
||||
/>
|
||||
</TableCell>
|
||||
</StyledTableRow>
|
||||
|
||||
@ -5,6 +5,7 @@ import { useDebouncedCallback } from 'use-debounce';
|
||||
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import isEmpty from 'lodash.isempty';
|
||||
import { useUpdateWorkspaceMutation } from '~/generated/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@ -28,6 +29,7 @@ export const NameField = ({
|
||||
autoSave = true,
|
||||
onNameUpdate,
|
||||
}: NameFieldProps) => {
|
||||
const { t } = useLingui();
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
||||
|
||||
@ -86,7 +88,7 @@ export const NameField = ({
|
||||
return (
|
||||
<StyledComboInputContainer>
|
||||
<TextInput
|
||||
label="Name"
|
||||
label={t`Name`}
|
||||
value={displayName}
|
||||
onChange={setDisplayName}
|
||||
placeholder="Apple"
|
||||
|
||||
@ -2,14 +2,17 @@ import { SupportDropdown } from '@/support/components/SupportDropdown';
|
||||
import { NavigationDrawer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawer';
|
||||
|
||||
import { NavigationDrawerSectionForObjectMetadataItems } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
|
||||
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
|
||||
import { DEFAULT_WORKSPACE_LOGO } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo';
|
||||
import { DEFAULT_WORKSPACE_NAME } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceName';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { getOsControlSymbol } from '@ui/utilities/device/getOsControlSymbol';
|
||||
import { IconSearch, IconSettings, useIsMobile } from 'twenty-ui';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
|
||||
const StyledMainSection = styled(NavigationDrawerSection)`
|
||||
min-height: fit-content;
|
||||
@ -31,27 +34,28 @@ export const SignInAppNavigationDrawerMock = ({
|
||||
className,
|
||||
}: SignInAppNavigationDrawerMockProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
const { t } = useLingui();
|
||||
|
||||
const children = (
|
||||
<>
|
||||
{!isMobile && (
|
||||
<StyledMainSection>
|
||||
<NavigationDrawerItem
|
||||
label="Search"
|
||||
label={t`Search`}
|
||||
Icon={IconSearch}
|
||||
onClick={() => {}}
|
||||
keyboard={[getOsControlSymbol(), 'K']}
|
||||
/>
|
||||
<NavigationDrawerItem
|
||||
label="Settings"
|
||||
to={'/settings/profile'}
|
||||
label={t`Settings`}
|
||||
to={getSettingsPath(SettingsPath.ProfilePage)}
|
||||
onClick={() => {}}
|
||||
Icon={IconSettings}
|
||||
/>
|
||||
</StyledMainSection>
|
||||
)}
|
||||
<NavigationDrawerSectionForObjectMetadataItems
|
||||
sectionTitle={'Workspace'}
|
||||
sectionTitle={t`Workspace`}
|
||||
isRemote={false}
|
||||
objectMetadataItems={generatedMockObjectMetadataItems.filter((item) =>
|
||||
WORKSPACE_FAVORITES.includes(item.nameSingular),
|
||||
|
||||
@ -42,9 +42,7 @@ export const SignInBackgroundMockContainer = () => {
|
||||
value={{ instanceId: recordIndexId }}
|
||||
>
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: recordIndexId,
|
||||
}}
|
||||
value={{ instanceId: recordIndexId }}
|
||||
>
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: recordIndexId }}
|
||||
|
||||
@ -29,9 +29,7 @@ export const Default = () => (
|
||||
onError={() => null}
|
||||
nextStep={() => null}
|
||||
setPreviousStepState={() => null}
|
||||
currentStepState={{
|
||||
type: SpreadsheetImportStepType.upload,
|
||||
}}
|
||||
currentStepState={{ type: SpreadsheetImportStepType.upload }}
|
||||
/>
|
||||
</ModalWrapper>
|
||||
</ReactSpreadsheetImportContextProvider>
|
||||
|
||||
@ -40,9 +40,7 @@ export const SupportDropdown = () => {
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownId,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -13,9 +13,7 @@ export const DialogManagerScope = ({
|
||||
}: DialogManagerScopeProps) => {
|
||||
return (
|
||||
<DialogManagerScopeInternalContext.Provider
|
||||
value={{
|
||||
scopeId: dialogManagerScopeId,
|
||||
}}
|
||||
value={{ scopeId: dialogManagerScopeId }}
|
||||
>
|
||||
{children}
|
||||
</DialogManagerScopeInternalContext.Provider>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { isUndefined } from '@sniptt/guards';
|
||||
import { ComponentPropsWithoutRef, ReactNode, useMemo } from 'react';
|
||||
import {
|
||||
@ -122,6 +123,7 @@ export const SnackBar = ({
|
||||
variant = SnackBarVariant.Default,
|
||||
}: SnackBarProps) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useLingui();
|
||||
const { animation: progressAnimation, value: progressValue } =
|
||||
useProgressAnimation({
|
||||
autoPlay: isUndefined(overrideProgressValue),
|
||||
@ -193,10 +195,10 @@ export const SnackBar = ({
|
||||
<StyledIcon>{icon}</StyledIcon>
|
||||
<StyledMessage>{message}</StyledMessage>
|
||||
<StyledActions>
|
||||
{!!onCancel && <LightButton title="Cancel" onClick={onCancel} />}
|
||||
{!!onCancel && <LightButton title={t`Cancel`} onClick={onCancel} />}
|
||||
|
||||
{!!onClose && (
|
||||
<LightIconButton title="Close" Icon={IconX} onClick={onClose} />
|
||||
<LightIconButton title={t`Close`} Icon={IconX} onClick={onClose} />
|
||||
)}
|
||||
</StyledActions>
|
||||
</StyledHeader>
|
||||
|
||||
@ -8,6 +8,7 @@ import {
|
||||
} from '@ui/testing';
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { SnackBar, SnackBarVariant } from '../SnackBar';
|
||||
|
||||
const meta: Meta<typeof SnackBar> = {
|
||||
@ -33,7 +34,7 @@ export default meta;
|
||||
type Story = StoryObj<typeof SnackBar>;
|
||||
|
||||
export const Default: Story = {
|
||||
decorators: [ComponentDecorator],
|
||||
decorators: [ComponentDecorator, I18nFrontDecorator],
|
||||
parameters: {
|
||||
chromatic: { disableSnapshot: true },
|
||||
},
|
||||
@ -43,7 +44,7 @@ export const Catalog: CatalogStory<Story, typeof SnackBar> = {
|
||||
args: {
|
||||
onCancel: fn(),
|
||||
},
|
||||
decorators: [CatalogDecorator],
|
||||
decorators: [CatalogDecorator, I18nFrontDecorator],
|
||||
parameters: {
|
||||
catalog: {
|
||||
dimensions: [
|
||||
|
||||
@ -13,9 +13,7 @@ export const SnackBarProviderScope = ({
|
||||
}: SnackBarProviderScopeProps) => {
|
||||
return (
|
||||
<SnackBarManagerScopeInternalContext.Provider
|
||||
value={{
|
||||
scopeId: snackBarManagerScopeId,
|
||||
}}
|
||||
value={{ scopeId: snackBarManagerScopeId }}
|
||||
>
|
||||
{children}
|
||||
</SnackBarManagerScopeInternalContext.Provider>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import React from 'react';
|
||||
@ -175,7 +175,7 @@ export const ImageInput = ({
|
||||
/>
|
||||
</StyledButtonContainer>
|
||||
<StyledText>
|
||||
We support your square PNGs, JPEGs and GIFs under 10MB
|
||||
<Trans>We support your square PNGs, JPEGs and GIFs under 10MB</Trans>
|
||||
</StyledText>
|
||||
{errorMessage && <StyledErrorText>{errorMessage}</StyledErrorText>}
|
||||
</StyledContent>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { ComponentDecorator } from 'twenty-ui';
|
||||
|
||||
import { i18nFrontDecorator } from '~/testing/decorators/i18nFrontDecorator';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { workspaceLogoUrl } from '~/testing/mock-data/users';
|
||||
|
||||
import { ImageInput } from '../ImageInput';
|
||||
@ -9,7 +9,7 @@ import { ImageInput } from '../ImageInput';
|
||||
const meta: Meta<typeof ImageInput> = {
|
||||
title: 'UI/Input/ImageInput/ImageInput',
|
||||
component: ImageInput,
|
||||
decorators: [ComponentDecorator, i18nFrontDecorator],
|
||||
decorators: [ComponentDecorator, I18nFrontDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
@ -15,6 +15,7 @@ import { useDebouncedCallback } from 'use-debounce';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
|
||||
import { Modal, ModalVariants } from '@/ui/layout/modal/components/Modal';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export type ConfirmationModalProps = {
|
||||
isOpen: boolean;
|
||||
@ -69,13 +70,14 @@ export const ConfirmationModal = ({
|
||||
subtitle,
|
||||
setIsOpen,
|
||||
onConfirmClick,
|
||||
deleteButtonText = 'Delete',
|
||||
deleteButtonText = `Delete`,
|
||||
confirmationValue,
|
||||
confirmationPlaceholder,
|
||||
confirmButtonAccent = 'danger',
|
||||
AdditionalButtons,
|
||||
modalVariant = 'primary',
|
||||
}: ConfirmationModalProps) => {
|
||||
const { t } = useLingui();
|
||||
const [inputConfirmationValue, setInputConfirmationValue] =
|
||||
useState<string>('');
|
||||
const [isValidValue, setIsValidValue] = useState(!confirmationValue);
|
||||
@ -146,7 +148,7 @@ export const ConfirmationModal = ({
|
||||
setIsOpen(false);
|
||||
}}
|
||||
variant="secondary"
|
||||
title="Cancel"
|
||||
title={t`Cancel`}
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { ComponentDecorator } from 'twenty-ui';
|
||||
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { ConfirmationModal } from '../ConfirmationModal';
|
||||
|
||||
const meta: Meta<typeof ConfirmationModal> = {
|
||||
title: 'UI/Layout/Modal/ConfirmationModal',
|
||||
component: ConfirmationModal,
|
||||
decorators: [ComponentDecorator],
|
||||
decorators: [ComponentDecorator, I18nFrontDecorator],
|
||||
};
|
||||
export default meta;
|
||||
|
||||
@ -98,9 +98,7 @@ export const DefaultLayout = () => {
|
||||
2
|
||||
: 0,
|
||||
}}
|
||||
transition={{
|
||||
duration: theme.animation.duration.normal,
|
||||
}}
|
||||
transition={{ duration: theme.animation.duration.normal }}
|
||||
>
|
||||
{showAuthModal ? (
|
||||
<StyledAppNavigationDrawerMock />
|
||||
|
||||
@ -83,9 +83,7 @@ export const RightDrawer = () => {
|
||||
isRightDrawerMinimized={isRightDrawerMinimized}
|
||||
animate={targetVariantForAnimation}
|
||||
variants={RIGHT_DRAWER_ANIMATION_VARIANTS}
|
||||
transition={{
|
||||
duration: theme.animation.duration.normal,
|
||||
}}
|
||||
transition={{ duration: theme.animation.duration.normal }}
|
||||
onAnimationComplete={handleAnimationComplete}
|
||||
>
|
||||
<StyledRightDrawer>
|
||||
|
||||
@ -108,9 +108,7 @@ export const ShowPageAddButton = ({
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: PageHotkeyScope.ShowPage,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: PageHotkeyScope.ShowPage }}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
|
||||
@ -101,9 +101,7 @@ export const NavigationDrawer = ({
|
||||
className={className}
|
||||
initial={false}
|
||||
animate={navigationDrawerAnimate}
|
||||
transition={{
|
||||
duration: theme.animation.duration.normal,
|
||||
}}
|
||||
transition={{ duration: theme.animation.duration.normal }}
|
||||
isSettings={isSettingsDrawer}
|
||||
>
|
||||
<StyledContainer
|
||||
|
||||
@ -43,9 +43,7 @@ export const NavigationDrawerAnimatedCollapseWrapper = ({
|
||||
<StyledAnimatedContainer
|
||||
initial={false}
|
||||
animate={animate}
|
||||
transition={{
|
||||
duration: theme.animation.duration.normal,
|
||||
}}
|
||||
transition={{ duration: theme.animation.duration.normal }}
|
||||
>
|
||||
{children}
|
||||
</StyledAnimatedContainer>
|
||||
|
||||
@ -117,9 +117,7 @@ export const NavigationDrawerInput = ({
|
||||
<StyledItemElementsContainer>
|
||||
{Icon && (
|
||||
<Icon
|
||||
style={{
|
||||
minWidth: theme.icon.size.md,
|
||||
}}
|
||||
style={{ minWidth: theme.icon.size.md }}
|
||||
size={theme.icon.size.md}
|
||||
stroke={theme.icon.stroke.md}
|
||||
color="currentColor"
|
||||
|
||||
@ -21,7 +21,7 @@ import { isDefined } from '~/utils/isDefined';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
const filterQueryParamsSchema = z.object({
|
||||
view: z.string().optional(),
|
||||
viewId: z.string().optional(),
|
||||
filter: z
|
||||
.record(
|
||||
z.record(
|
||||
@ -59,7 +59,7 @@ export const useViewFromQueryParams = () => {
|
||||
const viewIdQueryParam = useMemo(
|
||||
() =>
|
||||
queryParamsValidation.success
|
||||
? queryParamsValidation.data.view
|
||||
? queryParamsValidation.data.viewId
|
||||
: undefined,
|
||||
[queryParamsValidation],
|
||||
);
|
||||
|
||||
@ -179,9 +179,7 @@ export const WorkflowSingleRecordPicker = ({
|
||||
/>
|
||||
</RecordPickerComponentInstanceContext.Provider>
|
||||
}
|
||||
dropdownHotkeyScope={{
|
||||
scope: dropdownId,
|
||||
}}
|
||||
dropdownHotkeyScope={{ scope: dropdownId }}
|
||||
/>
|
||||
</DropdownScope>
|
||||
</StyledFormSelectContainer>
|
||||
|
||||
@ -132,9 +132,7 @@ export const WorkflowVariablesDropdownFieldItems = ({
|
||||
<DropdownMenuHeader
|
||||
StartIcon={IconChevronLeft}
|
||||
onClick={goBack}
|
||||
style={{
|
||||
position: 'fixed',
|
||||
}}
|
||||
style={{ position: 'fixed' }}
|
||||
>
|
||||
<OverflowingTextWithTooltip text={headerLabel} />
|
||||
</DropdownMenuHeader>
|
||||
|
||||
Reference in New Issue
Block a user