Compare commits
40
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60a203b371 | ||
|
|
79529a7a26 | ||
|
|
3c3a4daeb2 | ||
|
|
6926aa3c25 | ||
|
|
ad15eb371b | ||
|
|
0d46d98943 | ||
|
|
c206e2eee0 | ||
|
|
3bc887e12e | ||
|
|
d060c843d1 | ||
|
|
175df59c21 | ||
|
|
6ad581d178 | ||
|
|
712b1553bd | ||
|
|
cc1145c701 | ||
|
|
726b1373d9 | ||
|
|
783e57f5d8 | ||
|
|
163254baef | ||
|
|
aaa6511007 | ||
|
|
2a670520b9 | ||
|
|
10bd005021 | ||
|
|
0e25aeb5be | ||
|
|
e051cce24f | ||
|
|
bd03073b6d | ||
|
|
b3d8f8813f | ||
|
|
37d9828458 | ||
|
|
e16b6d6485 | ||
|
|
9626c7ce02 | ||
|
|
754de411fe | ||
|
|
530f74e28c | ||
|
|
5a46cf7bd3 | ||
|
|
7b10202c69 | ||
|
|
9e54a8082c | ||
|
|
1a13258302 | ||
|
|
c0ea049ad7 | ||
|
|
b33f86fbf5 | ||
|
|
88424611ec | ||
|
|
082400f751 | ||
|
|
a14b0ab6ca | ||
|
|
6e29f66ce8 | ||
|
|
9bcc2fc5d9 | ||
|
|
01e203a70b |
@@ -202,14 +202,6 @@ jobs:
|
||||
with:
|
||||
tag: scope:frontend
|
||||
tasks: ${{ matrix.task }}
|
||||
- name: Check for coverage threshold failure
|
||||
if: always() && steps.run-task.outcome == 'failure' && matrix.task == 'test'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::error::The test task failed. If no individual test is failing, this is likely a coverage threshold not being met."
|
||||
echo ""
|
||||
echo "To debug locally, run: npx nx run twenty-front:test:ci"
|
||||
exit 1
|
||||
- name: Save ${{ matrix.task }} cache
|
||||
uses: ./.github/actions/save-cache
|
||||
with:
|
||||
|
||||
+4
-4
@@ -91,10 +91,10 @@
|
||||
"@storybook/react-vite": "^10.1.11",
|
||||
"@storybook/test-runner": "^0.24.2",
|
||||
"@stylistic/eslint-plugin": "^1.5.0",
|
||||
"@swc-node/register": "1.8.0",
|
||||
"@swc-node/register": "1.11.1",
|
||||
"@swc/cli": "^0.3.12",
|
||||
"@swc/core": "1.13.3",
|
||||
"@swc/helpers": "~0.5.2",
|
||||
"@swc/core": "1.15.11",
|
||||
"@swc/helpers": "~0.5.18",
|
||||
"@swc/jest": "^0.2.39",
|
||||
"@testing-library/dom": "^10.4.0",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
@@ -137,7 +137,7 @@
|
||||
"@typescript-eslint/parser": "^8.39.0",
|
||||
"@typescript-eslint/utils": "^8.39.0",
|
||||
"@typescript/native-preview": "^7.0.0-dev.20260116.1",
|
||||
"@vitejs/plugin-react-swc": "3.11.0",
|
||||
"@vitejs/plugin-react-swc": "4.2.3",
|
||||
"@vitest/browser-playwright": "^4.0.18",
|
||||
"@vitest/coverage-istanbul": "^4.0.18",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
|
||||
@@ -89,6 +89,7 @@ In interactive mode, you can pick from:
|
||||
- **Example front component** — a React UI component (`front-components/hello-world.tsx`)
|
||||
- **Example view** — a saved view for the example object (`views/example-view.ts`)
|
||||
- **Example navigation menu item** — a sidebar link (`navigation-menu-items/example-navigation-menu-item.ts`)
|
||||
- **Example skill** — an AI agent skill definition (`skills/example-skill.ts`)
|
||||
|
||||
## What gets scaffolded
|
||||
|
||||
@@ -106,11 +107,12 @@ In interactive mode, you can pick from:
|
||||
- `front-components/hello-world.tsx` — Example front component
|
||||
- `views/example-view.ts` — Example saved view for the example object
|
||||
- `navigation-menu-items/example-navigation-menu-item.ts` — Example sidebar navigation link
|
||||
- `skills/example-skill.ts` — Example AI agent skill definition
|
||||
|
||||
## Next steps
|
||||
- Run `yarn twenty help` to see all available commands.
|
||||
- Use `yarn twenty auth:login` to authenticate with your Twenty workspace.
|
||||
- Explore the generated project and add your first entity with `yarn twenty entity:add` (logic functions, front components, objects, roles, views, navigation menu items).
|
||||
- Explore the generated project and add your first entity with `yarn twenty entity:add` (logic functions, front components, objects, roles, views, navigation menu items, skills).
|
||||
- Use `yarn twenty app:dev` while you iterate — it watches, builds, and syncs changes to your workspace in real time.
|
||||
- Types are auto‑generated by `yarn twenty app:dev` and stored in `node_modules/twenty-sdk/generated`.
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
## Base documentation
|
||||
|
||||
- Documentation: https://docs.twenty.com/developers/extend/capabilities/apps
|
||||
- Rich app example: https://github.com/twentyhq/twenty/tree/main/packages/twenty-sdk/src/cli/__tests__/apps/rich-app
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
- Creating an object without an index view associated. Unless this is a technical object, user will need to visualize it.
|
||||
- Creating a view without a navigationMenuItem associated. This will make the view available on the left sidebar.
|
||||
@@ -36,6 +36,10 @@ yarn twenty function:execute # Execute a function with JSON payload
|
||||
yarn twenty app:uninstall # Uninstall app from workspace
|
||||
```
|
||||
|
||||
## LLMs instructions
|
||||
|
||||
Main docs and pitfalls are available in LLMS.md file.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Twenty applications, take a look at the following resources:
|
||||
|
||||
@@ -114,6 +114,7 @@ export class CreateAppCommand {
|
||||
includeExampleFrontComponent: false,
|
||||
includeExampleView: false,
|
||||
includeExampleNavigationMenuItem: false,
|
||||
includeExampleSkill: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -125,6 +126,7 @@ export class CreateAppCommand {
|
||||
includeExampleFrontComponent: true,
|
||||
includeExampleView: true,
|
||||
includeExampleNavigationMenuItem: true,
|
||||
includeExampleSkill: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -164,6 +166,11 @@ export class CreateAppCommand {
|
||||
value: 'navigationMenuItem',
|
||||
checked: true,
|
||||
},
|
||||
{
|
||||
name: 'Example skill (AI agent skill definition)',
|
||||
value: 'skill',
|
||||
checked: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -189,6 +196,7 @@ export class CreateAppCommand {
|
||||
includeExampleView: includeView,
|
||||
includeExampleNavigationMenuItem:
|
||||
selectedExamples.includes('navigationMenuItem'),
|
||||
includeExampleSkill: selectedExamples.includes('skill'),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,4 +7,5 @@ export type ExampleOptions = {
|
||||
includeExampleFrontComponent: boolean;
|
||||
includeExampleView: boolean;
|
||||
includeExampleNavigationMenuItem: boolean;
|
||||
includeExampleSkill: boolean;
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
import { tmpdir } from 'os';
|
||||
import { copyBaseApplicationProject } from '@/utils/app-template';
|
||||
import { type ExampleOptions } from '@/types/scaffolding-options';
|
||||
import { GENERATED_DIR } from 'twenty-shared/application';
|
||||
import { copyBaseApplicationProject } from '@/utils/app-template';
|
||||
import * as fs from 'fs-extra';
|
||||
import { tmpdir } from 'os';
|
||||
import { join } from 'path';
|
||||
|
||||
// Mock fs-extra's copy function to skip copying base template (not available during tests)
|
||||
jest.mock('fs-extra', () => {
|
||||
@@ -23,11 +24,13 @@ const ALL_EXAMPLES: ExampleOptions = {
|
||||
includeExampleFrontComponent: true,
|
||||
includeExampleView: true,
|
||||
includeExampleNavigationMenuItem: true,
|
||||
includeExampleSkill: true,
|
||||
};
|
||||
|
||||
const NO_EXAMPLES: ExampleOptions = {
|
||||
includeExampleObject: false,
|
||||
includeExampleField: false,
|
||||
includeExampleSkill: false,
|
||||
includeExampleLogicFunction: false,
|
||||
includeExampleFrontComponent: false,
|
||||
includeExampleView: false,
|
||||
@@ -109,7 +112,7 @@ describe('copyBaseApplicationProject', () => {
|
||||
|
||||
const gitignoreContent = await fs.readFile(gitignorePath, 'utf8');
|
||||
expect(gitignoreContent).toContain('/node_modules');
|
||||
expect(gitignoreContent).toContain('generated');
|
||||
expect(gitignoreContent).toContain(GENERATED_DIR);
|
||||
});
|
||||
|
||||
it('should create yarn.lock file', async () => {
|
||||
@@ -437,6 +440,7 @@ describe('copyBaseApplicationProject', () => {
|
||||
exampleOptions: {
|
||||
includeExampleObject: false,
|
||||
includeExampleField: false,
|
||||
includeExampleSkill: false,
|
||||
includeExampleLogicFunction: false,
|
||||
includeExampleFrontComponent: true,
|
||||
includeExampleView: false,
|
||||
@@ -472,6 +476,7 @@ describe('copyBaseApplicationProject', () => {
|
||||
appDirectory: testAppDirectory,
|
||||
exampleOptions: {
|
||||
includeExampleObject: false,
|
||||
includeExampleSkill: false,
|
||||
includeExampleField: false,
|
||||
includeExampleLogicFunction: true,
|
||||
includeExampleFrontComponent: false,
|
||||
|
||||
@@ -89,6 +89,14 @@ export const copyBaseApplicationProject = async ({
|
||||
});
|
||||
}
|
||||
|
||||
if (exampleOptions.includeExampleSkill) {
|
||||
await createExampleSkill({
|
||||
appDirectory: sourceFolderPath,
|
||||
fileFolder: 'skills',
|
||||
fileName: 'example-skill.ts',
|
||||
});
|
||||
}
|
||||
|
||||
await createDefaultPostInstallFunction({
|
||||
appDirectory: sourceFolderPath,
|
||||
fileFolder: 'logic-functions',
|
||||
@@ -424,6 +432,36 @@ export default defineNavigationMenuItem({
|
||||
await fs.writeFile(join(appDirectory, fileFolder ?? '', fileName), content);
|
||||
};
|
||||
|
||||
const createExampleSkill = async ({
|
||||
appDirectory,
|
||||
fileFolder,
|
||||
fileName,
|
||||
}: {
|
||||
appDirectory: string;
|
||||
fileFolder?: string;
|
||||
fileName: string;
|
||||
}) => {
|
||||
const universalIdentifier = v4();
|
||||
|
||||
const content = `import { defineSkill } from 'twenty-sdk';
|
||||
|
||||
export const EXAMPLE_SKILL_UNIVERSAL_IDENTIFIER =
|
||||
'${universalIdentifier}';
|
||||
|
||||
export default defineSkill({
|
||||
universalIdentifier: EXAMPLE_SKILL_UNIVERSAL_IDENTIFIER,
|
||||
name: 'example-skill',
|
||||
label: 'Example Skill',
|
||||
description: 'A sample skill for your application',
|
||||
icon: 'IconBrain',
|
||||
content: 'Add your skill instructions here. Skills provide context and capabilities to AI agents.',
|
||||
});
|
||||
`;
|
||||
|
||||
await fs.ensureDir(join(appDirectory, fileFolder ?? ''));
|
||||
await fs.writeFile(join(appDirectory, fileFolder ?? '', fileName), content);
|
||||
};
|
||||
|
||||
const createApplicationConfig = async ({
|
||||
displayName,
|
||||
description,
|
||||
|
||||
@@ -14,6 +14,7 @@ Apps let you build and manage Twenty customizations **as code**. Instead of conf
|
||||
**What you can do today:**
|
||||
- Define custom objects and fields as code (managed data model)
|
||||
- Build logic functions with custom triggers
|
||||
- Define skills for AI agents
|
||||
- Deploy the same app across multiple workspaces
|
||||
|
||||
## Prerequisites
|
||||
@@ -44,7 +45,7 @@ yarn twenty app:dev
|
||||
The scaffolder supports three modes for controlling which example files are included:
|
||||
|
||||
```bash filename="Terminal"
|
||||
# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item)
|
||||
# Default (exhaustive): all examples (object, field, logic function, front component, view, navigation menu item, skill)
|
||||
npx create-twenty-app@latest my-app
|
||||
|
||||
# Minimal: only core files (application-config.ts and default-role.ts)
|
||||
@@ -117,8 +118,10 @@ my-twenty-app/
|
||||
│ └── hello-world.tsx # Example front component
|
||||
├── views/
|
||||
│ └── example-view.ts # Example saved view definition
|
||||
└── navigation-menu-items/
|
||||
└── example-navigation-menu-item.ts # Example sidebar navigation link
|
||||
├── navigation-menu-items/
|
||||
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
|
||||
└── skills/
|
||||
└── example-skill.ts # Example AI agent skill definition
|
||||
```
|
||||
|
||||
With `--minimal`, only the core files are created (`application-config.ts`, `roles/default-role.ts`, and `logic-functions/post-install.ts`). With `--interactive`, you choose which example files to include.
|
||||
@@ -147,6 +150,7 @@ The SDK detects entities by parsing your TypeScript files for **`export default
|
||||
| `defineField()` | Field extensions for existing objects |
|
||||
| `defineView()` | Saved view definitions |
|
||||
| `defineNavigationMenuItem()` | Navigation menu item definitions |
|
||||
| `defineSkill()` | AI agent skill definitions |
|
||||
|
||||
<Note>
|
||||
**File naming is flexible.** Entity detection is AST-based — the SDK scans your source files for the `export default define<Entity>({...})` pattern. You can organize your files and folders however you like. Grouping by entity type (e.g., `logic-functions/`, `roles/`) is just a convention for code organization, not a requirement.
|
||||
@@ -167,7 +171,7 @@ export default defineObject({
|
||||
Later commands will add more files and folders:
|
||||
|
||||
- `yarn twenty app:dev` will auto-generate a typed API client in `node_modules/twenty-sdk/generated` (typed Twenty client + workspace types).
|
||||
- `yarn twenty entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, or roles.
|
||||
- `yarn twenty entity:add` will add entity definition files under `src/` for your custom objects, functions, front components, roles, skills, and more.
|
||||
|
||||
## Authentication
|
||||
|
||||
@@ -220,6 +224,7 @@ The SDK provides helper functions for defining your app entities. As described i
|
||||
| `defineField()` | Extend existing objects with additional fields |
|
||||
| `defineView()` | Define saved views for objects |
|
||||
| `defineNavigationMenuItem()` | Define sidebar navigation links |
|
||||
| `defineSkill()` | Define AI agent skills |
|
||||
|
||||
These functions validate your configuration at build time and provide IDE autocompletion and type safety.
|
||||
|
||||
@@ -729,6 +734,40 @@ You can create new front components in two ways:
|
||||
- **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new front component.
|
||||
- **Manual**: Create a new `*.front-component.tsx` file and use `defineFrontComponent()`.
|
||||
|
||||
### Skills
|
||||
|
||||
Skills define reusable instructions and capabilities that AI agents can use within your workspace. Use `defineSkill()` to define skills with built-in validation:
|
||||
|
||||
```typescript
|
||||
// src/skills/example-skill.ts
|
||||
import { defineSkill } from 'twenty-sdk';
|
||||
|
||||
export default defineSkill({
|
||||
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
||||
name: 'sales-outreach',
|
||||
label: 'Sales Outreach',
|
||||
description: 'Guides the AI agent through a structured sales outreach process',
|
||||
icon: 'IconBrain',
|
||||
content: `You are a sales outreach assistant. When reaching out to a prospect:
|
||||
1. Research the company and recent news
|
||||
2. Identify the prospect's role and likely pain points
|
||||
3. Draft a personalized message referencing specific details
|
||||
4. Keep the tone professional but conversational`,
|
||||
});
|
||||
```
|
||||
|
||||
Key points:
|
||||
- `name` is a unique identifier string for the skill (kebab-case recommended).
|
||||
- `label` is the human-readable display name shown in the UI.
|
||||
- `content` contains the skill instructions — this is the text the AI agent uses.
|
||||
- `icon` (optional) sets the icon displayed in the UI.
|
||||
- `description` (optional) provides additional context about the skill's purpose.
|
||||
|
||||
You can create new skills in two ways:
|
||||
|
||||
- **Scaffolded**: Run `yarn twenty entity:add` and choose the option to add a new skill.
|
||||
- **Manual**: Create a new file and use `defineSkill()`, following the same pattern.
|
||||
|
||||
### Generated typed client
|
||||
|
||||
The typed client is auto-generated by `yarn twenty app:dev` and stored in `node_modules/twenty-sdk/generated` based on your workspace schema. Use it in your functions:
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lingui/cli": "^5.1.2",
|
||||
"@lingui/swc-plugin": "^5.6.0",
|
||||
"@lingui/swc-plugin": "^5.11.0",
|
||||
"@lingui/vite-plugin": "^5.1.2",
|
||||
"@react-email/preview-server": "5.1.0",
|
||||
"@tiptap/core": "^3.4.2",
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lingui/cli": "^5.1.2",
|
||||
"@lingui/swc-plugin": "^5.6.0",
|
||||
"@lingui/swc-plugin": "^5.11.0",
|
||||
"@lingui/vite-plugin": "^5.1.2",
|
||||
"@playwright/test": "^1.56.1",
|
||||
"@tiptap/suggestion": "3.4.2",
|
||||
|
||||
@@ -1045,7 +1045,7 @@ export type CreateNavigationMenuItemInput = {
|
||||
icon?: InputMaybe<Scalars['String']>;
|
||||
link?: InputMaybe<Scalars['String']>;
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
position?: InputMaybe<Scalars['Int']>;
|
||||
position?: InputMaybe<Scalars['Float']>;
|
||||
targetObjectMetadataId?: InputMaybe<Scalars['UUID']>;
|
||||
targetRecordId?: InputMaybe<Scalars['UUID']>;
|
||||
userWorkspaceId?: InputMaybe<Scalars['UUID']>;
|
||||
@@ -1494,7 +1494,6 @@ export enum FeatureFlagKey {
|
||||
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
|
||||
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED = 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED',
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED',
|
||||
IS_SSE_DB_EVENTS_ENABLED = 'IS_SSE_DB_EVENTS_ENABLED',
|
||||
IS_TASK_TARGET_MIGRATED = 'IS_TASK_TARGET_MIGRATED',
|
||||
IS_UNIQUE_INDEXES_ENABLED = 'IS_UNIQUE_INDEXES_ENABLED'
|
||||
}
|
||||
@@ -3378,6 +3377,12 @@ export type ObjectPermissionInput = {
|
||||
objectMetadataId: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type ObjectRecordCount = {
|
||||
__typename?: 'ObjectRecordCount';
|
||||
objectNamePlural: Scalars['String'];
|
||||
totalCount: Scalars['Int'];
|
||||
};
|
||||
|
||||
export type ObjectRecordEvent = {
|
||||
__typename?: 'ObjectRecordEvent';
|
||||
action: DatabaseEventAction;
|
||||
@@ -3751,6 +3756,7 @@ export type Query = {
|
||||
navigationMenuItem?: Maybe<NavigationMenuItem>;
|
||||
navigationMenuItems: Array<NavigationMenuItem>;
|
||||
object: Object;
|
||||
objectRecordCounts: Array<ObjectRecordCount>;
|
||||
objects: ObjectConnection;
|
||||
pieChartData: PieChartDataOutput;
|
||||
skill?: Maybe<Skill>;
|
||||
@@ -4563,13 +4569,11 @@ export type UpdateLogicFunctionFromSourceInput = {
|
||||
};
|
||||
|
||||
export type UpdateLogicFunctionFromSourceInputUpdates = {
|
||||
checksum?: InputMaybe<Scalars['String']>;
|
||||
cronTriggerSettings?: InputMaybe<Scalars['JSON']>;
|
||||
databaseEventTriggerSettings?: InputMaybe<Scalars['JSON']>;
|
||||
description?: InputMaybe<Scalars['String']>;
|
||||
handlerName?: InputMaybe<Scalars['String']>;
|
||||
httpRouteTriggerSettings?: InputMaybe<Scalars['JSON']>;
|
||||
isBuildUpToDate?: InputMaybe<Scalars['Boolean']>;
|
||||
isTool?: InputMaybe<Scalars['Boolean']>;
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
sourceHandlerCode?: InputMaybe<Scalars['String']>;
|
||||
@@ -4583,7 +4587,7 @@ export type UpdateNavigationMenuItemInput = {
|
||||
icon?: InputMaybe<Scalars['String']>;
|
||||
link?: InputMaybe<Scalars['String']>;
|
||||
name?: InputMaybe<Scalars['String']>;
|
||||
position?: InputMaybe<Scalars['Int']>;
|
||||
position?: InputMaybe<Scalars['Float']>;
|
||||
};
|
||||
|
||||
export type UpdateObjectPayload = {
|
||||
@@ -5956,6 +5960,11 @@ export type ObjectMetadataItemsQueryVariables = Exact<{ [key: string]: never; }>
|
||||
|
||||
export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', edges: Array<{ __typename?: 'ObjectEdge', node: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array<Array<string>> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } };
|
||||
|
||||
export type ObjectRecordCountsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ObjectRecordCountsQuery = { __typename?: 'Query', objectRecordCounts: Array<{ __typename?: 'ObjectRecordCount', objectNamePlural: string, totalCount: number }> };
|
||||
|
||||
export type SkipBookOnboardingStepMutationVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
@@ -11442,6 +11451,41 @@ export function useObjectMetadataItemsLazyQuery(baseOptions?: Apollo.LazyQueryHo
|
||||
export type ObjectMetadataItemsQueryHookResult = ReturnType<typeof useObjectMetadataItemsQuery>;
|
||||
export type ObjectMetadataItemsLazyQueryHookResult = ReturnType<typeof useObjectMetadataItemsLazyQuery>;
|
||||
export type ObjectMetadataItemsQueryResult = Apollo.QueryResult<ObjectMetadataItemsQuery, ObjectMetadataItemsQueryVariables>;
|
||||
export const ObjectRecordCountsDocument = gql`
|
||||
query ObjectRecordCounts {
|
||||
objectRecordCounts {
|
||||
objectNamePlural
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useObjectRecordCountsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useObjectRecordCountsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useObjectRecordCountsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useObjectRecordCountsQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useObjectRecordCountsQuery(baseOptions?: Apollo.QueryHookOptions<ObjectRecordCountsQuery, ObjectRecordCountsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ObjectRecordCountsQuery, ObjectRecordCountsQueryVariables>(ObjectRecordCountsDocument, options);
|
||||
}
|
||||
export function useObjectRecordCountsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ObjectRecordCountsQuery, ObjectRecordCountsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<ObjectRecordCountsQuery, ObjectRecordCountsQueryVariables>(ObjectRecordCountsDocument, options);
|
||||
}
|
||||
export type ObjectRecordCountsQueryHookResult = ReturnType<typeof useObjectRecordCountsQuery>;
|
||||
export type ObjectRecordCountsLazyQueryHookResult = ReturnType<typeof useObjectRecordCountsLazyQuery>;
|
||||
export type ObjectRecordCountsQueryResult = Apollo.QueryResult<ObjectRecordCountsQuery, ObjectRecordCountsQueryVariables>;
|
||||
export const SkipBookOnboardingStepDocument = gql`
|
||||
mutation SkipBookOnboardingStep {
|
||||
skipBookOnboardingStep {
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} Objekte"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}ste} other {{num}de}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount, plural, zero {لا كائنات} one {كائن وا
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objectes"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}r} other {{num}è}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objektů"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}.} few {{num}.} many {{num}.} other {{num}.}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objekter"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}ste} other {{num}te}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} Objekte"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}.} other {{num}.}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} Αντικείμενα"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}η} other {{num}η}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -306,6 +306,11 @@ msgstr "{morphRelationCount} Objects"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr "{numberOfSelectedItems} workspace members"
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objetos"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}º} other {{num}.º}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objektia"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}.} other {{num}.}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objets"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}er} other {{num}e}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} אובייקטים"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num} ראשון} two {{num} שני} many {{num} ־ות} other {{num} ־ות}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objektum"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}-ik} other {{num}-ik}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} oggetti"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} 個のオブジェクト"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, other {{num}番目}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "객체 {morphRelationCount}개"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, other {{num}번째}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objecten"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}e} other {{num}e}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objekter"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}.} other {{num}.}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount, plural, one {# obiekt} few {# obiekty} many {# obie
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}sz} two {{num}gi} few {{num}ci} other {{num}ty}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -306,6 +306,11 @@ msgstr ""
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objetos"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}º} other {{num}º}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} Objetos"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}º} other {{num}º}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} obiecte"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}st} few {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
Binary file not shown.
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} објеката"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}ст} few {{num}нд} other {{num}ти}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} objekt"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}:a} other {{num}e}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} Nesne"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}'inci} other {{num}'inci}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} об’єктів"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, one {{num}-й} few {{num}-й} many {{num}-й} other {{num}-й}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} Đối tượng"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, other {{num}}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} 个对象"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, other {{num}th}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -311,6 +311,11 @@ msgstr "{morphRelationCount} 個物件"
|
||||
msgid "{num, selectordinal, one {{num}st} two {{num}nd} few {{num}rd} other {{num}th}}"
|
||||
msgstr "{num, selectordinal, other {{num} 第}}"
|
||||
|
||||
#. js-lingui-id: fTSz8d
|
||||
#: src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownActorSelect.tsx
|
||||
msgid "{numberOfSelectedItems} workspace members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 7kYa/u
|
||||
#: src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
|
||||
msgid "{objectLabelPlural} ({totalCount})"
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useCloseActionMenu } from '@/action-menu/hooks/useCloseActionMenu';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { type ButtonAccent } from 'twenty-ui/input';
|
||||
|
||||
export type ActionModalProps = {
|
||||
@@ -49,7 +49,7 @@ export const ActionModal = ({
|
||||
|
||||
const modalId = `${actionConfig?.key}-action-modal-${actionMenuType}`;
|
||||
|
||||
const isModalOpened = useRecoilComponentValue(
|
||||
const isModalOpened = useRecoilComponentValueV2(
|
||||
isModalOpenedComponentState,
|
||||
modalId,
|
||||
);
|
||||
|
||||
+4
-4
@@ -2,9 +2,9 @@ import { type ActionDisplayProps } from '@/action-menu/actions/display/component
|
||||
import { getActionLabel } from '@/action-menu/utils/getActionLabel';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext';
|
||||
import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector';
|
||||
import { isSelectedItemIdComponentFamilyState } from '@/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
@@ -31,8 +31,8 @@ export const ActionDropdownItem = ({
|
||||
SelectableListComponentInstanceContext,
|
||||
);
|
||||
|
||||
const isSelected = useRecoilComponentFamilyValue(
|
||||
isSelectedItemIdComponentFamilySelector,
|
||||
const isSelected = useRecoilComponentFamilyValueV2(
|
||||
isSelectedItemIdComponentFamilyState,
|
||||
action.key,
|
||||
selectableListInstanceId,
|
||||
);
|
||||
|
||||
+2
-1
@@ -218,10 +218,11 @@ describe('useRelatedRecordActions', () => {
|
||||
expect(result.current['create-related-company'].position).toBe(19);
|
||||
});
|
||||
|
||||
it('should filter out system fields', () => {
|
||||
it('should filter out hidden system fields', () => {
|
||||
const fields = [
|
||||
{
|
||||
type: 'RELATION',
|
||||
name: 'position',
|
||||
relation: {
|
||||
type: 'ONE_TO_MANY',
|
||||
targetObjectMetadata: {
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@ import { ActionViewType } from '@/action-menu/actions/types/ActionViewType';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { isHiddenSystemField } from '@/object-metadata/utils/isHiddenSystemField';
|
||||
import { isRecordReadOnly } from '@/object-record/read-only/utils/isRecordReadOnly';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import React from 'react';
|
||||
@@ -35,7 +36,7 @@ export const useRelatedRecordActions = ({
|
||||
(field) =>
|
||||
field.type === 'RELATION' &&
|
||||
field.relation?.type === 'ONE_TO_MANY' &&
|
||||
!field.isSystem,
|
||||
!isHiddenSystemField(field),
|
||||
);
|
||||
|
||||
let currentPosition = startPosition;
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@ import { SelectableListItem } from '@/ui/layout/selectable-list/components/Selec
|
||||
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useContext } from 'react';
|
||||
@@ -61,7 +62,7 @@ export const RecordIndexActionMenuDropdown = () => {
|
||||
'more-actions',
|
||||
];
|
||||
|
||||
const selectedItemId = useRecoilComponentValue(
|
||||
const selectedItemId = useRecoilComponentValueV2(
|
||||
selectedItemIdComponentState,
|
||||
dropdownId,
|
||||
);
|
||||
|
||||
+4
-4
@@ -15,8 +15,8 @@ import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotke
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useComponentInstanceStateContext } from '@/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext';
|
||||
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useRecoilCallback, useRecoilValue } from 'recoil';
|
||||
import { AppPath } from 'twenty-shared/types';
|
||||
@@ -49,7 +49,7 @@ export const RecordShowRightDrawerOpenRecordButton = ({
|
||||
targetObjectId: recordId,
|
||||
});
|
||||
|
||||
const activeTabIdInRightDrawer = useRecoilComponentValue(
|
||||
const activeTabIdInRightDrawer = useRecoilComponentValueV2(
|
||||
activeTabIdComponentState,
|
||||
tabListComponentId,
|
||||
);
|
||||
@@ -58,7 +58,7 @@ export const RecordShowRightDrawerOpenRecordButton = ({
|
||||
targetObjectId: recordId,
|
||||
});
|
||||
|
||||
const setActiveTabIdInRecordPage = useSetRecoilComponentState(
|
||||
const setActiveTabIdInRecordPage = useSetRecoilComponentStateV2(
|
||||
activeTabIdComponentState,
|
||||
tabListComponentIdInRecordPage,
|
||||
);
|
||||
|
||||
@@ -17,12 +17,12 @@ import { ActivityList } from '@/activities/components/ActivityList';
|
||||
import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||
import { assertIsDefinedOrThrow, isDefined } from 'twenty-shared/utils';
|
||||
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
import { IconDownload, IconX } from 'twenty-ui/display';
|
||||
import { IconButton } from 'twenty-ui/input';
|
||||
import {
|
||||
FeatureFlagKey,
|
||||
PermissionFlagType,
|
||||
FeatureFlagKey,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { AttachmentRow } from './AttachmentRow';
|
||||
|
||||
@@ -212,20 +212,15 @@ export const AttachmentList = ({
|
||||
/>
|
||||
) : (
|
||||
<ActivityList>
|
||||
{attachments
|
||||
.filter(
|
||||
(attachment) =>
|
||||
!isFilesFieldMigrated || isDefined(attachment.file?.[0]),
|
||||
)
|
||||
.map((attachment) => (
|
||||
<AttachmentRow
|
||||
key={attachment.id}
|
||||
attachment={attachment}
|
||||
onPreview={
|
||||
isAttachmentPreviewEnabled ? handlePreview : undefined
|
||||
}
|
||||
/>
|
||||
))}
|
||||
{attachments.map((attachment) => (
|
||||
<AttachmentRow
|
||||
key={attachment.id}
|
||||
attachment={attachment}
|
||||
onPreview={
|
||||
isAttachmentPreviewEnabled ? handlePreview : undefined
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</ActivityList>
|
||||
)}
|
||||
</StyledDropZoneContainer>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import groupBy from 'lodash.groupby';
|
||||
import { IconPlus } from 'twenty-ui/display';
|
||||
@@ -55,7 +55,7 @@ export const TaskGroups = ({ targetableObject }: TaskGroupsProps) => {
|
||||
activityObjectNameSingular: CoreObjectNameSingular.Task,
|
||||
});
|
||||
|
||||
const activeTabId = useRecoilComponentValue(activeTabIdComponentState);
|
||||
const activeTabId = useRecoilComponentValueV2(activeTabIdComponentState);
|
||||
|
||||
const isLoading =
|
||||
(activeTabId !== 'done' && tasksLoading) ||
|
||||
|
||||
@@ -26,7 +26,7 @@ import { isThinkingStepPartActive } from '@/ai/utils/isThinkingStepPartActive';
|
||||
import { type ThinkingStepPart } from '@/ai/utils/thinkingStepPart';
|
||||
import { TabList } from '@/ui/layout/tab-list/components/TabList';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@@ -277,7 +277,7 @@ const ThinkingToolStepRow = ({
|
||||
? unwrappedResult.data.result
|
||||
: unwrappedOutput;
|
||||
const toolTabListComponentInstanceId = `ai-thinking-tool-tabs-${part.toolCallId ?? rawToolName}-${rowIndex}`;
|
||||
const activeToolTabId = useRecoilComponentValue(
|
||||
const activeToolTabId = useRecoilComponentValueV2(
|
||||
activeTabIdComponentState,
|
||||
toolTabListComponentInstanceId,
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { AI_CHAT_SCROLL_WRAPPER_ID } from '@/ai/constants/AiChatScrollWrapperId';
|
||||
import { useScrollWrapperHTMLElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperHTMLElement';
|
||||
import { scrollWrapperScrollBottomComponentState } from '@/ui/utilities/scroll/states/scrollWrapperScrollBottomComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
const SCROLL_BOTTOM_THRESHOLD_PX = 10;
|
||||
@@ -11,7 +11,7 @@ export const useAgentChatScrollToBottom = () => {
|
||||
AI_CHAT_SCROLL_WRAPPER_ID,
|
||||
);
|
||||
|
||||
const scrollBottom = useRecoilComponentValue(
|
||||
const scrollBottom = useRecoilComponentValueV2(
|
||||
scrollWrapperScrollBottomComponentState,
|
||||
AI_CHAT_SCROLL_WRAPPER_ID,
|
||||
);
|
||||
|
||||
@@ -14,9 +14,12 @@ import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadat
|
||||
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
|
||||
import { getTabListInstanceIdFromPageLayoutId } from '@/page-layout/utils/getTabListInstanceIdFromPageLayoutId';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { useStore } from 'jotai';
|
||||
import { coreViewFromViewIdFamilySelector } from '@/views/states/selectors/coreViewFromViewIdFamilySelector';
|
||||
|
||||
export const useGetBrowsingContext = () => {
|
||||
const store = useStore();
|
||||
|
||||
const getBrowsingContext = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(): BrowsingContext | null => {
|
||||
@@ -84,13 +87,11 @@ export const useGetBrowsingContext = () => {
|
||||
if (isDefined(pageLayoutId)) {
|
||||
const tabListInstanceId =
|
||||
getTabListInstanceIdFromPageLayoutId(pageLayoutId);
|
||||
const activeTabId = snapshot
|
||||
.getLoadable(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: tabListInstanceId,
|
||||
}),
|
||||
)
|
||||
.getValue();
|
||||
const activeTabId = store.get(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: tabListInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
...recordContext,
|
||||
@@ -154,7 +155,7 @@ export const useGetBrowsingContext = () => {
|
||||
|
||||
return null;
|
||||
},
|
||||
[],
|
||||
[store],
|
||||
);
|
||||
|
||||
return { getBrowsingContext };
|
||||
|
||||
+8
-10
@@ -3,8 +3,8 @@ import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilte
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { navigationDrawerExpandedMemorizedStateV2 } from '@/ui/navigation/states/navigationDrawerExpandedMemorizedStateV2';
|
||||
import { useGoToHotkeys } from '@/ui/utilities/hotkey/hooks/useGoToHotkeys';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { AppPath, SettingsPath } from 'twenty-shared/types';
|
||||
import { getAppPath, getSettingsPath } from 'twenty-shared/utils';
|
||||
|
||||
@@ -12,17 +12,15 @@ export const GotoHotkeysEffectsProvider = () => {
|
||||
const { activeNonSystemObjectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
useGoToHotkeys({
|
||||
key: 's',
|
||||
location: getSettingsPath(SettingsPath.ProfilePage),
|
||||
preNavigateFunction: useRecoilCallback(
|
||||
({ set }) =>
|
||||
() => {
|
||||
set(isNavigationDrawerExpandedState, true);
|
||||
jotaiStore.set(navigationDrawerExpandedMemorizedStateV2.atom, true);
|
||||
},
|
||||
[],
|
||||
),
|
||||
preNavigateFunction: useCallback(() => {
|
||||
store.set(isNavigationDrawerExpandedState.atom, true);
|
||||
store.set(navigationDrawerExpandedMemorizedStateV2.atom, true);
|
||||
}, [store]),
|
||||
});
|
||||
|
||||
return activeNonSystemObjectMetadataItems.map((objectMetadataItem) => {
|
||||
|
||||
@@ -23,8 +23,8 @@ import {
|
||||
useSignUpMutation,
|
||||
useVerifyEmailAndGetLoginTokenMutation,
|
||||
useVerifyEmailAndGetWorkspaceAgnosticTokenMutation,
|
||||
type AuthTokenPair,
|
||||
type AuthToken,
|
||||
type AuthTokenPair,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
import { tokenPairState } from '@/auth/states/tokenPairState';
|
||||
|
||||
+4
-4
@@ -2,8 +2,8 @@ import { SLASH_MENU_LIST_ID } from '@/ui/input/constants/SlashMenuListId';
|
||||
import { type SuggestionItem } from '@/blocknote-editor/types/types';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector';
|
||||
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
|
||||
import { isSelectedItemIdComponentFamilyState } from '@/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { MenuItemSuggestion } from 'twenty-ui/navigation';
|
||||
|
||||
export type CustomSlashMenuListItemProps = {
|
||||
@@ -15,8 +15,8 @@ export const CustomSlashMenuListItem = ({
|
||||
}: CustomSlashMenuListItemProps) => {
|
||||
const { resetSelectedItem } = useSelectableList(SLASH_MENU_LIST_ID);
|
||||
|
||||
const isSelectedItem = useRecoilComponentFamilyValue(
|
||||
isSelectedItemIdComponentFamilySelector,
|
||||
const isSelectedItem = useRecoilComponentFamilyValueV2(
|
||||
isSelectedItemIdComponentFamilyState,
|
||||
item.title,
|
||||
);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import { sentryConfigState } from '@/client-config/states/sentryConfigState';
|
||||
import { supportChatState } from '@/client-config/states/supportChatState';
|
||||
import { type ClientConfig } from '@/client-config/types/ClientConfig';
|
||||
import { domainConfigurationState } from '@/domain-manager/states/domainConfigurationState';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
import { isAttachmentPreviewEnabledStateV2 } from '@/client-config/states/isAttachmentPreviewEnabledStateV2';
|
||||
@@ -130,6 +130,8 @@ export const useClientConfig = (): UseClientConfigResult => {
|
||||
|
||||
const setAppVersion = useSetRecoilStateV2(appVersionState);
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const fetchClientConfig = useCallback(async () => {
|
||||
setClientConfigApiStatus((prev) => ({
|
||||
...prev,
|
||||
@@ -191,7 +193,7 @@ export const useClientConfig = (): UseClientConfigResult => {
|
||||
setGoogleMessagingEnabled(clientConfig?.isGoogleMessagingEnabled);
|
||||
setGoogleCalendarEnabled(clientConfig?.isGoogleCalendarEnabled);
|
||||
setIsAttachmentPreviewEnabled(clientConfig?.isAttachmentPreviewEnabled);
|
||||
jotaiStore.set(
|
||||
store.set(
|
||||
isAttachmentPreviewEnabledStateV2.atom,
|
||||
clientConfig?.isAttachmentPreviewEnabled,
|
||||
);
|
||||
@@ -252,6 +254,7 @@ export const useClientConfig = (): UseClientConfigResult => {
|
||||
setSentryConfig,
|
||||
setSupportChat,
|
||||
setAllowRequestsToTwentyIcons,
|
||||
store,
|
||||
]);
|
||||
|
||||
return {
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@ import { COMMAND_MENU_LIST_SELECTABLE_LIST_ID } from '@/command-menu/constants/C
|
||||
import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState';
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -16,7 +16,7 @@ export const CommandMenuDefaultSelectionEffect = ({
|
||||
COMMAND_MENU_LIST_SELECTABLE_LIST_ID,
|
||||
);
|
||||
|
||||
const selectedItemId = useRecoilComponentValue(
|
||||
const selectedItemId = useRecoilComponentValueV2(
|
||||
selectedItemIdComponentState,
|
||||
COMMAND_MENU_LIST_SELECTABLE_LIST_ID,
|
||||
);
|
||||
|
||||
@@ -4,8 +4,8 @@ import { IconArrowUpRight, type IconComponent } from 'twenty-ui/display';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
|
||||
import { useCommandMenuOnItemClick } from '@/command-menu/hooks/useCommandMenuOnItemClick';
|
||||
import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector';
|
||||
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
|
||||
import { isSelectedItemIdComponentFamilyState } from '@/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilyValueV2';
|
||||
|
||||
export type CommandMenuItemProps = {
|
||||
label: string;
|
||||
@@ -44,8 +44,8 @@ export const CommandMenuItem = ({
|
||||
Icon = IconArrowUpRight;
|
||||
}
|
||||
|
||||
const isSelectedItemId = useRecoilComponentFamilyValue(
|
||||
isSelectedItemIdComponentFamilySelector,
|
||||
const isSelectedItemId = useRecoilComponentFamilyValueV2(
|
||||
isSelectedItemIdComponentFamilyState,
|
||||
id,
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@ import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
|
||||
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
|
||||
import { currentFocusIdSelector } from '@/ui/utilities/focus/states/currentFocusIdSelector';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRef, useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type IconComponent } from 'twenty-ui/display';
|
||||
import {
|
||||
@@ -45,7 +45,7 @@ export const CommandMenuItemNumberInput = ({
|
||||
const [draftValue, setDraftValue] = useState(value);
|
||||
const [hasError, setHasError] = useState(false);
|
||||
|
||||
const currentFocusId = useRecoilValue(currentFocusIdSelector);
|
||||
const currentFocusId = useRecoilValueV2(currentFocusIdSelector);
|
||||
const isNumberInputCurrentlyFocused = currentFocusId === focusId;
|
||||
|
||||
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@ import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
|
||||
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
|
||||
import { currentFocusIdSelector } from '@/ui/utilities/focus/states/currentFocusIdSelector';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRef, useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { type IconComponent } from 'twenty-ui/display';
|
||||
|
||||
type CommandMenuItemTextInputProps = {
|
||||
@@ -37,7 +37,7 @@ export const CommandMenuItemTextInput = ({
|
||||
const focusId = `${id}-input`;
|
||||
const [draftValue, setDraftValue] = useState(value);
|
||||
|
||||
const currentFocusId = useRecoilValue(currentFocusIdSelector);
|
||||
const currentFocusId = useRecoilValueV2(currentFocusIdSelector);
|
||||
const isTextInputCurrentlyFocused = currentFocusId === focusId;
|
||||
|
||||
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector';
|
||||
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
|
||||
import { isSelectedItemIdComponentFamilyState } from '@/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { MenuItemToggle, type MenuItemToggleProps } from 'twenty-ui/navigation';
|
||||
|
||||
export type CommandMenuItemToggleProps = MenuItemToggleProps & {
|
||||
@@ -7,8 +7,8 @@ export type CommandMenuItemToggleProps = MenuItemToggleProps & {
|
||||
};
|
||||
|
||||
export const CommandMenuItemToggle = (props: CommandMenuItemToggleProps) => {
|
||||
const isSelectedItemId = useRecoilComponentFamilyValue(
|
||||
isSelectedItemIdComponentFamilySelector,
|
||||
const isSelectedItemId = useRecoilComponentFamilyValueV2(
|
||||
isSelectedItemIdComponentFamilyState,
|
||||
props.id,
|
||||
);
|
||||
|
||||
|
||||
+14
-15
@@ -11,6 +11,7 @@ import { RootStackingContextZIndices } from '@/ui/layout/constants/RootStackingC
|
||||
import { PAGE_HEADER_COMMAND_MENU_BUTTON_CLICK_OUTSIDE_ID } from '@/ui/layout/page-header/constants/PageHeaderCommandMenuButtonClickOutsideId';
|
||||
import { currentFocusIdSelector } from '@/ui/utilities/focus/states/currentFocusIdSelector';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { useStore } from 'jotai';
|
||||
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
|
||||
import { WORKFLOW_DIAGRAM_CREATE_STEP_NODE_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramCreateStepNodeClickOutsideId';
|
||||
import { WORKFLOW_DIAGRAM_STEP_NODE_BASE_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramStepNodeClickOutsideId';
|
||||
@@ -19,8 +20,7 @@ import { useTheme } from '@emotion/react';
|
||||
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useRef } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { LINK_CHIP_CLICK_OUTSIDE_ID } from 'twenty-ui/components';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
@@ -58,20 +58,19 @@ export const CommandMenuOpenContainer = ({
|
||||
isSidePanelAnimatingStateV2,
|
||||
);
|
||||
|
||||
const handleClickOutside = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(event: MouseEvent | TouchEvent) => {
|
||||
const currentFocusId = snapshot
|
||||
.getLoadable(currentFocusIdSelector)
|
||||
.getValue();
|
||||
const store = useStore();
|
||||
|
||||
if (currentFocusId === SIDE_PANEL_FOCUS_ID) {
|
||||
event.stopImmediatePropagation();
|
||||
event.preventDefault();
|
||||
closeCommandMenu();
|
||||
}
|
||||
},
|
||||
[closeCommandMenu],
|
||||
const handleClickOutside = useCallback(
|
||||
(event: MouseEvent | TouchEvent) => {
|
||||
const currentFocusId = store.get(currentFocusIdSelector.atom);
|
||||
|
||||
if (currentFocusId === SIDE_PANEL_FOCUS_ID) {
|
||||
event.stopImmediatePropagation();
|
||||
event.preventDefault();
|
||||
closeCommandMenu();
|
||||
}
|
||||
},
|
||||
[closeCommandMenu, store],
|
||||
);
|
||||
|
||||
useListenClickOutside({
|
||||
|
||||
@@ -10,7 +10,7 @@ import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { addToNavPayloadRegistryStateV2 } from '@/navigation-menu-item/states/addToNavPayloadRegistryStateV2';
|
||||
import { useCloseAnyOpenDropdown } from '@/ui/layout/dropdown/hooks/useCloseAnyOpenDropdown';
|
||||
import { emitSidePanelOpenEvent } from '@/ui/layout/right-drawer/utils/emitSidePanelOpenEvent';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { useStore } from 'jotai';
|
||||
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useCallback } from 'react';
|
||||
@@ -23,6 +23,8 @@ export const useCommandMenu = () => {
|
||||
const { removeFocusItemFromFocusStackById } =
|
||||
useRemoveFocusItemFromFocusStackById();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const closeCommandMenu = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
() => {
|
||||
@@ -31,9 +33,9 @@ export const useCommandMenu = () => {
|
||||
.getValue();
|
||||
|
||||
if (isCommandMenuOpened) {
|
||||
jotaiStore.set(addToNavPayloadRegistryStateV2.atom, new Map());
|
||||
store.set(addToNavPayloadRegistryStateV2.atom, new Map());
|
||||
set(isCommandMenuOpenedState, false);
|
||||
jotaiStore.set(isCommandMenuOpenedStateV2.atom, false);
|
||||
store.set(isCommandMenuOpenedStateV2.atom, false);
|
||||
set(isCommandMenuClosingState, true);
|
||||
closeAnyOpenDropdown();
|
||||
removeFocusItemFromFocusStackById({
|
||||
@@ -41,7 +43,7 @@ export const useCommandMenu = () => {
|
||||
});
|
||||
}
|
||||
},
|
||||
[closeAnyOpenDropdown, removeFocusItemFromFocusStackById],
|
||||
[closeAnyOpenDropdown, removeFocusItemFromFocusStackById, store],
|
||||
);
|
||||
|
||||
const openCommandMenu = useCallback(() => {
|
||||
|
||||
+7
-5
@@ -26,7 +26,7 @@ import { getShowPageTabListComponentId } from '@/ui/layout/show-page/utils/getSh
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { WORKFLOW_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/workflow-actions/code-action/constants/WorkflowLogicFunctionTabListComponentId';
|
||||
import { WorkflowLogicFunctionTabId } from '@/workflow/workflow-steps/workflow-actions/code-action/types/WorkflowLogicFunctionTabId';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { useStore } from 'jotai';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -39,6 +39,8 @@ export const useCommandMenuCloseAnimationCompleteCleanup = () => {
|
||||
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const commandMenuCloseAnimationCompleteCleanup = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
() => {
|
||||
@@ -106,7 +108,7 @@ export const useCommandMenuCloseAnimationCompleteCleanup = () => {
|
||||
instanceId: '',
|
||||
});
|
||||
set(isCommandMenuOpenedState, false);
|
||||
jotaiStore.set(isCommandMenuOpenedStateV2.atom, false);
|
||||
store.set(isCommandMenuOpenedStateV2.atom, false);
|
||||
set(commandMenuSearchState, '');
|
||||
set(commandMenuNavigationMorphItemsByPageState, new Map());
|
||||
set(commandMenuNavigationStackState, []);
|
||||
@@ -115,7 +117,7 @@ export const useCommandMenuCloseAnimationCompleteCleanup = () => {
|
||||
|
||||
emitSidePanelCloseEvent();
|
||||
set(isCommandMenuClosingState, false);
|
||||
set(
|
||||
store.set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: WORKFLOW_LOGIC_FUNCTION_TAB_LIST_COMPONENT_ID,
|
||||
}),
|
||||
@@ -125,7 +127,7 @@ export const useCommandMenuCloseAnimationCompleteCleanup = () => {
|
||||
for (const [pageId, morphItems] of snapshot
|
||||
.getLoadable(commandMenuNavigationMorphItemsByPageState)
|
||||
.getValue()) {
|
||||
set(
|
||||
store.set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: getShowPageTabListComponentId({
|
||||
pageId,
|
||||
@@ -136,7 +138,7 @@ export const useCommandMenuCloseAnimationCompleteCleanup = () => {
|
||||
);
|
||||
}
|
||||
},
|
||||
[closeDropdown, resetContextStoreStates, resetSelectedItem],
|
||||
[closeDropdown, resetContextStoreStates, resetSelectedItem, store],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -8,12 +8,15 @@ import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState
|
||||
import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState';
|
||||
import { getShowPageTabListComponentId } from '@/ui/layout/show-page/utils/getShowPageTabListComponentId';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { useStore } from 'jotai';
|
||||
import { isNonEmptyArray } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useCommandMenuHistory = () => {
|
||||
const { closeCommandMenu } = useCommandMenu();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const goBackFromCommandMenu = useRecoilCallback(
|
||||
({ snapshot, set }) => {
|
||||
return () => {
|
||||
@@ -53,7 +56,7 @@ export const useCommandMenuHistory = () => {
|
||||
|
||||
const morphItems = currentMorphItems.get(removedItem.pageId);
|
||||
if (isNonEmptyArray(morphItems)) {
|
||||
set(
|
||||
store.set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: getShowPageTabListComponentId({
|
||||
pageId: removedItem.pageId,
|
||||
@@ -69,62 +72,68 @@ export const useCommandMenuHistory = () => {
|
||||
set(hasUserSelectedCommandState, false);
|
||||
};
|
||||
},
|
||||
[closeCommandMenu],
|
||||
[closeCommandMenu, store],
|
||||
);
|
||||
|
||||
const navigateCommandMenuHistory = useRecoilCallback(({ snapshot, set }) => {
|
||||
return (pageIndex: number) => {
|
||||
const currentNavigationStack = snapshot
|
||||
.getLoadable(commandMenuNavigationStackState)
|
||||
.getValue();
|
||||
const navigateCommandMenuHistory = useRecoilCallback(
|
||||
({ snapshot, set }) => {
|
||||
return (pageIndex: number) => {
|
||||
const currentNavigationStack = snapshot
|
||||
.getLoadable(commandMenuNavigationStackState)
|
||||
.getValue();
|
||||
|
||||
const newNavigationStack = currentNavigationStack.slice(0, pageIndex + 1);
|
||||
|
||||
set(commandMenuNavigationStackState, newNavigationStack);
|
||||
|
||||
const newNavigationStackItem = newNavigationStack.at(-1);
|
||||
|
||||
if (!isDefined(newNavigationStackItem)) {
|
||||
throw new Error(
|
||||
`No command menu navigation stack item found for index ${pageIndex}`,
|
||||
const newNavigationStack = currentNavigationStack.slice(
|
||||
0,
|
||||
pageIndex + 1,
|
||||
);
|
||||
}
|
||||
|
||||
set(commandMenuPageState, newNavigationStackItem.page);
|
||||
set(commandMenuPageInfoState, {
|
||||
title: newNavigationStackItem.pageTitle,
|
||||
Icon: newNavigationStackItem.pageIcon,
|
||||
instanceId: newNavigationStackItem.pageId,
|
||||
});
|
||||
const currentMorphItems = snapshot
|
||||
.getLoadable(commandMenuNavigationMorphItemsByPageState)
|
||||
.getValue();
|
||||
set(commandMenuNavigationStackState, newNavigationStack);
|
||||
|
||||
for (const [pageId, morphItems] of currentMorphItems.entries()) {
|
||||
if (!newNavigationStack.some((item) => item.pageId === pageId)) {
|
||||
set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: getShowPageTabListComponentId({
|
||||
pageId,
|
||||
targetObjectId: morphItems[0].recordId,
|
||||
}),
|
||||
}),
|
||||
null,
|
||||
const newNavigationStackItem = newNavigationStack.at(-1);
|
||||
|
||||
if (!isDefined(newNavigationStackItem)) {
|
||||
throw new Error(
|
||||
`No command menu navigation stack item found for index ${pageIndex}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const newMorphItems = new Map(
|
||||
Array.from(currentMorphItems.entries()).filter(([pageId]) =>
|
||||
newNavigationStack.some((item) => item.pageId === pageId),
|
||||
),
|
||||
);
|
||||
set(commandMenuPageState, newNavigationStackItem.page);
|
||||
set(commandMenuPageInfoState, {
|
||||
title: newNavigationStackItem.pageTitle,
|
||||
Icon: newNavigationStackItem.pageIcon,
|
||||
instanceId: newNavigationStackItem.pageId,
|
||||
});
|
||||
const currentMorphItems = snapshot
|
||||
.getLoadable(commandMenuNavigationMorphItemsByPageState)
|
||||
.getValue();
|
||||
|
||||
set(commandMenuNavigationMorphItemsByPageState, newMorphItems);
|
||||
for (const [pageId, morphItems] of currentMorphItems.entries()) {
|
||||
if (!newNavigationStack.some((item) => item.pageId === pageId)) {
|
||||
store.set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: getShowPageTabListComponentId({
|
||||
pageId,
|
||||
targetObjectId: morphItems[0].recordId,
|
||||
}),
|
||||
}),
|
||||
null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
set(hasUserSelectedCommandState, false);
|
||||
};
|
||||
}, []);
|
||||
const newMorphItems = new Map(
|
||||
Array.from(currentMorphItems.entries()).filter(([pageId]) =>
|
||||
newNavigationStack.some((item) => item.pageId === pageId),
|
||||
),
|
||||
);
|
||||
|
||||
set(commandMenuNavigationMorphItemsByPageState, newMorphItems);
|
||||
|
||||
set(hasUserSelectedCommandState, false);
|
||||
};
|
||||
},
|
||||
[store],
|
||||
);
|
||||
|
||||
return {
|
||||
goBackFromCommandMenu,
|
||||
|
||||
@@ -15,7 +15,7 @@ import { type CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
|
||||
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { useStore } from 'jotai';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { type IconComponent } from 'twenty-ui/display';
|
||||
import { v4 } from 'uuid';
|
||||
@@ -36,6 +36,8 @@ export const useNavigateCommandMenu = () => {
|
||||
|
||||
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const openCommandMenu = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
() => {
|
||||
@@ -72,13 +74,14 @@ export const useNavigateCommandMenu = () => {
|
||||
});
|
||||
|
||||
set(isCommandMenuOpenedState, true);
|
||||
jotaiStore.set(isCommandMenuOpenedStateV2.atom, true);
|
||||
store.set(isCommandMenuOpenedStateV2.atom, true);
|
||||
set(hasUserSelectedCommandState, false);
|
||||
},
|
||||
[
|
||||
copyContextStoreStates,
|
||||
commandMenuCloseAnimationCompleteCleanup,
|
||||
pushFocusItemToFocusStack,
|
||||
store,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user