-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Implement airbyte form builder (#101)
Because - #55 - Implement Airbyte form builder This commit - Loop though json schema and generate formTree - Generate form UI from formTree
- Loading branch information
Showing
20 changed files
with
1,325 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
...ponents/forms/connector/destination/AsyncDestinationFormCell/AsyncDestinationFormCell.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { FC, useState, useMemo, Fragment } from "react"; | ||
import { | ||
BasicSingleSelect, | ||
SingleSelectOption, | ||
} from "@instill-ai/design-system"; | ||
import { useDestinationDefinitions } from "@/services/connector"; | ||
import { airbyteSchemaToAirbyteFormTree } from "@/lib/airbytes/airbyteSchemaToAirbyteFormTree"; | ||
import useBuildForm from "@/lib/airbytes/useBuildForm"; | ||
import { AirbyteFormErrors, AirbyteFormValues } from "@/lib/airbytes"; | ||
|
||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
|
||
export type AsyncDestinationFormCellProps = Record<string, any>; | ||
|
||
export type AsyncDestinationFormCellState = Record<string, any> & { | ||
destinationDefinition: string; | ||
}; | ||
|
||
const AsyncDestinationFormCell: FC<AsyncDestinationFormCellProps> = () => { | ||
const [cellState, setCellState] = useState<AsyncDestinationFormCellState>(); | ||
|
||
const destinationDefinitions = useDestinationDefinitions(); | ||
|
||
const destinationOptions = useMemo(() => { | ||
if (!destinationDefinitions.isSuccess) return []; | ||
|
||
const options: SingleSelectOption[] = []; | ||
|
||
for (const definition of destinationDefinitions.data) { | ||
options.push({ | ||
label: definition.id, | ||
value: definition.name, | ||
}); | ||
} | ||
|
||
return options; | ||
}, [destinationDefinitions.isSuccess, destinationDefinitions.data]); | ||
|
||
const selectedDestinationOption = useMemo(() => { | ||
if (!cellState?.destinationDefinition || !destinationOptions) return null; | ||
return ( | ||
destinationOptions.find( | ||
(e) => e.value === cellState.destinationDefinition | ||
) || null | ||
); | ||
}, [cellState?.destinationDefinition, destinationOptions]); | ||
|
||
const selectedDestinationFromTree = useMemo(() => { | ||
if (!selectedDestinationOption || !destinationDefinitions.isSuccess) { | ||
return null; | ||
} | ||
|
||
const selectedDestination = destinationDefinitions.data.find( | ||
(e) => e.name === selectedDestinationOption.value | ||
); | ||
|
||
if (!selectedDestination) { | ||
return null; | ||
} | ||
|
||
const formTree = airbyteSchemaToAirbyteFormTree( | ||
selectedDestination.connector_definition.spec.connection_specification | ||
); | ||
|
||
return formTree; | ||
}, [selectedDestinationOption]); | ||
|
||
const [fieldValues, setFieldValues] = useState<AirbyteFormValues>({}); | ||
const [fieldErrors, setFieldErrors] = useState<AirbyteFormErrors>({}); | ||
|
||
const fields = useBuildForm( | ||
selectedDestinationFromTree, | ||
false, | ||
fieldValues, | ||
setFieldValues, | ||
fieldErrors | ||
); | ||
|
||
console.log(fields); | ||
|
||
return ( | ||
<Fragment> | ||
<BasicSingleSelect | ||
id="destinationDefinition" | ||
instanceId="destinationDefinition" | ||
menuPlacement="auto" | ||
label="Destination type" | ||
additionalMessageOnLabel={null} | ||
description={""} | ||
disabled={false} | ||
readOnly={false} | ||
required={false} | ||
error={null} | ||
value={selectedDestinationOption} | ||
options={destinationOptions} | ||
onChangeInput={(_, option) => { | ||
setCellState((prev) => { | ||
return { | ||
...prev, | ||
destinationDefinition: option.value, | ||
}; | ||
}); | ||
}} | ||
/> | ||
{fields} | ||
</Fragment> | ||
); | ||
}; | ||
|
||
export default AsyncDestinationFormCell; |
2 changes: 2 additions & 0 deletions
2
src/components/forms/connector/destination/AsyncDestinationFormCell/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { default } from "./AsyncDestinationFormCell"; | ||
export * from "./AsyncDestinationFormCell"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# About the flow of generating Airbyte connector's form | ||
|
||
We are using Airbyte protocol for generating, maintain, create our connectors, frontend need to come up with a way that have backward compatability and onward support of any Airbyte connectors. Here is how we accomplishing it and the principle behind these implementation. | ||
|
||
## Principles and implementation | ||
|
||
- **Loose couple to all the involved library** | ||
- We use Formik just as Airbyte, but they had closely coupled with Formik to generate the whole form ([ref](https://github.com/airbytehq/airbyte/blob/59e20f20de73ced59ae2c782612fa7554fc1fced/airbyte-webapp/src/views/Connector/ServiceForm/ServiceForm.tsx)). Every details are controled by the Formik from form's state, validation schema and submit action. In this way they may have hard time if they have much complicated form structure. | ||
- **We try to isolated Airbyte connector's logic** | ||
- We separate all the types and functions into the folder | ||
- We make the form act like a small island, they have their own state, action and validation besides from our main form. | ||
|
||
## Useful refernece | ||
|
||
- [Airbyte - ServiceForm](https://github.com/airbytehq/airbyte/blob/59e20f20de73ced59ae2c782612fa7554fc1fced/airbyte-webapp/src/views/Connector/ServiceForm/ServiceForm.tsx) | ||
- [Airbyte - Form's types](https://github.com/airbytehq/airbyte/blob/master/airbyte-webapp/src/core/form/types.ts) | ||
- [Airbyte - SchemaToUiWidget](https://github.com/airbytehq/airbyte/blob/59e20f20de73ced59ae2c782612fa7554fc1fced/airbyte-webapp/src/core/jsonSchema/schemaToUiWidget.ts) | ||
- How they loop though json schema and construct FormBlock(In our terms, it's FormTree) | ||
- [Airbyte - FormSection](https://github.com/airbytehq/airbyte/blob/master/airbyte-webapp/src/views/Connector/ServiceForm/components/Sections/FormSection.tsx) | ||
- The FormSection is how they control their UI widget | ||
- [Airbyte - Control](https://github.com/airbytehq/airbyte/blob/master/airbyte-webapp/src/views/Connector/ServiceForm/components/Property/Control.tsx) | ||
- How they generate field based on their type, array, boolean, string, integer, array |
Oops, something went wrong.