Skip to content

Commit

Permalink
basic function for editing views
Browse files Browse the repository at this point in the history
  • Loading branch information
EDsCODE committed Apr 1, 2024
1 parent bf88a1c commit 1a158ed
Show file tree
Hide file tree
Showing 6 changed files with 326 additions and 188 deletions.
130 changes: 73 additions & 57 deletions frontend/src/queries/nodes/HogQLQuery/HogQLQueryEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ const kindToSortText = (kind: AutocompleteCompletionItem['kind'], label: string)
export interface HogQLQueryEditorProps {
query: HogQLQuery
setQuery?: (query: HogQLQuery) => void
onChange?: (query: string) => void
embedded?: boolean
editorFooter?: (hasErrors: boolean, errors: string | null, isValidView: boolean) => JSX.Element
}

let uniqueNode = 0
Expand All @@ -105,7 +107,14 @@ export function HogQLQueryEditor(props: HogQLQueryEditorProps): JSX.Element {
null as [Monaco, importedEditor.IStandaloneCodeEditor] | null
)
const [monaco, editor] = monacoAndEditor ?? []
const hogQLQueryEditorLogicProps = { query: props.query, setQuery: props.setQuery, key, editor, monaco }
const hogQLQueryEditorLogicProps = {
query: props.query,
setQuery: props.setQuery,
onChange: props.onChange,
key,
editor,
monaco,
}
const logic = hogQLQueryEditorLogic(hogQLQueryEditorLogicProps)
const { queryInput, hasErrors, error, prompt, aiAvailable, promptError, promptLoading, isValidView } =
useValues(logic)
Expand Down Expand Up @@ -357,62 +366,69 @@ export function HogQLQueryEditor(props: HogQLQueryEditorProps): JSX.Element {
</div>
</div>
<div className="flex flex-row">
<div className="flex-1">
<LemonButton
onClick={saveQuery}
type="primary"
disabledReason={
!props.setQuery
? 'No permission to update'
: hasErrors
? error ?? 'Query has errors'
: undefined
}
center
fullWidth
data-attr="hogql-query-editor-save"
>
{!props.setQuery ? 'No permission to update' : 'Update and run'}
</LemonButton>
</div>
{featureFlags[FEATURE_FLAGS.DATA_WAREHOUSE] ? (
<LemonButton
className="ml-2"
onClick={saveAsView}
type="primary"
center
disabledReason={
hasErrors
? error ?? 'Query has errors'
: !isValidView
? 'All fields must have an alias'
: ''
}
data-attr="hogql-query-editor-save-as-view"
>
Save as View
</LemonButton>
) : null}
{featureFlags[FEATURE_FLAGS.DATA_WAREHOUSE] && (
<LemonButtonWithDropdown
className="ml-2"
icon={<IconInfo />}
type="secondary"
size="small"
dropdown={{
overlay: (
<div>
Save a query as a view that can be referenced in another query. This is useful
for modeling data and organizing large queries into readable chunks.{' '}
<Link to="https://posthog.com/docs/data-warehouse">More Info</Link>{' '}
</div>
),
placement: 'right-start',
fallbackPlacements: ['left-start'],
actionable: true,
closeParentPopoverOnClickInside: true,
}}
/>
{props.editorFooter ? (
props.editorFooter(hasErrors, error, isValidView)
) : (
<>
<div className="flex-1">
<LemonButton
onClick={saveQuery}
type="primary"
disabledReason={
!props.setQuery
? 'No permission to update'
: hasErrors
? error ?? 'Query has errors'
: undefined
}
center
fullWidth
data-attr="hogql-query-editor-save"
>
{!props.setQuery ? 'No permission to update' : 'Update and run'}
</LemonButton>
</div>
{featureFlags[FEATURE_FLAGS.DATA_WAREHOUSE] ? (
<LemonButton
className="ml-2"
onClick={saveAsView}
type="primary"
center
disabledReason={
hasErrors
? error ?? 'Query has errors'
: !isValidView
? 'All fields must have an alias'
: ''
}
data-attr="hogql-query-editor-save-as-view"
>
Save as View
</LemonButton>
) : null}
{featureFlags[FEATURE_FLAGS.DATA_WAREHOUSE] && (
<LemonButtonWithDropdown
className="ml-2"
icon={<IconInfo />}
type="secondary"
size="small"
dropdown={{
overlay: (
<div>
Save a query as a view that can be referenced in another query. This is
useful for modeling data and organizing large queries into readable
chunks.{' '}
<Link to="https://posthog.com/docs/data-warehouse">More Info</Link>{' '}
</div>
),
placement: 'right-start',
fallbackPlacements: ['left-start'],
actionable: true,
closeParentPopoverOnClickInside: true,
}}
/>
)}
</>
)}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface HogQLQueryEditorLogicProps {
key: number
query: HogQLQuery
setQuery?: (query: HogQLQuery) => void
onChange?: (query: string) => void
monaco?: Monaco | null
editor?: editor.IStandaloneCodeEditor | null
}
Expand Down Expand Up @@ -139,6 +140,7 @@ export const hogQLQueryEditorLogic = kea<hogQLQueryEditorLogicType>([
}
actions.setIsValidView(response?.isValidView || false)
actions.setModelMarkers(markers)
props.onChange?.(queryInput)
},
draftFromPrompt: async () => {
if (!values.aiAvailable) {
Expand Down
133 changes: 4 additions & 129 deletions frontend/src/scenes/data-warehouse/external/DataWarehouseTables.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
import { IconBrackets, IconDatabase } from '@posthog/icons'
import { LemonButton, Link } from '@posthog/lemon-ui'
import { Link } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { DatabaseTableTree, TreeItem } from 'lib/components/DatabaseTableTree/DatabaseTableTree'
import { EmptyMessage } from 'lib/components/EmptyMessage/EmptyMessage'
import { FEATURE_FLAGS } from 'lib/constants'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { humanFriendlyDetailedTime } from 'lib/utils'
import { DatabaseTable } from 'scenes/data-management/database/DatabaseTable'
import { urls } from 'scenes/urls'

import { NodeKind } from '~/queries/schema'

import { DataWarehouseRowType, DataWarehouseTableType } from '../types'
import { viewLinkLogic } from '../viewLinkLogic'
import { ViewLinkModal } from '../ViewLinkModal'
import { dataWarehouseSceneLogic } from './dataWarehouseSceneLogic'
import SourceModal from './SourceModal'
import { TableData } from './TableData'

export const DataWarehouseTables = (): JSX.Element => {
const {
Expand All @@ -24,52 +17,11 @@ export const DataWarehouseTables = (): JSX.Element => {
dataWarehouseLoading,
posthogTables,
savedQueriesFormatted,
allTables,
selectedRow,
dataWarehouseSavedQueriesLoading,
} = useValues(dataWarehouseSceneLogic)
const { toggleSourceModal, selectRow, deleteDataWarehouseSavedQuery, deleteDataWarehouseTable } =
useActions(dataWarehouseSceneLogic)
const { toggleSourceModal, selectRow } = useActions(dataWarehouseSceneLogic)
const { featureFlags } = useValues(featureFlagLogic)
const { toggleJoinTableModal, selectSourceTable } = useActions(viewLinkLogic)

const deleteButton = (selectedRow: DataWarehouseTableType | null): JSX.Element => {
if (!selectedRow) {
return <></>
}

if (selectedRow.type === DataWarehouseRowType.View) {
return (
<LemonButton
type="secondary"
onClick={() => {
deleteDataWarehouseSavedQuery(selectedRow.payload)
}}
>
Delete
</LemonButton>
)
}

if (selectedRow.type === DataWarehouseRowType.ExternalTable) {
return (
<LemonButton
type="secondary"
onClick={() => {
deleteDataWarehouseTable(selectedRow.payload)
}}
>
Delete
</LemonButton>
)
}

if (selectedRow.type === DataWarehouseRowType.PostHogTable) {
return <></>
}

return <></>
}

const treeItems = (): TreeItem[] => {
const items: TreeItem[] = [
Expand Down Expand Up @@ -126,84 +78,7 @@ export const DataWarehouseTables = (): JSX.Element => {
<div className="sm:col-span-3 md:col-span-1 max-h-160">
<DatabaseTableTree onSelectRow={selectRow} items={treeItems()} selectedRow={selectedRow} />
</div>
{selectedRow ? (
<div className="px-4 py-3 col-span-2">
<div className="flex flex-row justify-between items-center">
<h3>{selectedRow.name}</h3>
<div className="flex flex-row gap-2 justify-between">
{deleteButton(selectedRow)}
<LemonButton
type="primary"
onClick={() => {
selectSourceTable(selectedRow.name)
toggleJoinTableModal()
}}
>
Add Join
</LemonButton>
<Link
to={urls.insightNew(
undefined,
undefined,
JSON.stringify({
kind: NodeKind.DataTableNode,
full: true,
source: {
kind: NodeKind.HogQLQuery,
// TODO: Use `hogql` tag?
query: `SELECT ${selectedRow.columns
.filter(({ table, fields, chain }) => !table && !fields && !chain)
.map(({ key }) => key)} FROM ${selectedRow.name} LIMIT 100`,
},
})
)}
>
<LemonButton type="primary">Query</LemonButton>
</Link>
</div>
</div>
{selectedRow.type == DataWarehouseRowType.ExternalTable && (
<div className="flex flex-col">
<>
<span className="card-secondary mt-2">Last Synced At</span>
<span>
{selectedRow.payload.external_schema?.last_synced_at
? humanFriendlyDetailedTime(
selectedRow.payload.external_schema?.last_synced_at,
'MMMM DD, YYYY',
'h:mm A'
)
: 'Not yet synced'}
</span>
</>

<>
<span className="card-secondary mt-2">Files URL pattern</span>
<span>{selectedRow.payload.url_pattern}</span>
</>

<>
<span className="card-secondary mt-2">File format</span>
<span>{selectedRow.payload.format}</span>
</>
</div>
)}

<div className="mt-2">
<span className="card-secondary">Columns</span>
<DatabaseTable table={selectedRow.name} tables={allTables} />
</div>
</div>
) : (
<div className="px-4 py-3 h-100 col-span-2 flex justify-center items-center">
<EmptyMessage
title="No table selected"
description="Please select a table from the list on the left"
buttonText="Learn more about data warehouse tables"
buttonTo="https://posthog.com/docs/data-warehouse"
/>
</div>
)}
<TableData />
</div>
<SourceModal isOpen={isSourceModalOpen} onClose={() => toggleSourceModal(false)} />
<ViewLinkModal />
Expand Down
Loading

0 comments on commit 1a158ed

Please sign in to comment.