Add missing translations (#10414)
As per title, add ~200 missing translations in different places of app. Most places are now available for translation with AI but still some aren't available - some enums (like in MenuItemSelectColor.tsx) or values in complex types (like in SettingsNonCompositeFieldTypeConfigs.ts) or values where are injected some variables (like in SettingsDataModelFieldNumberForm.tsx) --------- Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@ import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdow
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
import { useResetFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useResetFilterDropdown';
|
||||
import { t } from '@lingui/core/macro';
|
||||
type AddObjectFilterFromDetailsButtonProps = {
|
||||
filterDropdownId?: string;
|
||||
};
|
||||
@ -24,7 +25,7 @@ export const AddObjectFilterFromDetailsButton = ({
|
||||
<LightButton
|
||||
onClick={handleClick}
|
||||
Icon={IconPlus}
|
||||
title="Add filter"
|
||||
title={t`Add filter`}
|
||||
accent="tertiary"
|
||||
/>
|
||||
);
|
||||
|
||||
@ -1,39 +1,40 @@
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
export const getOperandLabel = (
|
||||
operand: ViewFilterOperand | null | undefined,
|
||||
) => {
|
||||
switch (operand) {
|
||||
case ViewFilterOperand.Contains:
|
||||
return 'Contains';
|
||||
return t`Contains`;
|
||||
case ViewFilterOperand.DoesNotContain:
|
||||
return "Doesn't contain";
|
||||
return t`Doesn't contain`;
|
||||
case ViewFilterOperand.GreaterThan:
|
||||
return 'Greater than';
|
||||
return t`Greater than`;
|
||||
case ViewFilterOperand.LessThan:
|
||||
return 'Less than';
|
||||
return t`Less than`;
|
||||
case ViewFilterOperand.IsBefore:
|
||||
return 'Is before';
|
||||
return t`Is before`;
|
||||
case ViewFilterOperand.IsAfter:
|
||||
return 'Is after';
|
||||
return t`Is after`;
|
||||
case ViewFilterOperand.Is:
|
||||
return 'Is';
|
||||
return t`Is`;
|
||||
case ViewFilterOperand.IsNot:
|
||||
return 'Is not';
|
||||
return t`Is not`;
|
||||
case ViewFilterOperand.IsNotNull:
|
||||
return 'Is not null';
|
||||
return t`Is not null`;
|
||||
case ViewFilterOperand.IsEmpty:
|
||||
return 'Is empty';
|
||||
return t`Is empty`;
|
||||
case ViewFilterOperand.IsNotEmpty:
|
||||
return 'Is not empty';
|
||||
return t`Is not empty`;
|
||||
case ViewFilterOperand.IsRelative:
|
||||
return 'Is relative';
|
||||
return t`Is relative`;
|
||||
case ViewFilterOperand.IsInPast:
|
||||
return 'Is in past';
|
||||
return t`Is in past`;
|
||||
case ViewFilterOperand.IsInFuture:
|
||||
return 'Is in future';
|
||||
return t`Is in future`;
|
||||
case ViewFilterOperand.IsToday:
|
||||
return 'Is today';
|
||||
return t`Is today`;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
@ -48,13 +49,13 @@ export const getOperandLabelShort = (
|
||||
return ': ';
|
||||
case ViewFilterOperand.IsNot:
|
||||
case ViewFilterOperand.DoesNotContain:
|
||||
return ': Not';
|
||||
return t`: Not`;
|
||||
case ViewFilterOperand.IsNotNull:
|
||||
return ': NotNull';
|
||||
return t`: NotNull`;
|
||||
case ViewFilterOperand.IsNotEmpty:
|
||||
return ': NotEmpty';
|
||||
return t`: NotEmpty`;
|
||||
case ViewFilterOperand.IsEmpty:
|
||||
return ': Empty';
|
||||
return t`: Empty`;
|
||||
case ViewFilterOperand.GreaterThan:
|
||||
return '\u00A0> ';
|
||||
case ViewFilterOperand.LessThan:
|
||||
@ -64,11 +65,11 @@ export const getOperandLabelShort = (
|
||||
case ViewFilterOperand.IsAfter:
|
||||
return '\u00A0> ';
|
||||
case ViewFilterOperand.IsInPast:
|
||||
return ': Past';
|
||||
return t`: Past`;
|
||||
case ViewFilterOperand.IsInFuture:
|
||||
return ': Future';
|
||||
return t`: Future`;
|
||||
case ViewFilterOperand.IsToday:
|
||||
return ': Today';
|
||||
return t`: Today`;
|
||||
default:
|
||||
return ': ';
|
||||
}
|
||||
|
||||
@ -8,8 +8,10 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export const ObjectOptionsDropdownFieldsContent = () => {
|
||||
const { t } = useLingui();
|
||||
const {
|
||||
viewType,
|
||||
recordIndexId,
|
||||
@ -50,10 +52,10 @@ export const ObjectOptionsDropdownFieldsContent = () => {
|
||||
return (
|
||||
<>
|
||||
<DropdownMenuHeader StartIcon={IconChevronLeft} onClick={resetContent}>
|
||||
Fields
|
||||
{t`Fields`}
|
||||
</DropdownMenuHeader>
|
||||
<ViewFieldsVisibilityDropdownSection
|
||||
title="Visible"
|
||||
title={t`Visible`}
|
||||
fields={visibleRecordFields}
|
||||
isDraggable
|
||||
onDragEnd={handleReorderFields}
|
||||
@ -66,7 +68,7 @@ export const ObjectOptionsDropdownFieldsContent = () => {
|
||||
<MenuItemNavigate
|
||||
onClick={() => onContentChange('hiddenFields')}
|
||||
LeftIcon={IconEyeOff}
|
||||
text="Hidden Fields"
|
||||
text={t`Hidden Fields`}
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
|
||||
@ -20,8 +20,10 @@ import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMe
|
||||
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export const ObjectOptionsDropdownHiddenFieldsContent = () => {
|
||||
const { t } = useLingui();
|
||||
const {
|
||||
viewType,
|
||||
recordIndexId,
|
||||
@ -67,11 +69,11 @@ export const ObjectOptionsDropdownHiddenFieldsContent = () => {
|
||||
StartIcon={IconChevronLeft}
|
||||
onClick={() => onContentChange('fields')}
|
||||
>
|
||||
Hidden Fields
|
||||
{t`Hidden Fields`}
|
||||
</DropdownMenuHeader>
|
||||
{hiddenRecordFields.length > 0 && (
|
||||
<ViewFieldsVisibilityDropdownSection
|
||||
title="Hidden"
|
||||
title={t`Hidden`}
|
||||
fields={hiddenRecordFields}
|
||||
isDraggable={false}
|
||||
onVisibilityChange={handleChangeFieldVisibility}
|
||||
@ -88,7 +90,7 @@ export const ObjectOptionsDropdownHiddenFieldsContent = () => {
|
||||
}}
|
||||
>
|
||||
<DropdownMenuItemsContainer scrollable={false}>
|
||||
<MenuItem LeftIcon={IconSettings} text="Edit Fields" />
|
||||
<MenuItem LeftIcon={IconSettings} text={t`Edit Fields`} />
|
||||
</DropdownMenuItemsContainer>
|
||||
</UndecoratedLink>
|
||||
</>
|
||||
|
||||
@ -22,8 +22,10 @@ import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
const { t } = useLingui();
|
||||
const {
|
||||
viewType,
|
||||
currentContentId,
|
||||
@ -98,7 +100,7 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
}}
|
||||
>
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItem LeftIcon={IconSettings} text="Edit field values" />
|
||||
<MenuItem LeftIcon={IconSettings} text={t`Edit field values`} />
|
||||
</DropdownMenuItemsContainer>
|
||||
</UndecoratedLink>
|
||||
</>
|
||||
|
||||
@ -35,8 +35,10 @@ import { ViewType } from '@/views/types/ViewType';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export const ObjectOptionsDropdownMenuContent = () => {
|
||||
const { t } = useLingui();
|
||||
const {
|
||||
recordIndexId,
|
||||
objectMetadataItem,
|
||||
@ -117,7 +119,7 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
<MenuItem
|
||||
onClick={() => onContentChange('viewSettings')}
|
||||
LeftIcon={IconLayout}
|
||||
text="View settings"
|
||||
text={t`View settings`}
|
||||
hasSubMenu
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
@ -129,7 +131,7 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
<MenuItem
|
||||
onClick={() => onContentChange('fields')}
|
||||
LeftIcon={IconTag}
|
||||
text="Fields"
|
||||
text={t`Fields`}
|
||||
contextualText={`${visibleBoardFields.length} shown`}
|
||||
hasSubMenu
|
||||
/>
|
||||
@ -142,10 +144,10 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
: onContentChange('recordGroupFields')
|
||||
}
|
||||
LeftIcon={IconLayoutList}
|
||||
text="Group by"
|
||||
text={t`Group by`}
|
||||
contextualText={
|
||||
!isGroupByEnabled
|
||||
? 'Not available on Default View'
|
||||
? t`Not available on Default View`
|
||||
: recordGroupFieldMetadata?.label
|
||||
}
|
||||
hasSubMenu
|
||||
@ -155,7 +157,7 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
{!isGroupByEnabled && (
|
||||
<AppTooltip
|
||||
anchorSelect={`#group-by-menu-item`}
|
||||
content="Not available on Default View"
|
||||
content={t`Not available on Default View`}
|
||||
noArrow
|
||||
place="bottom"
|
||||
width="100%"
|
||||
@ -177,7 +179,7 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
openObjectRecordsSpreasheetImportDialog();
|
||||
}}
|
||||
LeftIcon={IconFileImport}
|
||||
text="Import"
|
||||
text={t`Import`}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@ -188,7 +190,7 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
closeDropdown();
|
||||
}}
|
||||
LeftIcon={IconRotate2}
|
||||
text={`Deleted ${objectNamePlural}`}
|
||||
text={t`Deleted ${objectNamePlural}`}
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
|
||||
@ -29,8 +29,10 @@ import { useSetRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
const { t } = useLingui();
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const {
|
||||
@ -116,13 +118,13 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
<StyledInput
|
||||
autoFocus
|
||||
value={recordGroupFieldSearchInput}
|
||||
placeholder="Search fields"
|
||||
placeholder={t`Search fields`}
|
||||
onChange={(event) => setRecordGroupFieldSearchInput(event.target.value)}
|
||||
/>
|
||||
<DropdownMenuItemsContainer>
|
||||
{viewType === ViewType.Table && (
|
||||
<MenuItemSelect
|
||||
text="None"
|
||||
text={t`None`}
|
||||
selected={!isDefined(recordGroupFieldMetadata)}
|
||||
onClick={handleResetRecordGroupField}
|
||||
/>
|
||||
@ -146,7 +148,7 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
closeDropdown();
|
||||
}}
|
||||
>
|
||||
<MenuItem LeftIcon={IconSettings} text="Create select field" />
|
||||
<MenuItem LeftIcon={IconSettings} text={t`Create select field`} />
|
||||
</UndecoratedLink>
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
|
||||
@ -26,8 +26,10 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
const { t } = useLingui();
|
||||
const {
|
||||
viewType,
|
||||
currentContentId,
|
||||
@ -97,14 +99,14 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
<MenuItem
|
||||
onClick={() => onContentChange('recordGroupFields')}
|
||||
LeftIcon={IconLayoutList}
|
||||
text="Group by"
|
||||
text={t`Group by`}
|
||||
contextualText={recordGroupFieldMetadata?.label}
|
||||
hasSubMenu
|
||||
/>
|
||||
<MenuItem
|
||||
onClick={() => onContentChange('recordGroupSort')}
|
||||
LeftIcon={IconSortDescending}
|
||||
text="Sort"
|
||||
text={t`Sort`}
|
||||
contextualText={recordGroupSort}
|
||||
hasSubMenu
|
||||
/>
|
||||
@ -114,7 +116,7 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
LeftIcon={IconCircleOff}
|
||||
onToggleChange={handleHideEmptyRecordGroupChange}
|
||||
toggled={hideEmptyRecordGroup}
|
||||
text="Hide empty groups"
|
||||
text={t`Hide empty groups`}
|
||||
toggleSize="small"
|
||||
/>
|
||||
</DropdownMenuItemsContainer>
|
||||
@ -122,7 +124,7 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<RecordGroupsVisibilityDropdownSection
|
||||
title="Visible groups"
|
||||
title={t`Visible groups`}
|
||||
recordGroupIds={visibleRecordGroupIds}
|
||||
onDragEnd={handleRecordGroupOrderChangeWithModal}
|
||||
onVisibilityChange={handleRecordGroupVisibilityChange}
|
||||
|
||||
@ -18,8 +18,10 @@ import { ViewType } from '@/views/types/ViewType';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export const ObjectOptionsDropdownViewSettingsContent = () => {
|
||||
const { t } = useLingui();
|
||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||
|
||||
const {
|
||||
@ -46,7 +48,7 @@ export const ObjectOptionsDropdownViewSettingsContent = () => {
|
||||
return (
|
||||
<>
|
||||
<DropdownMenuHeader StartIcon={IconChevronLeft} onClick={resetContent}>
|
||||
View settings
|
||||
{t`View settings`}
|
||||
</DropdownMenuHeader>
|
||||
<DropdownMenuItemsContainer>
|
||||
{isCommandMenuV2Enabled && (
|
||||
@ -57,11 +59,11 @@ export const ObjectOptionsDropdownViewSettingsContent = () => {
|
||||
? IconLayoutSidebarRight
|
||||
: IconLayoutNavbar
|
||||
}
|
||||
text="Open in"
|
||||
text={t`Open in`}
|
||||
contextualText={
|
||||
recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL
|
||||
? 'Side Panel'
|
||||
: 'Record Page'
|
||||
? t`Side Panel`
|
||||
: t`Record Page`
|
||||
}
|
||||
hasSubMenu
|
||||
/>
|
||||
@ -76,7 +78,7 @@ export const ObjectOptionsDropdownViewSettingsContent = () => {
|
||||
)
|
||||
}
|
||||
toggled={isCompactModeActive}
|
||||
text="Compact view"
|
||||
text={t`Compact view`}
|
||||
toggleSize="small"
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -32,7 +32,7 @@ export const ObjectOptionsDropdownViewSettingsOpenInContent = () => {
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItemSelect
|
||||
LeftIcon={IconLayoutSidebarRight}
|
||||
text="Side Panel"
|
||||
text={t`Side Panel`}
|
||||
selected={recordIndexOpenRecordIn === ViewOpenRecordInType.SIDE_PANEL}
|
||||
onClick={() =>
|
||||
setAndPersistOpenRecordIn(
|
||||
@ -43,7 +43,7 @@ export const ObjectOptionsDropdownViewSettingsOpenInContent = () => {
|
||||
/>
|
||||
<MenuItemSelect
|
||||
LeftIcon={IconLayoutNavbar}
|
||||
text="Record Page"
|
||||
text={t`Record Page`}
|
||||
selected={
|
||||
recordIndexOpenRecordIn === ViewOpenRecordInType.RECORD_PAGE
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ import { useEffect } from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { ContextStoreDecorator } from '~/testing/decorators/ContextStoreDecorator';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
|
||||
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
@ -29,6 +30,7 @@ const meta: Meta<typeof ObjectOptionsDropdownContent> = {
|
||||
'Modules/ObjectRecord/ObjectOptionsDropdown/ObjectOptionsDropdownContent',
|
||||
component: ObjectOptionsDropdownContent,
|
||||
decorators: [
|
||||
I18nFrontDecorator,
|
||||
(Story) => {
|
||||
const setObjectMetadataItems = useSetRecoilState(
|
||||
objectMetadataItemsState,
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
within,
|
||||
} from '@storybook/test';
|
||||
import { DateTime } from 'luxon';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
import { FormDateFieldInput } from '../FormDateFieldInput';
|
||||
|
||||
const meta: Meta<typeof FormDateFieldInput> = {
|
||||
@ -18,6 +19,7 @@ const meta: Meta<typeof FormDateFieldInput> = {
|
||||
component: FormDateFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [I18nFrontDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
@ -12,12 +12,14 @@ import {
|
||||
within,
|
||||
} from '@storybook/test';
|
||||
import { DateTime } from 'luxon';
|
||||
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
|
||||
|
||||
const meta: Meta<typeof FormDateTimeFieldInput> = {
|
||||
title: 'UI/Data/Field/Form/Input/FormDateTimeFieldInput',
|
||||
component: FormDateTimeFieldInput,
|
||||
args: {},
|
||||
argTypes: {},
|
||||
decorators: [I18nFrontDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
@ -15,6 +15,7 @@ import { isDefined } from 'twenty-shared';
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
import { FieldMetadataType } from '~/generated/graphql';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
type GenerateExportOptions = {
|
||||
columns: ColumnDefinition<FieldMetadata>[];
|
||||
@ -100,7 +101,7 @@ const percentage = (part: number, whole: number): number => {
|
||||
|
||||
export const displayedExportProgress = (progress?: ExportProgress): string => {
|
||||
if (isUndefinedOrNull(progress?.exportedRecordCount)) {
|
||||
return 'Export';
|
||||
return t`Export`;
|
||||
}
|
||||
|
||||
if (
|
||||
|
||||
@ -69,7 +69,7 @@ export const RecordTableColumnAggregateFooterMenuContent = () => {
|
||||
onClick={() => {
|
||||
onContentChange('countAggregateOperationsOptions');
|
||||
}}
|
||||
text={'Count'}
|
||||
text={t`Count`}
|
||||
hasSubMenu
|
||||
/>
|
||||
{!fieldIsRelation && (
|
||||
@ -77,7 +77,7 @@ export const RecordTableColumnAggregateFooterMenuContent = () => {
|
||||
onClick={() => {
|
||||
onContentChange('percentAggregateOperationsOptions');
|
||||
}}
|
||||
text={'Percent'}
|
||||
text={t`Percent`}
|
||||
hasSubMenu
|
||||
/>
|
||||
)}
|
||||
@ -95,7 +95,7 @@ export const RecordTableColumnAggregateFooterMenuContent = () => {
|
||||
onClick={() => {
|
||||
onContentChange('moreAggregateOperationOptions');
|
||||
}}
|
||||
text={'More options'}
|
||||
text={t`More options`}
|
||||
hasSubMenu
|
||||
/>
|
||||
) : null}
|
||||
@ -106,7 +106,7 @@ export const RecordTableColumnAggregateFooterMenuContent = () => {
|
||||
resetContent();
|
||||
closeDropdown();
|
||||
}}
|
||||
text={'None'}
|
||||
text={t`None`}
|
||||
RightIcon={
|
||||
!isDefined(currentViewFieldAggregateOperation)
|
||||
? IconCheck
|
||||
|
||||
@ -15,8 +15,10 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export const RecordTableHeaderPlusButtonContent = () => {
|
||||
const { t } = useLingui();
|
||||
const { objectMetadataItem } = useRecordTableContextOrThrow();
|
||||
|
||||
const { closeDropdown } = useDropdown();
|
||||
@ -64,7 +66,7 @@ export const RecordTableHeaderPlusButtonContent = () => {
|
||||
setNavigationMemorizedUrl(location.pathname + location.search);
|
||||
}}
|
||||
>
|
||||
<MenuItem LeftIcon={IconSettings} text="Customize fields" />
|
||||
<MenuItem LeftIcon={IconSettings} text={t`Customize fields`} />
|
||||
</UndecoratedLink>
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
|
||||
@ -6,6 +6,7 @@ import { RecordTableActionRow } from '@/object-record/record-table/record-table-
|
||||
import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { IconPlus } from 'twenty-ui';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
export const RecordTableRecordGroupSectionAddNew = () => {
|
||||
const { recordTableId, objectMetadataItem } = useRecordTableContextOrThrow();
|
||||
@ -36,7 +37,7 @@ export const RecordTableRecordGroupSectionAddNew = () => {
|
||||
draggableId={`add-new-record-${currentRecordGroupId}`}
|
||||
draggableIndex={recordIds.length + 2}
|
||||
LeftIcon={IconPlus}
|
||||
text="Add new"
|
||||
text={t`Add new`}
|
||||
onClick={handleAddNewRecord}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { SettingsAccountsVisibilityIcon } from '@/settings/accounts/components/SettingsAccountsVisibilityIcon';
|
||||
import styled from '@emotion/styled';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
|
||||
import { MessageChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
@ -9,27 +10,24 @@ const StyledCardMedia = styled(SettingsAccountsVisibilityIcon)`
|
||||
|
||||
export const onboardingSyncEmailsOptions = [
|
||||
{
|
||||
title: 'Everything',
|
||||
description:
|
||||
'Your emails and events content will be shared with your team.',
|
||||
title: msg`Everything`,
|
||||
description: msg`Your emails and events content will be shared with your team.`,
|
||||
value: MessageChannelVisibility.SHARE_EVERYTHING,
|
||||
cardMedia: (
|
||||
<StyledCardMedia metadata="active" subject="active" body="active" />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Subject and metadata',
|
||||
description:
|
||||
'Your email subjects and meeting titles will be shared with your team.',
|
||||
title: msg`Subject and metadata`,
|
||||
description: msg`Your email subjects and meeting titles will be shared with your team.`,
|
||||
value: MessageChannelVisibility.SUBJECT,
|
||||
cardMedia: (
|
||||
<StyledCardMedia metadata="active" subject="active" body="inactive" />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Metadata',
|
||||
description:
|
||||
'Only the timestamp & participants will be shared with your team.',
|
||||
title: msg`Metadata`,
|
||||
description: msg`Only the timestamp & participants will be shared with your team.`,
|
||||
value: MessageChannelVisibility.METADATA,
|
||||
cardMedia: (
|
||||
<StyledCardMedia metadata="active" subject="inactive" body="inactive" />
|
||||
|
||||
@ -5,6 +5,7 @@ import { TableBody } from '@/ui/layout/table/components/TableBody';
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import styled from '@emotion/styled';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
type SettingsAccountsBlocklistTableProps = {
|
||||
blocklist: BlocklistItem[];
|
||||
@ -31,8 +32,8 @@ export const SettingsAccountsBlocklistTable = ({
|
||||
gridAutoColumns="200px 1fr 20px"
|
||||
mobileGridAutoColumns="120px 1fr 20px"
|
||||
>
|
||||
<TableHeader>Email/Domain</TableHeader>
|
||||
<TableHeader>Added to blocklist</TableHeader>
|
||||
<TableHeader>{t`Email/Domain`}</TableHeader>
|
||||
<TableHeader>{t`Added to blocklist`}</TableHeader>
|
||||
<TableHeader></TableHeader>
|
||||
</TableRow>
|
||||
<StyledTableBody>
|
||||
|
||||
@ -7,6 +7,7 @@ import styled from '@emotion/styled';
|
||||
import { Section } from '@react-email/components';
|
||||
import { Card, H2Title, IconUserPlus } from 'twenty-ui';
|
||||
import { CalendarChannelVisibility } from '~/generated-metadata/graphql';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
const StyledDetailsContainer = styled.div`
|
||||
display: flex;
|
||||
@ -50,8 +51,8 @@ export const SettingsAccountsCalendarChannelDetails = ({
|
||||
<StyledDetailsContainer>
|
||||
<Section>
|
||||
<H2Title
|
||||
title="Event visibility"
|
||||
description="Define what will be visible to other users in your workspace"
|
||||
title={t`Event visibility`}
|
||||
description={t`Define what will be visible to other users in your workspace`}
|
||||
/>
|
||||
<SettingsAccountsEventVisibilitySettingsCard
|
||||
value={calendarChannel.visibility}
|
||||
@ -60,14 +61,14 @@ export const SettingsAccountsCalendarChannelDetails = ({
|
||||
</Section>
|
||||
<Section>
|
||||
<H2Title
|
||||
title="Contact auto-creation"
|
||||
description="Automatically create contacts for people you've participated in an event with."
|
||||
title={t`Contact auto-creation`}
|
||||
description={t`Automatically create contacts for people you've participated in an event with.`}
|
||||
/>
|
||||
<Card rounded>
|
||||
<SettingsOptionCardContentToggle
|
||||
Icon={IconUserPlus}
|
||||
title="Auto-creation"
|
||||
description="Automatically create contacts for people."
|
||||
title={t`Auto-creation`}
|
||||
description={t`Automatically create contacts for people.`}
|
||||
checked={calendarChannel.isContactAutoCreationEnabled}
|
||||
onChange={() => {
|
||||
handleContactAutoCreationToggle(
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
CalendarChannelVisibility,
|
||||
TimelineCalendarEvent,
|
||||
} from '~/generated/graphql';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
const StyledGeneralContainer = styled.div`
|
||||
display: flex;
|
||||
@ -65,15 +66,15 @@ export const SettingsAccountsCalendarChannelsGeneral = () => {
|
||||
<StyledGeneralContainer>
|
||||
<Section>
|
||||
<H2Title
|
||||
title="Display"
|
||||
description="Configure how we should display your events in your calendar"
|
||||
title={t`Display`}
|
||||
description={t`Configure how we should display your events in your calendar`}
|
||||
/>
|
||||
<SettingsAccountsCalendarDisplaySettings />
|
||||
</Section>
|
||||
<Section>
|
||||
<H2Title
|
||||
title="Color code"
|
||||
description="Events you participated in are displayed in red."
|
||||
title={t`Color code`}
|
||||
description={t`Events you participated in are displayed in red.`}
|
||||
/>
|
||||
<CalendarContext.Provider
|
||||
value={{
|
||||
|
||||
@ -2,6 +2,7 @@ import styled from '@emotion/styled';
|
||||
|
||||
import { SettingsAccountsRadioSettingsCard } from '@/settings/accounts/components/SettingsAccountsRadioSettingsCard';
|
||||
import { SettingsAccountsVisibilityIcon } from '@/settings/accounts/components/SettingsAccountsVisibilityIcon';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { CalendarChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
type SettingsAccountsEventVisibilitySettingsCardProps = {
|
||||
@ -15,14 +16,14 @@ const StyledCardMedia = styled(SettingsAccountsVisibilityIcon)`
|
||||
|
||||
const eventSettingsVisibilityOptions = [
|
||||
{
|
||||
title: 'Everything',
|
||||
description: 'The whole event details will be shared with your team.',
|
||||
title: msg`Everything`,
|
||||
description: msg`The whole event details will be shared with your team.`,
|
||||
value: CalendarChannelVisibility.SHARE_EVERYTHING,
|
||||
cardMedia: <StyledCardMedia subject="active" body="active" />,
|
||||
},
|
||||
{
|
||||
title: 'Metadata',
|
||||
description: 'Only date & participants will be shared with your team.',
|
||||
title: msg`Metadata`,
|
||||
description: msg`Only date & participants will be shared with your team.`,
|
||||
value: CalendarChannelVisibility.METADATA,
|
||||
cardMedia: <StyledCardMedia subject="active" body="inactive" />,
|
||||
},
|
||||
|
||||
@ -7,6 +7,7 @@ import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { SettingsAccountsConnectedAccountsRowRightContainer } from '@/settings/accounts/components/SettingsAccountsConnectedAccountsRowRightContainer';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { SettingsListCard } from '../../components/SettingsListCard';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
const ProviderIcons: { [k: string]: IconComponent } = {
|
||||
google: IconGoogle,
|
||||
@ -21,6 +22,7 @@ export const SettingsAccountsConnectedAccountsListCard = ({
|
||||
loading?: boolean;
|
||||
}) => {
|
||||
const navigate = useNavigateSettings();
|
||||
const { t } = useLingui();
|
||||
|
||||
if (!accounts.length) {
|
||||
return <SettingsAccountsListEmptyStateCard />;
|
||||
@ -36,7 +38,7 @@ export const SettingsAccountsConnectedAccountsListCard = ({
|
||||
<SettingsAccountsConnectedAccountsRowRightContainer account={account} />
|
||||
)}
|
||||
hasFooter={true}
|
||||
footerButtonLabel="Add account"
|
||||
footerButtonLabel={t`Add account`}
|
||||
onFooterButtonClick={() => navigate(SettingsPath.NewAccount)}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -4,6 +4,7 @@ import { SyncStatus } from '@/settings/accounts/constants/SyncStatus';
|
||||
import { computeSyncStatus } from '@/settings/accounts/utils/computeSyncStatus';
|
||||
import { Status } from 'twenty-ui';
|
||||
import styled from '@emotion/styled';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
const StyledRowRightContainer = styled.div`
|
||||
align-items: center;
|
||||
@ -27,18 +28,18 @@ export const SettingsAccountsConnectedAccountsRowRightContainer = ({
|
||||
return (
|
||||
<StyledRowRightContainer>
|
||||
{status === SyncStatus.FAILED && (
|
||||
<Status color="red" text="Sync failed" weight="medium" />
|
||||
<Status color="red" text={t`Sync failed`} weight="medium" />
|
||||
)}
|
||||
{status === SyncStatus.SYNCED && (
|
||||
<Status color="green" text="Synced" weight="medium" />
|
||||
<Status color="green" text={t`Synced`} weight="medium" />
|
||||
)}
|
||||
{status === SyncStatus.NOT_SYNCED && (
|
||||
<Status color="orange" text="Not synced" weight="medium" />
|
||||
<Status color="orange" text={t`Not synced`} weight="medium" />
|
||||
)}
|
||||
{status === SyncStatus.IMPORTING && (
|
||||
<Status
|
||||
color="turquoise"
|
||||
text="Importing"
|
||||
text={t`Importing`}
|
||||
weight="medium"
|
||||
isLoaderVisible
|
||||
/>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { MessageChannelContactAutoCreationPolicy } from '@/accounts/types/MessageChannel';
|
||||
import { SettingsAccountsMessageAutoCreationIcon } from '@/settings/accounts/components/SettingsAccountsMessageAutoCreationIcon';
|
||||
import { SettingsAccountsRadioSettingsCard } from '@/settings/accounts/components/SettingsAccountsRadioSettingsCard';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
|
||||
type SettingsAccountsMessageAutoCreationCardProps = {
|
||||
onChange: (nextValue: MessageChannelContactAutoCreationPolicy) => void;
|
||||
@ -9,22 +10,22 @@ type SettingsAccountsMessageAutoCreationCardProps = {
|
||||
|
||||
const autoCreationOptions = [
|
||||
{
|
||||
title: 'Sent and Received',
|
||||
description: 'People I’ve sent emails to and received emails from.',
|
||||
title: msg`Sent and Received`,
|
||||
description: msg`People I’ve sent emails to and received emails from.`,
|
||||
value: MessageChannelContactAutoCreationPolicy.SENT_AND_RECEIVED,
|
||||
cardMedia: (
|
||||
<SettingsAccountsMessageAutoCreationIcon isSentActive isReceivedActive />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Sent',
|
||||
description: 'People I’ve sent emails to.',
|
||||
title: msg`Sent`,
|
||||
description: msg`People I’ve sent emails to.`,
|
||||
value: MessageChannelContactAutoCreationPolicy.SENT,
|
||||
cardMedia: <SettingsAccountsMessageAutoCreationIcon isSentActive />,
|
||||
},
|
||||
{
|
||||
title: 'None',
|
||||
description: 'Don’t auto-create contacts.',
|
||||
title: msg`None`,
|
||||
description: msg`Don’t auto-create contacts.`,
|
||||
value: MessageChannelContactAutoCreationPolicy.NONE,
|
||||
cardMedia: (
|
||||
<SettingsAccountsMessageAutoCreationIcon
|
||||
|
||||
@ -11,6 +11,7 @@ import { SettingsAccountsMessageAutoCreationCard } from '@/settings/accounts/com
|
||||
import { SettingsAccountsMessageVisibilityCard } from '@/settings/accounts/components/SettingsAccountsMessageVisibilityCard';
|
||||
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
|
||||
import { MessageChannelVisibility } from '~/generated-metadata/graphql';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
type SettingsAccountsMessageChannelDetailsProps = {
|
||||
messageChannel: Pick<
|
||||
@ -79,8 +80,8 @@ export const SettingsAccountsMessageChannelDetails = ({
|
||||
<StyledDetailsContainer>
|
||||
<Section>
|
||||
<H2Title
|
||||
title="Visibility"
|
||||
description="Define what will be visible to other users in your workspace"
|
||||
title={t`Visibility`}
|
||||
description={t`Define what will be visible to other users in your workspace`}
|
||||
/>
|
||||
<SettingsAccountsMessageVisibilityCard
|
||||
value={messageChannel.visibility}
|
||||
@ -89,8 +90,8 @@ export const SettingsAccountsMessageChannelDetails = ({
|
||||
</Section>
|
||||
<Section>
|
||||
<H2Title
|
||||
title="Contact auto-creation"
|
||||
description="Automatically create People records when receiving or sending emails"
|
||||
title={t`Contact auto-creation`}
|
||||
description={t`Automatically create People records when receiving or sending emails`}
|
||||
/>
|
||||
<SettingsAccountsMessageAutoCreationCard
|
||||
value={messageChannel.contactAutoCreationPolicy}
|
||||
@ -101,8 +102,8 @@ export const SettingsAccountsMessageChannelDetails = ({
|
||||
<Card rounded>
|
||||
<SettingsOptionCardContentToggle
|
||||
Icon={IconBriefcase}
|
||||
title="Exclude non-professional emails"
|
||||
description="Don’t create contacts from/to Gmail, Outlook emails"
|
||||
title={t`Exclude non-professional emails`}
|
||||
description={t`Don’t create contacts from/to Gmail, Outlook emails`}
|
||||
divider
|
||||
checked={messageChannel.excludeNonProfessionalEmails}
|
||||
onChange={() => {
|
||||
@ -113,8 +114,8 @@ export const SettingsAccountsMessageChannelDetails = ({
|
||||
/>
|
||||
<SettingsOptionCardContentToggle
|
||||
Icon={IconUsers}
|
||||
title="Exclude group emails"
|
||||
description="Don’t sync emails from team@ support@ noreply@..."
|
||||
title={t`Exclude group emails`}
|
||||
description={t`Don’t sync emails from team@ support@ noreply@...`}
|
||||
checked={messageChannel.excludeGroupEmails}
|
||||
onChange={() =>
|
||||
handleIsGroupEmailExcludedToggle(
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { SettingsAccountsRadioSettingsCard } from '@/settings/accounts/components/SettingsAccountsRadioSettingsCard';
|
||||
import { SettingsAccountsVisibilityIcon } from '@/settings/accounts/components/SettingsAccountsVisibilityIcon';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { MessageChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
type SettingsAccountsMessageVisibilityCardProps = {
|
||||
@ -9,8 +10,8 @@ type SettingsAccountsMessageVisibilityCardProps = {
|
||||
|
||||
const inboxSettingsVisibilityOptions = [
|
||||
{
|
||||
title: 'Everything',
|
||||
description: 'Subject, body and attachments will be shared with your team.',
|
||||
title: msg`Everything`,
|
||||
description: msg`Subject, body and attachments will be shared with your team.`,
|
||||
value: MessageChannelVisibility.SHARE_EVERYTHING,
|
||||
cardMedia: (
|
||||
<SettingsAccountsVisibilityIcon
|
||||
@ -21,8 +22,8 @@ const inboxSettingsVisibilityOptions = [
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Subject and metadata',
|
||||
description: 'Subject and metadata will be shared with your team.',
|
||||
title: msg`Subject and metadata`,
|
||||
description: msg`Subject and metadata will be shared with your team.`,
|
||||
value: MessageChannelVisibility.SUBJECT,
|
||||
cardMedia: (
|
||||
<SettingsAccountsVisibilityIcon
|
||||
@ -33,8 +34,8 @@ const inboxSettingsVisibilityOptions = [
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Metadata',
|
||||
description: 'Timestamp and participants will be shared with your team.',
|
||||
title: msg`Metadata`,
|
||||
description: msg`Timestamp and participants will be shared with your team.`,
|
||||
value: MessageChannelVisibility.METADATA,
|
||||
cardMedia: (
|
||||
<SettingsAccountsVisibilityIcon
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { MessageDescriptor } from '@lingui/core';
|
||||
import { Trans } from '@lingui/react';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { Card, CardContent, Radio } from 'twenty-ui';
|
||||
@ -40,8 +42,8 @@ const StyledRadio = styled(Radio)`
|
||||
export const SettingsAccountsRadioSettingsCard = <
|
||||
Option extends {
|
||||
cardMedia: ReactNode;
|
||||
description: string;
|
||||
title: string;
|
||||
description: MessageDescriptor;
|
||||
title: MessageDescriptor;
|
||||
value: string;
|
||||
},
|
||||
>({
|
||||
@ -59,8 +61,12 @@ export const SettingsAccountsRadioSettingsCard = <
|
||||
>
|
||||
{option.cardMedia}
|
||||
<div>
|
||||
<StyledTitle>{option.title}</StyledTitle>
|
||||
<StyledDescription>{option.description}</StyledDescription>
|
||||
<StyledTitle>
|
||||
<Trans id={option.title.id} />
|
||||
</StyledTitle>
|
||||
<StyledDescription>
|
||||
<Trans id={option.description.id} />
|
||||
</StyledDescription>
|
||||
</div>
|
||||
<StyledRadio
|
||||
name={name}
|
||||
|
||||
@ -19,6 +19,7 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { Trans, useLingui } from '@lingui/react/macro';
|
||||
|
||||
type SettingsAccountsRowDropdownMenuProps = {
|
||||
account: ConnectedAccount;
|
||||
@ -28,7 +29,7 @@ export const SettingsAccountsRowDropdownMenu = ({
|
||||
account,
|
||||
}: SettingsAccountsRowDropdownMenuProps) => {
|
||||
const dropdownId = `settings-account-row-${account.id}`;
|
||||
|
||||
const { t } = useLingui();
|
||||
const [isDeleteAccountModalOpen, setIsDeleteAccountModalOpen] =
|
||||
useState(false);
|
||||
|
||||
@ -59,7 +60,7 @@ export const SettingsAccountsRowDropdownMenu = ({
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItem
|
||||
LeftIcon={IconMail}
|
||||
text="Emails settings"
|
||||
text={t`Emails settings`}
|
||||
onClick={() => {
|
||||
navigate(SettingsPath.AccountsEmails);
|
||||
closeDropdown();
|
||||
@ -67,7 +68,7 @@ export const SettingsAccountsRowDropdownMenu = ({
|
||||
/>
|
||||
<MenuItem
|
||||
LeftIcon={IconCalendarEvent}
|
||||
text="Calendar settings"
|
||||
text={t`Calendar settings`}
|
||||
onClick={() => {
|
||||
navigate(SettingsPath.AccountsCalendars);
|
||||
closeDropdown();
|
||||
@ -76,7 +77,7 @@ export const SettingsAccountsRowDropdownMenu = ({
|
||||
{account.authFailedAt && (
|
||||
<MenuItem
|
||||
LeftIcon={IconRefresh}
|
||||
text="Reconnect"
|
||||
text={t`Reconnect`}
|
||||
onClick={() => {
|
||||
triggerApisOAuth(account.provider);
|
||||
closeDropdown();
|
||||
@ -86,7 +87,7 @@ export const SettingsAccountsRowDropdownMenu = ({
|
||||
<MenuItem
|
||||
accent="danger"
|
||||
LeftIcon={IconTrash}
|
||||
text="Remove account"
|
||||
text={t`Remove account`}
|
||||
onClick={() => {
|
||||
setIsDeleteAccountModalOpen(true);
|
||||
closeDropdown();
|
||||
@ -98,12 +99,14 @@ export const SettingsAccountsRowDropdownMenu = ({
|
||||
<ConfirmationModal
|
||||
isOpen={isDeleteAccountModalOpen}
|
||||
setIsOpen={setIsDeleteAccountModalOpen}
|
||||
title="Data deletion"
|
||||
title={t`Data deletion`}
|
||||
subtitle={
|
||||
<>All emails and events linked to this account will be deleted</>
|
||||
<Trans>
|
||||
All emails and events linked to this account will be deleted
|
||||
</Trans>
|
||||
}
|
||||
onConfirmClick={deleteAccount}
|
||||
deleteButtonText="Delete account"
|
||||
deleteButtonText={t`Delete account`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -4,6 +4,7 @@ import { SETTINGS_ADMIN_TABS_ID } from '@/settings/admin-panel/constants/Setting
|
||||
import { TabList } from '@/ui/layout/tab/components/TabList';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconHeart, IconSettings2, IconVariable } from 'twenty-ui';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
const StyledTabListContainer = styled.div`
|
||||
align-items: center;
|
||||
@ -17,17 +18,17 @@ export const SettingsAdminContent = () => {
|
||||
const tabs = [
|
||||
{
|
||||
id: SETTINGS_ADMIN_TABS.GENERAL,
|
||||
title: 'General',
|
||||
title: t`General`,
|
||||
Icon: IconSettings2,
|
||||
},
|
||||
{
|
||||
id: SETTINGS_ADMIN_TABS.ENV_VARIABLES,
|
||||
title: 'Env Variables',
|
||||
title: t`Env Variables`,
|
||||
Icon: IconVariable,
|
||||
},
|
||||
{
|
||||
id: SETTINGS_ADMIN_TABS.HEALTH_STATUS,
|
||||
title: 'Health Status',
|
||||
title: t`Health Status`,
|
||||
Icon: IconHeart,
|
||||
},
|
||||
];
|
||||
|
||||
@ -24,6 +24,7 @@ import {
|
||||
} from 'twenty-ui';
|
||||
import { REACT_APP_SERVER_BASE_URL } from '~/config';
|
||||
import { useUserLookupAdminPanelMutation } from '~/generated/graphql';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
import packageJson from '../../../../../package.json';
|
||||
|
||||
@ -120,7 +121,7 @@ export const SettingsAdminGeneral = () => {
|
||||
return (
|
||||
<>
|
||||
<Section>
|
||||
<H2Title title="About" description="Version of the application" />
|
||||
<H2Title title={t`About`} description={t`Version of the application`} />
|
||||
<GithubVersionLink version={packageJson.version} />
|
||||
</Section>
|
||||
|
||||
@ -128,13 +129,13 @@ export const SettingsAdminGeneral = () => {
|
||||
<H2Title
|
||||
title={
|
||||
canManageFeatureFlags
|
||||
? 'Feature Flags & Impersonation'
|
||||
: 'User Impersonation'
|
||||
? t`Feature Flags & Impersonation`
|
||||
: t`User Impersonation`
|
||||
}
|
||||
description={
|
||||
canManageFeatureFlags
|
||||
? 'Look up users and manage their workspace feature flags or impersonate them.'
|
||||
: 'Look up users to impersonate them.'
|
||||
? t`Look up users and manage their workspace feature flags or impersonate them.`
|
||||
: t`Look up users to impersonate them.`
|
||||
}
|
||||
/>
|
||||
|
||||
@ -143,7 +144,7 @@ export const SettingsAdminGeneral = () => {
|
||||
value={userIdentifier}
|
||||
onChange={setUserIdentifier}
|
||||
onInputEnter={handleSearch}
|
||||
placeholder="Enter user ID or email address"
|
||||
placeholder={t`Enter user ID or email address`}
|
||||
fullWidth
|
||||
disabled={isUserLookupLoading}
|
||||
/>
|
||||
@ -151,7 +152,7 @@ export const SettingsAdminGeneral = () => {
|
||||
Icon={IconSearch}
|
||||
variant="primary"
|
||||
accent="blue"
|
||||
title="Search"
|
||||
title={t`Search`}
|
||||
onClick={handleSearch}
|
||||
disabled={!userIdentifier.trim() || isUserLookupLoading}
|
||||
/>
|
||||
@ -161,16 +162,22 @@ export const SettingsAdminGeneral = () => {
|
||||
{isDefined(userLookupResult) && (
|
||||
<Section>
|
||||
<StyledUserInfo>
|
||||
<H1Title title="User Info" fontColor={H1TitleFontColor.Primary} />
|
||||
<H2Title title={userFullName} description="User Name" />
|
||||
<H1Title
|
||||
title={t`User Info`}
|
||||
fontColor={H1TitleFontColor.Primary}
|
||||
/>
|
||||
<H2Title title={userFullName} description={t`User Name`} />
|
||||
<H2Title
|
||||
title={userLookupResult.user.email}
|
||||
description="User Email"
|
||||
description={t`User Email`}
|
||||
/>
|
||||
<H2Title
|
||||
title={userLookupResult.user.id}
|
||||
description={t`User ID`}
|
||||
/>
|
||||
<H2Title title={userLookupResult.user.id} description="User ID" />
|
||||
</StyledUserInfo>
|
||||
|
||||
<H1Title title="Workspaces" fontColor={H1TitleFontColor.Primary} />
|
||||
<H1Title title={t`Workspaces`} fontColor={H1TitleFontColor.Primary} />
|
||||
<StyledTabListContainer>
|
||||
<TabList
|
||||
tabs={tabs}
|
||||
|
||||
@ -119,19 +119,19 @@ export const SettingsAdminWorkspaceContent = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<H2Title title={activeWorkspace.name} description={'Workspace Name'} />
|
||||
<H2Title title={activeWorkspace.name} description={t`Workspace Name`} />
|
||||
<H2Title
|
||||
title={`${activeWorkspace.totalUsers} ${
|
||||
activeWorkspace.totalUsers > 1 ? 'Users' : 'User'
|
||||
activeWorkspace.totalUsers > 1 ? t`Users` : t`User`
|
||||
}`}
|
||||
description={'Total Users'}
|
||||
description={t`Total Users`}
|
||||
/>
|
||||
{currentUser?.canImpersonate && (
|
||||
<Button
|
||||
Icon={IconUser}
|
||||
variant="primary"
|
||||
accent="blue"
|
||||
title={'Impersonate'}
|
||||
title={t`Impersonate`}
|
||||
onClick={() => handleImpersonate(activeWorkspace.id)}
|
||||
disabled={
|
||||
isImpersonateLoading || activeWorkspace.allowImpersonation === false
|
||||
@ -146,8 +146,8 @@ export const SettingsAdminWorkspaceContent = ({
|
||||
gridAutoColumns="1fr 100px"
|
||||
mobileGridAutoColumns="1fr 80px"
|
||||
>
|
||||
<TableHeader>Feature Flag</TableHeader>
|
||||
<TableHeader align="right">Status</TableHeader>
|
||||
<TableHeader>{t`Feature Flag`}</TableHeader>
|
||||
<TableHeader align="right">{t`Status`}</TableHeader>
|
||||
</TableRow>
|
||||
|
||||
{activeWorkspace.featureFlags.map((flag) => (
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Button, IconDeviceFloppy } from 'twenty-ui';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
type SaveButtonProps = {
|
||||
onSave?: () => void;
|
||||
@ -8,7 +9,7 @@ type SaveButtonProps = {
|
||||
export const SaveButton = ({ onSave, disabled }: SaveButtonProps) => {
|
||||
return (
|
||||
<Button
|
||||
title="Save"
|
||||
title={t`Save`}
|
||||
variant="primary"
|
||||
size="small"
|
||||
accent="blue"
|
||||
|
||||
@ -10,6 +10,7 @@ import { useLocation, useParams, useSearchParams } from 'react-router-dom';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { Button, IconChevronDown, MenuItem } from 'twenty-ui';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
align-items: center;
|
||||
@ -100,9 +101,9 @@ export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
|
||||
<StyledButtonContainer>
|
||||
<StyledDownChevron size={theme.icon.size.md} />
|
||||
{isConfigureStep ? (
|
||||
<StyledButton variant="tertiary" title="2. Configure" />
|
||||
<StyledButton variant="tertiary" title={t`2. Configure`} />
|
||||
) : (
|
||||
<StyledButton variant="tertiary" title="1. Type" />
|
||||
<StyledButton variant="tertiary" title={t`1. Type`} />
|
||||
)}
|
||||
</StyledButtonContainer>
|
||||
}
|
||||
@ -111,14 +112,14 @@ export const SettingsDataModelNewFieldBreadcrumbDropDown = () => {
|
||||
<DropdownMenuItemsContainer>
|
||||
<StyledMenuItemWrapper>
|
||||
<StyledMenuItem
|
||||
text="1. Type"
|
||||
text={t`1. Type`}
|
||||
onClick={() => handleClick('select')}
|
||||
selected={!isConfigureStep}
|
||||
/>
|
||||
</StyledMenuItemWrapper>
|
||||
<StyledMenuItemWrapper disabled={!isDefined(fieldType)}>
|
||||
<StyledMenuItem
|
||||
text="2. Configure"
|
||||
text={t`2. Configure`}
|
||||
onClick={() => handleClick('configure')}
|
||||
selected={isConfigureStep}
|
||||
disabled={!isDefined(fieldType)}
|
||||
|
||||
@ -9,6 +9,7 @@ import { IconCircleOff, IconComponentProps, IconMap } from 'twenty-ui';
|
||||
import { z } from 'zod';
|
||||
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
|
||||
import { stripSimpleQuotesFromString } from '~/utils/string/stripSimpleQuotesFromString';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
type SettingsDataModelFieldAddressFormProps = {
|
||||
disabled?: boolean;
|
||||
defaultCountry?: string;
|
||||
@ -30,6 +31,7 @@ export const SettingsDataModelFieldAddressForm = ({
|
||||
disabled,
|
||||
fieldMetadataItem,
|
||||
}: SettingsDataModelFieldAddressFormProps) => {
|
||||
const { t } = useLingui();
|
||||
const { control } = useFormContext<SettingsDataModelFieldTextFormValues>();
|
||||
const countries = [
|
||||
{
|
||||
@ -71,8 +73,8 @@ export const SettingsDataModelFieldAddressForm = ({
|
||||
return (
|
||||
<SettingsOptionCardContentSelect
|
||||
Icon={IconMap}
|
||||
title="Default Country"
|
||||
description="The default country for new addresses"
|
||||
title={t`Default Country`}
|
||||
description={t`The default country for new addresses`}
|
||||
>
|
||||
<Select<string>
|
||||
dropdownWidth={220}
|
||||
|
||||
@ -6,6 +6,7 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
|
||||
import { useBooleanSettingsFormInitialValues } from '@/settings/data-model/fields/forms/boolean/hooks/useBooleanSettingsFormInitialValues';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export const settingsDataModelFieldBooleanFormSchema = z.object({
|
||||
defaultValue: z.boolean(),
|
||||
@ -22,6 +23,7 @@ type SettingsDataModelFieldBooleanFormProps = {
|
||||
export const SettingsDataModelFieldBooleanForm = ({
|
||||
fieldMetadataItem,
|
||||
}: SettingsDataModelFieldBooleanFormProps) => {
|
||||
const { t } = useLingui();
|
||||
const { control } = useFormContext<SettingsDataModelFieldBooleanFormValues>();
|
||||
|
||||
const { initialDefaultValue } = useBooleanSettingsFormInitialValues({
|
||||
@ -36,8 +38,8 @@ export const SettingsDataModelFieldBooleanForm = ({
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<SettingsOptionCardContentSelect
|
||||
Icon={IconCheck}
|
||||
title="Default Value"
|
||||
description="Select the default value for this boolean field"
|
||||
title={t`Default Value`}
|
||||
description={t`Select the default value for this boolean field`}
|
||||
>
|
||||
<Select<boolean>
|
||||
value={value}
|
||||
@ -48,12 +50,12 @@ export const SettingsDataModelFieldBooleanForm = ({
|
||||
options={[
|
||||
{
|
||||
value: true,
|
||||
label: 'True',
|
||||
label: t`True`,
|
||||
Icon: IconCheck,
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
label: 'False',
|
||||
label: t`False`,
|
||||
Icon: IconX,
|
||||
},
|
||||
]}
|
||||
|
||||
@ -5,6 +5,7 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { fieldMetadataItemSchema } from '@/object-metadata/validation-schemas/fieldMetadataItemSchema';
|
||||
|
||||
import { TextArea } from '@/ui/input/components/TextArea';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
export const settingsDataModelFieldDescriptionFormSchema = () => {
|
||||
return fieldMetadataItemSchema([]).pick({
|
||||
@ -35,7 +36,7 @@ export const SettingsDataModelFieldDescriptionForm = ({
|
||||
defaultValue={fieldMetadataItem?.description}
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<TextArea
|
||||
placeholder="Write a description"
|
||||
placeholder={t`Write a description`}
|
||||
minRows={4}
|
||||
value={value ?? undefined}
|
||||
onChange={onChange}
|
||||
|
||||
@ -20,6 +20,7 @@ import { H2Title, IconSearch, UndecoratedLink } from 'twenty-ui';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { SettingsDataModelFieldTypeFormValues } from '~/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldSelect';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
type SettingsObjectNewFieldSelectorProps = {
|
||||
className?: string;
|
||||
@ -107,7 +108,7 @@ export const SettingsObjectNewFieldSelector = ({
|
||||
<Section>
|
||||
<StyledSearchInput
|
||||
LeftIcon={IconSearch}
|
||||
placeholder="Search a type"
|
||||
placeholder={t`Search a type`}
|
||||
value={searchQuery}
|
||||
onChange={setSearchQuery}
|
||||
/>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user