Skip to content
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

Enum custom field UI #2210

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open

Enum custom field UI #2210

wants to merge 17 commits into from

Conversation

niklasva82
Copy link
Member

@niklasva82 niklasva82 commented Sep 29, 2024

Description

This PR adds UI for enum_text type custom fields.

Screenshots

image
Screenshot from 2024-09-29 12-54-36
Screenshot from 2024-10-04 00-26-35
Screenshot from 2024-10-04 00-25-33
Screenshot from 2024-10-04 00-25-19

Changes

  • Maps key value to label value in person details
  • Select box to select option in edit person modal
  • Adds mapping between values and options in import configuration
  • Adds possibility of choosing enum field option in smart search
  • Adds view column for enum fields, mapping key to option label

Notes to reviewer

This requires backend PR: zetkin/zetkin-platform#848

Copy link
Member

@richardolsson richardolsson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would love to try this but the preview build is failing. 😞

Please fix all of the linting and formatting errors before a more thorough review.

@richardolsson
Copy link
Member

Please install the pre-commit hook, as suggested in the CONTRIBUTING.md file, to avoid committing code with formatting and type issues.

@niklasva82
Copy link
Member Author

Please install the pre-commit hook, as suggested in the CONTRIBUTING.md file, to avoid committing code with formatting and type issues.

Yes done now

…n renamed to PersonFieldColumn, it was only used by PersonField.
Copy link
Member

@richardolsson richardolsson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've taken an initial look, mostly focusing on the functional side (using the UI and seeing how it works). In that process I did find some problems that I've highlighted below. I will move on to do a full code review tomorrow but didn't want to hold you up if you do keep on working today.

Copy link
Member

@richardolsson richardolsson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work on this major new feature! I have tried a local build (with some changes to match recent changes to the backend) and I have reviewed all the code. Most of it works really well! 💯

I did find some bugs, and some things that I think can be improved in the code, as well as a bunch of things where I don't feel entirely comfortable but can definitely be persuaded if I hear your reasoning. Please have a read and reach out if you want to discuss.

src/features/import/l10n/messageIds.ts Show resolved Hide resolved
src/features/import/hooks/useColumn.ts Show resolved Hide resolved
src/features/import/hooks/useColumn.ts Outdated Show resolved Hide resolved
Comment on lines +57 to +66
if (column.kind === ColumnKind.ENUM) {
column.mapping.forEach((mappedColumn) => {
if (mappedColumn.value === row[colIdx]) {
personPreviewOp.data = {
...personPreviewOp.data,
[`${column.field}`]: row[colIdx],
};
}
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test case to createPreviewData.spec.ts that encompasses this. Maybe this code is related to the fact that the preview doesn't seem to be working (see separate comment) and you can try to reproduce that in a test and TDD a solution?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test should verify that mapping empty values work as expected. Right now it does not seem to be working. The store looks ok after mapping an empty value, but the preview does not render anything. I'm not sure if it's here, or if it's the UI.

image

src/features/smartSearch/l10n/messageIds.ts Outdated Show resolved Hide resolved
src/features/smartSearch/l10n/messageIds.ts Outdated Show resolved Hide resolved
Copy link
Member

@richardolsson richardolsson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I commented in two places where "" is used and need to be translated to null. Not sure if there are more? How about Smart Search?

if (mappedColumn.value === row.data[colIdx] && mappedColumn.key) {
personImportOps[rowIndex].data = {
...personImportOps[rowIndex].data,
[`${column.field}`]: mappedColumn.key,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be translated to null if "" (could also be solved elsewhere, e.g. closer to the UI, but doing it here should make it testable).

fullWidth
label={field.title}
onChange={(ev) => {
onChange(field.slug, ev.target.value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we need to translate from "" to null.

valueGetter: (params) => {
const cell = params.row[params.field];
if (column.config.enum_choices) {
this.enumChoices = column.config.enum_choices;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting this.enumChoices here and then relying on it in several other places feels risky. This instance is not for one specific column, it's for all columns of this type. So there is nothing guaranteeing (at least not type/syntax-wise) that this method will be called before, say, cellToString() or that this method can't be called for another method before calling cellToString().

Most likely this will fail for views that have more than one column of enum type.

Comment on lines +13 to +15
if (this.enumChoices) {
const choice = this.enumChoices.find((c) => c.key == cell);
return choice ? choice.label : '';
Copy link
Member

@richardolsson richardolsson Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell, this never happens when exporting a CSV, because this code is executed on the backend where getColDef will have never been called, and that's where the this.enumChoices state is (riskily) set.

I'm thinking it makes sense to pass in column to these functions instead.

Copy link
Member

@richardolsson richardolsson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've gone over this again and I did find some additional bugs. Details below.

Comment on lines +112 to +121
if (column.kind === ColumnKind.ENUM) {
column.mapping.forEach((mappedColumn) => {
if (mappedColumn.value === row.data[colIdx] && mappedColumn.key) {
personImportOps[rowIndex].data = {
...personImportOps[rowIndex].data,
[`${column.field}`]: mappedColumn.key,
};
}
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A test should make sure that mapping empty values work as expected. Right now, it does not seem to be working. Configuring empty values using the UI yields the expected configuration in the store, but when submitted to the backend the mappings for "empty values" seem lost.

image

image

Comment on lines +57 to +66
if (column.kind === ColumnKind.ENUM) {
column.mapping.forEach((mappedColumn) => {
if (mappedColumn.value === row[colIdx]) {
personPreviewOp.data = {
...personPreviewOp.data,
[`${column.field}`]: row[colIdx],
};
}
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test should verify that mapping empty values work as expected. Right now it does not seem to be working. The store looks ok after mapping an empty value, but the preview does not render anything. I'm not sure if it's here, or if it's the UI.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants