Add people position

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
Bryan Frimin
2025-07-11 09:05:00 +02:00
parent 452c1b5381
commit 6fda84e5c7
10 changed files with 95 additions and 25 deletions

View File

@@ -80,6 +80,7 @@ const paginatedPeopleFragment = graphql`
fullName fullName
primaryEmailAddress primaryEmailAddress
kind kind
position
additionalEmailAddresses additionalEmailAddresses
} }
} }
@@ -157,6 +158,7 @@ export const peopleNodeQuery = graphql`
id id
fullName fullName
primaryEmailAddress primaryEmailAddress
position
kind kind
additionalEmailAddresses additionalEmailAddresses
} }
@@ -171,6 +173,7 @@ export const updatePeopleMutation = graphql`
id id
fullName fullName
primaryEmailAddress primaryEmailAddress
position
kind kind
additionalEmailAddresses additionalEmailAddresses
} }

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<006f8f3dc3c4d41a23cc71a870aa571c>> * @generated SignedSource<<71df408810680ded020fb0e1cc93ff79>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -19,6 +19,7 @@ export type PeopleGraphNodeQuery$data = {
readonly fullName?: string; readonly fullName?: string;
readonly id?: string; readonly id?: string;
readonly kind?: PeopleKind; readonly kind?: PeopleKind;
readonly position?: string | null | undefined;
readonly primaryEmailAddress?: string; readonly primaryEmailAddress?: string;
}; };
}; };
@@ -67,10 +68,17 @@ v5 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
"name": "kind", "name": "position",
"storageKey": null "storageKey": null
}, },
v6 = { v6 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "kind",
"storageKey": null
},
v7 = {
"alias": null, "alias": null,
"args": null, "args": null,
"kind": "ScalarField", "kind": "ScalarField",
@@ -99,7 +107,8 @@ return {
(v3/*: any*/), (v3/*: any*/),
(v4/*: any*/), (v4/*: any*/),
(v5/*: any*/), (v5/*: any*/),
(v6/*: any*/) (v6/*: any*/),
(v7/*: any*/)
], ],
"type": "People", "type": "People",
"abstractKey": null "abstractKey": null
@@ -139,7 +148,8 @@ return {
(v3/*: any*/), (v3/*: any*/),
(v4/*: any*/), (v4/*: any*/),
(v5/*: any*/), (v5/*: any*/),
(v6/*: any*/) (v6/*: any*/),
(v7/*: any*/)
], ],
"type": "People", "type": "People",
"abstractKey": null "abstractKey": null
@@ -150,16 +160,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "319f5f4ff11db061920a25bbfda43244", "cacheID": "850de97d42fdda9d2335c0e5219fd067",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "PeopleGraphNodeQuery", "name": "PeopleGraphNodeQuery",
"operationKind": "query", "operationKind": "query",
"text": "query PeopleGraphNodeQuery(\n $peopleId: ID!\n) {\n node(id: $peopleId) {\n __typename\n ... on People {\n id\n fullName\n primaryEmailAddress\n kind\n additionalEmailAddresses\n }\n id\n }\n}\n" "text": "query PeopleGraphNodeQuery(\n $peopleId: ID!\n) {\n node(id: $peopleId) {\n __typename\n ... on People {\n id\n fullName\n primaryEmailAddress\n position\n kind\n additionalEmailAddresses\n }\n id\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "b4e6fe403e30fbc27ae638d464ad7543"; (node as any).hash = "f39d45664dba2b3bcdad07ef8baebfe9";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<e4fcd65491a7570cf56382a3f977e06d>> * @generated SignedSource<<5eba326084bfab4966727af60e2aa85c>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -21,6 +21,7 @@ export type PeopleGraphPaginatedFragment$data = {
readonly fullName: string; readonly fullName: string;
readonly id: string; readonly id: string;
readonly kind: PeopleKind; readonly kind: PeopleKind;
readonly position: string | null | undefined;
readonly primaryEmailAddress: string; readonly primaryEmailAddress: string;
}; };
}>; }>;
@@ -159,6 +160,13 @@ return {
"name": "kind", "name": "kind",
"storageKey": null "storageKey": null
}, },
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "position",
"storageKey": null
},
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -247,6 +255,6 @@ return {
}; };
})(); })();
(node as any).hash = "c163b7909a337efd22088852b9908045"; (node as any).hash = "5e095baf6a65e7cdbaa804d4658cbb6b";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<43878b22fe8a689f41bcd506711ddb5f>> * @generated SignedSource<<1ec11120f71d4bc3040bcdd2665904c0>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -160,6 +160,13 @@ return {
"name": "kind", "name": "kind",
"storageKey": null "storageKey": null
}, },
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "position",
"storageKey": null
},
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -256,12 +263,12 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "b154e94ac7e783a492bc5aed7d44229d", "cacheID": "1139d090f54b12e62e08f0a1970c9af0",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "PeopleGraphPaginatedQuery", "name": "PeopleGraphPaginatedQuery",
"operationKind": "query", "operationKind": "query",
"text": "query PeopleGraphPaginatedQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n ...PeopleGraphPaginatedFragment\n }\n id\n }\n}\n\nfragment PeopleGraphPaginatedFragment on Organization {\n peoples(first: 50) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n kind\n additionalEmailAddresses\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n" "text": "query PeopleGraphPaginatedQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n ...PeopleGraphPaginatedFragment\n }\n id\n }\n}\n\nfragment PeopleGraphPaginatedFragment on Organization {\n peoples(first: 50) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n kind\n position\n additionalEmailAddresses\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n"
} }
}; };
})(); })();

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<b798b75c1d930af818109fd819d5cef3>> * @generated SignedSource<<18d62863109c347d5fcf7b5701a9c57b>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -30,6 +30,7 @@ export type PeopleGraphUpdateMutation$data = {
readonly fullName: string; readonly fullName: string;
readonly id: string; readonly id: string;
readonly kind: PeopleKind; readonly kind: PeopleKind;
readonly position: string | null | undefined;
readonly primaryEmailAddress: string; readonly primaryEmailAddress: string;
}; };
}; };
@@ -91,6 +92,13 @@ v1 = [
"name": "primaryEmailAddress", "name": "primaryEmailAddress",
"storageKey": null "storageKey": null
}, },
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "position",
"storageKey": null
},
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -130,16 +138,16 @@ return {
"selections": (v1/*: any*/) "selections": (v1/*: any*/)
}, },
"params": { "params": {
"cacheID": "c61ca0a6b20067ce5e0c708fc55509d8", "cacheID": "814551d1fb24548c41d417342625071f",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "PeopleGraphUpdateMutation", "name": "PeopleGraphUpdateMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation PeopleGraphUpdateMutation(\n $input: UpdatePeopleInput!\n) {\n updatePeople(input: $input) {\n people {\n id\n fullName\n primaryEmailAddress\n kind\n additionalEmailAddresses\n }\n }\n}\n" "text": "mutation PeopleGraphUpdateMutation(\n $input: UpdatePeopleInput!\n) {\n updatePeople(input: $input) {\n people {\n id\n fullName\n primaryEmailAddress\n position\n kind\n additionalEmailAddresses\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "48c2618963704a8cd3b1f0a68817cdad"; (node as any).hash = "ecc5666046434d5c8e80eaab0e508c11";
export default node; export default node;

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<e7dfc0de7524eaa22ca235ac0b6e3011>> * @generated SignedSource<<4cfc7218bc48a818eedc2ea87ac521e6>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -233,6 +233,13 @@ return {
"name": "kind", "name": "kind",
"storageKey": null "storageKey": null
}, },
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "position",
"storageKey": null
},
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -329,16 +336,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "a17ff68897dbcf3daa33b073bc83f1bb", "cacheID": "8134caa0eab10c19236a49728f1f77b6",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "PeopleListQuery", "name": "PeopleListQuery",
"operationKind": "query", "operationKind": "query",
"text": "query PeopleListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: PeopleOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...PeopleGraphPaginatedFragment_16fISc\n id\n }\n}\n\nfragment PeopleGraphPaginatedFragment_16fISc on Organization {\n peoples(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n kind\n additionalEmailAddresses\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n" "text": "query PeopleListQuery(\n $after: CursorKey = null\n $before: CursorKey = null\n $first: Int = 50\n $last: Int = null\n $order: PeopleOrder = null\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...PeopleGraphPaginatedFragment_16fISc\n id\n }\n}\n\nfragment PeopleGraphPaginatedFragment_16fISc on Organization {\n peoples(first: $first, after: $after, last: $last, before: $before, orderBy: $order) {\n edges {\n node {\n id\n fullName\n primaryEmailAddress\n kind\n position\n additionalEmailAddresses\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n id\n}\n"
} }
}; };
})(); })();
(node as any).hash = "c163b7909a337efd22088852b9908045"; (node as any).hash = "5e095baf6a65e7cdbaa804d4658cbb6b";
export default node; export default node;

View File

@@ -59,6 +59,7 @@ export default function PeopleListPage({
<Tr> <Tr>
<SortableTh field="FULL_NAME">{__("Name")}</SortableTh> <SortableTh field="FULL_NAME">{__("Name")}</SortableTh>
<SortableTh field="KIND">{__("Role")}</SortableTh> <SortableTh field="KIND">{__("Role")}</SortableTh>
<Th>{__("Position")}</Th>
<Th>{__("Actions")}</Th> <Th>{__("Actions")}</Th>
</Tr> </Tr>
</Thead> </Thead>
@@ -101,6 +102,7 @@ function PeopleRow({
</div> </div>
</Td> </Td>
<Td className="text-sm">{getRole(__, people.kind)}</Td> <Td className="text-sm">{getRole(__, people.kind)}</Td>
<Td className="text-sm">{people.position}</Td>
<Td noLink width={50} className="text-end"> <Td noLink width={50} className="text-end">
<ActionDropdown> <ActionDropdown>
<DropdownItem <DropdownItem

View File

@@ -26,11 +26,12 @@ type Props = {
const schema = z.object({ const schema = z.object({
fullName: z.string().min(1), fullName: z.string().min(1),
position: z.string().min(1),
primaryEmailAddress: z.string().email(), primaryEmailAddress: z.string().email(),
additionalEmailAddresses: z.preprocess( additionalEmailAddresses: z.preprocess(
// Empty additional emails are skipped // Empty additional emails are skipped
(v) => (v as string[]).filter((v) => !!v), (v) => (v as string[]).filter((v) => !!v),
z.array(z.string().email()), z.array(z.string().email())
), ),
kind: z.enum(peopleRoles), kind: z.enum(peopleRoles),
}); });
@@ -46,6 +47,7 @@ export const createPeopleMutation = graphql`
id id
fullName fullName
primaryEmailAddress primaryEmailAddress
position
kind kind
additionalEmailAddresses additionalEmailAddresses
} }
@@ -103,6 +105,12 @@ export function CreatePeopleDialog({ children, connectionId }: Props) {
{...register("primaryEmailAddress")} {...register("primaryEmailAddress")}
type="email" type="email"
/> />
<Field
label={__("Position")}
{...register("position")}
type="text"
placeholder={__("e.g. CEO, CFO, etc.")}
/>
<ControlledField <ControlledField
control={control} control={control}
name="kind" name="kind"

View File

@@ -1,5 +1,5 @@
/** /**
* @generated SignedSource<<fce211be2cfe7f4b313cf2db7f4f127c>> * @generated SignedSource<<cf446d4f8991b5ff332b3d81174c3247>>
* @lightSyntaxTransform * @lightSyntaxTransform
* @nogrep * @nogrep
*/ */
@@ -32,6 +32,7 @@ export type CreatePeopleDialogMutation$data = {
readonly fullName: string; readonly fullName: string;
readonly id: string; readonly id: string;
readonly kind: PeopleKind; readonly kind: PeopleKind;
readonly position: string | null | undefined;
readonly primaryEmailAddress: string; readonly primaryEmailAddress: string;
}; };
}; };
@@ -97,6 +98,13 @@ v3 = {
"name": "primaryEmailAddress", "name": "primaryEmailAddress",
"storageKey": null "storageKey": null
}, },
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "position",
"storageKey": null
},
{ {
"alias": null, "alias": null,
"args": null, "args": null,
@@ -183,16 +191,16 @@ return {
] ]
}, },
"params": { "params": {
"cacheID": "634c2845825a02a0343c3211b41c90a0", "cacheID": "4065779551f13f5555fa8a0f1b1ae54c",
"id": null, "id": null,
"metadata": {}, "metadata": {},
"name": "CreatePeopleDialogMutation", "name": "CreatePeopleDialogMutation",
"operationKind": "mutation", "operationKind": "mutation",
"text": "mutation CreatePeopleDialogMutation(\n $input: CreatePeopleInput!\n) {\n createPeople(input: $input) {\n peopleEdge {\n node {\n id\n fullName\n primaryEmailAddress\n kind\n additionalEmailAddresses\n }\n }\n }\n}\n" "text": "mutation CreatePeopleDialogMutation(\n $input: CreatePeopleInput!\n) {\n createPeople(input: $input) {\n peopleEdge {\n node {\n id\n fullName\n primaryEmailAddress\n position\n kind\n additionalEmailAddresses\n }\n }\n }\n}\n"
} }
}; };
})(); })();
(node as any).hash = "867aad1276c26bd787ddf80c6f166abe"; (node as any).hash = "1fbca12cb827104dc700c70a677f92aa";
export default node; export default node;

View File

@@ -13,6 +13,7 @@ import { EmailsField } from "/components/form/EmailsField";
const schema = z.object({ const schema = z.object({
fullName: z.string().min(1), fullName: z.string().min(1),
primaryEmailAddress: z.string().email(), primaryEmailAddress: z.string().email(),
position: z.string().min(1).nullable(),
additionalEmailAddresses: z.preprocess( additionalEmailAddresses: z.preprocess(
// Empty additional emails are skipped // Empty additional emails are skipped
(v) => (v as string[]).filter((v) => !!v), (v) => (v as string[]).filter((v) => !!v),
@@ -32,6 +33,7 @@ export default function PeopleProfileTab() {
kind: people.kind, kind: people.kind,
fullName: people.fullName, fullName: people.fullName,
primaryEmailAddress: people.primaryEmailAddress, primaryEmailAddress: people.primaryEmailAddress,
position: people.position,
additionalEmailAddresses: [...(people.additionalEmailAddresses ?? [])], additionalEmailAddresses: [...(people.additionalEmailAddresses ?? [])],
}, },
}); });
@@ -50,6 +52,7 @@ export default function PeopleProfileTab() {
id: people.id!, id: people.id!,
fullName: data.fullName, fullName: data.fullName,
primaryEmailAddress: data.primaryEmailAddress, primaryEmailAddress: data.primaryEmailAddress,
position: data.position,
additionalEmailAddresses: data.additionalEmailAddresses, additionalEmailAddresses: data.additionalEmailAddresses,
// TODO : make these field optional in the query (server side) // TODO : make these field optional in the query (server side)
kind: people.kind, kind: people.kind,
@@ -65,6 +68,12 @@ export default function PeopleProfileTab() {
<form onSubmit={onSubmit} className="space-y-4"> <form onSubmit={onSubmit} className="space-y-4">
<Card padded className="space-y-4"> <Card padded className="space-y-4">
<Field label={__("Full name")} {...register("fullName")} type="text" /> <Field label={__("Full name")} {...register("fullName")} type="text" />
<Field
label={__("Position")}
{...register("position")}
type="text"
placeholder={__("e.g. CEO, CFO, etc.")}
/>
<Field <Field
label={__("Primary email")} label={__("Primary email")}
{...register("primaryEmailAddress")} {...register("primaryEmailAddress")}