-
-
Notifications
You must be signed in to change notification settings - Fork 336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Send null for string like columns that don't allow empty strings when cell is cleared #4030
base: develop
Are you sure you want to change the base?
Send null for string like columns that don't allow empty strings when cell is cleared #4030
Conversation
90fa086
to
3a99532
Compare
@seancolsen does this fit the requirement? Please let me know if any changes are required. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this, @aniketkulkarni17. This kind of works, but has some issues...
Issues
-
For Email and URI columns, the front end is sending
null
to the API (good). But it doesn't displayNULL
to the user afterwards. If you click Refresh, then you seeNULL
, but that's not great UX. -
Database types like
time without time zone
are no included in your string set and thus don't receive this fix. We could potentially address that by adding more database types to your string set. But I'd rather fix this at a lower level. -
This PR has a failing test because the code in your changes is not formatted correctly. We use Prettier to automatically format code. You can read more in our docs about using it. Personally, I have VS Code configured to format on save which I love.
docker exec -it -w /code/mathesar_ui mathesar_service_dev npx prettier --write .
I'd like you to take a different direction with the overal implementation of this PR, but when doing so, make sure to run Prettier at some point in your workflow and commit the changes it makes. The changes from Prettier don't need to be in a separate commit but it's also fine if they are.
New direction
I said I'd like you to fix this at a lower level, and part of the reason is that the UI for inputting a cell value actually gets used in a lot of places. Not just within the sheet, but also the record page, the default value setting, the filter conditions on the table page, the filter transformations within the data explorer, the record selector etc. Some of those might be unaffected by this bug due to higher-level logic that handles null values, but suffice to say: the clean way to handle this is to do it at a low level, per-type.
(As a disclaimer, I'll say that this work touches on some of the messiest and hard-to-work-with parts of our front end codebase, so, sorry about that! You're going to end up on somewhat of a wild goose chase.)
Recall that I said:
Interestingly, the Duration type actually already works as expected.
Let's dig deeper to see why it works for Duration...
-
Go to src/stores/abstract-types/type-configs/ and you'll see one file for each UI type. In the code, a "UI Type" is called an "AbstractType". But the idea is that each UI type potentially maps to multiple database types. And one database type maps to one UI type. The default object exported from each of those files defines the UI type. Look at the
cellInfo.type
property, and you'll see the name of the cell type that we use to work with this UI type. So in duration.ts we see acellInfo.type
of 'duration'. Good. (But other UI types, like Email won't necessarily line up one-for-one like this!) -
Now if you look in the src/components/cell-fabric/data-types/ directory, you'll see files which match up with those cell types. So within duration.ts (same file name, different directory) you'll see that getInput() is returning a
FormattedInputProps
component with props that specify that theformatter
is to be aDurationFormatter
. Ok cool. So, what is aDurationFormatter
, and how does it work? -
In src/utils/duration/DurationFormatter.ts, we're specifying a parse() function. That's the entry point to the logic that translates the string the user entered into a standardized value. Notice that within ParseResult the value can be
T | null
, meaning that the return value of the parse function should benull
to represent aNULL
cell value. Cool. So where is the logic that returnsnull
for an empty string input? -
Higher up in
DurationFormatter.ts
, we have thislet cleanedInput = userInput.trim(); if (cleanedInput === '') { return null; }
Boom! That' exactly what we want to see. Not only does it translate an empty string to a
null
value, it also trims the string first. Brilliant!
So, what I'd like you to do to fix this issue is walk through the same steps above but for the problematic UI Types (not database types). So if we start with the Date type, we'd go to step 1.
and navigate to src/stores/abstract-types/type-configs/
. See that cellInfo.type
is date
. Then go to src/components/cell-fabric/data-types/
and open date.ts
, find the component returned from getInput()
, look at its props, and eventually get to DateTimeFormatter
which has a parse function that doesn't handle empty strings correctly. Wonderful. Here is where we need to make the fix for the Date type.
We could consider adding a new abstraction like some sort of intermediate formatter that automatically handles empty strings, and then we'd use that formatter as a basis for the custom formatters used in these types. But I'm not sure that's worth it at this stage.
URI and Email are going to be a little trickier, so leave those for last. We'll probably need to add a new email.ts
file in src/components/cell-fabric/data-types/
. I'm not entirely sure.
Fixes #3784
Technical details
Screenshots
Before
After
Checklist
Update index.md
).develop
branch of the repositoryvisible errors.
Developer Certificate of Origin
Developer Certificate of Origin