diff --git a/packages/twenty-apps/hello-world/yarn.lock b/packages/twenty-apps/hello-world/yarn.lock
index e6c3ea0039..d4d935541e 100644
--- a/packages/twenty-apps/hello-world/yarn.lock
+++ b/packages/twenty-apps/hello-world/yarn.lock
@@ -1083,7 +1083,7 @@ __metadata:
resolution: "hello-world@workspace:."
dependencies:
"@types/node": "npm:^24.7.2"
- twenty-sdk: "npm:0.2.1"
+ twenty-sdk: "npm:0.2.4"
languageName: unknown
linkType: soft
@@ -1904,9 +1904,9 @@ __metadata:
languageName: node
linkType: hard
-"twenty-sdk@npm:0.2.1":
- version: 0.2.1
- resolution: "twenty-sdk@npm:0.2.1"
+"twenty-sdk@npm:0.2.4":
+ version: 0.2.4
+ resolution: "twenty-sdk@npm:0.2.4"
dependencies:
"@genql/cli": "npm:^3.0.3"
axios: "npm:^1.6.0"
@@ -1927,7 +1927,7 @@ __metadata:
uuid: "npm:^13.0.0"
bin:
twenty: dist/cli.cjs
- checksum: 10c0/5a4f4674129cc747e8e5091bf75025260db20087f76f1cee49896a073c8cf83b8c95e1dce3f2f2cbaaf9570aa1886c4c9a5585f0e61e0ee79552eab4d292fb4e
+ checksum: 10c0/91bcc2c6a96d8bb7997c6584de338d370ffd4cebbc052ffdd5dd8bb8894f1851c039601a2ce0bb0f3b97e210f3bc877de0572125b8c3b601f6e1baac2f99a8c5
languageName: node
linkType: hard
diff --git a/packages/twenty-front/index.html b/packages/twenty-front/index.html
index c21e6c5ebf..eaeec6ba19 100644
--- a/packages/twenty-front/index.html
+++ b/packages/twenty-front/index.html
@@ -32,6 +32,10 @@
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
/>
+
Twenty
diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
index 91f3435a4f..31f8ad600d 100644
--- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
+++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -136,6 +136,13 @@ export const SettingsObjectFieldItemTableRow = ({
fieldName: fieldMetadataItem.name,
});
+ // eslint-disable-next-line @nx/workspace-no-navigate-prefer-link
+ const navigateToFieldEdit = () =>
+ navigate(SettingsPath.ObjectFieldEdit, {
+ objectNamePlural: objectMetadataItem.namePlural,
+ fieldName: fieldMetadataItem.name,
+ });
+
const { activateMetadataField } = useFieldMetadataItem();
const { deleteOneFieldMetadataItem } = useDeleteOneFieldMetadataItem();
@@ -195,15 +202,7 @@ export const SettingsObjectFieldItemTableRow = ({
return (
- navigate(SettingsPath.ObjectFieldEdit, {
- objectNamePlural: objectMetadataItem.namePlural,
- fieldName: fieldMetadataItem.name,
- })
- : undefined
- }
+ onClick={mode === 'view' ? navigateToFieldEdit : undefined}
>
@@ -251,12 +250,7 @@ export const SettingsObjectFieldItemTableRow = ({
{status === 'active' ? (
mode === 'view' ? (
-
+
- navigate(SettingsPath.ObjectFieldEdit, {
- objectNamePlural: objectMetadataItem.namePlural,
- fieldName: fieldMetadataItem.name,
- })
- }
+ onEdit={navigateToFieldEdit}
onActivate={() =>
activateMetadataField(fieldMetadataItem.id, objectMetadataItem.id)
}
diff --git a/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx b/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx
index f31b084dfd..b266ff05dd 100644
--- a/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx
+++ b/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx
@@ -217,7 +217,7 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => {
label: t`Documentation`,
onClick: () =>
window.open(
- getDocumentationUrl(currentWorkspaceMember?.locale),
+ getDocumentationUrl({ locale: currentWorkspaceMember?.locale }),
'_blank',
),
Icon: IconHelpCircle,
diff --git a/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsFieldItemTableRow.tsx b/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsFieldItemTableRow.tsx
index 093550170a..80999430c6 100644
--- a/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsFieldItemTableRow.tsx
+++ b/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsFieldItemTableRow.tsx
@@ -1,19 +1,20 @@
import styled from '@emotion/styled';
-import { TableRow } from '@/ui/layout/table/components/TableRow';
import { type ServerlessFunction } from '~/generated-metadata/graphql';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { useTheme } from '@emotion/react';
import { IconChevronRight } from 'twenty-ui/display';
-
-export const StyledApisFieldTableRow = styled(TableRow)`
- grid-template-columns: 312px 132px 68px;
-`;
+import { StyledTableRow } from '@/settings/serverless-functions/components/SettingsServerlessFunctionsTable';
const StyledNameTableCell = styled(TableCell)`
color: ${({ theme }) => theme.font.color.primary};
gap: ${({ theme }) => theme.spacing(2)};
`;
+const StyledRuntimeTableCell = styled(TableCell)`
+ color: ${({ theme }) => theme.font.color.secondary};
+ gap: ${({ theme }) => theme.spacing(2)};
+`;
+
const StyledIconTableCell = styled(TableCell)`
justify-content: center;
padding-right: ${({ theme }) => theme.spacing(1)};
@@ -32,15 +33,18 @@ export const SettingsServerlessFunctionsFieldItemTableRow = ({
}) => {
const theme = useTheme();
return (
-
+
{serverlessFunction.name}
- {serverlessFunction.runtime}
+
+
+ {serverlessFunction.runtime}
+
-
+
);
};
diff --git a/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsTable.tsx b/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsTable.tsx
index 075d7b6a04..d3181b12a7 100644
--- a/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsTable.tsx
+++ b/packages/twenty-front/src/modules/settings/serverless-functions/components/SettingsServerlessFunctionsTable.tsx
@@ -10,8 +10,8 @@ import { type ServerlessFunction } from '~/generated-metadata/graphql';
import { useLingui } from '@lingui/react/macro';
import { useParams } from 'react-router-dom';
-const StyledTableRow = styled(TableRow)`
- grid-template-columns: 312px 132px 68px;
+export const StyledTableRow = styled(TableRow)`
+ grid-template-columns: 164px 1fr 96px 32px;
`;
const StyledTableBody = styled(TableBody)`
@@ -35,6 +35,7 @@ export const SettingsServerlessFunctionsTable = ({
{t`Name`}
+
{t`Runtime`}
diff --git a/packages/twenty-front/src/modules/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTabEnvironmentVariableTableRow.tsx b/packages/twenty-front/src/modules/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTabEnvironmentVariableTableRow.tsx
index 4ff1343be1..2e447b0dae 100644
--- a/packages/twenty-front/src/modules/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTabEnvironmentVariableTableRow.tsx
+++ b/packages/twenty-front/src/modules/settings/serverless-functions/components/tabs/SettingsServerlessFunctionTabEnvironmentVariableTableRow.tsx
@@ -1,4 +1,3 @@
-import { type EnvironmentVariable } from '~/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTableRow';
import { TextInput } from '@/ui/input/components/TextInput';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
@@ -19,6 +18,7 @@ import {
} from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
import { MenuItem } from 'twenty-ui/navigation';
+import type { ApplicationVariable } from '~/generated/graphql';
const StyledEditModeTableRow = styled(TableRow)`
grid-template-columns: 180px auto 56px;
@@ -34,8 +34,8 @@ export const SettingsServerlessFunctionTabEnvironmentVariableTableRow = ({
onDelete,
initialEditMode = false,
}: {
- envVariable: EnvironmentVariable;
- onChange: (newEnvVariable: EnvironmentVariable) => void;
+ envVariable: ApplicationVariable;
+ onChange: (newEnvVariable: ApplicationVariable) => void;
onDelete: () => void;
initialEditMode?: boolean;
}) => {
diff --git a/packages/twenty-front/src/modules/support/utils/getDocumentationUrl.ts b/packages/twenty-front/src/modules/support/utils/getDocumentationUrl.ts
index 98610d44e8..c7ac1d8b79 100644
--- a/packages/twenty-front/src/modules/support/utils/getDocumentationUrl.ts
+++ b/packages/twenty-front/src/modules/support/utils/getDocumentationUrl.ts
@@ -4,17 +4,23 @@ const DOCUMENTATION_PATH = '/user-guide/introduction';
// Locales that have documentation translations available
const SUPPORTED_DOC_LOCALES = ['fr', 'pt', 'de', 'es', 'it', 'ja', 'ko', 'zh'];
-export const getDocumentationUrl = (locale?: string | null): string => {
+export const getDocumentationUrl = ({
+ locale,
+ path = DOCUMENTATION_PATH,
+}: {
+ locale?: string | null;
+ path?: string;
+}): string => {
if (!locale) {
- return `${DOCUMENTATION_BASE_URL}${DOCUMENTATION_PATH}`;
+ return `${DOCUMENTATION_BASE_URL}${path}`;
}
// Extract language code from locale (e.g., 'fr' from 'fr-FR')
const langCode = locale.split('-')[0].toLowerCase();
if (SUPPORTED_DOC_LOCALES.includes(langCode)) {
- return `${DOCUMENTATION_BASE_URL}/l/${langCode}${DOCUMENTATION_PATH}`;
+ return `${DOCUMENTATION_BASE_URL}/l/${langCode}${path}`;
}
- return `${DOCUMENTATION_BASE_URL}${DOCUMENTATION_PATH}`;
+ return `${DOCUMENTATION_BASE_URL}${path}`;
};
diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownDefaultComponents.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownDefaultComponents.tsx
index e27e0c3563..5236709f25 100644
--- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownDefaultComponents.tsx
+++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownDefaultComponents.tsx
@@ -84,7 +84,10 @@ export const MultiWorkspaceDropdownDefaultComponents = () => {
};
const handleDocumentation = () => {
- window.open(getDocumentationUrl(currentWorkspaceMember?.locale), '_blank');
+ window.open(
+ getDocumentationUrl({ locale: currentWorkspaceMember?.locale }),
+ '_blank',
+ );
closeDropdown(MULTI_WORKSPACE_DROPDOWN_ID);
};
diff --git a/packages/twenty-front/src/pages/settings/applications/SettingsApplicationDetails.tsx b/packages/twenty-front/src/pages/settings/applications/SettingsApplicationDetails.tsx
index 7c7c8714ae..c921c19835 100644
--- a/packages/twenty-front/src/pages/settings/applications/SettingsApplicationDetails.tsx
+++ b/packages/twenty-front/src/pages/settings/applications/SettingsApplicationDetails.tsx
@@ -5,7 +5,7 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBa
import { useParams } from 'react-router-dom';
import { useFindOneApplicationQuery } from '~/generated-metadata/graphql';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
-import { IconInfoCircle, IconSettings, IconBroadcast } from 'twenty-ui/display';
+import { IconInfoCircle, IconSettings, IconBox } from 'twenty-ui/display';
import { SettingsApplicationDetailSkeletonLoader } from '~/pages/settings/applications/components/SettingsApplicationDetailSkeletonLoader';
import { TabList } from '@/ui/layout/tab-list/components/TabList';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
@@ -39,22 +39,22 @@ export const SettingsApplicationDetails = () => {
const tabs = [
{ id: 'about', title: t`About`, Icon: IconInfoCircle },
+ { id: 'content', title: t`Content`, Icon: IconBox },
{ id: 'settings', title: t`Settings`, Icon: IconSettings },
- { id: 'content', title: t`Content`, Icon: IconBroadcast },
];
const renderActiveTabContent = () => {
switch (activeTabId) {
case 'about':
return ;
- case 'settings':
- return (
-
- );
case 'content':
return (
);
+ case 'settings':
+ return (
+
+ );
default:
return <>>;
}
diff --git a/packages/twenty-front/src/pages/settings/applications/SettingsApplications.tsx b/packages/twenty-front/src/pages/settings/applications/SettingsApplications.tsx
index 66ccd4c625..0bd7042a22 100644
--- a/packages/twenty-front/src/pages/settings/applications/SettingsApplications.tsx
+++ b/packages/twenty-front/src/pages/settings/applications/SettingsApplications.tsx
@@ -1,22 +1,56 @@
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
-import { LinkDisplay } from '@/ui/field/display/components/LinkDisplay';
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
-import styled from '@emotion/styled';
-import { t } from '@lingui/core/macro';
-import { Trans } from '@lingui/react/macro';
import { SettingsPath } from 'twenty-shared/types';
import { getSettingsPath } from 'twenty-shared/utils';
-import { Section } from 'twenty-ui/layout';
import { useFindManyApplicationsQuery } from '~/generated-metadata/graphql';
import { SettingsApplicationsTable } from '~/pages/settings/applications/components/SettingsApplicationsTable';
+import {
+ H2Title,
+ CommandBlock,
+ IconCopy,
+ IconFileInfo,
+} from 'twenty-ui/display';
+import { Section } from 'twenty-ui/layout';
+import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
+import { useLingui } from '@lingui/react/macro';
+import { Button } from 'twenty-ui/input';
+import styled from '@emotion/styled';
+import { useRecoilValue } from 'recoil';
+import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
+import { getDocumentationUrl } from '@/support/utils/getDocumentationUrl';
-const StyledNoApplicationContainer = styled.div``;
+const StyledButtonContainer = styled.div`
+ margin: ${({ theme }) => theme.spacing(2)} 0;
+`;
export const SettingsApplications = () => {
+ const { t } = useLingui();
+
+ const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
+
const { data } = useFindManyApplicationsQuery();
+ const { copyToClipboard } = useCopyToClipboard();
+
const applications = data?.findManyApplications ?? [];
+ const commands = [
+ // eslint-disable-next-line lingui/no-unlocalized-strings
+ 'npx create-twenty-app@latest my-twenty-app',
+ // eslint-disable-next-line lingui/no-unlocalized-strings
+ 'cd my-twenty-app',
+ ];
+
+ const button = (
+