-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Conversation
…of control buttons
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.
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
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>; | ||
} |
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.
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.
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.
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
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.
@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 } => { |
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.
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 |
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.
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 👍
<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> |
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.
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.
fixed this one
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.
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 => { |
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.
There's a typo here
export const useOnHandeSubmit = (props: UseOnHandleSubmitHookProps): UseOnHandleSubmitHookResult => { | |
export const useOnHandleSubmit = (props: UseOnHandleSubmitHookProps): UseOnHandleSubmitHookResult => { |
saved: boolean; | ||
} | ||
|
||
export const useOnHandeSubmit = (props: UseOnHandleSubmitHookProps): UseOnHandleSubmitHookResult => { |
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.
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.
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 Few things I suggested:
The structure will be:
Also, we need to keep in mind that our future design completely follows this way - splitting the Form into multiple separate Cards: 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 |
@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? |
@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. |
Just as an additional clarification: We're going to put this PR here on hold until we're done with #18168, right? |
Great! Deal!
Yes, I would like to do so |
No reason 😁 |
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 |
This was resolved through another approach. Closing... |
What
Closes #16469
How
This PR refactors
ServiceForm
andConnectorCard
components, soFormik
andServiceFormContext
are moved on the top level insideConnectorCard
component. Also, I created two custom hooks to make the code inside components more readable.useConnectorCardService
is responsible for logic that touches bothServiceForm
andConnectorCard
.useDeleteModal
is responsible fordelete
modal logic that is used insideEditControls
andDeleteBlock
components. Also, changes in this PR will be beneficial in future development since the new design Figma forConnectorCard
components uses a couple ofCard
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.