ee08060798
Closes [1918](https://github.com/twentyhq/core-team-issues/issues/1918). - For the first point in the issue, we just show the deactivated entries along with the deactivated text. --- - For the second point, we show a banner and control the enabled/disabled state of save button depending on whether we're allowing the user to create table with the typed name. - For example, we do not want to allow the user to create a table with reserved name, so we disable the save button without showing a banner. - Similarly, we do not want the user to create a table with a name that already exists in the database. In this case, we show a banner and we also disable the save button. - Finally, we do not want to allow the user to create a table where singular and plural name are the same. Therefore, we disable the save button for names like `works`. --- - For the third point, if we add the delete button, it logically means that we allow the user to delete a custom object/field even it has not been deactivated yet, so did that. - Upon deleting the object/field, if we wait for the metadata to refetch before we navigate, this is what we see because the path does not exist any longer after deletion and we're waiting for refetch on the path until we navigate away. https://github.com/user-attachments/assets/dbe0569c-db88-4285-851f-22551b1ca81e - To avoid this page from appearing, I replaced awaiting refetch to not awaiting refetch and redirecting while the refetch happens in the background. - Therefore, when we delete something, there is a slight delay for when it is actually cleared out from the list, but the Not Found view does not appear on the screen. https://github.com/user-attachments/assets/47f49579-ce51-4d6a-b857-72046247bb4b - I tried optimistically removing the object/field from the metadata, but it leads to some issues (crashes the app) and I have not been able to find a solution for it yet. - Therefore, instead of getting stuck at perfection and blocking myself, I stopped getting into the issue further and created this PR by ensuring that the desired functionality works. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Display deactivated objects/fields by default, add delete actions with confirmation, and unify metadata name computation (auto-suffix reserved keywords) across front/back with conflict checks in object creation. > > - **Frontend (Settings/Data Model)**: > - **Visibility/UX**: Show `Deactivated` labels for objects/fields; filters default to include inactive (`showDeactivated`/`showInactive` true); replace field action dropdown with chevron link. > - **Delete flows**: Add delete buttons for custom objects/fields with confirmation modals and background refetch to avoid Not Found flashes. > - **Creation/Edit validation**: Add name conflict detection banner in `SettingsDataModelObjectAboutForm` and disable Save on conflicts; simplify `metadataLabelSchema` to use computed name; form fields validate on change and sync API names. > - **Shared (twenty-shared/metadata)**: > - Add `computeMetadataNameFromLabel` util (slugify+camelCase) and `RESERVED_METADATA_NAME_KEYWORDS`; auto-append `Custom` to reserved names; export constants/utilities. > - **Backend**: > - Migrate to shared `computeMetadataNameFromLabel`; update validators to use shared reserved keywords with new messages; allow deletion of active custom fields/objects (keep standard guards); adjust services/decorators accordingly. > - **Tests/Stories**: > - Update unit/integration snapshots for new reserved-name messages and behaviors; add missing i18n/router decorators in stories. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 5b126155606f6dbc8f7f91e2192cffb7bd2ebd2c. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Félix Malfait <felix.malfait@gmail.com> Co-authored-by: Félix Malfait <felix@twenty.com>
12 lines
448 B
TypeScript
12 lines
448 B
TypeScript
import { computeMetadataNameFromLabel as computeMetadataNameFromLabelCore } from 'twenty-shared/metadata';
|
|
|
|
// Frontend-specific wrapper that returns empty string on error instead of throwing
|
|
// This is needed for form validation and UI components that prefer graceful degradation
|
|
export const computeMetadataNameFromLabel = (label: string): string => {
|
|
try {
|
|
return computeMetadataNameFromLabelCore(label);
|
|
} catch {
|
|
return '';
|
|
}
|
|
};
|