fix: hide add-select-option prompt for users without data model permission (#23410)
Fixes #23341 ## Problem A user whose role lacks the `DATA_MODEL` permission flag still saw the `Add "…" to options` prompt when typing a value that matched no option in a multiselect. Clicking it did nothing. `MultiSelectInput` renders `AddSelectOptionMenuItem` based purely on whether the callback exists: ```tsx {onAddSelectOption && searchFilter && filteredOptionsInDropDown.length === 0 && ( ``` `MultiSelectFieldInput` always passed a callback, and did the permission check *inside* it: ```tsx const handleAddSelectOption = (optionName: string) => { if (!canAddSelectOption) { return; } addSelectOption(optionName); }; ``` So the guard suppressed the click but not the render, which is exactly the reported symptom: the prompt is visible and inert. ## Fix Gate at the prop instead of inside the handler, so the menu item is never rendered when the action is unavailable: ```tsx onAddSelectOption={canAddSelectOption ? addSelectOption : undefined} ``` The wrapper is now redundant and removed; `addSelectOption` already has the matching `(optionName: string) => void` signature. `SelectFieldInput` had the byte-identical bug (`SelectInput` gates on `onAddSelectOption &&` the same way), so it gets the same change. ## Note on scope `useCanAddSelectOption` requires `objectNamePlural` from the route in addition to the permission flag: ```ts const canAddSelectOption = userHasPermissionToEditDataModel && isNonEmptyString(fieldName) && isNonEmptyString(objectNamePlural); ``` Record *detail* pages (`/object/:objectNameSingular/:recordId`) have no `objectNamePlural`, so the prompt was dead there for **every** user, admins included. This change hides it in that case too, which is the correct behavior since the click could never have worked. ## Testing Verified manually against a local instance, toggling the patch in and out on the same cell so before/after is directly comparable. Company `Work Policy` (multiselect) in the Companies table view, typing a string that matches no option: | user | route | before | after | |---|---|---|---| | Member (no `DATA_MODEL`) | `/objects/companies` | prompt shown, click does nothing | prompt hidden | | Admin | `/objects/companies` | prompt shown, click works | prompt shown, click works (navigates to `/settings/objects/companies/workPolicy?newOption=…`) | | Admin | `/object/company/:id` | prompt shown, click does nothing | prompt hidden | `nx lint:diff-with-main twenty-front` and `nx typecheck twenty-front` both pass. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/23410?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+1
-8
@@ -41,13 +41,6 @@ export const MultiSelectFieldInput = () => {
|
||||
onSubmit?.({ newValue: draftValue });
|
||||
};
|
||||
|
||||
const handleAddSelectOption = (optionName: string) => {
|
||||
if (!canAddSelectOption) {
|
||||
return;
|
||||
}
|
||||
addSelectOption(optionName);
|
||||
};
|
||||
|
||||
return (
|
||||
<MultiSelectInput
|
||||
selectableListComponentInstanceId={
|
||||
@@ -58,7 +51,7 @@ export const MultiSelectFieldInput = () => {
|
||||
onCancel={handleCancel}
|
||||
onOptionSelected={handleOptionSelected}
|
||||
values={draftValue}
|
||||
onAddSelectOption={handleAddSelectOption}
|
||||
onAddSelectOption={canAddSelectOption ? addSelectOption : undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
+1
-8
@@ -55,13 +55,6 @@ export const SelectFieldInput = () => {
|
||||
onCancel?.();
|
||||
};
|
||||
|
||||
const handleAddSelectOption = (optionName: string) => {
|
||||
if (!canAddSelectOption) {
|
||||
return;
|
||||
}
|
||||
addSelectOption(optionName);
|
||||
};
|
||||
|
||||
const handleSubmit = (option: SelectOption) => {
|
||||
onSubmit?.({ newValue: option.value });
|
||||
|
||||
@@ -110,7 +103,7 @@ export const SelectFieldInput = () => {
|
||||
: undefined
|
||||
}
|
||||
clearLabel={fieldDefinition.label}
|
||||
onAddSelectOption={handleAddSelectOption}
|
||||
onAddSelectOption={canAddSelectOption ? addSelectOption : undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user