feat: added workspace member filter for actor fields (#16628)
Closes #16619 This PR adds support for filtering ACTOR fields by `Workspace Member` subfield, enabling users to filter records by who created them with a `Me` option. I replicated the same UX and code structure as the Relation field filter for consistency. Each filter selection triggers a server-side GraphQL call. But there is client-side filtering in `isRecordMatchingFilter.ts` which instantly filters already-loaded records while the server is fetching new results. I replicated this behaviour from how `FULL_NAME` and other composite fields handle filtering. UX decision that were taken by me (Let me know if changes are needed) : - The filter shows comma separated selected workspace member names until 3 members are selected. After that it shows [no of selected members] workspace members. <img width="643" height="283" alt="Screenshot 2025-12-17 at 8 01 23 PM" src="https://github.com/user-attachments/assets/18d524f4-979b-4d92-ad64-aa7b63be7897" /> <img width="774" height="309" alt="Screenshot 2025-12-17 at 8 01 33 PM" src="https://github.com/user-attachments/assets/779f374f-1501-48f9-afa2-a78628e067b1" /> <img width="737" height="397" alt="Screenshot 2025-12-17 at 8 01 40 PM" src="https://github.com/user-attachments/assets/4e8b963e-8a0f-467d-91ae-48bca4e1d842" /> <img width="697" height="334" alt="Screenshot 2025-12-17 at 8 01 53 PM" src="https://github.com/user-attachments/assets/c9a0e4bb-48b4-486b-a4f9-d7c49ff3852c" /> <img width="684" height="343" alt="Screenshot 2025-12-17 at 8 02 04 PM" src="https://github.com/user-attachments/assets/d5c45eba-06a3-40fc-b9d0-d585dc8bc136" /> --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
+32
-7
@@ -1,6 +1,11 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { COMPANY_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/company-data-seeds.constant';
|
||||
import { PERSON_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/person-data-seeds.constant';
|
||||
import { WORKSPACE_MEMBER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
|
||||
import {
|
||||
WORKSPACE_MEMBER_DATA_SEED_IDS,
|
||||
WORKSPACE_MEMBER_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
|
||||
|
||||
type OpportunityDataSeed = {
|
||||
id: string;
|
||||
@@ -177,7 +182,17 @@ const GENERATE_OPPORTUNITY_SEEDS = (): OpportunityDataSeed[] => {
|
||||
|
||||
CLOSE_DATE.setDate(CLOSE_DATE.getDate() + DAYS_AHEAD);
|
||||
|
||||
OPPORTUNITY_SEEDS.push({
|
||||
const workspaceMemberId = Object.values(WORKSPACE_MEMBER_DATA_SEED_IDS)[
|
||||
INDEX % 4
|
||||
];
|
||||
const workspaceMember = WORKSPACE_MEMBER_DATA_SEEDS.find(
|
||||
(workspaceMember) => workspaceMember.id === workspaceMemberId,
|
||||
);
|
||||
const workspaceMemberName = isDefined(workspaceMember)
|
||||
? `${workspaceMember?.nameFirstName} ${workspaceMember?.nameLastName}`
|
||||
: 'Unkonwn';
|
||||
|
||||
const rawSeed: OpportunityDataSeed = {
|
||||
id: OPPORTUNITY_DATA_SEED_IDS[`ID_${INDEX}`],
|
||||
name: TEMPLATE.name,
|
||||
amountAmountMicros: TEMPLATE.amount * 1000000,
|
||||
@@ -195,12 +210,22 @@ const GENERATE_OPPORTUNITY_SEEDS = (): OpportunityDataSeed[] => {
|
||||
] || COMPANY_DATA_SEED_IDS.ID_1,
|
||||
ownerId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
createdByName: 'Tim Cook',
|
||||
updatedBySource: 'MANUAL',
|
||||
updatedByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
updatedByName: 'Tim Cook',
|
||||
});
|
||||
createdByWorkspaceMemberId: workspaceMemberId,
|
||||
createdByName: workspaceMemberName,
|
||||
updatedByWorkspaceMemberId: workspaceMemberId,
|
||||
updatedByName: workspaceMemberName,
|
||||
};
|
||||
|
||||
const opportunityDataSeedWithSQLColumnOrder: OpportunityDataSeed =
|
||||
Object.fromEntries(
|
||||
OPPORTUNITY_DATA_SEED_COLUMNS.map((column) => [
|
||||
column,
|
||||
rawSeed[column as keyof OpportunityDataSeed],
|
||||
]),
|
||||
) as OpportunityDataSeed;
|
||||
|
||||
OPPORTUNITY_SEEDS.push(opportunityDataSeedWithSQLColumnOrder);
|
||||
}
|
||||
|
||||
return OPPORTUNITY_SEEDS;
|
||||
|
||||
+43
-14
@@ -1,5 +1,10 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { COMPANY_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/company-data-seeds.constant';
|
||||
import { WORKSPACE_MEMBER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
|
||||
import {
|
||||
WORKSPACE_MEMBER_DATA_SEED_IDS,
|
||||
WORKSPACE_MEMBER_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
|
||||
|
||||
type PersonDataSeed = {
|
||||
id: string;
|
||||
@@ -11,12 +16,12 @@ type PersonDataSeed = {
|
||||
linkedinLinkPrimaryLinkUrl: string;
|
||||
jobTitle: string;
|
||||
companyId: string;
|
||||
createdBySource: string;
|
||||
createdByWorkspaceMemberId: string;
|
||||
createdByName: string;
|
||||
phonesPrimaryPhoneNumber: string;
|
||||
phonesPrimaryPhoneCountryCode: string;
|
||||
phonesPrimaryPhoneCallingCode: string;
|
||||
createdBySource: string;
|
||||
createdByWorkspaceMemberId: string;
|
||||
createdByName: string;
|
||||
updatedBySource: string;
|
||||
updatedByWorkspaceMemberId: string;
|
||||
updatedByName: string;
|
||||
@@ -33,12 +38,12 @@ export const PERSON_DATA_SEED_COLUMNS: (keyof PersonDataSeed)[] = [
|
||||
'linkedinLinkPrimaryLinkUrl',
|
||||
'jobTitle',
|
||||
'companyId',
|
||||
'createdBySource',
|
||||
'createdByWorkspaceMemberId',
|
||||
'createdByName',
|
||||
'phonesPrimaryPhoneNumber',
|
||||
'phonesPrimaryPhoneCountryCode',
|
||||
'phonesPrimaryPhoneCallingCode',
|
||||
'createdBySource',
|
||||
'createdByWorkspaceMemberId',
|
||||
'createdByName',
|
||||
'updatedBySource',
|
||||
'updatedByWorkspaceMemberId',
|
||||
'updatedByName',
|
||||
@@ -21654,13 +21659,37 @@ const PERSON_DATA_SEEDS_RAW = [
|
||||
];
|
||||
|
||||
export const PERSON_DATA_SEEDS: PersonDataSeed[] = PERSON_DATA_SEEDS_RAW.map(
|
||||
(person, index) => ({
|
||||
...person,
|
||||
updatedBySource: person.createdBySource,
|
||||
updatedByWorkspaceMemberId: person.createdByWorkspaceMemberId,
|
||||
updatedByName: person.createdByName,
|
||||
position: index + 1,
|
||||
}),
|
||||
(person, index) => {
|
||||
const workspaceMemberId = Object.values(WORKSPACE_MEMBER_DATA_SEED_IDS)[
|
||||
index % 4
|
||||
];
|
||||
const workspaceMember = WORKSPACE_MEMBER_DATA_SEEDS.find(
|
||||
(workspaceMember) => workspaceMember.id === workspaceMemberId,
|
||||
);
|
||||
const workspaceMemberName = isDefined(workspaceMember)
|
||||
? `${workspaceMember?.nameFirstName} ${workspaceMember?.nameLastName}`
|
||||
: 'Unkonwn';
|
||||
|
||||
const dataSeed: PersonDataSeed = {
|
||||
...person,
|
||||
createdBySource: person.createdBySource,
|
||||
createdByWorkspaceMemberId: workspaceMemberId,
|
||||
createdByName: workspaceMemberName,
|
||||
updatedBySource: person.createdBySource,
|
||||
updatedByWorkspaceMemberId: workspaceMemberId,
|
||||
updatedByName: workspaceMemberName,
|
||||
position: index + 1,
|
||||
};
|
||||
|
||||
const personDataSeedWithSQLColumnOrder: PersonDataSeed = Object.fromEntries(
|
||||
PERSON_DATA_SEED_COLUMNS.map((column) => [
|
||||
column,
|
||||
dataSeed[column as keyof PersonDataSeed],
|
||||
]),
|
||||
) as PersonDataSeed;
|
||||
|
||||
return personDataSeedWithSQLColumnOrder;
|
||||
},
|
||||
);
|
||||
|
||||
// Map for O(1) lookups by person ID
|
||||
|
||||
Reference in New Issue
Block a user