diff --git a/.github/workflows/ci-front.yaml b/.github/workflows/ci-front.yaml index c13fca662b..80e56c4f54 100644 --- a/.github/workflows/ci-front.yaml +++ b/.github/workflows/ci-front.yaml @@ -223,4 +223,4 @@ jobs: uses: ./.github/workflows/actions/nx-affected with: tag: scope:frontend - tasks: ${{ matrix.task }} \ No newline at end of file + tasks: ${{ matrix.task }} diff --git a/.github/workflows/ci-tinybird.yaml b/.github/workflows/ci-tinybird.yaml new file mode 100644 index 0000000000..acc57bfd75 --- /dev/null +++ b/.github/workflows/ci-tinybird.yaml @@ -0,0 +1,21 @@ +name: CI Tinybird +on: + push: + branches: + - main + + pull_request: + + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + ci: + uses: tinybirdco/ci/.github/workflows/ci.yml@main + with: + data_project_dir: packages/twenty-tinybird + secrets: + tb_admin_token: ${{ secrets.TB_ADMIN_TOKEN }} + tb_host: https://api.eu-central-1.aws.tinybird.co \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0d87dfc1cd..20f9749222 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ .nx/installation .nx/cache -projectStructure.cache.json .pnp.* .yarn/* @@ -30,3 +29,4 @@ storybook-static .nyc_output test-results/ dump.rdb +.tinyb diff --git a/oss-gg/twenty-content-challenges/1-create-youtube-video-about-20.md b/oss-gg/twenty-content-challenges/1-create-youtube-video-about-20.md index 2f8d1d1553..6688b4795f 100644 --- a/oss-gg/twenty-content-challenges/1-create-youtube-video-about-20.md +++ b/oss-gg/twenty-content-challenges/1-create-youtube-video-about-20.md @@ -20,4 +20,8 @@ Your turn 👇 » 19-October-2024 by [Thefool76](https://oss.gg/thefool76) YouTube Link: [YouTube](https://youtu.be/KuAycGuW698?si=q-YxcukbbYuO8BWf) +» 26-October-2024 by [Khaan25](https://oss.gg/Khaan25) YouTube Link: [YouTube](https://www.youtube.com/watch?v=1ruo4tTWNIg) + +» 28-October-2024 by [sateshcharan](https://oss.gg/sateshcharan) Youtube Link: [Youtube](https://youtu.be/qfZyhrhCeyo) + --- diff --git a/oss-gg/twenty-content-challenges/2-write-blog-post-about-20.md b/oss-gg/twenty-content-challenges/2-write-blog-post-about-20.md index 8899872748..7b28342aed 100644 --- a/oss-gg/twenty-content-challenges/2-write-blog-post-about-20.md +++ b/oss-gg/twenty-content-challenges/2-write-blog-post-about-20.md @@ -25,3 +25,11 @@ Your turn 👇 » 22-October-2024 by [rajeevDewangan](https://oss.gg/rajeevDewangan) blog Link: [blog](https://open.substack.com/pub/rajeevdewangan/p/comprehensive-guide-to-self-hosting?r=4lly3x&utm_campaign=post&utm_medium=web&showWelcomeOnShare=true) » 22-October-2024 by [Khaan25](https://oss.gg/Khaan25) blog Link: [blog](https://medium.com/@ziaurzai/twenty-crm-modern-solution-for-modern-problems-a0b65fec9d6c) + +» 27-October-2024 by [Karan0207](https://oss.gg/karan0207) blog Link: [blog](https://medium.com/@karansingh0201k/my-journey-with-twenty-the-open-source-crm-that-really-gets-it-133879af6280) + +» 27-October-2024 by [Vardhaman619](https://oss.gg/vardhaman619) blog Link: [blog](https://dev.to/vardhaman619/my-experience-with-modern-open-source-crm-twenty-crm-2hen) + +» 28-October-2024 by [harshsbhat](https://oss.gg/harshsbhat) blog Link: [blog](https://www.harshbhat.me/blog/twenty-crm) + +» 28-October-2024 by [AshishViradiya153](https://oss.gg/AshishViradiya153) blog Link: [blog](https://medium.com/@ashishviradiya153/is-twenty-crm-the-right-tool-for-your-business-heres-my-honest-review-0d41e9d8a7eb) \ No newline at end of file diff --git a/oss-gg/twenty-content-challenges/3-write-selfthost-guide-blog-post-20.md b/oss-gg/twenty-content-challenges/3-write-selfthost-guide-blog-post-20.md index fb1682663c..b472cd70b7 100644 --- a/oss-gg/twenty-content-challenges/3-write-selfthost-guide-blog-post-20.md +++ b/oss-gg/twenty-content-challenges/3-write-selfthost-guide-blog-post-20.md @@ -20,8 +20,14 @@ Your turn 👇 » 21-October-2024 by [sateshcharan](https://oss.gg/sateshcharan) blog Link: [blog](https://dev.to/sateshcharan/streamlined-self-hosting-with-twenty-crm-1-click-docker-compose-setup-188o) +» 24-October-2024 by [Shrey](https://oss.gg/shreykx) guide link : [https://github.com/shreykx/newfolder/blob/8046bc7373b8632b7fc2bfa28c360b86f8890a81/twentyguide.md] » 23-October-2024 by [Thefool76](https://oss.gg/thefool76) blog Link: [blog](https://k5lo7h.hashnode.dev/a-detailed-guide-to-self-host-twenty-crm-on-you-local-server) » 24-October-2024 by [Khaan25](https://oss.gg/Khaan25) blog Link: [blog](https://medium.com/@ziaurzai/detailed-guide-on-self-hosting-twenty-crm-on-your-server-troubleshooting-and-best-practices-1f2ca15cd6eb) +» 26-October-2024 by [Yash-1511](https://oss.gg/Yash-1511) blog Link: [blog](https://medium.com/@yashp3020/a-comprehensive-guide-to-self-hosting-twenty-crm-with-docker-compose-40ea3fb4afdc) --- + +» 28-October-2024 by [harshsbhat](https://oss.gg/harshsbhat) blog Link: [blog](https://www.harshbhat.me/blog/twenty-self-host) + +» 28-October-2024 by [AshishViradiya153](https://oss.gg/AshishViradiya153) blog Link: [blog](https://medium.com/@ashishviradiya153/comprehensive-guide-to-self-hosting-twenty-crm-26e7fa36c846) \ No newline at end of file diff --git a/oss-gg/twenty-content-challenges/4-create-promotional-video-20-share.md b/oss-gg/twenty-content-challenges/4-create-promotional-video-20-share.md index e52cb43a42..c6b38619ec 100644 --- a/oss-gg/twenty-content-challenges/4-create-promotional-video-20-share.md +++ b/oss-gg/twenty-content-challenges/4-create-promotional-video-20-share.md @@ -18,4 +18,12 @@ Your turn 👇 » 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) video Link: [video](https://twenty.com/) ---- \ No newline at end of file +» 24-October-2024 by [Thefool76](https://oss.gg/thefool76) video Link: [video](https://youtube.com/shorts/lC4oqm7UlCI?si=Md-nsfK9F6Shzjkv) + +» 27-October-2024 by [Khaan25](https://oss.gg/Khaan25) video Link: [video](https://x.com/zia_webdev/status/1850409233663115529) + +» 27-October-2024 by [sateshcharan](https://oss.gg/sateshcharan) video link: [video](https://youtube.com/shorts/OK52eaq0pAQ?feature=share) + +» 28-October-2024 by [adityadeshlahre](https://oss.gg/adityadeshlahre) video link: [video](https://youtu.be/65sOHce1gjw) + +--- diff --git a/oss-gg/twenty-design-challenges/3-create-custom-interfact-theme-20.md b/oss-gg/twenty-design-challenges/3-create-custom-interfact-theme-20.md index 736bb3f71f..34aac74a08 100644 --- a/oss-gg/twenty-design-challenges/3-create-custom-interfact-theme-20.md +++ b/oss-gg/twenty-design-challenges/3-create-custom-interfact-theme-20.md @@ -18,7 +18,11 @@ Your turn 👇 //////////////////////////// » 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) Figma Link: [Figma](https://twenty.com/) - +» 22-October-2024 by [rajeevDewangan](https://oss.gg/rajeevDewangan) Figma Link: [Figma](https://www.figma.com/design/XE21QdkFuy0IJHtmW7TURa/Twenty-(rajeevDewangan)?node-id=0-1&node-type=canvas&t=BYBulCT6hpJu6E8G-0) » 24-October-2024 by [Khaan25](https://oss.gg/Khaan25) Figma Link: [Figma](https://www.figma.com/design/HqYQrzel3e2TjzujwfdCXZ/Twenty-(Copy)---Khaan25?node-id=478-19796&t=QTB8gzKTudbVNeNs-1) +» 24-October-2024 by [sateshcharan](https://oss.gg/sateshcharan) Figma Link: [Figma](https://www.figma.com/design/2qlAPS3llwf8jrWKGHEf6O/Twenty-(sateshcharan)?node-id=1633-94880&t=GIceWxqyY0ajWXnZ-1) +» 28-October-2024 by [Vanshdeep Singh](https://oss.gg/Vanshdeepsingh-2232) Figma Link:[Figma](https://www.figma.com/design/akgDOb37YLUW9iWLB155EV/Twenty-(Copy)?node-id=478-19796&t=8Gz1yqls2Q3dsN9h-1) + + + ---- diff --git a/oss-gg/twenty-dev-challenges/1-write-migration-script-other-crm-to-20.md b/oss-gg/twenty-dev-challenges/1-write-migration-script-other-crm-to-20.md index f3dbdb16ef..25667a6317 100644 --- a/oss-gg/twenty-dev-challenges/1-write-migration-script-other-crm-to-20.md +++ b/oss-gg/twenty-dev-challenges/1-write-migration-script-other-crm-to-20.md @@ -1,4 +1,4 @@ -**Side Quest**: Develop a script to facilitate the migration of data from another CRM to Twenty. +**Side Quest**: Develop a script to facilitate the migration of data from another CRM to Twenty. **Points**: 750 Points **Proof**: Add your oss handle and record video and share link to the list below. In video show the working proof of your created script. @@ -19,4 +19,5 @@ Your turn 👇 » 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) video Link: [video](https://twenty.com/) » 22-October-2024 by [FaheemOnHub](https://oss.gg/FaheemOnHub) video Link: [video](https://drive.google.com/file/d/1bR59Q5gqoqHjzgdrF6K68U2hloexkQYM/view) ---- \ No newline at end of file + +» 27-October-2024 by [Khaan25](https://oss.gg/Khaan25) video Link: [video](https://drive.google.com/file/d/1-wgzofJaWmnMcFgZZV5uYNNgtbJKJ_1G/view?usp=sharing/) diff --git a/oss-gg/twenty-no-code-challenges/1-create-n8n-template-integrate-20-API.md b/oss-gg/twenty-no-code-challenges/1-create-n8n-template-integrate-20-API.md index 6786e5a945..62bf695ddd 100644 --- a/oss-gg/twenty-no-code-challenges/1-create-n8n-template-integrate-20-API.md +++ b/oss-gg/twenty-no-code-challenges/1-create-n8n-template-integrate-20-API.md @@ -18,4 +18,6 @@ Your turn 👇 » 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) template Link: [template](https://twenty.com/) ---- \ No newline at end of file +» 25-October-2024 by [sateshcharan](https://oss.gg/sateshcharan) template Link: [template]() + +--- diff --git a/oss-gg/twenty-no-code-challenges/2-write-selfthost-guide-blog-post-20.md b/oss-gg/twenty-no-code-challenges/2-write-a-blog-on-how-to-integrate-Twenty-with-marketing-automation-tool-(n8n, Zapier).md similarity index 78% rename from oss-gg/twenty-no-code-challenges/2-write-selfthost-guide-blog-post-20.md rename to oss-gg/twenty-no-code-challenges/2-write-a-blog-on-how-to-integrate-Twenty-with-marketing-automation-tool-(n8n, Zapier).md index 58fa6de4d8..247d13dbec 100644 --- a/oss-gg/twenty-no-code-challenges/2-write-selfthost-guide-blog-post-20.md +++ b/oss-gg/twenty-no-code-challenges/2-write-a-blog-on-how-to-integrate-Twenty-with-marketing-automation-tool-(n8n, Zapier).md @@ -18,4 +18,6 @@ Your turn 👇 » 02-October-2024 by [yourhandle](https://oss.gg/yourhandle) guide Link: [guide](https://twenty.com/) ---- \ No newline at end of file +» 26-October-2024 by [sateshcharan](https://oss.gg/sateshcharan) guide Link: [guide](https://dev.to/sateshcharan/supercharge-your-marketing-with-twentycrm-n8n-1hfd) + +--- diff --git a/oss-gg/twenty-side-quest/6-quest-wizard.md b/oss-gg/twenty-side-quest/6-quest-wizard.md index 53d5fc0659..21d4c4be42 100644 --- a/oss-gg/twenty-side-quest/6-quest-wizard.md +++ b/oss-gg/twenty-side-quest/6-quest-wizard.md @@ -18,4 +18,8 @@ Your turn 👇 » 21-October-2024 by [sateshcharan](https://oss.gg/sateshcharan) -» 22-October-2024 by [Khaan25](https://oss.gg/Khaan25) \ No newline at end of file +» 22-October-2024 by [Khaan25](https://oss.gg/Khaan25) + +» 26-October-2024 by [Naprila](https://oss.gg/Naprila) + +» 28-October-2024 by [Aditya Deshlahre](https://oss.gg/adityadeshlahre) diff --git a/package.json b/package.json index 816fe84a53..2d44842899 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@stoplight/elements": "^8.0.5", "@swc/jest": "^0.2.29", "@tabler/icons-react": "^2.44.0", + "@tiptap/extension-hard-break": "^2.9.1", "@types/dompurify": "^3.0.5", "@types/facepaint": "^1.2.5", "@types/lodash.camelcase": "^4.3.7", @@ -295,7 +296,7 @@ "eslint-plugin-jsx-a11y": "^6.8.0", "eslint-plugin-prefer-arrow": "^1.2.3", "eslint-plugin-prettier": "^5.1.2", - "eslint-plugin-project-structure": "^3.7.2", + "eslint-plugin-project-structure": "^3.9.1", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.4", diff --git a/packages/twenty-chrome-extension/src/options/Loading.tsx b/packages/twenty-chrome-extension/src/options/Loading.tsx index 1fde24f2b9..a0543c9c6d 100644 --- a/packages/twenty-chrome-extension/src/options/Loading.tsx +++ b/packages/twenty-chrome-extension/src/options/Loading.tsx @@ -1,6 +1,5 @@ -import styled from '@emotion/styled'; - import { Loader } from '@/ui/display/loader/components/Loader'; +import styled from '@emotion/styled'; const StyledContainer = styled.div` align-items: center; diff --git a/packages/twenty-front/.gitignore b/packages/twenty-front/.gitignore index a9e8e5b674..49985254be 100644 --- a/packages/twenty-front/.gitignore +++ b/packages/twenty-front/.gitignore @@ -41,4 +41,7 @@ dist-ssr *.sw? .vite/ -.nyc_output/ \ No newline at end of file +.nyc_output/ + +# eslint-plugin-project-structure +projectStructure.cache.json diff --git a/packages/twenty-front/.storybook/main.ts b/packages/twenty-front/.storybook/main.ts index 04dd231aaa..6d34593abb 100644 --- a/packages/twenty-front/.storybook/main.ts +++ b/packages/twenty-front/.storybook/main.ts @@ -57,5 +57,6 @@ const config: StorybookConfig = { }, }); }, + logLevel: 'error', }; export default config; diff --git a/packages/twenty-front/.storybook/preview.tsx b/packages/twenty-front/.storybook/preview.tsx index 1d67634e2a..d35b87e856 100644 --- a/packages/twenty-front/.storybook/preview.tsx +++ b/packages/twenty-front/.storybook/preview.tsx @@ -29,6 +29,7 @@ initialize({ with payload ${JSON.stringify(requestBody)}\n This request should be mocked with MSW`); }, + quiet: true, }); const preview: Preview = { diff --git a/packages/twenty-front/folderStructure.json b/packages/twenty-front/folderStructure.json index 9c8fcb827c..2509807f51 100644 --- a/packages/twenty-front/folderStructure.json +++ b/packages/twenty-front/folderStructure.json @@ -1,57 +1,45 @@ { "$schema": "../../node_modules/eslint-plugin-project-structure/folderStructure.schema.json", + "projectRoot": "packages/twenty-front", + "structureRoot": "src", "regexParameters": { - "camelCase": "^[a-z]+[A-Za-z0-9]+" + "camelCase": "^[a-z]+([A-Za-z0-9]+)+", + "kebab-case": "[a-z][a-z0-9]*(?:-[a-z0-9]+)*" }, "structure": [ - { - "name": "packages", - "children": [ - { - "name": "twenty-front", - "children": [ - { "name": "*", "children": [] }, - { "name": "*" }, - { - "name": "src", - "children": [ - { "name": "*", "children": [] }, - { "name": "*" }, - { - "name": "modules", - "children": [ - { "ruleId": "moduleFolderRule" }, - { "name": "types", "ruleId": "doNotCheckLeafFolderRule" } - ] - } - ] - } - ] - } - ] - } + { "name": "*" }, + { "name": "*", "children": [] }, + { "name": "modules", "ruleId": "modulesFolderRule" } ], "rules": { + "modulesFolderRule": { + "children": [ + { "ruleId": "moduleFolderRule" }, + { "name": "types", "children": [] } + ] + }, + "moduleFolderRule": { - "name": "^(?!utils$|hooks$|states$|types$|graphql$|components$|effect-components$|constants$|validation-schemas$|contexts$|scopes$|services$|errors$)[a-z][a-z0-9]**(?:-[a-z0-9]+)**$", + "name": "{kebab-case}", "folderRecursionLimit": 6, "children": [ { "ruleId": "moduleFolderRule" }, { "name": "hooks", "ruleId": "hooksLeafFolderRule" }, { "name": "utils", "ruleId": "utilsLeafFolderRule" }, - { "name": "states", "ruleId": "doNotCheckLeafFolderRule" }, - { "name": "types", "ruleId": "doNotCheckLeafFolderRule" }, - { "name": "graphql", "ruleId": "doNotCheckLeafFolderRule" }, - { "name": "components", "ruleId": "doNotCheckLeafFolderRule" }, - { "name": "effect-components", "ruleId": "doNotCheckLeafFolderRule" }, - { "name": "constants", "ruleId": "doNotCheckLeafFolderRule" }, - { "name": "validation-schemas", "ruleId": "doNotCheckLeafFolderRule" }, - { "name": "contexts", "ruleId": "doNotCheckLeafFolderRule" }, - { "name": "scopes", "ruleId": "doNotCheckLeafFolderRule" }, - { "name": "services", "ruleId": "doNotCheckLeafFolderRule" }, - { "name": "errors", "ruleId": "doNotCheckLeafFolderRule" } + { "name": "states", "children": [] }, + { "name": "types", "children": [] }, + { "name": "graphql", "children": [] }, + { "name": "components", "children": [] }, + { "name": "effect-components", "children": [] }, + { "name": "constants", "children": [] }, + { "name": "validation-schemas", "children": [] }, + { "name": "contexts", "children": [] }, + { "name": "scopes", "children": [] }, + { "name": "services", "children": [] }, + { "name": "errors", "children": [] } ] }, + "hooksLeafFolderRule": { "folderRecursionLimit": 2, "children": [ @@ -63,12 +51,8 @@ { "name": "internal", "ruleId": "hooksLeafFolderRule" } ] }, - "doNotCheckLeafFolderRule": { - "folderRecursionLimit": 1, - "children": [{ "name": "*" }, { "name": "*", "children": [] }] - }, + "utilsLeafFolderRule": { - "folderRecursionLimit": 1, "children": [ { "name": "{camelCase}.ts" }, { diff --git a/packages/twenty-front/jest.config.ts b/packages/twenty-front/jest.config.ts index c3e8ab4148..ecf046e155 100644 --- a/packages/twenty-front/jest.config.ts +++ b/packages/twenty-front/jest.config.ts @@ -25,9 +25,9 @@ const jestConfig: JestConfigWithTsJest = { extensionsToTreatAsEsm: ['.ts', '.tsx'], coverageThreshold: { global: { - statements: 59, + statements: 58, lines: 55, - functions: 49, + functions: 47, }, }, collectCoverageFrom: ['/src/**/*.ts'], diff --git a/packages/twenty-front/src/__stories__/AppRouter.stories.tsx b/packages/twenty-front/src/__stories__/AppRouter.stories.tsx index 9d2fe91a65..f322919bae 100644 --- a/packages/twenty-front/src/__stories__/AppRouter.stories.tsx +++ b/packages/twenty-front/src/__stories__/AppRouter.stories.tsx @@ -1,18 +1,18 @@ import { getOperationName } from '@apollo/client/utilities'; import { jest } from '@storybook/jest'; import { Meta, StoryObj } from '@storybook/react'; -import { graphql, HttpResponse } from 'msw'; +import { HttpResponse, graphql } from 'msw'; import { HelmetProvider } from 'react-helmet-async'; import { RecoilRoot } from 'recoil'; -import { IconsProvider } from 'twenty-ui'; import { AppErrorBoundary } from '@/error-handler/components/AppErrorBoundary'; import indexAppPath from '@/navigation/utils/indexAppPath'; -import { AppPath } from '@/types/AppPath'; import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope'; import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser'; import { AppRouter } from '@/app/components/AppRouter'; +import { AppPath } from '@/types/AppPath'; +import { IconsProvider } from 'twenty-ui'; import { graphqlMocks } from '~/testing/graphqlMocks'; import { mockedUserData } from '~/testing/mock-data/users'; diff --git a/packages/twenty-front/src/generated-metadata/gql.ts b/packages/twenty-front/src/generated-metadata/gql.ts index 68c28acf6b..9abd3ec4f6 100644 --- a/packages/twenty-front/src/generated-metadata/gql.ts +++ b/packages/twenty-front/src/generated-metadata/gql.ts @@ -32,7 +32,7 @@ const documents = { "\n mutation DeleteOneObjectMetadataItem($idToDelete: UUID!) {\n deleteOneObject(input: { id: $idToDelete }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n }\n }\n": types.DeleteOneObjectMetadataItemDocument, "\n mutation DeleteOneFieldMetadataItem($idToDelete: UUID!) {\n deleteOneField(input: { id: $idToDelete }) {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n settings\n }\n }\n": types.DeleteOneFieldMetadataItemDocument, "\n mutation DeleteOneRelationMetadataItem($idToDelete: UUID!) {\n deleteOneRelation(input: { id: $idToDelete }) {\n id\n }\n }\n": types.DeleteOneRelationMetadataItemDocument, - "\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n shouldSyncLabelAndName\n indexMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n name\n indexWhereClause\n indexType\n isUnique\n indexFieldMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n order\n fieldMetadataId\n }\n }\n }\n }\n }\n }\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n isUnique\n createdAt\n updatedAt\n defaultValue\n options\n settings\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n": types.ObjectMetadataItemsDocument, + "\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n shortcut\n isLabelSyncedWithName\n indexMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n name\n indexWhereClause\n indexType\n isUnique\n indexFieldMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n order\n fieldMetadataId\n }\n }\n }\n }\n }\n }\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n isUnique\n createdAt\n updatedAt\n defaultValue\n options\n settings\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n": types.ObjectMetadataItemsDocument, "\n fragment ServerlessFunctionFields on ServerlessFunction {\n id\n name\n description\n runtime\n syncStatus\n latestVersion\n publishedVersions\n createdAt\n updatedAt\n }\n": types.ServerlessFunctionFieldsFragmentDoc, "\n \n mutation CreateOneServerlessFunctionItem(\n $input: CreateServerlessFunctionInput!\n ) {\n createOneServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n": types.CreateOneServerlessFunctionItemDocument, "\n \n mutation DeleteOneServerlessFunction($input: ServerlessFunctionIdInput!) {\n deleteOneServerlessFunction(input: $input) {\n ...ServerlessFunctionFields\n }\n }\n": types.DeleteOneServerlessFunctionDocument, @@ -138,7 +138,7 @@ export function graphql(source: "\n mutation DeleteOneRelationMetadataItem($idT /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n shouldSyncLabelAndName\n indexMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n name\n indexWhereClause\n indexType\n isUnique\n indexFieldMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n order\n fieldMetadataId\n }\n }\n }\n }\n }\n }\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n isUnique\n createdAt\n updatedAt\n defaultValue\n options\n settings\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n"): (typeof documents)["\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n shouldSyncLabelAndName\n indexMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n name\n indexWhereClause\n indexType\n isUnique\n indexFieldMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n order\n fieldMetadataId\n }\n }\n }\n }\n }\n }\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n isUnique\n createdAt\n updatedAt\n defaultValue\n options\n settings\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n"]; +export function graphql(source: "\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n shortcut\n isLabelSyncedWithName\n indexMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n name\n indexWhereClause\n indexType\n isUnique\n indexFieldMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n order\n fieldMetadataId\n }\n }\n }\n }\n }\n }\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n isUnique\n createdAt\n updatedAt\n defaultValue\n options\n settings\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n"): (typeof documents)["\n query ObjectMetadataItems(\n $objectFilter: objectFilter\n $fieldFilter: fieldFilter\n ) {\n objects(paging: { first: 1000 }, filter: $objectFilter) {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isRemote\n isActive\n isSystem\n createdAt\n updatedAt\n labelIdentifierFieldMetadataId\n imageIdentifierFieldMetadataId\n shortcut\n isLabelSyncedWithName\n indexMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n name\n indexWhereClause\n indexType\n isUnique\n indexFieldMetadatas(paging: { first: 100 }) {\n edges {\n node {\n id\n createdAt\n updatedAt\n order\n fieldMetadataId\n }\n }\n }\n }\n }\n }\n fields(paging: { first: 1000 }, filter: $fieldFilter) {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n isCustom\n isActive\n isSystem\n isNullable\n isUnique\n createdAt\n updatedAt\n defaultValue\n options\n settings\n relationDefinition {\n relationId\n direction\n sourceObjectMetadata {\n id\n nameSingular\n namePlural\n }\n sourceFieldMetadata {\n id\n name\n }\n targetObjectMetadata {\n id\n nameSingular\n namePlural\n }\n targetFieldMetadata {\n id\n name\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index e390776e93..5db253223c 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -162,6 +162,11 @@ export type ClientConfig = { support: Support; }; +export type ComputeStepOutputSchemaInput = { + /** Step JSON format */ + step: Scalars['JSON']['input']; +}; + export type CreateAppTokenInput = { expiresAt: Scalars['DateTime']['input']; }; @@ -188,6 +193,7 @@ export type CreateObjectInput = { description?: InputMaybe; icon?: InputMaybe; imageIdentifierFieldMetadataId?: InputMaybe; + isLabelSyncedWithName?: InputMaybe; isRemote?: InputMaybe; labelIdentifierFieldMetadataId?: InputMaybe; labelPlural: Scalars['String']['input']; @@ -196,7 +202,7 @@ export type CreateObjectInput = { nameSingular: Scalars['String']['input']; primaryKeyColumnType?: InputMaybe; primaryKeyFieldMetadataSettings?: InputMaybe; - shouldSyncLabelAndName?: InputMaybe; + shortcut?: InputMaybe; }; export type CreateOneAppTokenInput = { @@ -528,6 +534,7 @@ export type Mutation = { authorizeApp: AuthorizeApp; challenge: LoginToken; checkoutSession: SessionEntity; + computeStepOutputSchema: Scalars['JSON']['output']; createOIDCIdentityProvider: SetupSsoOutput; createOneAppToken: AppToken; createOneField: Field; @@ -624,6 +631,11 @@ export type MutationCheckoutSessionArgs = { }; +export type MutationComputeStepOutputSchemaArgs = { + input: ComputeStepOutputSchemaInput; +}; + + export type MutationCreateOidcIdentityProviderArgs = { input: SetupOidcSsoInput; }; @@ -1429,12 +1441,13 @@ export type UpdateObjectPayload = { icon?: InputMaybe; imageIdentifierFieldMetadataId?: InputMaybe; isActive?: InputMaybe; + isLabelSyncedWithName?: InputMaybe; labelIdentifierFieldMetadataId?: InputMaybe; labelPlural?: InputMaybe; labelSingular?: InputMaybe; namePlural?: InputMaybe; nameSingular?: InputMaybe; - shouldSyncLabelAndName?: InputMaybe; + shortcut?: InputMaybe; }; export type UpdateOneFieldMetadataInput = { @@ -1769,6 +1782,7 @@ export type Object = { indexMetadatas: ObjectIndexMetadatasConnection; isActive: Scalars['Boolean']['output']; isCustom: Scalars['Boolean']['output']; + isLabelSyncedWithName: Scalars['Boolean']['output']; isRemote: Scalars['Boolean']['output']; isSystem: Scalars['Boolean']['output']; labelIdentifierFieldMetadataId?: Maybe; @@ -1776,7 +1790,7 @@ export type Object = { labelSingular: Scalars['String']['output']; namePlural: Scalars['String']['output']; nameSingular: Scalars['String']['output']; - shouldSyncLabelAndName: Scalars['Boolean']['output']; + shortcut?: Maybe; updatedAt: Scalars['DateTime']['output']; }; @@ -1963,7 +1977,7 @@ export type ObjectMetadataItemsQueryVariables = Exact<{ }>; -export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', edges: Array<{ __typename?: 'objectEdge', node: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, createdAt: any, updatedAt: any, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, shouldSyncLabelAndName: boolean, indexMetadatas: { __typename?: 'ObjectIndexMetadatasConnection', edges: Array<{ __typename?: 'indexEdge', node: { __typename?: 'index', id: any, createdAt: any, updatedAt: any, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, indexFieldMetadatas: { __typename?: 'IndexIndexFieldMetadatasConnection', edges: Array<{ __typename?: 'indexFieldEdge', node: { __typename?: 'indexField', id: any, createdAt: any, updatedAt: any, order: number, fieldMetadataId: any } }> } } }> }, fields: { __typename?: 'ObjectFieldsConnection', edges: Array<{ __typename?: 'fieldEdge', node: { __typename?: 'field', id: any, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: any, updatedAt: any, defaultValue?: any | null, options?: any | null, settings?: any | null, relationDefinition?: { __typename?: 'RelationDefinition', relationId: any, direction: RelationDefinitionType, sourceObjectMetadata: { __typename?: 'object', id: any, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'field', id: any, name: string }, targetObjectMetadata: { __typename?: 'object', id: any, nameSingular: string, namePlural: string }, targetFieldMetadata: { __typename?: 'field', id: any, name: string } } | null } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } }; +export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', edges: Array<{ __typename?: 'objectEdge', node: { __typename?: 'object', id: any, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, createdAt: any, updatedAt: any, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, shortcut?: string | null, isLabelSyncedWithName: boolean, indexMetadatas: { __typename?: 'ObjectIndexMetadatasConnection', edges: Array<{ __typename?: 'indexEdge', node: { __typename?: 'index', id: any, createdAt: any, updatedAt: any, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, indexFieldMetadatas: { __typename?: 'IndexIndexFieldMetadatasConnection', edges: Array<{ __typename?: 'indexFieldEdge', node: { __typename?: 'indexField', id: any, createdAt: any, updatedAt: any, order: number, fieldMetadataId: any } }> } } }> }, fields: { __typename?: 'ObjectFieldsConnection', edges: Array<{ __typename?: 'fieldEdge', node: { __typename?: 'field', id: any, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: any, updatedAt: any, defaultValue?: any | null, options?: any | null, settings?: any | null, relationDefinition?: { __typename?: 'RelationDefinition', relationId: any, direction: RelationDefinitionType, sourceObjectMetadata: { __typename?: 'object', id: any, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'field', id: any, name: string }, targetObjectMetadata: { __typename?: 'object', id: any, nameSingular: string, namePlural: string }, targetFieldMetadata: { __typename?: 'field', id: any, name: string } } | null } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } }; export type ServerlessFunctionFieldsFragment = { __typename?: 'ServerlessFunction', id: any, name: string, description?: string | null, runtime: string, syncStatus: ServerlessFunctionSyncStatus, latestVersion?: string | null, publishedVersions: Array, createdAt: any, updatedAt: any }; @@ -2046,7 +2060,7 @@ export const UpdateOneObjectMetadataItemDocument = {"kind":"Document","definitio export const DeleteOneObjectMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneObjectMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}}]}}]}}]} as unknown as DocumentNode; export const DeleteOneFieldMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneFieldMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"settings"}}]}}]}}]} as unknown as DocumentNode; export const DeleteOneRelationMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneRelationMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneRelation"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode; -export const ObjectMetadataItemsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ObjectMetadataItems"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"objectFilter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"objectFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"fieldFilter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"fieldFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"objects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"1000"}}]}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"objectFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isRemote"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"shouldSyncLabelAndName"}},{"kind":"Field","name":{"kind":"Name","value":"indexMetadatas"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"100"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"indexWhereClause"}},{"kind":"Field","name":{"kind":"Name","value":"indexType"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"indexFieldMetadatas"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"100"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"order"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}}]}}]}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"fields"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"1000"}}]}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"fieldFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"settings"}},{"kind":"Field","name":{"kind":"Name","value":"relationDefinition"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"relationId"}},{"kind":"Field","name":{"kind":"Name","value":"direction"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]} as unknown as DocumentNode; +export const ObjectMetadataItemsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ObjectMetadataItems"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"objectFilter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"objectFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"fieldFilter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"fieldFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"objects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"1000"}}]}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"objectFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isRemote"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"shortcut"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}},{"kind":"Field","name":{"kind":"Name","value":"indexMetadatas"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"100"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"indexWhereClause"}},{"kind":"Field","name":{"kind":"Name","value":"indexType"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"indexFieldMetadatas"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"100"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"order"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}}]}}]}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"fields"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"paging"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"first"},"value":{"kind":"IntValue","value":"1000"}}]}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"fieldFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"settings"}},{"kind":"Field","name":{"kind":"Name","value":"relationDefinition"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"relationId"}},{"kind":"Field","name":{"kind":"Name","value":"direction"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateOneServerlessFunctionItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneServerlessFunctionItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"publishedVersions"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const DeleteOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunctionIdInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ServerlessFunctionFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ServerlessFunctionFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ServerlessFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"runtime"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"latestVersion"}},{"kind":"Field","name":{"kind":"Name","value":"publishedVersions"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const ExecuteOneServerlessFunctionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ExecuteOneServerlessFunction"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ExecuteServerlessFunctionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"executeOneServerlessFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"data"}},{"kind":"Field","name":{"kind":"Name","value":"duration"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/generated/graphql.tsx b/packages/twenty-front/src/generated/graphql.tsx index 386ab99f23..8635146f8a 100644 --- a/packages/twenty-front/src/generated/graphql.tsx +++ b/packages/twenty-front/src/generated/graphql.tsx @@ -1,5 +1,5 @@ -import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; +import { gql } from '@apollo/client'; export type Maybe = T | null; export type InputMaybe = Maybe; export type Exact = { [K in keyof T]: T[K] }; @@ -155,6 +155,11 @@ export type ClientConfig = { support: Support; }; +export type ComputeStepOutputSchemaInput = { + /** Step JSON format */ + step: Scalars['JSON']; +}; + export type CreateServerlessFunctionInput = { description?: InputMaybe; name: Scalars['String']; @@ -424,6 +429,7 @@ export type Mutation = { authorizeApp: AuthorizeApp; challenge: LoginToken; checkoutSession: SessionEntity; + computeStepOutputSchema: Scalars['JSON']; createOIDCIdentityProvider: SetupSsoOutput; createOneAppToken: AppToken; createOneObject: Object; @@ -509,6 +515,11 @@ export type MutationCheckoutSessionArgs = { }; +export type MutationComputeStepOutputSchemaArgs = { + input: ComputeStepOutputSchemaInput; +}; + + export type MutationCreateOidcIdentityProviderArgs = { input: SetupOidcSsoInput; }; @@ -1155,12 +1166,13 @@ export type UpdateObjectPayload = { icon?: InputMaybe; imageIdentifierFieldMetadataId?: InputMaybe; isActive?: InputMaybe; + isLabelSyncedWithName?: InputMaybe; labelIdentifierFieldMetadataId?: InputMaybe; labelPlural?: InputMaybe; labelSingular?: InputMaybe; namePlural?: InputMaybe; nameSingular?: InputMaybe; - shouldSyncLabelAndName?: InputMaybe; + shortcut?: InputMaybe; }; export type UpdateOneObjectInput = { @@ -1271,6 +1283,7 @@ export type Workspace = { displayName?: Maybe; domainName?: Maybe; featureFlags?: Maybe>; + hasValidEntrepriseKey: Scalars['Boolean']; id: Scalars['UUID']; inviteHash?: Maybe; isPublicInviteLinkEnabled: Scalars['Boolean']; @@ -1470,6 +1483,7 @@ export type Object = { indexMetadatas: ObjectIndexMetadatasConnection; isActive: Scalars['Boolean']; isCustom: Scalars['Boolean']; + isLabelSyncedWithName: Scalars['Boolean']; isRemote: Scalars['Boolean']; isSystem: Scalars['Boolean']; labelIdentifierFieldMetadataId?: Maybe; @@ -1477,7 +1491,7 @@ export type Object = { labelSingular: Scalars['String']; namePlural: Scalars['String']; nameSingular: Scalars['String']; - shouldSyncLabelAndName: Scalars['Boolean']; + shortcut?: Maybe; updatedAt: Scalars['DateTime']; }; @@ -1675,7 +1689,7 @@ export type ImpersonateMutationVariables = Exact<{ }>; -export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, analyticsTinybirdJwt?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; +export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, analyticsTinybirdJwt?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, hasValidEntrepriseKey: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type RenewTokenMutationVariables = Exact<{ appToken: Scalars['String']; @@ -1708,7 +1722,7 @@ export type VerifyMutationVariables = Exact<{ }>; -export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, analyticsTinybirdJwt?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; +export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, analyticsTinybirdJwt?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, hasValidEntrepriseKey: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type CheckUserExistsQueryVariables = Exact<{ email: Scalars['String']; @@ -1795,7 +1809,7 @@ export type ListSsoIdentityProvidersByWorkspaceIdQueryVariables = Exact<{ [key: export type ListSsoIdentityProvidersByWorkspaceIdQuery = { __typename?: 'Query', listSSOIdentityProvidersByWorkspaceId: Array<{ __typename?: 'FindAvailableSSOIDPOutput', type: IdpType, id: string, name: string, issuer: string, status: SsoIdentityProviderStatus }> }; -export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, analyticsTinybirdJwt?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }; +export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, analyticsTinybirdJwt?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, hasValidEntrepriseKey: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }; export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>; @@ -1812,7 +1826,7 @@ export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProf export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>; -export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, analyticsTinybirdJwt?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> } }; +export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, analyticsTinybirdJwt?: string | null, onboardingStatus?: OnboardingStatus | null, userVars: any, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, hasValidEntrepriseKey: boolean, metadataVersion: number, workspaceMembersCount?: number | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: SubscriptionStatus, interval?: SubscriptionInterval | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> } }; export type ActivateWorkflowVersionMutationVariables = Exact<{ workflowVersionId: Scalars['String']; @@ -1821,6 +1835,13 @@ export type ActivateWorkflowVersionMutationVariables = Exact<{ export type ActivateWorkflowVersionMutation = { __typename?: 'Mutation', activateWorkflowVersion: boolean }; +export type ComputeStepOutputSchemaMutationVariables = Exact<{ + input: ComputeStepOutputSchemaInput; +}>; + + +export type ComputeStepOutputSchemaMutation = { __typename?: 'Mutation', computeStepOutputSchema: any }; + export type DeactivateWorkflowVersionMutationVariables = Exact<{ workflowVersionId: Scalars['String']; }>; @@ -2042,6 +2063,7 @@ export const UserQueryFragmentFragmentDoc = gql` allowImpersonation activationStatus isPublicInviteLinkEnabled + hasValidEntrepriseKey featureFlags { id key @@ -3441,6 +3463,37 @@ export function useActivateWorkflowVersionMutation(baseOptions?: Apollo.Mutation export type ActivateWorkflowVersionMutationHookResult = ReturnType; export type ActivateWorkflowVersionMutationResult = Apollo.MutationResult; export type ActivateWorkflowVersionMutationOptions = Apollo.BaseMutationOptions; +export const ComputeStepOutputSchemaDocument = gql` + mutation ComputeStepOutputSchema($input: ComputeStepOutputSchemaInput!) { + computeStepOutputSchema(input: $input) +} + `; +export type ComputeStepOutputSchemaMutationFn = Apollo.MutationFunction; + +/** + * __useComputeStepOutputSchemaMutation__ + * + * To run a mutation, you first call `useComputeStepOutputSchemaMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useComputeStepOutputSchemaMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [computeStepOutputSchemaMutation, { data, loading, error }] = useComputeStepOutputSchemaMutation({ + * variables: { + * input: // value for 'input' + * }, + * }); + */ +export function useComputeStepOutputSchemaMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(ComputeStepOutputSchemaDocument, options); + } +export type ComputeStepOutputSchemaMutationHookResult = ReturnType; +export type ComputeStepOutputSchemaMutationResult = Apollo.MutationResult; +export type ComputeStepOutputSchemaMutationOptions = Apollo.BaseMutationOptions; export const DeactivateWorkflowVersionDocument = gql` mutation DeactivateWorkflowVersion($workflowVersionId: String!) { deactivateWorkflowVersion(workflowVersionId: $workflowVersionId) diff --git a/packages/twenty-front/src/hooks/__tests__/usePageChangeEffectNavigateLocation.test.ts b/packages/twenty-front/src/hooks/__tests__/usePageChangeEffectNavigateLocation.test.ts index 95c2a58b79..a7b683e660 100644 --- a/packages/twenty-front/src/hooks/__tests__/usePageChangeEffectNavigateLocation.test.ts +++ b/packages/twenty-front/src/hooks/__tests__/usePageChangeEffectNavigateLocation.test.ts @@ -2,6 +2,7 @@ import { useIsLogged } from '@/auth/hooks/useIsLogged'; import { useDefaultHomePagePath } from '@/navigation/hooks/useDefaultHomePagePath'; import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus'; import { AppPath } from '@/types/AppPath'; + import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus'; import { OnboardingStatus, SubscriptionStatus } from '~/generated/graphql'; diff --git a/packages/twenty-front/src/hooks/useCleanRecoilState.ts b/packages/twenty-front/src/hooks/useCleanRecoilState.ts index 3f0a41df4a..9da98c006a 100644 --- a/packages/twenty-front/src/hooks/useCleanRecoilState.ts +++ b/packages/twenty-front/src/hooks/useCleanRecoilState.ts @@ -1,8 +1,9 @@ -import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation'; -import { SettingsPath } from '@/types/SettingsPath'; import { apiKeyTokenState } from '@/settings/developers/states/generatedApiKeyTokenState'; -import { useRecoilValue, useResetRecoilState } from 'recoil'; import { AppPath } from '@/types/AppPath'; +import { SettingsPath } from '@/types/SettingsPath'; +import { useRecoilValue, useResetRecoilState } from 'recoil'; +import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation'; + import { isDefined } from '~/utils/isDefined'; export const useCleanRecoilState = () => { diff --git a/packages/twenty-front/src/index.css b/packages/twenty-front/src/index.css index 808fd8917d..30952751bd 100644 --- a/packages/twenty-front/src/index.css +++ b/packages/twenty-front/src/index.css @@ -10,6 +10,6 @@ html { } /* https://stackoverflow.com/questions/44543157/how-to-hide-the-google-invisible-recaptcha-badge */ -.grecaptcha-badge { +.grecaptcha-badge { visibility: hidden !important; } diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx index a1f1f34f1d..208ae8ffc3 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx @@ -1,5 +1,5 @@ +import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries'; -import { ActionMenuType } from '@/action-menu/types/ActionMenuType'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; @@ -12,17 +12,15 @@ import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTabl import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useContext, useEffect, useState } from 'react'; import { IconTrash, isDefined } from 'twenty-ui'; export const DeleteRecordsActionEffect = ({ position, objectMetadataItem, - actionMenuType, }: { position: number; objectMetadataItem: ObjectMetadataItem; - actionMenuType: ActionMenuType; }) => { const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries(); @@ -93,6 +91,9 @@ export const DeleteRecordsActionEffect = ({ contextStoreNumberOfSelectedRecords < DELETE_MAX_COUNT && contextStoreNumberOfSelectedRecords > 0; + const { isInRightDrawer, onActionExecutedCallback } = + useContext(ActionMenuContext); + useEffect(() => { if (canDelete) { addActionMenuEntry({ @@ -120,17 +121,14 @@ export const DeleteRecordsActionEffect = ({ } can be recovered from the Options menu.`} onConfirmClick={() => { handleDeleteClick(); - - if (actionMenuType === 'recordShow') { + onActionExecutedCallback?.(); + if (isInRightDrawer) { closeRightDrawer(); } }} deleteButtonText={`Delete ${ contextStoreNumberOfSelectedRecords > 1 ? 'Records' : 'Record' }`} - modalVariant={ - actionMenuType === 'recordShow' ? 'tertiary' : 'primary' - } /> ), }); @@ -142,13 +140,14 @@ export const DeleteRecordsActionEffect = ({ removeActionMenuEntry('delete'); }; }, [ - actionMenuType, addActionMenuEntry, canDelete, closeRightDrawer, contextStoreNumberOfSelectedRecords, handleDeleteClick, isDeleteRecordsModalOpen, + isInRightDrawer, + onActionExecutedCallback, position, removeActionMenuEntry, ]); diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter.tsx deleted file mode 100644 index f1fcd52c9b..0000000000 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect'; -import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect'; -import { ActionMenuType } from '@/action-menu/types/ActionMenuType'; -import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; - -const actionEffects = [ExportRecordsActionEffect, DeleteRecordsActionEffect]; - -export const MultipleRecordsActionMenuEntriesSetter = ({ - objectMetadataItem, - actionMenuType, -}: { - objectMetadataItem: ObjectMetadataItem; - actionMenuType: ActionMenuType; -}) => { - return ( - <> - {actionEffects.map((ActionEffect, index) => ( - - ))} - - ); -}; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx index 5ed405684b..fc4b47209d 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx @@ -1,16 +1,23 @@ -import { MultipleRecordsActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter'; -import { SingleRecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter'; -import { ActionMenuType } from '@/action-menu/types/ActionMenuType'; +import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect'; +import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect'; +import { ManageFavoritesActionEffect } from '@/action-menu/actions/record-actions/components/ManageFavoritesActionEffect'; import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -export const RecordActionMenuEntriesSetter = ({ - actionMenuType, -}: { - actionMenuType: ActionMenuType; -}) => { +const singleRecordActionEffects = [ + ManageFavoritesActionEffect, + ExportRecordsActionEffect, + DeleteRecordsActionEffect, +]; + +const multipleRecordActionEffects = [ + ExportRecordsActionEffect, + DeleteRecordsActionEffect, +]; + +export const RecordActionMenuEntriesSetter = () => { const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2( contextStoreNumberOfSelectedRecordsComponentState, ); @@ -33,19 +40,20 @@ export const RecordActionMenuEntriesSetter = ({ return null; } - if (contextStoreNumberOfSelectedRecords === 1) { - return ( - - ); - } + const actions = + contextStoreNumberOfSelectedRecords === 1 + ? singleRecordActionEffects + : multipleRecordActionEffects; return ( - + <> + {actions.map((ActionEffect, index) => ( + + ))} + ); }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter.tsx deleted file mode 100644 index 7bf10746fb..0000000000 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect'; -import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect'; -import { ManageFavoritesActionEffect } from '@/action-menu/actions/record-actions/components/ManageFavoritesActionEffect'; -import { ActionMenuType } from '@/action-menu/types/ActionMenuType'; -import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; - -export const SingleRecordActionMenuEntriesSetter = ({ - objectMetadataItem, - actionMenuType, -}: { - objectMetadataItem: ObjectMetadataItem; - actionMenuType: ActionMenuType; -}) => { - const actionEffects = [ - ManageFavoritesActionEffect, - ExportRecordsActionEffect, - DeleteRecordsActionEffect, - ]; - return ( - <> - {actionEffects.map((ActionEffect, index) => ( - - ))} - - ); -}; diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx index 866303d3f5..95df542d91 100644 --- a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx +++ b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx @@ -3,16 +3,12 @@ import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMen import { RecordIndexActionMenuBar } from '@/action-menu/components/RecordIndexActionMenuBar'; import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown'; import { RecordIndexActionMenuEffect } from '@/action-menu/components/RecordIndexActionMenuEffect'; +import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; -import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -export const RecordIndexActionMenu = ({ - actionMenuId, -}: { - actionMenuId: string; -}) => { +export const RecordIndexActionMenu = () => { const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( contextStoreCurrentObjectMetadataIdComponentState, ); @@ -20,15 +16,18 @@ export const RecordIndexActionMenu = ({ return ( <> {contextStoreCurrentObjectMetadataId && ( - {}, + }} > - - + + )} ); diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuEffect.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuEffect.tsx index 97c785af7f..19cd64c38c 100644 --- a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuEffect.tsx +++ b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuEffect.tsx @@ -1,7 +1,9 @@ import { useActionMenu } from '@/action-menu/hooks/useActionMenu'; import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; +import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState'; +import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; @@ -25,6 +27,9 @@ export const RecordIndexActionMenuEffect = () => { `action-menu-dropdown-${actionMenuId}`, ), ); + const { isRightDrawerOpen } = useRightDrawer(); + + const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState); useEffect(() => { if (contextStoreNumberOfSelectedRecords > 0 && !isDropdownOpen) { @@ -43,5 +48,11 @@ export const RecordIndexActionMenuEffect = () => { isDropdownOpen, ]); + useEffect(() => { + if (isRightDrawerOpen || isCommandMenuOpened) { + closeActionBar(); + } + }, [closeActionBar, isRightDrawerOpen, isCommandMenuOpened]); + return null; }; diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx index 80bbfe4e14..6ce6218e0b 100644 --- a/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx +++ b/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx @@ -1,30 +1,53 @@ import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter'; import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals'; -import { RecordShowActionMenuBar } from '@/action-menu/components/RecordShowActionMenuBar'; +import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; -import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { RecordShowPageBaseHeader } from '~/pages/object-record/RecordShowPageBaseHeader'; export const RecordShowActionMenu = ({ - actionMenuId, + isFavorite, + handleFavoriteButtonClick, + record, + objectMetadataItem, + objectNameSingular, }: { - actionMenuId: string; + isFavorite: boolean; + handleFavoriteButtonClick: () => void; + record: ObjectRecord | undefined; + objectMetadataItem: ObjectMetadataItem; + objectNameSingular: string; }) => { const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( contextStoreCurrentObjectMetadataIdComponentState, ); + // TODO: refactor RecordShowPageBaseHeader to use the context store + return ( <> {contextStoreCurrentObjectMetadataId && ( - {}, + }} > - + - - + + )} ); diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordShowRightDrawerActionMenu.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordShowRightDrawerActionMenu.tsx new file mode 100644 index 0000000000..c4399a42a1 --- /dev/null +++ b/packages/twenty-front/src/modules/action-menu/components/RecordShowRightDrawerActionMenu.tsx @@ -0,0 +1,30 @@ +import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter'; +import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals'; +import { RecordShowRightDrawerActionMenuBar } from '@/action-menu/components/RecordShowRightDrawerActionMenuBar'; +import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; + +import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; + +export const RecordShowRightDrawerActionMenu = () => { + const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2( + contextStoreCurrentObjectMetadataIdComponentState, + ); + + return ( + <> + {contextStoreCurrentObjectMetadataId && ( + {}, + }} + > + + + + + )} + + ); +}; diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBar.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordShowRightDrawerActionMenuBar.tsx similarity index 91% rename from packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBar.tsx rename to packages/twenty-front/src/modules/action-menu/components/RecordShowRightDrawerActionMenuBar.tsx index c4fefcef4a..85ab16ab01 100644 --- a/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBar.tsx +++ b/packages/twenty-front/src/modules/action-menu/components/RecordShowRightDrawerActionMenuBar.tsx @@ -2,7 +2,7 @@ import { RecordShowActionMenuBarEntry } from '@/action-menu/components/RecordSho import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -export const RecordShowActionMenuBar = () => { +export const RecordShowRightDrawerActionMenuBar = () => { const actionMenuEntries = useRecoilComponentValueV2( actionMenuEntriesComponentSelector, ); diff --git a/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordShowActionMenuBar.stories.tsx b/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordShowActionMenuBar.stories.tsx index 22f1bab670..2be67a5677 100644 --- a/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordShowActionMenuBar.stories.tsx +++ b/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordShowActionMenuBar.stories.tsx @@ -2,7 +2,7 @@ import { expect, jest } from '@storybook/jest'; import { Meta, StoryObj } from '@storybook/react'; import { RecoilRoot } from 'recoil'; -import { RecordShowActionMenuBar } from '@/action-menu/components/RecordShowActionMenuBar'; +import { RecordShowRightDrawerActionMenuBar } from '@/action-menu/components/RecordShowRightDrawerActionMenuBar'; import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState'; import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; @@ -20,9 +20,9 @@ const deleteMock = jest.fn(); const addToFavoritesMock = jest.fn(); const exportMock = jest.fn(); -const meta: Meta = { - title: 'Modules/ActionMenu/RecordShowActionMenuBar', - component: RecordShowActionMenuBar, +const meta: Meta = { + title: 'Modules/ActionMenu/RecordShowRightDrawerActionMenuBar', + component: RecordShowRightDrawerActionMenuBar, decorators: [ (Story) => ( = { export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Default: Story = { args: { diff --git a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContext.ts b/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContext.ts new file mode 100644 index 0000000000..0c1482f40b --- /dev/null +++ b/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContext.ts @@ -0,0 +1,11 @@ +import { createContext } from 'react'; + +type ActionMenuContextType = { + isInRightDrawer: boolean; + onActionExecutedCallback: () => void; +}; + +export const ActionMenuContext = createContext({ + isInRightDrawer: false, + onActionExecutedCallback: () => {}, +}); diff --git a/packages/twenty-front/src/modules/action-menu/types/ActionMenuType.ts b/packages/twenty-front/src/modules/action-menu/types/ActionMenuType.ts deleted file mode 100644 index a0e7d0e4b5..0000000000 --- a/packages/twenty-front/src/modules/action-menu/types/ActionMenuType.ts +++ /dev/null @@ -1 +0,0 @@ -export type ActionMenuType = 'recordIndex' | 'recordShow'; diff --git a/packages/twenty-front/src/modules/activities/calendar/components/Calendar.tsx b/packages/twenty-front/src/modules/activities/calendar/components/Calendar.tsx index b8da221c6a..29beb12258 100644 --- a/packages/twenty-front/src/modules/activities/calendar/components/Calendar.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/components/Calendar.tsx @@ -8,6 +8,7 @@ import { AnimatedPlaceholderEmptyTitle, EMPTY_PLACEHOLDER_TRANSITION_PROPS, H3Title, + Section, } from 'twenty-ui'; import { CalendarMonthCard } from '@/activities/calendar/components/CalendarMonthCard'; @@ -21,7 +22,6 @@ import { SkeletonLoader } from '@/activities/components/SkeletonLoader'; import { useCustomResolver } from '@/activities/hooks/useCustomResolver'; import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { Section } from '@/ui/layout/section/components/Section'; import { TimelineCalendarEventsWithTotal } from '~/generated/graphql'; const StyledContainer = styled.div` diff --git a/packages/twenty-front/src/modules/activities/calendar/components/CalendarDayCardContent.tsx b/packages/twenty-front/src/modules/activities/calendar/components/CalendarDayCardContent.tsx index ca656f3b52..1ccf037161 100644 --- a/packages/twenty-front/src/modules/activities/calendar/components/CalendarDayCardContent.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/components/CalendarDayCardContent.tsx @@ -4,7 +4,7 @@ import { differenceInSeconds, endOfDay, format } from 'date-fns'; import { CalendarEventRow } from '@/activities/calendar/components/CalendarEventRow'; import { getCalendarEventStartDate } from '@/activities/calendar/utils/getCalendarEventStartDate'; -import { CardContent } from '@/ui/layout/card/components/CardContent'; +import { CardContent } from 'twenty-ui'; import { TimelineCalendarEvent } from '~/generated/graphql'; type CalendarDayCardContentProps = { diff --git a/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx b/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx index cb9548f8ba..5874898e00 100644 --- a/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/components/CalendarEventRow.tsx @@ -9,6 +9,8 @@ import { IconArrowRight, IconLock, isDefined, + Card, + CardContent, } from 'twenty-ui'; import { CalendarCurrentEventCursor } from '@/activities/calendar/components/CalendarCurrentEventCursor'; @@ -18,8 +20,6 @@ import { getCalendarEventEndDate } from '@/activities/calendar/utils/getCalendar import { getCalendarEventStartDate } from '@/activities/calendar/utils/getCalendarEventStartDate'; import { hasCalendarEventEnded } from '@/activities/calendar/utils/hasCalendarEventEnded'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; -import { Card } from '@/ui/layout/card/components/Card'; -import { CardContent } from '@/ui/layout/card/components/CardContent'; import { CalendarChannelVisibility, TimelineCalendarEvent, diff --git a/packages/twenty-front/src/modules/activities/calendar/components/CalendarMonthCard.tsx b/packages/twenty-front/src/modules/activities/calendar/components/CalendarMonthCard.tsx index f42f2e35f5..97ca1d0297 100644 --- a/packages/twenty-front/src/modules/activities/calendar/components/CalendarMonthCard.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/components/CalendarMonthCard.tsx @@ -2,7 +2,7 @@ import { useContext } from 'react'; import { CalendarDayCardContent } from '@/activities/calendar/components/CalendarDayCardContent'; import { CalendarContext } from '@/activities/calendar/contexts/CalendarContext'; -import { Card } from '@/ui/layout/card/components/Card'; +import { Card } from 'twenty-ui'; type CalendarMonthCardProps = { dayTimes: number[]; diff --git a/packages/twenty-front/src/modules/activities/components/ActivityList.tsx b/packages/twenty-front/src/modules/activities/components/ActivityList.tsx index b8b8b2f61d..0bb0e367e5 100644 --- a/packages/twenty-front/src/modules/activities/components/ActivityList.tsx +++ b/packages/twenty-front/src/modules/activities/components/ActivityList.tsx @@ -1,5 +1,5 @@ -import { Card } from '@/ui/layout/card/components/Card'; import styled from '@emotion/styled'; +import { Card } from 'twenty-ui'; const StyledList = styled(Card)` & > :not(:last-child) { diff --git a/packages/twenty-front/src/modules/activities/components/ActivityRow.tsx b/packages/twenty-front/src/modules/activities/components/ActivityRow.tsx index 00fdbb1a68..075758fc82 100644 --- a/packages/twenty-front/src/modules/activities/components/ActivityRow.tsx +++ b/packages/twenty-front/src/modules/activities/components/ActivityRow.tsx @@ -1,5 +1,5 @@ -import { CardContent } from '@/ui/layout/card/components/CardContent'; import styled from '@emotion/styled'; +import { CardContent } from 'twenty-ui'; import React from 'react'; const StyledRowContent = styled(CardContent)<{ diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailLoader.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailLoader.tsx index f301828ff4..444685852b 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/EmailLoader.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailLoader.tsx @@ -1,9 +1,9 @@ -import { Loader } from '@/ui/feedback/loader/components/Loader'; import { AnimatedPlaceholder, AnimatedPlaceholderEmptyContainer, AnimatedPlaceholderEmptyTextContainer, AnimatedPlaceholderEmptyTitle, + Loader, } from 'twenty-ui'; export const EmailLoader = ({ loadingText }: { loadingText?: string }) => ( diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx index f8c9b317f6..38f150dcc3 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailThreads.tsx @@ -8,6 +8,7 @@ import { EMPTY_PLACEHOLDER_TRANSITION_PROPS, H1Title, H1TitleFontColor, + Section, } from 'twenty-ui'; import { ActivityList } from '@/activities/components/ActivityList'; @@ -20,7 +21,6 @@ import { getTimelineThreadsFromPersonId } from '@/activities/emails/graphql/quer import { useCustomResolver } from '@/activities/hooks/useCustomResolver'; import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; -import { Section } from '@/ui/layout/section/components/Section'; import { TimelineThread, TimelineThreadsWithTotal } from '~/generated/graphql'; const StyledContainer = styled.div` diff --git a/packages/twenty-front/src/modules/activities/tasks/components/TaskRow.tsx b/packages/twenty-front/src/modules/activities/tasks/components/TaskRow.tsx index ad46a8a43b..90e11ab064 100644 --- a/packages/twenty-front/src/modules/activities/tasks/components/TaskRow.tsx +++ b/packages/twenty-front/src/modules/activities/tasks/components/TaskRow.tsx @@ -1,11 +1,15 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; -import { IconCalendar, OverflowingTextWithTooltip } from 'twenty-ui'; +import { + Checkbox, + CheckboxShape, + IconCalendar, + OverflowingTextWithTooltip, +} from 'twenty-ui'; import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer'; import { ActivityTargetsInlineCell } from '@/activities/inline-cell/components/ActivityTargetsInlineCell'; import { getActivitySummary } from '@/activities/utils/getActivitySummary'; -import { Checkbox, CheckboxShape } from '@/ui/input/components/Checkbox'; import { beautifyExactDate, hasDatePassed } from '~/utils/date-utils'; import { ActivityRow } from '@/activities/components/ActivityRow'; diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/rows/components/EventCard.tsx b/packages/twenty-front/src/modules/activities/timeline-activities/rows/components/EventCard.tsx index 67e4f78cd7..52b8fa0de8 100644 --- a/packages/twenty-front/src/modules/activities/timeline-activities/rows/components/EventCard.tsx +++ b/packages/twenty-front/src/modules/activities/timeline-activities/rows/components/EventCard.tsx @@ -1,6 +1,6 @@ import styled from '@emotion/styled'; -import { Card } from '@/ui/layout/card/components/Card'; +import { Card } from 'twenty-ui'; type EventCardProps = { children: React.ReactNode; diff --git a/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts b/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts index b70cbdd17c..104364957c 100644 --- a/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts +++ b/packages/twenty-front/src/modules/apollo/hooks/useApolloFactory.ts @@ -10,12 +10,12 @@ import { previousUrlState } from '@/auth/states/previousUrlState'; import { tokenPairState } from '@/auth/states/tokenPairState'; import { workspacesState } from '@/auth/states/workspaces'; import { isDebugModeState } from '@/client-config/states/isDebugModeState'; -import { AppPath } from '@/types/AppPath'; import { REACT_APP_SERVER_BASE_URL } from '~/config'; import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation'; import { useUpdateEffect } from '~/hooks/useUpdateEffect'; import { isDefined } from '~/utils/isDefined'; +import { AppPath } from '@/types/AppPath'; import { ApolloFactory, Options } from '../services/apollo.factory'; export const useApolloFactory = (options: Partial> = {}) => { diff --git a/packages/twenty-front/src/modules/app/effect-components/GotoHotkeysEffectsProvider.tsx b/packages/twenty-front/src/modules/app/effect-components/GotoHotkeysEffectsProvider.tsx index 44267f5c34..2cc96f5158 100644 --- a/packages/twenty-front/src/modules/app/effect-components/GotoHotkeysEffectsProvider.tsx +++ b/packages/twenty-front/src/modules/app/effect-components/GotoHotkeysEffectsProvider.tsx @@ -27,11 +27,17 @@ export const GotoHotkeysEffectsProvider = () => { ), }); - return nonSystemActiveObjectMetadataItems.map((objectMetadataItem) => ( - - )); + return nonSystemActiveObjectMetadataItems.map((objectMetadataItem) => { + if (!objectMetadataItem.shortcut) { + return null; + } + + return ( + + ); + }); }; diff --git a/packages/twenty-front/src/modules/app/effect-components/PageChangeEffect.tsx b/packages/twenty-front/src/modules/app/effect-components/PageChangeEffect.tsx index a8b05f4c09..3af2f15ada 100644 --- a/packages/twenty-front/src/modules/app/effect-components/PageChangeEffect.tsx +++ b/packages/twenty-front/src/modules/app/effect-components/PageChangeEffect.tsx @@ -1,7 +1,6 @@ import { useEffect, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; -import { IconCheckbox } from 'twenty-ui'; import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; import { @@ -21,6 +20,7 @@ import { AppPath } from '@/types/AppPath'; import { PageHotkeyScope } from '@/types/PageHotkeyScope'; import { SettingsPath } from '@/types/SettingsPath'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; +import { IconCheckbox } from 'twenty-ui'; import { useCleanRecoilState } from '~/hooks/useCleanRecoilState'; import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation'; import { usePageChangeEffectNavigateLocation } from '~/hooks/usePageChangeEffectNavigateLocation'; @@ -115,7 +115,7 @@ export const PageChangeEffect = () => { break; } case isMatchingLocation(AppPath.CreateWorkspace): { - setHotkeyScope(PageHotkeyScope.CreateWokspace); + setHotkeyScope(PageHotkeyScope.CreateWorkspace); break; } case isMatchingLocation(AppPath.SyncEmails): { diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx b/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx index 38856d33d5..4a72dc617c 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx +++ b/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx @@ -2,14 +2,16 @@ import { FooterNote } from '@/auth/sign-in-up/components/FooterNote'; import { HorizontalSeparator } from '@/auth/sign-in-up/components/HorizontalSeparator'; import { useHandleResetPassword } from '@/auth/sign-in-up/hooks/useHandleResetPassword'; import { SignInUpMode, useSignInUp } from '@/auth/sign-in-up/hooks/useSignInUp'; -import { useSignInUpForm } from '@/auth/sign-in-up/hooks/useSignInUpForm'; +import { + useSignInUpForm, + validationSchema, +} from '@/auth/sign-in-up/hooks/useSignInUpForm'; import { useSignInWithGoogle } from '@/auth/sign-in-up/hooks/useSignInWithGoogle'; import { useSignInWithMicrosoft } from '@/auth/sign-in-up/hooks/useSignInWithMicrosoft'; import { SignInUpStep } from '@/auth/states/signInUpStepState'; import { isRequestingCaptchaTokenState } from '@/captcha/states/isRequestingCaptchaTokenState'; import { authProvidersState } from '@/client-config/states/authProvidersState'; import { captchaProviderState } from '@/client-config/states/captchaProviderState'; -import { Loader } from '@/ui/feedback/loader/components/Loader'; import { TextInput } from '@/ui/input/components/TextInput'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; @@ -23,7 +25,9 @@ import { IconGoogle, IconKey, IconMicrosoft, + Loader, MainButton, + StyledText, } from 'twenty-ui'; import { isDefined } from '~/utils/isDefined'; @@ -127,7 +131,8 @@ export const SignInUpForm = () => { const isEmailStepSubmitButtonDisabledCondition = signInUpStep === SignInUpStep.Email && - (form.watch('email')?.length === 0 || shouldWaitForCaptchaToken); + (!validationSchema.shape.email.safeParse(form.watch('email')).success || + shouldWaitForCaptchaToken); // TODO: isValid is actually a proxy function. If it is not rendered the first time, react might not trigger re-renders // We make the isValid check synchronous and update a reactState to make sure this does not happen @@ -183,7 +188,9 @@ export const SignInUpForm = () => { )} - + {(authProviders.google || + authProviders.microsoft || + authProviders.sso) && } {authProviders.password && (signInUpStep === SignInUpStep.Password || @@ -263,6 +270,12 @@ export const SignInUpForm = () => { disableHotkeys onKeyDown={handleKeyDown} /> + {signInUpMode === SignInUpMode.SignUp && ( + + )} )} /> diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx index a80473854c..53994713c9 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx @@ -5,20 +5,20 @@ import { useParams, useSearchParams } from 'react-router-dom'; import { Form } from '@/auth/sign-in-up/hooks/useSignInUpForm'; import { useReadCaptchaToken } from '@/captcha/hooks/useReadCaptchaToken'; import { useRequestFreshCaptchaToken } from '@/captcha/hooks/useRequestFreshCaptchaToken'; -import { AppPath } from '@/types/AppPath'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; -import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation'; import { useRecoilState, useSetRecoilState } from 'recoil'; +import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation'; import { isDefined } from '~/utils/isDefined'; -import { useAuth } from '../../hooks/useAuth'; +import { useSSO } from '@/auth/sign-in-up/hooks/useSSO'; +import { availableSSOIdentityProvidersState } from '@/auth/states/availableWorkspacesForSSO'; import { SignInUpStep, signInUpStepState, } from '@/auth/states/signInUpStepState'; -import { useSSO } from '@/auth/sign-in-up/hooks/useSSO'; -import { availableSSOIdentityProvidersState } from '@/auth/states/availableWorkspacesForSSO'; +import { AppPath } from '@/types/AppPath'; +import { useAuth } from '../../hooks/useAuth'; export enum SignInUpMode { SignIn = 'sign-in', diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts index 817b276678..07e2aaf7b1 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts @@ -1,13 +1,13 @@ +import { zodResolver } from '@hookform/resolvers/zod'; import { useEffect } from 'react'; import { useForm } from 'react-hook-form'; -import { zodResolver } from '@hookform/resolvers/zod'; import { useRecoilValue } from 'recoil'; import { z } from 'zod'; import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex'; import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState'; -const validationSchema = z +export const validationSchema = z .object({ exist: z.boolean(), email: z.string().trim().email('Email must be a valid email'), diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useWorkspaceFromInviteHash.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useWorkspaceFromInviteHash.ts index a51365b98a..0e238c3ab7 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useWorkspaceFromInviteHash.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useWorkspaceFromInviteHash.ts @@ -3,11 +3,12 @@ import { useNavigate, useParams } from 'react-router-dom'; import { useRecoilValue, useSetRecoilState } from 'recoil'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; -import { AppPath } from '@/types/AppPath'; + import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { isDefaultLayoutAuthModalVisibleState } from '@/ui/layout/states/isDefaultLayoutAuthModalVisibleState'; +import { AppPath } from '@/types/AppPath'; import { useGetWorkspaceFromInviteHashQuery } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; diff --git a/packages/twenty-front/src/modules/auth/states/currentWorkspaceState.ts b/packages/twenty-front/src/modules/auth/states/currentWorkspaceState.ts index e384b5b6a9..fde9761138 100644 --- a/packages/twenty-front/src/modules/auth/states/currentWorkspaceState.ts +++ b/packages/twenty-front/src/modules/auth/states/currentWorkspaceState.ts @@ -14,6 +14,7 @@ export type CurrentWorkspace = Pick< | 'currentBillingSubscription' | 'workspaceMembersCount' | 'isPublicInviteLinkEnabled' + | 'hasValidEntrepriseKey' | 'metadataVersion' >; diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx index 02f6365827..4dd360c934 100644 --- a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx @@ -10,6 +10,7 @@ import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchS import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState'; import { Command, CommandType } from '@/command-menu/types/Command'; import { Company } from '@/companies/types/Company'; +import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { getCompanyDomainName } from '@/object-metadata/utils/getCompanyDomainName'; @@ -287,6 +288,14 @@ export const CommandMenu = () => { : true) && cmd.type === CommandType.Create, ); + const matchingActionCommands = commandMenuCommands.filter( + (cmd) => + (deferredCommandMenuSearch.length > 0 + ? checkInShortcuts(cmd, deferredCommandMenuSearch) || + checkInLabels(cmd, deferredCommandMenuSearch) + : true) && cmd.type === CommandType.Action, + ); + useListenClickOutside({ refs: [commandMenuRef], callback: closeCommandMenu, @@ -312,6 +321,7 @@ export const CommandMenu = () => { const selectableItemIds = copilotCommands .map((cmd) => cmd.id) + .concat(matchingActionCommands.map((cmd) => cmd.id)) .concat(matchingCreateCommand.map((cmd) => cmd.id)) .concat(matchingNavigateCommand.map((cmd) => cmd.id)) .concat(people?.map((person) => person.id)) @@ -320,22 +330,28 @@ export const CommandMenu = () => { .concat(notes?.map((note) => note.id)); const isNoResults = + !matchingActionCommands.length && !matchingCreateCommand.length && !matchingNavigateCommand.length && !people?.length && !companies?.length && !notes?.length && !opportunities?.length; + const isLoading = isPeopleLoading || isNotesLoading || isOpportunitiesLoading || isCompaniesLoading; + const mainContextStoreComponentInstanceId = useRecoilValue( + mainContextStoreComponentInstanceIdState, + ); + return ( <> {isCommandMenuOpened && ( - + { )} + {mainContextStoreComponentInstanceId && ( + + {matchingActionCommands?.map((actionCommand) => ( + + + + ))} + + )} {matchingCreateCommand.map((cmd) => ( diff --git a/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useCommandMenu.test.tsx b/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useCommandMenu.test.tsx index c2449c755e..db4bdf31a1 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useCommandMenu.test.tsx +++ b/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useCommandMenu.test.tsx @@ -124,7 +124,8 @@ describe('useCommandMenu', () => { namePlural: 'tasks', labelSingular: 'Task', labelPlural: 'Tasks', - shouldSyncLabelAndName: true, + isLabelSyncedWithName: true, + shortcut: 'T', description: 'A task', icon: 'IconCheckbox', isCustom: false, diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts b/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts index d19c314a1c..06fc6469bc 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts +++ b/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts @@ -1,7 +1,7 @@ import { isNonEmptyString } from '@sniptt/guards'; import { useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; -import { useRecoilCallback, useSetRecoilState } from 'recoil'; +import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil'; import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; @@ -9,7 +9,9 @@ import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousH import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope'; import { isDefined } from '~/utils/isDefined'; +import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector'; import { COMMAND_MENU_COMMANDS } from '@/command-menu/constants/CommandMenuCommands'; +import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { ALL_ICONS } from '@ui/display/icon/providers/internal/AllIcons'; import { sortByProperty } from '~/utils/array/sortByProperty'; @@ -27,10 +29,43 @@ export const useCommandMenu = () => { goBackToPreviousHotkeyScope, } = usePreviousHotkeyScope(); - const openCommandMenu = useCallback(() => { - setIsCommandMenuOpened(true); - setHotkeyScopeAndMemorizePreviousScope(AppHotkeyScope.CommandMenuOpen); - }, [setHotkeyScopeAndMemorizePreviousScope, setIsCommandMenuOpened]); + const mainContextStoreComponentInstanceId = useRecoilValue( + mainContextStoreComponentInstanceIdState, + ); + + const openCommandMenu = useRecoilCallback( + ({ snapshot }) => + () => { + if (isDefined(mainContextStoreComponentInstanceId)) { + const actionMenuEntries = snapshot.getLoadable( + actionMenuEntriesComponentSelector.selectorFamily({ + instanceId: mainContextStoreComponentInstanceId, + }), + ); + + const actionCommands = actionMenuEntries + .getValue() + ?.map((actionMenuEntry) => ({ + id: actionMenuEntry.key, + label: actionMenuEntry.label, + Icon: actionMenuEntry.Icon, + onCommandClick: actionMenuEntry.onClick, + type: CommandType.Action, + })); + + setCommands(actionCommands); + } + + setIsCommandMenuOpened(true); + setHotkeyScopeAndMemorizePreviousScope(AppHotkeyScope.CommandMenuOpen); + }, + [ + mainContextStoreComponentInstanceId, + setCommands, + setHotkeyScopeAndMemorizePreviousScope, + setIsCommandMenuOpened, + ], + ); const closeCommandMenu = useRecoilCallback( ({ snapshot }) => @@ -83,8 +118,8 @@ export const useCommandMenu = () => { to: `/objects/${item.namePlural}`, label: `Go to ${item.labelPlural}`, type: CommandType.Navigate, - firstHotKey: 'G', - secondHotKey: item.labelPlural[0], + firstHotKey: item.shortcut ? 'G' : undefined, + secondHotKey: item.shortcut, Icon: ALL_ICONS[ (item?.icon as keyof typeof ALL_ICONS) ?? 'IconArrowUpRight' ], diff --git a/packages/twenty-front/src/modules/command-menu/types/Command.ts b/packages/twenty-front/src/modules/command-menu/types/Command.ts index 38b430bb34..b43b23f9c0 100644 --- a/packages/twenty-front/src/modules/command-menu/types/Command.ts +++ b/packages/twenty-front/src/modules/command-menu/types/Command.ts @@ -3,13 +3,14 @@ import { IconComponent } from 'twenty-ui'; export enum CommandType { Navigate = 'Navigate', Create = 'Create', + Action = 'Action', } export type Command = { id: string; - to: string; + to?: string; label: string; - type: CommandType.Navigate | CommandType.Create; + type: CommandType.Navigate | CommandType.Create | CommandType.Action; Icon?: IconComponent; firstHotKey?: string; secondHotKey?: string; diff --git a/packages/twenty-front/src/modules/context-store/components/SetMainContextStoreComponentInstanceIdEffect.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreComponentInstanceIdSetterEffect.tsx similarity index 91% rename from packages/twenty-front/src/modules/context-store/components/SetMainContextStoreComponentInstanceIdEffect.tsx rename to packages/twenty-front/src/modules/context-store/components/MainContextStoreComponentInstanceIdSetterEffect.tsx index b1acc25d84..cc838bb7ed 100644 --- a/packages/twenty-front/src/modules/context-store/components/SetMainContextStoreComponentInstanceIdEffect.tsx +++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreComponentInstanceIdSetterEffect.tsx @@ -3,7 +3,7 @@ import { mainContextStoreComponentInstanceIdState } from '@/context-store/states import { useContext, useEffect } from 'react'; import { useSetRecoilState } from 'recoil'; -export const SetMainContextStoreComponentInstanceIdEffect = () => { +export const MainContextStoreComponentInstanceIdSetterEffect = () => { const setMainContextStoreComponentInstanceId = useSetRecoilState( mainContextStoreComponentInstanceIdState, ); diff --git a/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts b/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts index edc4e17336..5126ae272c 100644 --- a/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts +++ b/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts @@ -1,7 +1,7 @@ import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter'; -import { turnFiltersIntoQueryFilter } from '@/object-record/record-filter/utils/turnFiltersIntoQueryFilter'; +import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter'; import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables'; export const computeContextStoreFilters = ( @@ -12,9 +12,10 @@ export const computeContextStoreFilters = ( if (contextStoreTargetedRecordsRule.mode === 'exclusion') { queryFilter = makeAndFilterVariables([ - turnFiltersIntoQueryFilter( + computeViewRecordGqlOperationFilter( contextStoreTargetedRecordsRule.filters, objectMetadataItem?.fields ?? [], + [], ), contextStoreTargetedRecordsRule.excludedRecordIds.length > 0 ? { diff --git a/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts index 84cf2310c8..2cf9a03c54 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/__mocks__/useFavorites.ts @@ -85,238 +85,238 @@ export const mocks = [ mutation CreateOneFavorite($input: FavoriteCreateInput!) { createFavorite(data: $input) { __typename - company { - __typename - accountOwnerId - address { - addressStreet1 - addressStreet2 - addressCity - addressState - addressCountry - addressPostcode - addressLat - addressLng - } - annualRecurringRevenue { - amountMicros - currencyCode - } - createdAt - createdBy { - source + company { + __typename + accountOwnerId + address { + addressStreet1 + addressStreet2 + addressCity + addressState + addressCountry + addressPostcode + addressLat + addressLng + } + annualRecurringRevenue { + amountMicros + currencyCode + } + createdAt + createdBy { + source + workspaceMemberId + name + } + deletedAt + domainName { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + employees + id + idealCustomerProfile + introVideo { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + linkedinLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + name + position + tagline + updatedAt + visaSponsorship + workPolicy + xLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + } + companyId + createdAt + deletedAt + id + note { + __typename + body + createdAt + createdBy { + source + workspaceMemberId + name + } + deletedAt + id + position + title + updatedAt + } + noteId + opportunity { + __typename + amount { + amountMicros + currencyCode + } + closeDate + companyId + createdAt + createdBy { + source + workspaceMemberId + name + } + deletedAt + id + name + pointOfContactId + position + stage + updatedAt + } + opportunityId + person { + __typename + avatarUrl + city + companyId + createdAt + createdBy { + source + workspaceMemberId + name + } + deletedAt + emails { + primaryEmail + additionalEmails + } + id + intro + jobTitle + linkedinLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + name { + firstName + lastName + } + performanceRating + phones { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } + position + updatedAt + whatsapp { + primaryPhoneNumber + primaryPhoneCountryCode + additionalPhones + } + workPreference + xLink { + primaryLinkUrl + primaryLinkLabel + secondaryLinks + } + } + personId + position + rocket { + __typename + createdAt + createdBy { + source + workspaceMemberId + name + } + deletedAt + id + name + position + updatedAt + } + rocketId + task { + __typename + assigneeId + body + createdAt + createdBy { + source + workspaceMemberId + name + } + deletedAt + dueAt + id + position + status + title + updatedAt + } + taskId + updatedAt + view { + __typename + createdAt + deletedAt + icon + id + isCompact + kanbanFieldMetadataId + key + name + objectMetadataId + position + type + updatedAt + } + viewId + workflow { + __typename + createdAt + deletedAt + id + lastPublishedVersionId + name + position + statuses + updatedAt + } + workflowId + workspaceMember { + __typename + avatarUrl + colorScheme + createdAt + dateFormat + deletedAt + id + locale + name { + firstName + lastName + } + timeFormat + timeZone + updatedAt + userEmail + userId + } workspaceMemberId - name - } - deletedAt - domainName { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - employees - id - idealCustomerProfile - introVideo { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - linkedinLink { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - name - position - tagline - updatedAt - visaSponsorship - workPolicy - xLink { - primaryLinkUrl - primaryLinkLabel - secondaryLinks } } - companyId - createdAt - deletedAt - id - note { - __typename - body - createdAt - createdBy { - source - workspaceMemberId - name - } - deletedAt - id - position - title - updatedAt - } - noteId - opportunity { - __typename - amount { - amountMicros - currencyCode - } - closeDate - companyId - createdAt - createdBy { - source - workspaceMemberId - name - } - deletedAt - id - name - pointOfContactId - position - stage - updatedAt - } - opportunityId - person { - __typename - avatarUrl - city - companyId - createdAt - createdBy { - source - workspaceMemberId - name - } - deletedAt - emails { - primaryEmail - additionalEmails - } - id - intro - jobTitle - linkedinLink { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - name { - firstName - lastName - } - performanceRating - phones { - primaryPhoneNumber - primaryPhoneCountryCode - additionalPhones - } - position - updatedAt - whatsapp { - primaryPhoneNumber - primaryPhoneCountryCode - additionalPhones - } - workPreference - xLink { - primaryLinkUrl - primaryLinkLabel - secondaryLinks - } - } - personId - position - rocket { - __typename - createdAt - createdBy { - source - workspaceMemberId - name - } - deletedAt - id - name - position - updatedAt - } - rocketId - task { - __typename - assigneeId - body - createdAt - createdBy { - source - workspaceMemberId - name - } - deletedAt - dueAt - id - position - status - title - updatedAt - } - taskId - updatedAt - view { - __typename - createdAt - deletedAt - icon - id - isCompact - kanbanFieldMetadataId - key - name - objectMetadataId - position - type - updatedAt - } - viewId - workflow { - __typename - createdAt - deletedAt - id - lastPublishedVersionId - name - position - statuses - updatedAt - } - workflowId - workspaceMember { - __typename - avatarUrl - colorScheme - createdAt - dateFormat - deletedAt - id - locale - name { - firstName - lastName - } - timeFormat - timeZone - updatedAt - userEmail - userId - } - workspaceMemberId - } - } `, variables: { input: { diff --git a/packages/twenty-front/src/modules/localization/utils/__tests__/findAvailableTimeZoneOption.test.ts b/packages/twenty-front/src/modules/localization/utils/__tests__/findAvailableTimeZoneOption.test.ts index fa2bc25078..2199b3a104 100644 --- a/packages/twenty-front/src/modules/localization/utils/__tests__/findAvailableTimeZoneOption.test.ts +++ b/packages/twenty-front/src/modules/localization/utils/__tests__/findAvailableTimeZoneOption.test.ts @@ -3,13 +3,18 @@ import { findAvailableTimeZoneOption } from '@/localization/utils/findAvailableT describe('findAvailableTimeZoneOption', () => { it('should find the matching available IANA time zone select option from a given IANA time zone', () => { const ianaTimeZone = 'Europe/Paris'; - const expectedOption = { - label: '(GMT+02:00) Central European Summer Time - Paris', - value: 'Europe/Paris', - }; + const expectedValue = 'Europe/Paris'; + const expectedLabelWinter = + '(GMT+01:00) Central European Standard Time - Paris'; + const expectedLabelSummer = + '(GMT+02:00) Central European Summer Time - Paris'; const option = findAvailableTimeZoneOption(ianaTimeZone); - expect(option).toEqual(expectedOption); + expect(option.value).toEqual(expectedValue); + expect( + expectedLabelWinter === option.label || + expectedLabelSummer === option.label, + ).toBeTruthy(); }); }); diff --git a/packages/twenty-front/src/modules/localization/utils/__tests__/formatTimeZoneLabel.test.ts b/packages/twenty-front/src/modules/localization/utils/__tests__/formatTimeZoneLabel.test.ts index bec60cc4e0..64d53d8980 100644 --- a/packages/twenty-front/src/modules/localization/utils/__tests__/formatTimeZoneLabel.test.ts +++ b/packages/twenty-front/src/modules/localization/utils/__tests__/formatTimeZoneLabel.test.ts @@ -3,11 +3,17 @@ import { formatTimeZoneLabel } from '@/localization/utils/formatTimeZoneLabel'; describe('formatTimeZoneLabel', () => { it('should format the time zone label correctly when location is included in the label', () => { const ianaTimeZone = 'Europe/Paris'; - const expectedLabel = '(GMT+02:00) Central European Summer Time - Paris'; + const expectedLabelSummer = + '(GMT+02:00) Central European Summer Time - Paris'; + const expectedLabelWinter = + '(GMT+01:00) Central European Standard Time - Paris'; const formattedLabel = formatTimeZoneLabel(ianaTimeZone); - expect(formattedLabel).toEqual(expectedLabel); + expect( + expectedLabelSummer === formattedLabel || + expectedLabelWinter === formattedLabel, + ).toBeTruthy(); }); it('should format the time zone label correctly when location is not included in the label', () => { diff --git a/packages/twenty-front/src/modules/navigation/components/__stories__/AppNavigationDrawer.stories.tsx b/packages/twenty-front/src/modules/navigation/components/__stories__/AppNavigationDrawer.stories.tsx index 3bb6f1acaf..b7db0bd263 100644 --- a/packages/twenty-front/src/modules/navigation/components/__stories__/AppNavigationDrawer.stories.tsx +++ b/packages/twenty-front/src/modules/navigation/components/__stories__/AppNavigationDrawer.stories.tsx @@ -4,13 +4,12 @@ import { MemoryRouter } from 'react-router-dom'; import { useSetRecoilState } from 'recoil'; import { currentMobileNavigationDrawerState } from '@/navigation/states/currentMobileNavigationDrawerState'; -import { AppPath } from '@/types/AppPath'; - import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator'; import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator'; import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; +import { AppPath } from '@/types/AppPath'; import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded'; import { AppNavigationDrawer, diff --git a/packages/twenty-front/src/modules/navigation/utils/__tests__/indexAppPath.test.ts b/packages/twenty-front/src/modules/navigation/utils/__tests__/indexAppPath.test.ts index 8920f6fa74..294dd6a5fc 100644 --- a/packages/twenty-front/src/modules/navigation/utils/__tests__/indexAppPath.test.ts +++ b/packages/twenty-front/src/modules/navigation/utils/__tests__/indexAppPath.test.ts @@ -1,5 +1,4 @@ import { AppPath } from '@/types/AppPath'; - import indexAppPath from '../indexAppPath'; describe('getIndexAppPath', () => { diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx index 8c7f1e3ced..e4602fa0c5 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx @@ -43,8 +43,7 @@ export const NavigationDrawerItemForObjectMetadataItem = ({ const shouldSubItemsBeDisplayed = isActive && objectMetadataViews.length > 1; const sortedObjectMetadataViews = [...objectMetadataViews].sort( - (viewA, viewB) => - viewA.key === 'INDEX' ? -1 : viewA.position - viewB.position, + (viewA, viewB) => viewA.position - viewB.position, ); const selectedSubItemIndex = sortedObjectMetadataViews.findIndex( diff --git a/packages/twenty-front/src/modules/object-metadata/graphql/queries.ts b/packages/twenty-front/src/modules/object-metadata/graphql/queries.ts index 7a6a79265b..2faa56fa52 100644 --- a/packages/twenty-front/src/modules/object-metadata/graphql/queries.ts +++ b/packages/twenty-front/src/modules/object-metadata/graphql/queries.ts @@ -24,7 +24,8 @@ export const FIND_MANY_OBJECT_METADATA_ITEMS = gql` updatedAt labelIdentifierFieldMetadataId imageIdentifierFieldMetadataId - shouldSyncLabelAndName + shortcut + isLabelSyncedWithName indexMetadatas(paging: { first: 100 }) { edges { node { diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useDeleteOneRelationMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useDeleteOneRelationMetadataItem.ts index eb439e70f9..92570c3711 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useDeleteOneRelationMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useDeleteOneRelationMetadataItem.ts @@ -11,5 +11,5 @@ export const query = gql` export const variables = { idToDelete: 'idToDelete' }; export const responseData = { - id: 'idToDelete' + id: 'idToDelete', }; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts index 0e7470a103..b33c4dc1d5 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFieldMetadataItem.ts @@ -2,7 +2,8 @@ import { gql } from '@apollo/client'; import { FieldMetadataType } from '~/generated/graphql'; export const FIELD_METADATA_ID = '2c43466a-fe9e-4005-8d08-c5836067aa6c'; -export const FIELD_RELATION_METADATA_ID = '4da0302d-358a-45cd-9973-9f92723ed3c1'; +export const FIELD_RELATION_METADATA_ID = + '4da0302d-358a-45cd-9973-9f92723ed3c1'; export const RELATION_METADATA_ID = 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6'; const baseFields = ` @@ -29,12 +30,12 @@ export const queries = { } `, deleteMetadataFieldRelation: gql` - mutation DeleteOneRelationMetadataItem($idToDelete: UUID!) { - deleteOneRelation(input: { id: $idToDelete }) { - id + mutation DeleteOneRelationMetadataItem($idToDelete: UUID!) { + deleteOneRelation(input: { id: $idToDelete }) { + id + } } - } -`, + `, activateMetadataField: gql` mutation UpdateOneFieldMetadataItem( $idToUpdate: UUID! @@ -94,7 +95,7 @@ export const variables = { deactivateMetadataField: { idToUpdate: FIELD_METADATA_ID, updatePayload: { isActive: false, label: undefined }, - } + }, }; const defaultResponseData = { @@ -127,4 +128,3 @@ export const responseData = { options: [], }, }; - diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFindManyObjectMetadataItems.ts b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFindManyObjectMetadataItems.ts index c9324a846f..3b541a9d6c 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFindManyObjectMetadataItems.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__mocks__/useFindManyObjectMetadataItems.ts @@ -24,6 +24,8 @@ export const query = gql` updatedAt labelIdentifierFieldMetadataId imageIdentifierFieldMetadataId + shortcut + isLabelSyncedWithName fields(paging: { first: 1000 }, filter: $fieldFilter) { edges { node { diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromFieldMetadata.test.ts b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromFieldMetadata.test.ts index 13f5bec9a5..2205cd82af 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromFieldMetadata.test.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromFieldMetadata.test.ts @@ -16,6 +16,7 @@ const Wrapper = getJestMetadataAndApolloMocksWrapper({ featureFlags: [], allowImpersonation: false, activationStatus: WorkspaceActivationStatus.Active, + hasValidEntrepriseKey: false, metadataVersion: 1, isPublicInviteLinkEnabled: false, }); diff --git a/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts b/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts index 8ac533f76a..bf872fafbc 100644 --- a/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts +++ b/packages/twenty-front/src/modules/object-metadata/types/CoreObjectNameSingular.ts @@ -24,7 +24,9 @@ export enum CoreObjectNameSingular { View = 'view', ViewField = 'viewField', ViewFilter = 'viewFilter', + ViewFilterGroup = 'viewFilterGroup', ViewSort = 'viewSort', + ViewGroup = 'viewGroup', Webhook = 'webhook', WorkspaceMember = 'workspaceMember', MessageThreadSubscriber = 'messageThreadSubscriber', diff --git a/packages/twenty-front/src/modules/object-metadata/validation-schemas/__tests__/objectMetadataItemSchema.test.ts b/packages/twenty-front/src/modules/object-metadata/validation-schemas/__tests__/objectMetadataItemSchema.test.ts index 7fc130833b..64e513214f 100644 --- a/packages/twenty-front/src/modules/object-metadata/validation-schemas/__tests__/objectMetadataItemSchema.test.ts +++ b/packages/twenty-front/src/modules/object-metadata/validation-schemas/__tests__/objectMetadataItemSchema.test.ts @@ -30,7 +30,7 @@ describe('objectMetadataItemSchema', () => { namePlural: 'notCamelCase', nameSingular: 'notCamelCase', updatedAt: 'invalid date', - shouldSyncLabelAndName: 'not a boolean', + isLabelSyncedWithName: 'not a boolean', }; // When diff --git a/packages/twenty-front/src/modules/object-metadata/validation-schemas/objectMetadataItemSchema.ts b/packages/twenty-front/src/modules/object-metadata/validation-schemas/objectMetadataItemSchema.ts index 38ce3cbd1e..1c40e62586 100644 --- a/packages/twenty-front/src/modules/object-metadata/validation-schemas/objectMetadataItemSchema.ts +++ b/packages/twenty-front/src/modules/object-metadata/validation-schemas/objectMetadataItemSchema.ts @@ -26,5 +26,6 @@ export const objectMetadataItemSchema = z.object({ namePlural: camelCaseStringSchema, nameSingular: camelCaseStringSchema, updatedAt: z.string().datetime(), - shouldSyncLabelAndName: z.boolean(), + shortcut: z.string().nullable().optional(), + isLabelSyncedWithName: z.boolean(), }) satisfies z.ZodType; diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx new file mode 100644 index 0000000000..2e82b72fc8 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx @@ -0,0 +1,161 @@ +import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById'; +import { useUpsertCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useUpsertCombinedViewFilterGroup'; +import { getOperandsForFilterDefinition } from '@/object-record/object-filter-dropdown/utils/getOperandsForFilterType'; +import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; +import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; +import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; +import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId'; +import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; +import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters'; +import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState'; +import { ViewFilterGroup } from '@/views/types/ViewFilterGroup'; +import { ViewFilterGroupLogicalOperator } from '@/views/types/ViewFilterGroupLogicalOperator'; +import { useCallback } from 'react'; +import { IconLibraryPlus, IconPlus, isDefined, LightButton } from 'twenty-ui'; +import { v4 } from 'uuid'; + +type AdvancedFilterAddFilterRuleSelectProps = { + viewFilterGroup: ViewFilterGroup; + lastChildPosition?: number; +}; + +export const AdvancedFilterAddFilterRuleSelect = ({ + viewFilterGroup, + lastChildPosition = 0, +}: AdvancedFilterAddFilterRuleSelectProps) => { + const dropdownId = `advanced-filter-add-filter-rule-${viewFilterGroup.id}`; + + const { currentViewId } = useGetCurrentView(); + + const { upsertCombinedViewFilterGroup } = useUpsertCombinedViewFilterGroup(); + const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(); + + const newPositionInViewFilterGroup = lastChildPosition + 1; + + const { closeDropdown } = useDropdown(dropdownId); + + const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(); + + const objectMetadataId = + currentViewWithCombinedFiltersAndSorts?.objectMetadataId; + + if (!objectMetadataId) { + throw new Error('Object metadata id is missing from current view'); + } + + const { objectMetadataItem } = useObjectMetadataItemById({ + objectId: objectMetadataId, + }); + + const availableFilterDefinitions = useRecoilComponentValueV2( + availableFilterDefinitionsComponentState, + ); + + const getDefaultFilterDefinition = useCallback(() => { + const defaultFilterDefinition = + availableFilterDefinitions.find( + (filterDefinition) => + filterDefinition.fieldMetadataId === + objectMetadataItem?.labelIdentifierFieldMetadataId, + ) ?? availableFilterDefinitions?.[0]; + + if (!defaultFilterDefinition) { + throw new Error('Missing default filter definition'); + } + + return defaultFilterDefinition; + }, [availableFilterDefinitions, objectMetadataItem]); + + const handleAddFilter = () => { + closeDropdown(); + + const defaultFilterDefinition = getDefaultFilterDefinition(); + + upsertCombinedViewFilter({ + id: v4(), + fieldMetadataId: defaultFilterDefinition.fieldMetadataId, + operand: getOperandsForFilterDefinition(defaultFilterDefinition)[0], + definition: defaultFilterDefinition, + value: '', + displayValue: '', + viewFilterGroupId: viewFilterGroup.id, + positionInViewFilterGroup: newPositionInViewFilterGroup, + }); + }; + + const handleAddFilterGroup = () => { + closeDropdown(); + + if (!currentViewId) { + throw new Error('Missing view id'); + } + + const newViewFilterGroup = { + id: v4(), + viewId: currentViewId, + logicalOperator: ViewFilterGroupLogicalOperator.AND, + parentViewFilterGroupId: viewFilterGroup.id, + positionInViewFilterGroup: newPositionInViewFilterGroup, + }; + + upsertCombinedViewFilterGroup(newViewFilterGroup); + + const defaultFilterDefinition = getDefaultFilterDefinition(); + + upsertCombinedViewFilter({ + id: v4(), + fieldMetadataId: defaultFilterDefinition.fieldMetadataId, + operand: getOperandsForFilterDefinition(defaultFilterDefinition)[0], + definition: defaultFilterDefinition, + value: '', + displayValue: '', + viewFilterGroupId: newViewFilterGroup.id, + positionInViewFilterGroup: newPositionInViewFilterGroup, + }); + }; + + const isFilterRuleGroupOptionVisible = !isDefined( + viewFilterGroup.parentViewFilterGroupId, + ); + + if (!isFilterRuleGroupOptionVisible) { + return ( + + ); + } + + return ( + + } + dropdownComponents={ + + + {isFilterRuleGroupOptionVisible && ( + + )} + + } + dropdownHotkeyScope={{ scope: ADVANCED_FILTER_DROPDOWN_ID }} + dropdownOffset={{ y: 8, x: 0 }} + dropdownPlacement="bottom-start" + /> + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterLogicalOperatorCell.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterLogicalOperatorCell.tsx new file mode 100644 index 0000000000..b4e7055067 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterLogicalOperatorCell.tsx @@ -0,0 +1,41 @@ +import { AdvancedFilterLogicalOperatorDropdown } from '@/object-record/advanced-filter/components/AdvancedFilterLogicalOperatorDropdown'; +import { ViewFilterGroup } from '@/views/types/ViewFilterGroup'; +import styled from '@emotion/styled'; +import { capitalize } from '~/utils/string/capitalize'; + +const StyledText = styled.div` + height: ${({ theme }) => theme.spacing(8)}; + display: flex; + align-items: center; +`; + +const StyledContainer = styled.div` + align-items: start; + display: flex; + min-width: ${({ theme }) => theme.spacing(20)}; + color: ${({ theme }) => theme.font.color.tertiary}; +`; + +type AdvancedFilterLogicalOperatorCellProps = { + index: number; + viewFilterGroup: ViewFilterGroup; +}; + +export const AdvancedFilterLogicalOperatorCell = ({ + index, + viewFilterGroup, +}: AdvancedFilterLogicalOperatorCellProps) => ( + + {index === 0 ? ( + Where + ) : index === 1 ? ( + + ) : ( + + {capitalize(viewFilterGroup.logicalOperator.toLowerCase())} + + )} + +); diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterLogicalOperatorDropdown.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterLogicalOperatorDropdown.tsx new file mode 100644 index 0000000000..68fa9f8763 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterLogicalOperatorDropdown.tsx @@ -0,0 +1,33 @@ +import { ADVANCED_FILTER_LOGICAL_OPERATOR_OPTIONS } from '@/object-record/advanced-filter/constants/AdvancedFilterLogicalOperatorOptions'; +import { useUpsertCombinedViewFilterGroup } from '@/object-record/advanced-filter/hooks/useUpsertCombinedViewFilterGroup'; +import { Select } from '@/ui/input/components/Select'; +import { ViewFilterGroup } from '@/views/types/ViewFilterGroup'; +import { ViewFilterGroupLogicalOperator } from '@/views/types/ViewFilterGroupLogicalOperator'; + +type AdvancedFilterLogicalOperatorDropdownProps = { + viewFilterGroup: ViewFilterGroup; +}; + +export const AdvancedFilterLogicalOperatorDropdown = ({ + viewFilterGroup, +}: AdvancedFilterLogicalOperatorDropdownProps) => { + const { upsertCombinedViewFilterGroup } = useUpsertCombinedViewFilterGroup(); + + const handleChange = (value: ViewFilterGroupLogicalOperator) => { + upsertCombinedViewFilterGroup({ + ...viewFilterGroup, + logicalOperator: value, + }); + }; + + return ( + - triggerGoogleApisOAuth({ redirectLocation: redirectUrl }), - Icon: IconPlus, - text: 'Add account', - }} - onChange={(connectedAccountId) => { - field.onChange(connectedAccountId); - handleSave(true); - }} - /> - )} - /> - ( - { - field.onChange(email); - handleSave(); - }} - /> - )} - /> - ( - { - field.onChange(email); - handleSave(); - }} - /> - )} - /> - - ( -