-
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
🪟 🎉 Select dbt jobs with dropdown #19502
Conversation
const dbtCloudDomain = "https://cloud.getdbt.com"; | ||
const webhookConfigName = "dbt cloud"; | ||
const executionBody = `{"cause": "airbyte"}`; | ||
const jobName = (t: DbtCloudJob) => `${t.account}/${t.job}`; | ||
|
||
const isDbtWebhookConfig = (webhookConfig: WebhookConfigRead) => !!webhookConfig.name?.includes("dbt"); | ||
|
||
const toDbtCloudJob = (operation: OperationRead): DbtCloudJob => { |
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.
toDbtCloudJob
is rewritten to handle either a saved webhook (OperationRead
) or dbt-Cloud-supplied JSON job record (DbtCloudJobInfo
) as input; existing logic is unchanged except for wrapping it in a type-narrowing conditional.
@@ -47,17 +54,62 @@ export const DbtCloudTransformationsCard = ({ connection }: { connection: WebBac | |||
// THEN show the jobs list and the "+ Add transformation" button | |||
|
|||
const { hasDbtIntegration, saveJobs, dbtCloudJobs } = useDbtIntegration(connection); | |||
|
|||
return hasDbtIntegration ? <DbtJobsForm saveJobs={saveJobs} dbtCloudJobs={dbtCloudJobs} /> : <NoDbtIntegration />; |
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.
The top-level card component now delegates all content; its main role is sussing out whether the user's workspace has a dbt Cloud integration and rendering the appropriate UI.
The component used to contain a decent chunk of the "has dbt integration" UI; that got extracted to a helper component mostly unchanged (except, of course, for changing the "Add transformation" button to a dropdown.
Also includes a cheeky little test usage which probably should have had a name starting with an underscore (I did not commit the test code which added the new variable's contents to `(window as any).availableJobs`, on grounds that it was very ugly, but I did want to have the import and call of the wrapper function hit the git history here).
Selecting job from dropdown adds it to saved jobs, but the new endpoint is unconditionally called even though it will always throw an error for users with no dbt Cloud integration configured.
Well, I suppose throwing a runtime error for every connection which could support dbt Cloud jobs but is part of a workspace with no integration set up, but that doesn't exactly seem ideal. Instead, this pulls all logic out of the top-level card except for pulling the dbt Cloud integration information; then it delegates the rest to either of two fairly self-contained components, `NoDbtIntegration` or the new `DbtJobsForm`. The immediate benefit is that I have a nice component boundary in which I can unconditionally run dbt-Cloud-only logic to fetch available jobs.
5e2af7f
to
8714b6a
Compare
Since the values are now supplied by dbt Cloud via API, the user no longer has to manually input anything; and this sudden lack of user input rather obviates the need to validate user input.
8714b6a
to
b9ee03c
Compare
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.
Looks good! Just left a few non-blocking comments. Did not (yet) test locally.
Also a general thought: there are 5 components in DbtCloudTransformationsCard.tsx
. I tend to aggressively break out components into separate files, unless they are really small and trivial. Mostly this helps me use Cmd + P
to quickly open components 😄 but I also find it easier to scope styles, tests, etc. when components are in separate files. Do you have any criteria by which you would choose to put a component in a new file?
This is a pretty subjective code style question, so maybe something we should discuss in the frontend chapter. Not bringing it up because I feel super strongly one way or another, but I would be interested in having some sort of convention.
background-color: colors.$grey-50; | ||
flex-grow: 2; | ||
padding: variables.$spacing-sm; | ||
border-radius: variables.$border-radius-sm; |
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.
Styling of the icon / border radius looks a bit off? (icon too big, text too close to icon, border radius). Maybe I'm looking at an old Figma design.
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.
Agreed, it could use a few small tweaks. The icon size at least is as designed, but the text is definitely a bit too close and now that it holds the job's display name instead of a generic "hey this is a dbt cloud job" title, it's probably a bit too small also. I'm going to merge this as-is for now, though, so Sophia can test it out while rewriting the documentation to reflect the updated UI.
}; | ||
|
||
const NoDbtIntegration = () => { | ||
const { workspaceId } = useCurrentWorkspace(); |
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.
nit: we also have useCurrentWorkspaceId()
btw
const results = useQuery( | ||
["dbtCloud", dbtConfigId, "list"], | ||
() => webBackendGetAvailableDbtJobsForWorkspace({ workspaceId, dbtConfigId }, requestOptions), | ||
{ | ||
suspense: true, | ||
} | ||
); | ||
|
||
// casting type to remove `| undefined`, since `suspense: true` will ensure the value | ||
// is, in fact, available | ||
return (results.data as WorkspaceGetDbtJobsResponse).availableDbtJobs; |
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.
You can use useSuspenseQuery()
wrapper to avoid the | undefined
and { suspense: true }
option. I don't know why useSuspenseQuery()
currently lives in services/connector/useSuspenseQuery
, but that's where you can find it!
Please don't forget to update the PR title (and thus squash commit msg) to bring it in our standard format, before merging. |
@josephkmh I intend (in a follow-up) to break out the |
* Add wrapper for cloud dbt endpoint Also includes a cheeky little test usage which probably should have had a name starting with an underscore (I did not commit the test code which added the new variable's contents to `(window as any).availableJobs`, on grounds that it was very ugly, but I did want to have the import and call of the wrapper function hit the git history here). * Add dbt Cloud jobs via dropdown (WIP: breaks if no integration) Selecting job from dropdown adds it to saved jobs, but the new endpoint is unconditionally called even though it will always throw an error for users with no dbt Cloud integration configured. * Refactor to stop errors in non-dbt-integrated workspaces Well, I suppose throwing a runtime error for every connection which could support dbt Cloud jobs but is part of a workspace with no integration set up, but that doesn't exactly seem ideal. Instead, this pulls all logic out of the top-level card except for pulling the dbt Cloud integration information; then it delegates the rest to either of two fairly self-contained components, `NoDbtIntegration` or the new `DbtJobsForm`. The immediate benefit is that I have a nice component boundary in which I can unconditionally run dbt-Cloud-only logic to fetch available jobs. * Filter already-selected jobs out of dropdown * Use dbt's jobNames and read-only {account,job}Id in job list * Remove obsolete yup validations for dbt Cloud jobs Since the values are now supplied by dbt Cloud via API, the user no longer has to manually input anything; and this sudden lack of user input rather obviates the need to validate user input. * Add button loading state when saving dbt Cloud jobs
What this does
Fetches all dbt Cloud jobs that the current workspace's dbt Cloud token authorizes us to access via a new cloud endpoint (resolves https://github.com/airbytehq/airbyte-cloud/issues/2875). The new data is used for two improvements to this feature:
What this does not do yet
DbtCloudJob
type to use the now-canonicalacountId
andjobId
field names (instead of the currentaccount
andjob
) or types (number
instead ofstring
, which was chosen for convenience when working with the now-removed text inputs) :: I'm deferring this work until the backend fully supports structured dbt Cloud data (including for saved webhook operations).How
orval
(using the same setup as Generate cloud api client from airbyte-cloud if present #19091); afterwards I manually moved all generated code relevant to the new dbt Cloud endpoint toairbyte-webapp/src/packages/cloud/lib/domain/dbtCloud/api.ts
, deleted the rest, and defined a wrapper function.yup
validations; since there's no longer any user-supplied values in a saved job definition, there's no longer any need to validate them as such.jobName
(only if present, the old generic name still exists as a fallback)Recommended reading order
airbyte-webapp/src/packages/cloud/lib/domain/dbtCloud/api.ts
; the main definition to take note of isDbtCloudJobInfo
airbyte-webapp/src/packages/cloud/services/dbtCloud.ts
airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/ConnectionTransformationTab/DbtCloudTransformationsCard.tsx