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 Raw JSON Form Field Input #9078

Merged
merged 7 commits into from
Dec 18, 2024
Merged

Add Raw JSON Form Field Input #9078

merged 7 commits into from
Dec 18, 2024

Conversation

Devessier
Copy link
Contributor

@Devessier Devessier commented Dec 16, 2024

  • Implemented the renderText method for VariableTag. This method returns the variable attribute of the node, i.e. {{test}}.
  • Used the editor.getText() function to simply get the textual representation of the field without relying on editor.getJSON() and parseEditorContent.
  • Implemented the RawJSON form field, which is heavily based on the TextVariableEditor component.
    • This component is inspired from the RawJsonFieldInput field, especially the JSON validation.

Closes https://github.com/twentyhq/private-issues/issues/180

@Devessier Devessier force-pushed the add-uuid-form-field-input branch 2 times, most recently from 480eb2e to 34e959b Compare December 17, 2024 15:18
@Devessier Devessier force-pushed the add-uuid-form-field-input branch from 34e959b to 90e7dc2 Compare December 17, 2024 16:14
@Devessier Devessier marked this pull request as ready for review December 17, 2024 17:37
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

Implemented a new FormRawJsonFieldInput component for handling JSON validation and variable tag insertion in form fields, with support for variable tags in JSON content.

  • Added FormRawJsonFieldInput.tsx with JSON validation that replaces variable tags with '0' for validation and converts empty strings to null
  • Added comprehensive Storybook tests in FormRawJsonFieldInput.stories.tsx covering JSON validation, variable insertion, and edge cases
  • Added renderText method to variableTag.ts to return raw variable attributes (e.g., '{{test}}')
  • Exported CAPTURE_VARIABLE_TAG_REGEX and CAPTURE_ALL_VARIABLE_TAG_INNER_REGEX constants for reuse in variable tag parsing
  • Modified FormFieldInput.tsx to support the new RawJson field type

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

) : isFieldRawJson(field) ? (
<FormRawJsonFieldInput
label={field.label}
defaultValue={defaultValue as string | 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 casting to string | undefined may be insufficient for raw JSON - consider using JsonValue type instead to properly handle nested objects and arrays

Comment on lines 61 to 66
await Promise.all([
userEvent.type(editor, '{{ "a": {{ "b" : "d" } }'),

waitFor(() => {
expect(args.onPersist).toHaveBeenCalledWith('{ "a": { "b" : "d" } }');
}),
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Using Promise.all here is unnecessary since there's only one waitFor condition. This could lead to race conditions if more promises are added later.

Comment on lines +200 to +205
await Promise.all([
userEvent.type(editor, `{Backspace>${defaultValueStringLength}}`),

waitFor(() => {
expect(args.onPersist).toHaveBeenCalledWith(null);
}),
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Using Promise.all with a single waitFor condition is unnecessary and could mask timing issues. Consider removing Promise.all wrapper.

Comment on lines 51 to 58
let isValidJson;
try {
JSON.parse(textWithReplacedVariables);

isValidJson = true;
} catch {
isValidJson = false;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Empty catch block silently fails JSON validation. Consider providing feedback to user about invalid JSON format.

Comment on lines 46 to 49
const textWithReplacedVariables = text.replaceAll(
new RegExp(CAPTURE_VARIABLE_TAG_REGEX, 'g'),
'0',
);
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Replacing variables with '0' could validate successfully but produce invalid JSON when actual variable values are longer/shorter. Consider using a placeholder that matches expected value length.

Comment on lines +68 to +76
const handleVariableTagInsert = (variableName: string) => {
if (!isDefined(editor)) {
throw new Error(
'Expected the editor to be defined when a variable is selected',
);
}

editor.commands.insertVariableTag(variableName);
};
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: handleVariableTagInsert throws if editor undefined, but component renders null in that case. This error should never occur - consider removing the check or logging a warning instead.

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

const editor = useTextVariableEditor({
Copy link
Contributor

Choose a reason for hiding this comment

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

style: onUpdate callback is recreated on every render. Consider memoizing with useCallback to prevent unnecessary re-renders.

onPersist: (value: string | null) => void;
readonly?: boolean;
VariablePicker?: VariablePickerComponent;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

not for this PR, but I think we will build a base props interface for those components

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 could! It would be great to harmonize the props every component takes. For instance, only some fields take a readonly prop. We might want to add this behavior to every component.


if (!isValidJson) {
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not a big fan of this. We will want to valid the field indeed. But we do not want to avoid persisting without letting the user notice. This is why we do not have any validation on links and email yet, we leave the user save whatever he wants.

Next step would be to discuss with Thomas on a common behavior for field content validation. Also maybe not let the workflow being activated if a field is invalid so we know the workflow would fail.

I would:

  • remove that step
  • add a fast follow to discuss validation

Wdyt?

Copy link
Contributor Author

@Devessier Devessier Dec 18, 2024

Choose a reason for hiding this comment

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

I agree that we still need to talk about validation. I already added validation to the Date field. The input doesn't allow you to submit invalid dates.
I can remove the validation step for the Raw JSON field for now.

@Devessier Devessier merged commit deb37ed into main Dec 18, 2024
22 checks passed
@Devessier Devessier deleted the add-uuid-form-field-input branch December 18, 2024 10:42
Copy link

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

Contributions

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

Successfully merging this pull request may close these issues.

3 participants