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

🪟 🔧 [DRAFT] Refactor ServiceForm and ConnectorCard to move Formik and ServiceFormContext on top level #18229

Closed
wants to merge 12 commits into from

Conversation

YatsukBogdan1
Copy link
Contributor

What

Closes #16469

How

This PR refactors ServiceForm and ConnectorCard components, so Formik and ServiceFormContext are moved on the top level inside ConnectorCard component. Also, I created two custom hooks to make the code inside components more readable. useConnectorCardService is responsible for logic that touches both ServiceForm and ConnectorCard. useDeleteModal is responsible for delete modal logic that is used inside EditControls and DeleteBlock components. Also, changes in this PR will be beneficial in future development since the new design Figma for ConnectorCard components uses a couple of Card components to have different form controls inside them.
Currently, the tests for the ServiceForm component is commented out due to lots of changes inside the component, planning to work on them, after approving the final state of the component.

@YatsukBogdan1 YatsukBogdan1 requested a review from a team as a code owner October 20, 2022 12:26
@github-actions github-actions bot added area/platform issues related to the platform area/frontend Related to the Airbyte webapp labels Oct 20, 2022
Copy link
Contributor

@lmossman lmossman left a comment

Choose a reason for hiding this comment

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

Left some comments with my initial impressions. I like the delete changes. The useConnectorCardService though feels like it is doing a bit too much, and I'd like to see if there is any room to simplify or break that down further so that it is more readable

Comment on lines 30 to 51
interface UseConnectorCardServiceHookResult {
advancedMode: boolean;
isFormSubmitting: boolean;
isTestConnectionInProgress: boolean;
job?: SynchronousJobRead | null;
onHandleSubmit: (values: ServiceFormValues) => Promise<void>;
onStopTesting: () => void;
saved: boolean;
testConnector: (v?: ServiceFormValues) => Promise<CheckConnectionRead>;
error: Error | null;
selectedConnectorDefinitionSpecificationId?: string;
uniqueFormId?: string;
jsonSchema: JSONSchema7;
initialValues: ServiceFormValues;
formFields: FormBlock;
validationSchema: AnySchema;
uiWidgetsInfo: WidgetConfigMap;
setUiWidgetsInfo: (widgetId: string, updatedValues: WidgetConfig) => void;
resetUiWidgetsInfo: () => void;
getValues: <T = unknown>(values: ServiceFormValues<T>) => ServiceFormValues<T>;
onFormSubmit: (values: ServiceFormValues) => Promise<void>;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

While I do think this refactor has made the ServiceForm and ConnectorCard components more readable, it feels like all of their complexity has just been shoved into this service instead.

Could you try to simplify this or break it into smaller services? It feels like there is a ton going on here which makes this service pretty hard to understand on its own without going and seeing how each result value is used.

For example, this returns an onHandleSubmit and an onFormSubmit, both of which have the same input and return types -- why are both necessary?

It feels like this service could be split up into more readable pieces. Maybe all of the uiWidget logic can be contained in a single place, and/or maybe more comments/documentation could be added here to help make it easier to understand.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, that makes sense. I am currently working on this, but still a bit hard, assuming I am not familiar with logic inside this component at all

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@lmossman you can check now, I added two new smaller hooks that split some logic from useConnectorCardService, and are used inside the original hook


import { DeleteBlockProps } from "./interfaces";

export const useDeleteModal = ({ type, onDelete }: Partial<DeleteBlockProps>): { onDeleteButtonClick: () => void } => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the introduction of this hook - its a nice way to keep this logic encapsulated while allowing it to be used in either a DeleteBlock or directly by a button

/>
</div>
{additionalSelectorComponent}
<Formik
Copy link
Contributor

Choose a reason for hiding this comment

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

Initially I thought it felt slightly weird to have the Formik be declared outside of ServiceForm, but given that the goal of this is to move the "controls" outside of the card itself, then this structure probably makes sense 👍

Comment on lines 77 to 88
<Button type="submit" disabled={isSubmitting || !dirty || Object.keys(unfinishedFlows).length > 0}>
<FormattedMessage id="form.saveChangesAndTest" />
</Button>
<Button
className={styles.cancelButton}
type="button"
variant="secondary"
disabled={isSubmitting || !dirty}
onClick={onCancelClick}
>
<FormattedMessage id="form.cancel" />
</Button>
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we swap the order of these two buttons, and change the form.saveChangesAndTest text to be Save & Test?

Those two changes would bring this in line with the design on Figma:

Screen Shot 2022-10-20 at 5 16 47 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed this one

Copy link
Contributor

@lmossman lmossman left a comment

Choose a reason for hiding this comment

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

Had a couple more comments. I think this is looking good overall but I'm still not sure if I love the connector card hook structure.

@edmundito or @timroes could one of you take a look and let me know if you agree about the hook structure in this PR? I want to double check my thoughts with you and/or see if there are any other approaches you have in mind. Thanks!

saved: boolean;
}

export const useOnHandeSubmit = (props: UseOnHandleSubmitHookProps): UseOnHandleSubmitHookResult => {
Copy link
Contributor

Choose a reason for hiding this comment

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

There's a typo here

Suggested change
export const useOnHandeSubmit = (props: UseOnHandleSubmitHookProps): UseOnHandleSubmitHookResult => {
export const useOnHandleSubmit = (props: UseOnHandleSubmitHookProps): UseOnHandleSubmitHookResult => {

saved: boolean;
}

export const useOnHandeSubmit = (props: UseOnHandleSubmitHookProps): UseOnHandleSubmitHookResult => {
Copy link
Contributor

@lmossman lmossman Oct 25, 2022

Choose a reason for hiding this comment

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

I don't know if encapsulating this logic in a hook is actually helpful, and it feels like a slightly strange thing to put in a hook to me.

I feel like it might be more readable to just put this onSubmit logic directly in the ConnectorCard component, since that is where the Formik form is defined, so having the form submission logic live close to the form itself might be nice.

If this change is made, you may even be able to get rid of the useConnectorCardService hook, and just keep the useUIWidget hook, since that one still seems useful for encapsulating the uiWidget logic.

Definitely open to feedback here though if anyone disagrees - I'm still trying to learn what the best practices are around when and how exactly hooks should be used.

@lmossman lmossman requested review from edmundito and timroes October 25, 2022 20:14
@dizel852
Copy link
Contributor

I had a sync with @YatsukBogdan1, we were discussing the best way how to merge this PR and mine.

I noticed, that in order to render the Buttons outside of the Card, the whole card is wrapped with <Formik /> context since we need to manipulate with Form controls being in the <Formik /> context
That is exactly what we tried to avoid, and that was a goal of this PR
image

Few things I suggested:

  • move form controls outside the Card component using css - probably the worst I could suggest 😅
  • create two Cards: one for Dropdown, and one for Form, and tweak the styles for both, to make it look like an entire form, here is an example with hardcoded styles:

image

The structure will be:

<ConnectorCard>
  
  <Card>
    <ConnectorDropdownSelect>
  </Card>

  <ConnectorForm>
    <FormikContext>
        <Card>
           <Form/>
        </Card>
       
        <FormContorls>
    
    </FormikContext>
  </ConnectorForm>
</ConnectorCard>

Also, we need to keep in mind that our future design completely follows this way - splitting the Form into multiple separate Cards:
https://www.figma.com/proto/mFVUWYYjDm5zz6FFx8hTP6/FORMS-FIELDS?page-id=1%3A4&node-id=301%3A10567&viewport=606%2C64%2C0.16&scaling=min-zoom&starting-point-node-id=301%3A10567

The thing I really like, it's the ConnectorCardService hook: https://github.com/airbytehq/airbyte/pull/18229/files/a06f74a2fdd3dd7913fc1016ae7a2defd0ce27bd#r1001231672

But I'm pretty sure, the hook should be implemented after the PR will be merged, since I removed some of the redundant props due to extra calculation.

@timroes @lmossman @edmundito
Need to hear your thoughts, guys

@lmossman
Copy link
Contributor

lmossman commented Oct 27, 2022

@dizel852 @YatsukBogdan1 @timroes My opinion here: The design that we eventually want to achieve has the connector type and name inputs in a separate cards anyway. I think the component structure you laid out above makes sense, and it also seems fine to me to just have the type & name inputs in one card, and the rest of the connector form inputs in a separate card, without doing any odd CSS things to try to make them look like a single card.

Is there any reason we shouldn't just have them in separate cards, allowing us to achieve the component structure you laid out and bringing us one step closer to the final design?

@timroes
Copy link
Collaborator

timroes commented Oct 27, 2022

@dizel852 I would strongly advertise against CSS hacks if possible :)

Regarding the structure I also think the way your linked refactoring is going is correct and we want to have the formik context on a lower level as you did, specifically given that we've seen a lot of issue based on the formik context isn't rerendered when the type change (e.g. #18558).

I'd also second Lake in, let's try to even avoid the design hacks to move the cards together and just see it as a move towards the final design and already treat it as separate cards.

@timroes
Copy link
Collaborator

timroes commented Oct 27, 2022

Just as an additional clarification: We're going to put this PR here on hold until we're done with #18168, right?

@dizel852
Copy link
Contributor

I'd also second Lake in, let's try to even avoid the design hacks to move the cards together and just see it as a move towards the final design and already treat it as separate cards.

Great! Deal!

Just as an additional clarification: We're going to put this PR here on hold until we're done with #18168, right?

Yes, I would like to do so

@dizel852
Copy link
Contributor

Is there any reason we shouldn't just have them in separate cards, allowing us to achieve the component structure you laid out and bringing us one step closer to the final design?

No reason 😁
But we won't be able to put ConnectorSelector(Dropdown) and Connector name fields in one separate card since the Connector name is inside the Formik context.

@YatsukBogdan1
Copy link
Contributor Author

I am moving this PR into the draft until @dizel852 PR #18168 will be merged

@YatsukBogdan1 YatsukBogdan1 changed the title 🪟 🔧 Refactor ServiceForm and ConnectorCard to move Formik and ServiceFormContext on top level 🪟 🔧 [DRAFT] Refactor ServiceForm and ConnectorCard to move Formik and ServiceFormContext on top level Oct 31, 2022
@YatsukBogdan1 YatsukBogdan1 marked this pull request as draft October 31, 2022 07:48
@YatsukBogdan1
Copy link
Contributor Author

I created a new PR for this issue #19099. If any of the current code changes will be useful later, we can still take them from this PR

@edmundito
Copy link
Contributor

This was resolved through another approach. Closing...

@edmundito edmundito closed this Feb 15, 2023
@edmundito edmundito deleted the byatusk/move-connector-card-buttons branch February 15, 2023 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/frontend Related to the Airbyte webapp area/platform issues related to the platform
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Dup] Move connector create/save button outside of the card
5 participants