This PR introduces refactors and tradeoffs in the API around the events of field input. # Refactored usePersistField The hook `usePersistField` has been refactored to be used anywhere in the app, not just inside a FieldContext. This was meant to solve a bug at the beginning but now it is just used once in `RecordDetailRelationSection` outside of the context, still this is better to have this hook like that for future use cases. We also introduce `usePersistFieldFromFieldInputContext`, for an easier API inside a FieldContext. # Introduced a new `FieldInputEventContext` To remove the drill-down of events, we introduce `FieldInputEventContext`, this allows to set only once the handlers / events. In practice it allows to have an easier time maintaining the events for the many different field inputs, because it matches the pattern we already use of taking everything from a context (`FieldContext`). # Removed drill-down from FieldInput The heavy drill-down in FieldInput has been completely removed, since everything can be derived from `FieldContext` and `FieldInputEventContext`. Also there was some readonly and other specific props, but they were all drilled down from FieldContext, so it was easier to just use FieldContext where needed. # Refactored events of `MultiItemFieldInputProps` The component `MultiItemFieldInputProps` has a contrived API, here we just remove the complex part that was persisting from inside. We now only give a classic API with `onChange` and `onEscape` the rest is left to higher levels, where it should be, because this generic component shouldn't be aware of persisting things. # Extracted the parsing logic of persisted values For each input field component, we now have a clear util that was before bound to the persist call, # Tradeoff with persist times The tradeoff before was that persistField was called anywhere, before exiting the component sometimes, now it is only called by the higher levels like table or show page, which handles this abstraction. This could be challenged, however I think that having a lot of different events, and not just `handleSubmit` and `handleCancel`, convey enough meaning for the higher levels to decide what to do in each case. A `skipPersist` argument was added in events in the rare edge cases where we want to voluntarily skip persisting even with a submit or escape, but that could be challenged because we could also say that we should use cancel for that and stick to that convention. # Handling of the bug in `ActivityRichTextEditor` Initially this refactor was prioritized for solving this bug, which was very annoying for the users. But while fixing it with the new persistField hook I just understood that the problem is not just for record title cells but for anything that is open when we click on a rich text editor. The issue is described here : https://github.com/twentyhq/core-team-issues/issues/1317 So right now I just let it as is. # Stories The stories were checking that a request was sent in some cases where persist was called before a component exiting, now that persist is only called by higher-levels I just removed those tests from the stories, because that should be the responsibility of higher levels. Also a helper `getFieldInputEventContextProviderWithJestMocks` was created that exposes a context and jest mock functions for testing this new API in stories. # Miscellaneous Deactivated tui with nx by default, because it can be annoying.
The #1 Open-Source CRM
🌐 Website · 📚 Documentation · Roadmap ·
Discord ·
Figma
Installation
See:
🚀 Self-hosting
🖥️ Local Setup
Does the world need another CRM?
We built Twenty for three reasons:
CRMs are too expensive, and users are trapped. Companies use locked-in customer data to hike prices. It shouldn't be that way.
A fresh start is required to build a better experience. We can learn from past mistakes and craft a cohesive experience inspired by new UX patterns from tools like Notion, Airtable or Linear.
We believe in Open-source and community. Hundreds of developers are already building Twenty together. Once we have plugin capabilities, a whole ecosystem will grow around it.
What You Can Do With Twenty
Please feel free to flag any specific needs you have by creating an issue.
Below are a few features we have implemented to date:
- Personalize layouts with filters, sort, group by, kanban and table views
- Customize your objects and fields
- Create and manage permissions with custom roles
- Automate workflow with triggers and actions
- Emails, calendar events, files, and more
Personalize layouts with filters, sort, group by, kanban and table views
Customize your objects and fields
Create and manage permissions with custom roles
Automate workflow with triggers and actions
Emails, calendar events, files, and more
Stack
- TypeScript
- Nx
- NestJS, with BullMQ, PostgreSQL, Redis
- React, with Recoil, Emotion and Lingui
Thanks
Thanks to these amazing services that we use and recommend for UI testing (Chromatic), code review (Greptile), catching bugs (Sentry) and translating (Crowdin).
Join the Community
- Star the repo
- Subscribe to releases (watch -> custom -> releases)
- Follow us on Twitter or LinkedIn
- Join our Discord
- Improve translations on Crowdin
- Contributions are, of course, most welcome!




