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

Add Select form field #8815

Merged
merged 14 commits into from
Dec 4, 2024
Merged

Add Select form field #8815

merged 14 commits into from
Dec 4, 2024

Conversation

Devessier
Copy link
Contributor

@Devessier Devessier commented Nov 29, 2024

Closes #8815

I took inspiration from existing parts of the codebase. Please, see the comments I left below.

Remaining questions:

  • I'm not sure about the best way to handle hotkey scopes in the components easily
CleanShot.2024-12-02.at.17.35.16.mp4

@Devessier Devessier self-assigned this Nov 29, 2024

{draftValue.editingMode === 'edit' ? (
<SelectableList
selectableListId={SINGLE_RECORD_SELECT_BASE_LIST}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure about the id to use here.

}: FormSelectFieldInputProps) => {
const inputId = useId();

const hotkeyScope = InlineCellHotkeyScope.InlineCell;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We might want to create another scope

@Devessier Devessier marked this pull request as ready for review December 2, 2024 16:38
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

PR Summary

This PR introduces a new select form field component and integrates it into the existing form system, with support for variable picking and keyboard navigation.

  • Added new FormSelectFieldInput.tsx component with hotkey scope management and variable support
  • Modified FormFieldInput.tsx to handle select fields using isFieldSelect guard
  • Updated WorkflowEditActionFormRecordCreate.tsx to support metadata-driven select fields
  • Added type safety improvements by replacing FieldMetadataItem with FieldDefinition<FieldMetadata>
  • Implemented keyboard navigation and filtering in select field component following existing patterns

3 file(s) reviewed, 6 comment(s)
Edit PR Review Bot Settings | Greptile

@@ -23,7 +26,6 @@ export const FormFieldInput = ({
}: FormFieldInputProps) => {
return isFieldNumber(field) ? (
<FormNumberFieldInput
key={field.id}
label={field.label}
defaultValue={defaultValue as string | number | undefined}
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: type assertion could be unsafe here - consider adding runtime type checking before the cast

onPersist={onPersist}
field={field}
VariablePicker={VariablePicker}
/>
) : null;
Copy link
Contributor

Choose a reason for hiding this comment

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

style: consider throwing an error for unhandled field types instead of silently returning null

Comment on lines +98 to +101
const onCancel = () => {
if (draftValue.type !== 'static') {
throw new Error('Can only be called when editing a static value');
}
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Consider handling this error case more gracefully instead of throwing - could lead to runtime crashes if state gets corrupted

Comment on lines +195 to +201
const optionIds = [
`No ${field.label}`,
...filteredOptions.map((option) => option.value),
];
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: optionIds includes 'No {field.label}' but this ID isn't handled in handleSelectEnter - could cause undefined behavior

Copy link
Contributor

@martmull martmull left a comment

Choose a reason for hiding this comment

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

Nice work, some comments

Comment on lines 218 to 224
<Tag
preventShrink
color={selectedOption.color}
text={selectedOption.label}
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

can you use <SelectFieldDisplay component here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've considered using the existing FieldInput components; however, they rely on the FieldContext. See the useSelectField and useSelectFieldDisplay hooks. We don't currently provide this context. If we do, we will couple the FormFieldInputs with the usual FieldInputs. This might be considered, but it is an opinionated choice.

I duplicated most of SelectFieldInput's code. We might reconsider this and find a way to reduce the code.

Copy link
Contributor

Choose a reason for hiding this comment

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

we might create a new components to decouple the component design definition from the fieldContext. Thus we will be able to factorize

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I created a component to unify what we display for the display mode of a select input.

Copy link
Contributor

Choose a reason for hiding this comment

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

nice, is it possible to do the same with the input mode?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would you like to extract this part?

<SelectableList
  selectableListId={SINGLE_RECORD_SELECT_BASE_LIST}
  selectableItemIdArray={optionIds}
  hotkeyScope={hotkeyScope}
  onEnter={(itemId) => {
    const option = filteredOptions.find(
      (option) => option.value === itemId,
    );
    if (isDefined(option)) {
      onSubmit?.(() => persistField(option.value));
      resetSelectedItem();
    }
  }}
>
  <SelectInput
    parentRef={selectWrapperRef}
    onOptionSelected={handleSubmit}
    options={fieldDefinition.metadata.options}
    onCancel={onCancel}
    defaultOption={selectedOption}
    onFilterChange={setFilteredOptions}
    onClear={
      fieldDefinition.metadata.isNullable ? handleClearField : undefined
    }
    clearLabel={fieldDefinition.label}
    hotkeyScope={hotkeyScope}
  />
</SelectableList>

I'm not sure it would be great, as I would end up with a component taking +10 unrelated props.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For me, the SelectableList and SelectInput components are well enough abstracted. They own the design decisions. These two components are meta components with business logic. I don't think we need to go deeper into the refactoring.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think yes you should extract this part into packages/twenty-front/src/modules/ui/field/input/components in a SelectInput component and use that in FormSelectFieldInput and in SelectFieldInput

Copy link
Contributor

Choose a reason for hiding this comment

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

Like this, the way to display or modify a SELECT value is uniquely defined throughout the application

</StyledDisplayModeContainer>

{draftValue.editingMode === 'edit' ? (
<SelectableList
Copy link
Contributor

Choose a reason for hiding this comment

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

same here, can you use <SelectFieldInput component?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The same reasoning applies here: #8815 (comment)

Comment on lines 66 to 73
const availableFieldMetadataItems = objectMetadataItem.fields
.filter(
(fieldMetadataItem) =>
fieldMetadataItem.type !== FieldMetadataType.Relation &&
!fieldMetadataItem.isSystem &&
fieldMetadataItem.isActive,
)
.sort((fieldMetadataItemA, fieldMetadataItemB) =>
Copy link
Contributor

Choose a reason for hiding this comment

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

@thomtrp, we should not forget to do that also for Update Action when developed

@Devessier Devessier force-pushed the add-select-form-field branch from 664c2b7 to 943dca6 Compare December 3, 2024 10:15
Comment on lines 1 to 13
import { Tag, ThemeColor } from 'twenty-ui';

type SelectFieldDisplayContentProps = {
color: ThemeColor;
label: string;
};

export const SelectFieldDisplayContent = ({
color,
label,
}: SelectFieldDisplayContentProps) => {
return <Tag preventShrink color={color} text={label} />;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

think you should move that to packages/twenty-front/src/modules/ui/field/display/components and call it SelectDisplay

@Devessier Devessier force-pushed the add-select-form-field branch from 278d2f1 to 09f15d0 Compare December 4, 2024 11:44
Copy link
Contributor

@martmull martmull left a comment

Choose a reason for hiding this comment

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

LGTM

@Devessier Devessier merged commit 9142bdf into main Dec 4, 2024
19 checks passed
@Devessier Devessier deleted the add-select-form-field branch December 4, 2024 14:39
Copy link

github-actions bot commented Dec 4, 2024

Thanks @Devessier for your contribution!
This marks your 33rd PR on the repo. You're top 1% of all our contributors 🎉
See contributor page - Share on LinkedIn - Share on Twitter

Contributions

mdrazak2001 pushed a commit to mdrazak2001/twenty that referenced this pull request Dec 4, 2024
Closes twentyhq#8815

I took inspiration from existing parts of the codebase. Please, see the
comments I left below.

Remaining questions:

- I'm not sure about the best way to handle hotkey scopes in the
components easily



https://github.com/user-attachments/assets/7a6dd144-d528-4f68-97cd-c9181f3954f9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants