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

chore(data-warehouse): dw billing #18168

Merged
merged 93 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
bd5368b
create airbyte source api
EDsCODE Sep 19, 2023
72393c6
comment test
EDsCODE Sep 19, 2023
32721ef
rename and add connection
EDsCODE Oct 9, 2023
586fc69
merge master
EDsCODE Oct 9, 2023
2095297
comment out test
EDsCODE Oct 9, 2023
acdfd7e
frontend updates and additional API calls on airbyte
EDsCODE Oct 12, 2023
80cfca6
some more UI and retrieve endpoint
EDsCODE Oct 16, 2023
b29b4e2
restore lock file
EDsCODE Oct 17, 2023
ed5f583
connecting the dots
EDsCODE Oct 17, 2023
b991656
add destination logic
EDsCODE Oct 18, 2023
5c27ad2
make destinatino parquet
EDsCODE Oct 18, 2023
2497605
merge master
EDsCODE Oct 18, 2023
9100a3e
ui updates
EDsCODE Oct 19, 2023
441c06c
add task to billing usage report
EDsCODE Oct 24, 2023
a492eea
update task
EDsCODE Oct 24, 2023
ba231d7
rename data
EDsCODE Oct 26, 2023
63df8bd
more renaming
EDsCODE Oct 26, 2023
2a41eec
migration
EDsCODE Oct 26, 2023
9ce61f8
merge master
EDsCODE Oct 26, 2023
dbebbf7
remove test
EDsCODE Oct 26, 2023
9dd6eee
rename
EDsCODE Oct 27, 2023
ea31b48
Update UI snapshots for `chromium` (2)
github-actions[bot] Oct 27, 2023
c21def1
missing file
EDsCODE Oct 27, 2023
59650c1
Merge branch 'master' into dw-airbyte
EDsCODE Oct 27, 2023
e808dbe
merge master
EDsCODE Oct 27, 2023
dd83e0f
typing
EDsCODE Oct 27, 2023
a59a315
remove unneeded field
EDsCODE Oct 27, 2023
fc2bf91
remove 'billable' and unnecessary field
EDsCODE Oct 29, 2023
a6bba42
merge'
EDsCODE Oct 29, 2023
f58b8b5
add rollback deletions if one fo the related resources fails
EDsCODE Oct 29, 2023
b9a082e
Merge branch 'dw-airbyte' into dw-airbyte-billing
EDsCODE Oct 29, 2023
3952c17
Merge branch 'master' into dw-airbyte
EDsCODE Oct 30, 2023
3dd7a13
Merge branch 'dw-airbyte' into dw-airbyte-billing
EDsCODE Oct 30, 2023
3de924e
fix types
EDsCODE Oct 30, 2023
cdc5f5c
change type
EDsCODE Oct 30, 2023
b6a989a
merge master
EDsCODE Nov 7, 2023
cc16163
remove fluff
EDsCODE Nov 7, 2023
293412f
remove migration
EDsCODE Nov 7, 2023
14d16a6
Update UI snapshots for `chromium` (1)
github-actions[bot] Nov 7, 2023
3776015
new attempt
EDsCODE Nov 7, 2023
50c1912
add tests
EDsCODE Nov 7, 2023
a6ba41a
Merge branch 'dw-airbyte-billing' of github.com:PostHog/posthog into …
EDsCODE Nov 7, 2023
2dc3d20
add comment
EDsCODE Nov 7, 2023
18de41f
move around ph_client
EDsCODE Nov 7, 2023
d25a7d6
Update query snapshots
github-actions[bot] Nov 7, 2023
13c9b7d
Update query snapshots
github-actions[bot] Nov 7, 2023
53d814e
Update query snapshots
github-actions[bot] Nov 7, 2023
4917793
Update query snapshots
github-actions[bot] Nov 7, 2023
fcd82a5
Update UI snapshots for `chromium` (2)
github-actions[bot] Nov 7, 2023
5272fb3
Update UI snapshots for `chromium` (2)
github-actions[bot] Nov 7, 2023
4015bfa
Update UI snapshots for `chromium` (2)
github-actions[bot] Nov 7, 2023
81c8277
Update UI snapshots for `chromium` (2)
github-actions[bot] Nov 7, 2023
177acaf
merge master
EDsCODE Nov 8, 2023
734575d
Update query snapshots
github-actions[bot] Nov 8, 2023
e553003
Update UI snapshots for `chromium` (2)
github-actions[bot] Nov 8, 2023
31e1c72
Update UI snapshots for `chromium` (2)
github-actions[bot] Nov 8, 2023
958e0a8
add job
EDsCODE Nov 8, 2023
bea7740
usage report task and tests
EDsCODE Nov 8, 2023
ad29f13
test
EDsCODE Nov 8, 2023
0ae2990
Merge branch 'dw-airbyte-billing' of github.com:PostHog/posthog into …
EDsCODE Nov 8, 2023
9c52426
add limit checker task
EDsCODE Nov 8, 2023
2796342
add conversion
EDsCODE Nov 9, 2023
49248d0
add tests
EDsCODE Nov 9, 2023
e2bc69a
address comments
EDsCODE Nov 13, 2023
6793f74
merge master
EDsCODE Nov 13, 2023
4d5abaa
Update query snapshots
github-actions[bot] Nov 13, 2023
cbecb6a
Update query snapshots
github-actions[bot] Nov 13, 2023
0701297
update test
EDsCODE Nov 13, 2023
fc0d573
Merge branch 'dw-airbyte-billing' of github.com:PostHog/posthog into …
EDsCODE Nov 13, 2023
7695006
revised
EDsCODE Nov 13, 2023
16f4cf1
fix tests
EDsCODE Nov 13, 2023
0142f5b
Update query snapshots
github-actions[bot] Nov 13, 2023
4dfacbc
Update query snapshots
github-actions[bot] Nov 13, 2023
597c10c
Update query snapshots
github-actions[bot] Nov 13, 2023
f7c70dc
Update query snapshots
github-actions[bot] Nov 13, 2023
88ebd26
add typing
EDsCODE Nov 13, 2023
1fcb993
Merge branch 'dw-airbyte-billing' of github.com:PostHog/posthog into …
EDsCODE Nov 13, 2023
79c7609
update tests
EDsCODE Nov 13, 2023
5e185c1
rename
EDsCODE Nov 13, 2023
44865ee
typing
EDsCODE Nov 14, 2023
53295b3
fix tests
EDsCODE Nov 14, 2023
ef3ab78
Update query snapshots
github-actions[bot] Nov 14, 2023
d5e9903
Update query snapshots
github-actions[bot] Nov 14, 2023
7b6751b
Update query snapshots
github-actions[bot] Nov 14, 2023
463a843
fix tests and types
EDsCODE Nov 14, 2023
fa20ba7
Merge branch 'dw-airbyte-billing' of github.com:PostHog/posthog into …
EDsCODE Nov 14, 2023
d6f8b64
fix typo
EDsCODE Nov 14, 2023
9d54e1f
naming
EDsCODE Nov 14, 2023
9aeacbc
verbose
EDsCODE Nov 14, 2023
5ba58ed
remove verbose
EDsCODE Nov 14, 2023
e8fe816
typo
EDsCODE Nov 14, 2023
036cc72
restore main
EDsCODE Nov 14, 2023
e3c8e14
adjust timing
EDsCODE Nov 14, 2023
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
1 change: 1 addition & 0 deletions frontend/public/stripe-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions frontend/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import {
BatchExportRun,
UserBasicType,
NotebookNodeResource,
AirbyteStripeResourceCreatePayload,
AirbyteStripeResource,
} from '~/types'
import { getCurrentOrganizationId, getCurrentTeamId } from './utils/logics'
import { CheckboxValueType } from 'antd/lib/checkbox/Group'
Expand Down Expand Up @@ -566,6 +568,11 @@ class ApiRequest {
return this.batchExportRun(id, runId, teamId).addPathComponent('logs')
}

// Airbyte
public airbyteResources(teamId?: TeamType['id']): ApiRequest {
return this.projectsDetail(teamId).addPathComponent('airbyte_resources')
}

// Request finalization
public async get(options?: ApiMethodOptions): Promise<any> {
return await api.get(this.assembleFullUrl(), options)
Expand Down Expand Up @@ -1571,6 +1578,15 @@ const api = {
},
},

airbyteResources: {
async list(): Promise<PaginatedResponse<AirbyteStripeResource>> {
return await new ApiRequest().airbyteResources().get()
},
async create(data: Partial<AirbyteStripeResourceCreatePayload>): Promise<AirbyteStripeResourceCreatePayload> {
return await new ApiRequest().airbyteResources().create({ data })
},
},

dataWarehouseViewLinks: {
async list(): Promise<PaginatedResponse<DataWarehouseViewLink>> {
return await new ApiRequest().dataWarehouseViewLinks().get()
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/scenes/appScenes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Scene } from 'scenes/sceneTypes'
import { preloadedScenes } from 'scenes/scenes'

export const appScenes: Record<Scene, () => any> = {

Check failure on line 4 in frontend/src/scenes/appScenes.ts

View workflow job for this annotation

GitHub Actions / Code quality checks

Property '[Scene.DataWarehouseTable]' is missing in type '{ 404: () => { default: SceneComponent; }; "4xx": () => { default: SceneComponent; }; ProjectUnavailable: () => { default: SceneComponent; }; Dashboards: () => Promise<...>; ... 74 more ...; Onboarding: () => Promise<...>; }' but required in type 'Record<Scene, () => any>'.
[Scene.Error404]: () => ({ default: preloadedScenes[Scene.Error404].component }),
[Scene.ErrorNetwork]: () => ({ default: preloadedScenes[Scene.ErrorNetwork].component }),
[Scene.ErrorProjectUnavailable]: () => ({ default: preloadedScenes[Scene.ErrorProjectUnavailable].component }),
Expand Down Expand Up @@ -44,7 +44,7 @@
[Scene.DataWarehousePosthog]: () => import('./data-warehouse/posthog/DataWarehousePosthogScene'),
[Scene.DataWarehouseExternal]: () => import('./data-warehouse/external/DataWarehouseExternalScene'),
[Scene.DataWarehouseSavedQueries]: () => import('./data-warehouse/saved_queries/DataWarehouseSavedQueriesScene'),
[Scene.DataWarehouseTable]: () => import('./data-warehouse/DataWarehouseTable'),
[Scene.DataWarehouseSettings]: () => import('./data-warehouse/settings/DataWarehouseSettingsScene'),
[Scene.OrganizationSettings]: () => import('./organization/Settings'),
[Scene.OrganizationCreateFirst]: () => import('./organization/Create'),
[Scene.OrganizationCreationConfirm]: () => import('./organization/ConfirmOrganization/ConfirmOrganization'),
Expand Down
69 changes: 2 additions & 67 deletions frontend/src/scenes/data-warehouse/DataWarehouseTable.tsx
Original file line number Diff line number Diff line change
@@ -1,76 +1,11 @@
import { SceneExport } from 'scenes/sceneTypes'
import { dataWarehouseTableLogic } from './dataWarehouseTableLogic'
import { useActions, useValues } from 'kea'
import { Form } from 'kea-forms'
import { PageHeader } from 'lib/components/PageHeader'
import { LemonSkeleton } from 'lib/lemon-ui/LemonSkeleton'
import { LemonButton, LemonDivider, LemonInput, LemonSelect } from '@posthog/lemon-ui'
import { router } from 'kea-router'
import { urls } from 'scenes/urls'
import { LemonInput, LemonSelect } from '@posthog/lemon-ui'
import { Field } from 'lib/forms/Field'

export const scene: SceneExport = {
component: DataWarehousetTable,
logic: dataWarehouseTableLogic,
paramsToProps: ({ params: { id } }): (typeof dataWarehouseTableLogic)['props'] => ({
id: id,
}),
}

export function DataWarehousetTable({ id }: { id?: string } = {}): JSX.Element {
const { isEditingTable } = useValues(dataWarehouseTableLogic)
const showTableForm = id === 'new' || isEditingTable
return <div>{!id ? <LemonSkeleton /> : <>{showTableForm ? <TableForm id={id} /> : <></>}</>}</div>
}

export function TableForm({ id }: { id: string }): JSX.Element {
const { table, tableLoading, isEditingTable } = useValues(dataWarehouseTableLogic)
const { loadTable, editingTable } = useActions(dataWarehouseTableLogic)

export function DatawarehouseTableForm(): JSX.Element {
return (
<Form formKey="table" logic={dataWarehouseTableLogic} className="space-y-4" enableFormOnSubmit>
<PageHeader
title={id === 'new' ? 'New table' : table.name}
buttons={
<div className="flex items-center gap-2">
<LemonButton
data-attr="cancel-table"
type="secondary"
loading={tableLoading}
onClick={() => {
if (isEditingTable) {
editingTable(false)
loadTable()
} else {
router.actions.push(urls.dataWarehouse())
}
}}
>
Cancel
</LemonButton>
<LemonButton
type="primary"
data-attr="save-feature-flag"
htmlType="submit"
loading={tableLoading}
>
Save
</LemonButton>
</div>
}
caption={
<div>
External tables are supported through object storage systems like S3.{' '}
<a
href="https://posthog.com/docs/data/data-warehouse#step-1-creating-a-bucket-in-s3"
target="_blank"
>
Learn how to set up your data
</a>
</div>
}
/>
<LemonDivider />
<div className="flex flex-col gap-2 max-w-160">
<Field name="name" label="Table Name">
<LemonInput
Expand Down
26 changes: 2 additions & 24 deletions frontend/src/scenes/data-warehouse/dataWarehouseTableLogic.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { lemonToast } from '@posthog/lemon-ui'
import { kea, path, props, key, listeners, afterMount, reducers, actions, selectors, connect } from 'kea'
import { kea, path, props, listeners, reducers, actions, selectors, connect } from 'kea'
import { forms } from 'kea-forms'
import { loaders } from 'kea-loaders'
import { router, urlToAction } from 'kea-router'
import { router } from 'kea-router'
import api from 'lib/api'
import { urls } from 'scenes/urls'
import { AnyPropertyFilter, Breadcrumb, DataWarehouseTable } from '~/types'
Expand All @@ -29,7 +29,6 @@ const NEW_WAREHOUSE_TABLE: DataWarehouseTable = {
export const dataWarehouseTableLogic = kea<dataWarehouseTableLogicType>([
path(['scenes', 'data-warehouse', 'tableLogic']),
props({} as TableLogicProps),
key(({ id }) => id),
connect(() => ({
actions: [databaseSceneLogic, ['loadDatabase']],
})),
Expand Down Expand Up @@ -122,25 +121,4 @@ export const dataWarehouseTableLogic = kea<dataWarehouseTableLogicType>([
},
},
})),
urlToAction(({ actions, props }) => ({
[urls.dataWarehouseTable(props.id ?? 'new')]: (_, __, ___, { method }) => {
// If the URL was pushed (user clicked on a link), reset the scene's data.
// This avoids resetting form fields if you click back/forward.
if (method === 'PUSH') {
if (props.id) {
actions.loadTable()
} else {
actions.resetTable()
}
}
},
})),
afterMount(async ({ props, actions }) => {
// if (props.id !== 'new') {
// await actions.loadTable()
// }
if (props.id === 'new') {
actions.resetTable()
}
}),
])
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import { LemonButton, LemonTag } from '@posthog/lemon-ui'
import { LemonButtonWithSideAction, LemonTag } from '@posthog/lemon-ui'
import { PageHeader } from 'lib/components/PageHeader'
import { SceneExport } from 'scenes/sceneTypes'
import { urls } from 'scenes/urls'
import { useValues } from 'kea'
import { useActions, useValues } from 'kea'
import { router } from 'kea-router'
import { ProductIntroduction } from 'lib/components/ProductIntroduction/ProductIntroduction'
import { ProductKey } from '~/types'
import { DataWarehouseTablesContainer } from './DataWarehouseTables'
import { dataWarehouseSceneLogic } from './dataWarehouseSceneLogic'
import { DataWarehousePageTabs, DataWarehouseTab } from '../DataWarehousePageTabs'
import SourceModal from './SourceModal'
import { IconSettings } from 'lib/lemon-ui/icons'

export const scene: SceneExport = {
component: DataWarehouseExternalScene,
logic: dataWarehouseSceneLogic,
}

export function DataWarehouseExternalScene(): JSX.Element {
const { shouldShowEmptyState, shouldShowProductIntroduction } = useValues(dataWarehouseSceneLogic)
const { shouldShowEmptyState, shouldShowProductIntroduction, isSourceModalOpen } =
useValues(dataWarehouseSceneLogic)
const { toggleSourceModal } = useActions(dataWarehouseSceneLogic)

return (
<div>
Expand All @@ -30,15 +34,19 @@ export function DataWarehouseExternalScene(): JSX.Element {
</div>
}
buttons={
!shouldShowProductIntroduction ? (
<LemonButton
type="primary"
to={urls.dataWarehouseTable('new')}
data-attr="new-data-warehouse-table"
>
New Table
</LemonButton>
) : undefined
<LemonButtonWithSideAction
type="primary"
sideAction={{
icon: <IconSettings />,
onClick: () => router.actions.push(urls.dataWarehouseSettings()),
'data-attr': 'saved-insights-new-insight-dropdown',
}}
data-attr="new-data-warehouse-easy-link"
key={'new-data-warehouse-easy-link'}
onClick={toggleSourceModal}
>
Link Source
</LemonButtonWithSideAction>
}
caption={
<div>
Expand All @@ -59,13 +67,14 @@ export function DataWarehouseExternalScene(): JSX.Element {
description={
'Bring your production database, revenue data, CRM contacts or any other data into PostHog.'
}
action={() => router.actions.push(urls.dataWarehouseTable('new'))}
action={() => toggleSourceModal()}
isEmpty={shouldShowEmptyState}
docsURL="https://posthog.com/docs/data/data-warehouse"
productKey={ProductKey.DATA_WAREHOUSE}
/>
)}
{!shouldShowEmptyState && <DataWarehouseTablesContainer />}
<SourceModal isOpen={isSourceModalOpen} onClose={toggleSourceModal} />
</div>
)
}
119 changes: 119 additions & 0 deletions frontend/src/scenes/data-warehouse/external/SourceModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { LemonButton, LemonDivider, LemonInput, LemonModal, LemonModalProps } from '@posthog/lemon-ui'
import { Form } from 'kea-forms'
import { ConnectorConfigType, sourceModalLogic } from './sourceModalLogic'
import { useActions, useValues } from 'kea'
import { DatawarehouseTableForm } from '../DataWarehouseTable'
import { Field } from 'lib/forms/Field'
import stripeLogo from 'public/stripe-logo.svg'

interface SourceModalProps extends LemonModalProps {}

export default function SourceModal(props: SourceModalProps): JSX.Element {
const { tableLoading, isAirbyteResourceSubmitting, selectedConnector, isManualLinkFormVisible, connectors } =
useValues(sourceModalLogic)
const { selectConnector, toggleManualLinkFormVisible, resetAirbyteResource, resetTable } =
useActions(sourceModalLogic)

const MenuButton = (config: ConnectorConfigType): JSX.Element => {
const onClick = (): void => {
selectConnector(config)
}

return (
<LemonButton onClick={onClick} className="w-100" center type="secondary">
<img src={stripeLogo} alt={`stripe logo`} height={50} />
</LemonButton>
)
}

const onClear = (): void => {
selectConnector(null)
toggleManualLinkFormVisible(false)
resetAirbyteResource()
resetTable()
}

const onManualLinkClick = (): void => {
toggleManualLinkFormVisible(true)
}

const formToShow = (): JSX.Element => {
if (selectedConnector) {
return (
<Form logic={sourceModalLogic} formKey={'airbyteResource'} className="space-y-4" enableFormOnSubmit>
<Field name="account_id" label="Account Id">
<LemonInput className="ph-ignore-input" autoFocus data-attr="account-id" placeholder="acct_" />
</Field>
<Field name="client_secret" label="Client Secret">
<LemonInput
className="ph-ignore-input"
autoFocus
data-attr="client-secret"
placeholder="sklive"
/>
</Field>
<LemonDivider className="mt-4" />
<div className="mt-2 flex flex-row justify-end gap-2">
<LemonButton type="secondary" center data-attr="source-modal-back-button" onClick={onClear}>
Back
</LemonButton>
<LemonButton
type="primary"
center
htmlType="submit"
data-attr="source-link"
loading={isAirbyteResourceSubmitting}
>
Link
</LemonButton>
</div>
</Form>
)
}

if (isManualLinkFormVisible) {
return (
<div>
<DatawarehouseTableForm />
<LemonDivider className="mt-4" />
<div className="mt-2 flex flex-row justify-end gap-2">
<LemonButton type="secondary" center data-attr="source-modal-back-button" onClick={onClear}>
Back
</LemonButton>
<LemonButton
type="primary"
center
htmlType="submit"
data-attr="source-link"
loading={tableLoading}
>
Link
</LemonButton>
</div>
</div>
)
}

return (
<div className="flex flex-col gap-2">
{connectors.map((config, index) => (
<MenuButton key={config.name + '_' + index} {...config} />
))}
<LemonButton onClick={onManualLinkClick} className="w-100" center type="secondary">
Manual Link
</LemonButton>
</div>
)
}

return (
<LemonModal
{...props}
onAfterClose={() => onClear()}
title="Data Sources"
description={selectedConnector ? selectedConnector.caption : null}
>
{formToShow()}
</LemonModal>
)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { afterMount, connect, kea, path, selectors } from 'kea'
import { actions, afterMount, connect, kea, path, reducers, selectors } from 'kea'
import { loaders } from 'kea-loaders'
import api, { PaginatedResponse } from 'lib/api'
import { DataWarehouseTable, ProductKey } from '~/types'
Expand All @@ -12,6 +12,17 @@ export const dataWarehouseSceneLogic = kea<dataWarehouseSceneLogicType>([
connect(() => ({
values: [userLogic, ['user']],
})),
actions({
toggleSourceModal: true,
}),
reducers({
isSourceModalOpen: [
false,
{
toggleSourceModal: (state) => !state,
},
],
}),
loaders({
dataWarehouse: [
null as PaginatedResponse<DataWarehouseTable> | null,
Expand Down
Loading
Loading