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

[Connector Builder] Add stream slicer #20748

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
133 commits
Select commit Hold shift + click to select a range
699470e
move connector builder components into the same shared components/con…
lmossman Dec 1, 2022
827532b
move diff over from poc branch
lmossman Dec 1, 2022
4899673
save current progress
lmossman Dec 3, 2022
a1b62f1
add modal for adding streams
lmossman Dec 3, 2022
39e8ba8
focus stream after adding and reset button style
lmossman Dec 5, 2022
2352ef9
add reset confirm modal and select view on add
lmossman Dec 6, 2022
df492fa
style global config and streams buttons
lmossman Dec 6, 2022
5a99c7a
styling improvements
lmossman Dec 6, 2022
62fc08c
handle long stream names better
lmossman Dec 6, 2022
7b26b78
pull in connector manifest schema directly
lmossman Dec 6, 2022
71a88f1
add box shadows to resizable panels
lmossman Dec 6, 2022
d7bee54
upgrade orval and use connector manifest schema directly
lmossman Dec 6, 2022
162ecf2
remove airbyte protocol from connector builder api spec
lmossman Dec 6, 2022
def60b0
Merge branch 'master' into lmossman/use-connector-manifest-schema-dir…
lmossman Dec 6, 2022
ff9aa76
generate python models from openapi change
lmossman Dec 6, 2022
3678956
merge with lmossman/use-connector-manifest-schema-directly
lmossman Dec 6, 2022
b16d4a8
fix position of yaml toggle
lmossman Dec 6, 2022
67fb9dd
handle no stream case with better looking message
lmossman Dec 7, 2022
bb42007
group global fields into single object and fix console error
lmossman Dec 7, 2022
9bb1812
confirmation modal on toggling dirty form + cleanup
lmossman Dec 7, 2022
587ca2f
merge with master
lmossman Dec 7, 2022
81cf108
fix connector name display
lmossman Dec 7, 2022
094a045
undo change to manifest schema
lmossman Dec 7, 2022
d1c8c80
remove commented code
lmossman Dec 7, 2022
aebac20
remove unnecessary change
lmossman Dec 7, 2022
1e39be4
fix spacing
lmossman Dec 7, 2022
09cf875
use shadow mixin for connector img
lmossman Dec 7, 2022
ec65d67
add comment about connector img
lmossman Dec 7, 2022
f9a3fa1
Merge remote-tracking branch 'origin/master' into lmossman/connector-…
Dec 8, 2022
603820a
change onSubmit to no-op
lmossman Dec 8, 2022
cb2f299
remove console log
lmossman Dec 8, 2022
d1672a0
clean up styling
lmossman Dec 8, 2022
7255784
simplify sidebar to remove StreamSelectButton component
lmossman Dec 8, 2022
65cd42b
swap colors of toggle
lmossman Dec 8, 2022
10d7893
move FormikPatch to src/core/form
lmossman Dec 8, 2022
fc89001
move types up to connectorBuilder/ level
lmossman Dec 8, 2022
24eaaff
use grid display for ui yaml toggle button
lmossman Dec 8, 2022
de604f6
use spread instead of setting array index directly
lmossman Dec 8, 2022
e696e57
add intl in missing places
lmossman Dec 8, 2022
5952f70
merge with master
lmossman Dec 8, 2022
b7c08f6
pull connector manifest schema in through separate openapi spec
lmossman Dec 8, 2022
dd04e61
erge branch 'lmossman/connector-builder-config-ui' of github.com:airb…
Dec 9, 2022
d6f10b4
use correct intl string id
lmossman Dec 9, 2022
5ffe20e
throttle setting json manifest in yaml editor
lmossman Dec 9, 2022
b82ba2a
use button prop instead of manually styling
lmossman Dec 9, 2022
b9580b4
consolidate AddStreamButton styles
lmossman Dec 9, 2022
1587243
fix sidebar flex styles
lmossman Dec 9, 2022
62a60e5
use specific flex properties instead of flex
lmossman Dec 9, 2022
092821d
clean up download and reset button styles
lmossman Dec 10, 2022
7b8dec8
use row-reverse for yaml editor download button
lmossman Dec 10, 2022
6d68db9
fix stream selector styles to remove margins
lmossman Dec 10, 2022
91bc357
give connector setup guide panel same corner and shadow styles
lmossman Dec 10, 2022
4ffb969
remove blur from page display
lmossman Dec 10, 2022
70afdf8
set view to stream when selected in test panel
lmossman Dec 10, 2022
f656506
add placeholder when stream name is empty
lmossman Dec 10, 2022
c437d30
switch to index-based stream selection to preserve testing panel sele…
lmossman Dec 10, 2022
3cdbc70
handle empty name in stream selector
lmossman Dec 10, 2022
831f574
Merge branch 'lmossman/connector-builder-config-ui' of github.com:air…
Dec 12, 2022
e2730fe
Merge branch 'lmossman/connector-builder-config-ui' into flash1293/in…
Dec 12, 2022
269ae82
make connector form work in connector builder
Dec 12, 2022
901fc63
wip
Dec 12, 2022
4944d3f
Merge branch 'flash1293/connector-form-remove-ui-widget-state' into f…
Dec 13, 2022
3255298
fix small stuff
Dec 13, 2022
333fb0b
Merge branch 'flash1293/connector-form-remove-ui-widget-state' into f…
Dec 13, 2022
cec206f
Merge branch 'flash1293/integrate-connector-form' into flash1293/allo…
Dec 13, 2022
ba28014
add basic input UI
Dec 13, 2022
53ad55f
Merge branch 'flash1293/connector-form-remove-ui-widget-state' into f…
Dec 14, 2022
5300933
Merge remote-tracking branch 'origin/master' into flash1293/integrate…
Dec 14, 2022
935188b
Merge branch 'flash1293/integrate-connector-form' into flash1293/allo…
Dec 14, 2022
b694dc5
user inputs
Dec 14, 2022
e7d81ea
make most of inputs configuration work
Dec 14, 2022
3de021a
Merge branch 'flash1293/connector-form-remove-ui-widget-state' into f…
Dec 15, 2022
552fc65
Merge branch 'flash1293/integrate-connector-form' into flash1293/allo…
Dec 15, 2022
ace1299
fix a bunch of stuff
Dec 15, 2022
7fa1752
handle unknown config types
Dec 15, 2022
7196409
Merge branch 'flash1293/connector-form-remove-ui-widget-state' into f…
Dec 16, 2022
4a37a67
add warning label
Dec 16, 2022
10fa73e
Merge branch 'flash1293/integrate-connector-form' into flash1293/allo…
Dec 16, 2022
7e48ba5
fix label
Dec 16, 2022
75db697
fix some styling
Dec 16, 2022
b340ef4
Merge branch 'flash1293/connector-form-remove-ui-widget-state' into f…
Dec 16, 2022
98c146c
Merge branch 'flash1293/integrate-connector-form' into flash1293/allo…
Dec 16, 2022
9835a5c
review comments
Dec 18, 2022
c352df0
Merge branch 'feature/connector-builder' into flash1293/integrate-con…
Dec 19, 2022
ed43eab
Merge branch 'flash1293/integrate-connector-form' into flash1293/allo…
Dec 19, 2022
7958ef1
improve state management and error handling
Dec 19, 2022
beb4968
Merge branch 'feature/connector-builder' into flash1293/integrate-con…
Dec 19, 2022
b3cfb8f
Merge branch 'flash1293/integrate-connector-form' into flash1293/allo…
Dec 19, 2022
49f55a1
Merge branch 'flash1293/allow-configuring-inputs' of github.com:airby…
Dec 19, 2022
04d87cf
allow auth configuration
Dec 19, 2022
b796201
check for conflicts with the inferred inputs
Dec 19, 2022
18498c7
fix invisible inputs
Dec 19, 2022
9ffa34e
handle stored form values that don't contain new fields properly
lmossman Dec 19, 2022
8c4b6c7
Merge branch 'flash1293/allow-configuring-inputs' into flash1293/conn…
lmossman Dec 19, 2022
c0350d3
Merge branch 'flash1293/allow-configuring-inputs' of github.com:airby…
Dec 20, 2022
e98ebc1
Merge branch 'feature/connector-builder' into flash1293/allow-configu…
Dec 20, 2022
fb1ec21
Merge branch 'flash1293/allow-configuring-inputs' into flash1293/conn…
Dec 20, 2022
a17ab05
session token and oauth authentication
Dec 20, 2022
7b6470e
fill in session token variable
Dec 20, 2022
23f4fbe
fix merge of default values
lmossman Dec 20, 2022
d4975bf
add primaryKey and cursorField to builder types, and consolidate defa…
lmossman Dec 20, 2022
32213f8
add cursor and primary key fields to ui
lmossman Dec 20, 2022
3e20324
save
lmossman Dec 20, 2022
3ee0ffb
add page size and token option inputs
lmossman Dec 21, 2022
0576478
fixes after rebase
lmossman Dec 21, 2022
5e45f59
add pagination
lmossman Dec 21, 2022
f101602
fix pagination types
lmossman Dec 21, 2022
5fb62e2
handle empty field_name better
lmossman Dec 21, 2022
7cce350
Update airbyte-webapp/src/locales/en.json
Dec 21, 2022
20e8044
Update airbyte-webapp/src/components/connectorBuilder/Builder/InputsV…
Dec 21, 2022
50bddcb
inputs editing weirdness
Dec 21, 2022
0ca37ad
input form reset
Dec 21, 2022
8095fda
using the Label component
Dec 21, 2022
fbeb2e1
Merge branch 'flash1293/allow-configuring-inputs' into flash1293/conn…
Dec 21, 2022
1bccbbd
reduce redundancy and hide advanced input options for inferred inputs
Dec 21, 2022
eaec279
unnecessary validation
Dec 21, 2022
a338590
typo
Dec 21, 2022
2429d29
unnecessary effect hook
Dec 21, 2022
6dd02d9
build spec even for invalid forms but do not update stream list
Dec 21, 2022
84803ce
Merge branch 'flash1293/connector-builder-authentication' into flash1…
Dec 21, 2022
4bd0bdc
typos
Dec 21, 2022
ca0219b
make sure validation error does not go away
Dec 21, 2022
134fc17
Merge branch 'flash1293/oauth-session-auth' into lmossman/connector-b…
Dec 21, 2022
ed9860e
make primary key and cursor optional, and reorder
lmossman Dec 21, 2022
e029279
save toggle group progress
lmossman Dec 21, 2022
e964eb8
fix style of toggle label
lmossman Dec 21, 2022
a23ffb8
handle empty values better
lmossman Dec 21, 2022
e3c578d
fix page size/token option field validation and rendering
lmossman Dec 21, 2022
24bfc32
handle cursor pagination page size option correctly
lmossman Dec 21, 2022
25eb391
save stream slicer progress
lmossman Dec 21, 2022
3651ae2
finish stream slicer
lmossman Dec 21, 2022
1e3cad9
fix stream slicer fields and validation
lmossman Dec 22, 2022
e421e1e
Merge branch 'feature/connector-builder' into lmossman/connector-buil…
Dec 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface BaseFieldProps {
tooltip?: string;
readOnly?: boolean;
optional?: boolean;
pattern?: RegExp;
}

type BuilderFieldProps = BaseFieldProps &
Expand Down Expand Up @@ -66,6 +67,7 @@ export const BuilderField: React.FC<BuilderFieldProps> = ({
tooltip,
optional = false,
readOnly,
pattern,
...props
}) => {
const [field, meta, helpers] = useField(path);
Expand Down Expand Up @@ -116,7 +118,10 @@ export const BuilderField: React.FC<BuilderFieldProps> = ({
)}
{hasError && (
<Text className={styles.error}>
<FormattedMessage id={meta.error} />
<FormattedMessage
id={meta.error}
values={meta.error === "form.pattern.error" && pattern ? { pattern: String(pattern) } : undefined}
/>
</Text>
)}
</ControlLabels>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { BuilderTitle } from "./BuilderTitle";
import { KeyValueListField } from "./KeyValueListField";
import { PaginationSection } from "./PaginationSection";
import styles from "./StreamConfigView.module.scss";
import { StreamSlicerSection } from "./StreamSlicerSection";

interface StreamConfigViewProps {
streamNum: number;
Expand Down Expand Up @@ -97,6 +98,7 @@ export const StreamConfigView: React.FC<StreamConfigViewProps> = ({ streamNum })
/>
</BuilderCard>
<PaginationSection streamFieldPath={streamFieldPath} />
<StreamSlicerSection streamFieldPath={streamFieldPath} />
<BuilderCard>
<KeyValueListField
path={streamFieldPath("requestOptions.requestParameters")}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import { useField } from "formik";

import { ControlLabels } from "components/LabeledControl";

import { timeDeltaRegex } from "../types";
import { BuilderCard } from "./BuilderCard";
import { BuilderField } from "./BuilderField";
import { BuilderOneOf } from "./BuilderOneOf";
import { BuilderOptional } from "./BuilderOptional";
import { InjectRequestOptionFields } from "./InjectRequestOptionFields";
import { ToggleGroupField } from "./ToggleGroupField";

interface StreamSlicerSectionProps {
streamFieldPath: (fieldPath: string) => string;
}

export const StreamSlicerSection: React.FC<StreamSlicerSectionProps> = ({ streamFieldPath }) => {
const [field, , helpers] = useField(streamFieldPath("streamSlicer"));

const handleToggle = (newToggleValue: boolean) => {
if (newToggleValue) {
helpers.setValue({
type: "ListStreamSlicer",
slice_values: [],
cursor_field: "",
});
} else {
helpers.setValue(undefined);
}
};
const toggledOn = field.value !== undefined;

return (
<BuilderCard
toggleConfig={{
label: (
<ControlLabels
label="Stream slicer"
infoTooltipContent="Configure how to partition a stream into subsets of records and iterate over the data"
/>
),
toggledOn,
onToggle: handleToggle,
}}
>
<BuilderOneOf
path={streamFieldPath("streamSlicer")}
label="Mode"
tooltip="Stream slicer method to use on this stream"
options={[
{
label: "List",
typeValue: "ListStreamSlicer",
children: (
<>
<BuilderField
type="array"
path={streamFieldPath("streamSlicer.slice_values")}
label="Slice values"
tooltip="List of values to iterate over"
/>
<BuilderField
type="string"
path={streamFieldPath("streamSlicer.cursor_field")}
label="Cursor field"
tooltip="Field on record to use as the cursor"
/>
<ToggleGroupField
label="Slice request option"
tooltip="Optionally configures how the slice values will be sent in requests to the source API"
fieldPath={streamFieldPath("streamSlicer.request_option")}
initialValues={{
inject_into: "request_parameter",
field_name: "",
}}
>
<InjectRequestOptionFields
path={streamFieldPath("streamSlicer.request_option")}
descriptor="slice value"
excludeInjectIntoValues={["path"]}
/>
</ToggleGroupField>
</>
),
},
{
label: "Datetime",
typeValue: "DatetimeStreamSlicer",
children: (
<>
<BuilderField
type="string"
path={streamFieldPath("streamSlicer.datetime_format")}
label="Datetime format"
tooltip="Specify the format of the start and end time, e.g. %Y-%m-%d"
/>
<BuilderField
type="string"
path={streamFieldPath("streamSlicer.start_datetime")}
label="Start datetime"
tooltip="Start time to start slicing"
/>
<BuilderField
type="string"
path={streamFieldPath("streamSlicer.end_datetime")}
label="End datetime"
tooltip="End time to end slicing"
/>
<BuilderField
type="string"
path={streamFieldPath("streamSlicer.step")}
label="Step"
tooltip="Time interval for which to break up stream into slices, e.g. 1d"
pattern={timeDeltaRegex}
/>
<BuilderField
type="string"
path={streamFieldPath("streamSlicer.cursor_field")}
label="Cursor field"
tooltip="Field on record to use as the cursor"
/>
<BuilderOptional>
<BuilderField
type="string"
path={streamFieldPath("streamSlicer.lookback_window")}
label="Lookback window"
tooltip="How many days before the start_datetime to read data for, e.g. 31d"
optional
/>
<ToggleGroupField
label="Start time request option"
tooltip="Optionally configures how the start datetime will be sent in requests to the source API"
fieldPath={streamFieldPath("streamSlicer.start_time_option")}
initialValues={{
inject_into: "request_parameter",
field_name: "",
}}
>
<InjectRequestOptionFields
path={streamFieldPath("streamSlicer.start_time_option")}
descriptor="start datetime"
excludeInjectIntoValues={["path"]}
/>
</ToggleGroupField>
<ToggleGroupField
label="End time request option"
tooltip="Optionally configures how the end datetime will be sent in requests to the source API"
fieldPath={streamFieldPath("streamSlicer.end_time_option")}
initialValues={{
inject_into: "request_parameter",
field_name: "",
}}
>
<InjectRequestOptionFields
path={streamFieldPath("streamSlicer.end_time_option")}
descriptor="end datetime"
excludeInjectIntoValues={["path"]}
/>
</ToggleGroupField>
<BuilderField
type="string"
path={streamFieldPath("streamSlicer.stream_state_field_start")}
label="Stream state field start"
tooltip="Set which field on the stream state to use to determine the starting point"
optional
/>
<BuilderField
type="string"
path={streamFieldPath("streamSlicer.stream_state_field_end")}
label="Stream state field end"
tooltip="Set which field on the stream state to use to determine the ending point"
optional
/>
</BuilderOptional>
</>
),
},
]}
/>
</BuilderCard>
);
};
81 changes: 73 additions & 8 deletions airbyte-webapp/src/components/connectorBuilder/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
SessionTokenAuthenticator,
DefaultPaginatorAllOfPaginationStrategy,
RequestOption,
SimpleRetrieverAllOfStreamSlicer,
} from "core/request/ConnectorManifest";

export interface BuilderFormInput {
Expand Down Expand Up @@ -61,6 +62,7 @@ export interface BuilderStream {
pageTokenOption: RequestOption;
pageSizeOption?: RequestOption;
};
streamSlicer?: SimpleRetrieverAllOfStreamSlicer;
}

export const DEFAULT_BUILDER_FORM_VALUES: BuilderFormValues = {
Expand Down Expand Up @@ -213,6 +215,17 @@ export function getInferredInputs(values: BuilderFormValues): BuilderFormInput[]
}

export const injectIntoValues = ["request_parameter", "header", "path", "body_data", "body_json"];
const nonPathRequestOptionSchema = yup
.object()
.shape({
inject_into: yup.mixed().oneOf(injectIntoValues.filter((val) => val !== "path")),
field_name: yup.string().required("form.empty.error"),
})
.notRequired()
.default(undefined);

// eslint-disable-next-line no-useless-escape
export const timeDeltaRegex = /^(([\.\d]+?)y)?(([\.\d]+?)m)?(([\.\d]+?)w)?(([\.\d]+?)d)?$/;

export const builderFormValidationSchema = yup.object().shape({
global: yup.object().shape({
Expand Down Expand Up @@ -261,14 +274,7 @@ export const builderFormValidationSchema = yup.object().shape({
paginator: yup
.object()
.shape({
pageSizeOption: yup
.object()
.shape({
inject_into: yup.mixed().oneOf(injectIntoValues.filter((val) => val !== "path")),
field_name: yup.string().required("form.empty.error"),
})
.notRequired()
.default(undefined),
pageSizeOption: nonPathRequestOptionSchema,
pageTokenOption: yup.object().shape({
inject_into: yup.mixed().oneOf(injectIntoValues),
field_name: yup.mixed().when("inject_into", {
Expand Down Expand Up @@ -305,6 +311,64 @@ export const builderFormValidationSchema = yup.object().shape({
})
.notRequired()
.default(undefined),
streamSlicer: yup
.object()
.shape({
cursor_field: yup.string().required("form.empty.error"),
slice_values: yup.mixed().when("type", {
is: "ListStreamSlicer",
then: yup.array().of(yup.string()),
otherwise: (schema) => schema.strip(),
}),
request_option: nonPathRequestOptionSchema,
start_datetime: yup.mixed().when("type", {
is: "DatetimeStreamSlicer",
then: yup.string().required("form.empty.error"),
otherwise: (schema) => schema.strip(),
}),
end_datetime: yup.mixed().when("type", {
is: "DatetimeStreamSlicer",
then: yup.string().required("form.empty.error"),
otherwise: (schema) => schema.strip(),
}),
step: yup.mixed().when("type", {
is: "DatetimeStreamSlicer",
then: yup.string().matches(timeDeltaRegex, "form.pattern.error").required("form.empty.error"),
otherwise: (schema) => schema.strip(),
}),
datetime_format: yup.mixed().when("type", {
is: "DatetimeStreamSlicer",
then: yup.string().required("form.empty.error"),
otherwise: (schema) => schema.strip(),
}),
start_time_option: yup.mixed().when("type", {
is: "DatetimeStreamSlicer",
then: nonPathRequestOptionSchema,
otherwise: (schema) => schema.strip(),
}),
end_time_option: yup.mixed().when("type", {
is: "DatetimeStreamSlicer",
then: nonPathRequestOptionSchema,
otherwise: (schema) => schema.strip(),
}),
stream_state_field_start: yup.mixed().when("type", {
is: "DatetimeStreamSlicer",
then: yup.string(),
otherwise: (schema) => schema.strip(),
}),
stream_state_field_end: yup.mixed().when("type", {
is: "DatetimeStreamSlicer",
then: yup.string(),
otherwise: (schema) => schema.strip(),
}),
lookback_window: yup.mixed().when("type", {
is: "DatetimeStreamSlicer",
then: yup.string(),
otherwise: (schema) => schema.strip(),
}),
})
.notRequired()
.default(undefined),
})
),
});
Expand Down Expand Up @@ -369,6 +433,7 @@ export const convertToManifest = (values: BuilderFormValues): PatchedConnectorMa
url_base: values.global?.urlBase,
}
: { type: "NoPagination" },
stream_slicer: stream.streamSlicer,
config: {},
},
config: {},
Expand Down