11447bd96f
Fixes #23339 Follow-up to #23410, which fixed the neighbouring issue (#23341) for users *without* the `DATA_MODEL` permission. ## Problem In #23339 the reporter added a multiselect field to Person and then found the inline "create option" prompt unresponsive. They clearly have `DATA_MODEL` permission, since they just created the field, so the permission check isn't what's blocking them. The blocker is the *other* precondition. Both hooks read the object name from the router: ```ts const { objectNamePlural } = useParams(); ``` `objectNamePlural` only exists on record index routes (`/objects/:objectNamePlural`). Record **detail** pages are `/object/:objectNameSingular/:objectRecordId`, so on a record page the param is `undefined` and: - `useCanAddSelectOption` returns false via `isNonEmptyString(objectNamePlural)` - `useAddSelectOption` bails out at `if (!fieldName || !objectNamePlural) return;` So the action was dead on record pages for **every** user, admins included, and the navigation target it needed was never reachable from there. ## Fix Resolve the field and its object from `fieldMetadataId`, which `FieldDefinition` already carries, instead of reading the object name off the URL: ```ts const { fieldMetadataItem, objectMetadataItem } = useFieldMetadataItemById(fieldMetadataId); ``` This drops the route dependency entirely, so the action behaves the same wherever the field is rendered, and `canAddSelectOption` now reflects only the real permission check. It also lets both hooks take a single `fieldMetadataId` argument: `fieldMetadataItem.name` is the same value the callers were previously passing as `fieldName`, so that parameter is no longer needed. Resolving both values from one id means the guard and the action can't disagree about which field they're describing. `useFieldMetadataItemById` is used rather than `useFieldMetadataItemByIdOrThrow` because a lookup miss should disable the prompt, not crash the field input. ## Reproduction On the code the reporter was running (immediately before #23410), as an **admin** with full `DATA_MODEL`, on a company record page, typing a value matching no option: - `Add "…" to options` renders - clicking it does nothing — URL unchanged, no navigation - pressing <kbd>Enter</kbd> does nothing either which matches #23339 exactly, including the note about the Enter keypress. After #23410 the same root cause shows up differently: the prompt is no longer rendered at all on record pages, since the guard it's now gated on is false there. Still broken, just silent. ## Testing Verified manually on a local instance, swapping only these files between three states and re-running the identical steps on the same cell. | code state | user | route | result | |---|---|---|---| | before #23410 | Admin | `/object/company/:id` | prompt shown, click and Enter both do nothing | | current main | Admin | `/object/company/:id` | prompt not shown, action unreachable | | **this PR** | Admin | `/object/company/:id` | prompt shown, navigates to `/settings/objects/companies/workPolicy?newOption=…` | | **this PR** | Admin | `/objects/tasks` (`Status`, single select) | still works, navigates to `/settings/objects/tasks/status?newOption=…` | | **this PR** | Member (no `DATA_MODEL`) | `/object/company/:id` | prompt not shown | The settings form opens with the typed value prefilled alongside the existing options, so the end-to-end flow works from a record page for the first time. The Member row confirms #23341 stays fixed: dropping the route dependency doesn't weaken the permission gate. The single-select row covers `SelectFieldInput`, which takes the same change. `nx lint:diff-with-main twenty-front` and `nx typecheck twenty-front` both pass.