From ff49b86e59573ae36558803186bbef0cc5818675 Mon Sep 17 00:00:00 2001 From: Pavel Baluev Date: Fri, 9 Feb 2024 15:59:09 +0100 Subject: [PATCH] Make an onboarding contact field required for specified roles --- .../client/components/UserRolesEditorModal.tsx | 2 +- src/modules/users/client/components/Welcome.tsx | 14 ++++++++++---- src/modules/users/metadata-schema.ts | 1 + .../20231206175252_users_add-roles-list.js | 9 +++++++++ src/modules/users/server/router.ts | 1 + src/modules/users/types.ts | 1 + 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/modules/users/client/components/UserRolesEditorModal.tsx b/src/modules/users/client/components/UserRolesEditorModal.tsx index 42942dce..c73e79c9 100644 --- a/src/modules/users/client/components/UserRolesEditorModal.tsx +++ b/src/modules/users/client/components/UserRolesEditorModal.tsx @@ -93,7 +93,7 @@ export const UserRolesEditorModal: React.FC<{ }, [props.onChange, props.onClose, groupedRoleIds, unsupportedRoleIds]) return ( - +
diff --git a/src/modules/users/client/components/Welcome.tsx b/src/modules/users/client/components/Welcome.tsx index cb2967c4..de29be28 100644 --- a/src/modules/users/client/components/Welcome.tsx +++ b/src/modules/users/client/components/Welcome.tsx @@ -381,13 +381,19 @@ const Contacts: React.FC<{ onSubmit: (value: { contacts: Record }) => void onMoveBack: () => void }> = ({ metadata, onSubmit, onMoveBack }) => { + const me = useStore(stores.me) const metadataFields = Object.keys(metadata) const [state, setState] = React.useState>({}) const [isValid, setIsValid] = React.useState(false) - const requiredFieldsIds: string[] = metadataFields.filter( - (contactId) => metadata[contactId].required - ) + const requiredFieldsIds: string[] = metadataFields.filter((contactId) => { + const contactField = metadata[contactId] + const userRoles = me?.roles || [] + return ( + contactField.required || + fp.hasIntersection(contactField.requiredForRoles, userRoles) + ) + }) const [selectedFieldIds, setSelectedFieldIds] = React.useState(requiredFieldsIds) @@ -462,7 +468,7 @@ const Contacts: React.FC<{ } label={x.label} containerClassName="w-full mb-4" - required={x.required} + required={requiredFieldsIds.includes(x.id)} /> ) })} diff --git a/src/modules/users/metadata-schema.ts b/src/modules/users/metadata-schema.ts index f9a6506b..ffbc253c 100644 --- a/src/modules/users/metadata-schema.ts +++ b/src/modules/users/metadata-schema.ts @@ -4,6 +4,7 @@ const contactFieldSchema = z.object({ label: z.string().optional(), placeholder: z.string().optional(), required: z.boolean().optional(), + requiredForRoles: z.array(z.string()).default([]), prefix: z.string().optional(), // Optional because not all fields have it }) diff --git a/src/modules/users/server/migrations/20231206175252_users_add-roles-list.js b/src/modules/users/server/migrations/20231206175252_users_add-roles-list.js index e2cafc2f..709fdcfd 100644 --- a/src/modules/users/server/migrations/20231206175252_users_add-roles-list.js +++ b/src/modules/users/server/migrations/20231206175252_users_add-roles-list.js @@ -22,6 +22,15 @@ module.exports = { `, { transaction } ) + await queryInterface.changeColumn( + 'users', + 'role', + { + type: DataTypes.STRING, + allowNull: true, + }, + { transaction } + ) }) }, async down({ context: queryInterface, appConfig }) { diff --git a/src/modules/users/server/router.ts b/src/modules/users/server/router.ts index ab62a020..a32ad6b0 100644 --- a/src/modules/users/server/router.ts +++ b/src/modules/users/server/router.ts @@ -638,6 +638,7 @@ const adminRouter: FastifyPluginCallback = async function (fastify, opts) { if (!roles.length) continue const users = await fastify.db.User.findAll({ where: { + id: { [Op.not]: req.params.userId }, roles: { [Op.overlap]: roles, }, diff --git a/src/modules/users/types.ts b/src/modules/users/types.ts index d2fd565e..b3d12c8b 100644 --- a/src/modules/users/types.ts +++ b/src/modules/users/types.ts @@ -198,6 +198,7 @@ export type ProfileField = { required: boolean placeholder?: string prefix?: string + requiredForRoles: string[] } export type ProfileFieldsMetadata = {