Skip to content

Commit

Permalink
Merge branch 'master' into feat/use-preview-remote-config
Browse files Browse the repository at this point in the history
  • Loading branch information
benjackwhite authored Dec 15, 2024
2 parents b454f89 + e1d346e commit e0e0b75
Show file tree
Hide file tree
Showing 42 changed files with 4,080 additions and 432 deletions.
3 changes: 3 additions & 0 deletions cypress/e2e/insights-navigation-open-sql-insight-first.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ describe('Insights', () => {

it('can open a new stickiness insight', () => {
insight.clickTab('STICKINESS')
// this test flaps, so check for a parent element, that is present even when failing
// in the hope that it slows the test down a little and stops it flapping
cy.get('.InsightVizDisplay--type-stickiness').should('exist')
cy.get('.TrendsInsight canvas').should('exist')
})

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export const sidePanelActivityLogic = kea<sidePanelActivityLogicType>([
],
})),

listeners(({ values, actions }) => ({
listeners(({ values, actions, cache }) => ({
setActiveTab: ({ tab }) => {
if (tab === SidePanelActivityTab.All && !values.allActivityResponseLoading) {
actions.loadAllActivity()
Expand All @@ -191,6 +191,13 @@ export const sidePanelActivityLogic = kea<sidePanelActivityLogicType>([
actions.setActiveTab(options as SidePanelActivityTab)
}
},
togglePolling: ({ pageIsVisible }) => {
if (pageIsVisible) {
actions.loadImportantChanges()
} else {
clearTimeout(cache.pollTimeout)
}
},
})),
selectors({
allActivity: [
Expand Down
18 changes: 16 additions & 2 deletions frontend/src/queries/nodes/DataNode/dataNodeLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ export const dataNodeLogic = kea<dataNodeLogicType>([
if (cache.localResults[stringifiedQuery] && !refresh) {
return cache.localResults[stringifiedQuery]
}

if (!query.query) {
return null
}
}

if (!values.currentTeamId) {
Expand Down Expand Up @@ -337,6 +341,12 @@ export const dataNodeLogic = kea<dataNodeLogicType>([
],
})),
reducers(({ props }) => ({
isRefresh: [
false,
{
loadData: (_, { refresh }) => !!refresh,
},
],
dataLoading: [
false,
{
Expand Down Expand Up @@ -474,8 +484,12 @@ export const dataNodeLogic = kea<dataNodeLogicType>([
(variablesOverride) => !!variablesOverride,
],
isShowingCachedResults: [
() => [(_, props) => props.cachedResults ?? null, (_, props) => props.query],
(cachedResults: AnyResponseType | null, query: DataNode): boolean => {
(s) => [(_, props) => props.cachedResults ?? null, (_, props) => props.query, s.isRefresh],
(cachedResults: AnyResponseType | null, query: DataNode, isRefresh): boolean => {
if (isRefresh) {
return false
}

return (
!!cachedResults ||
(cache.localResults && 'query' in query && JSON.stringify(query.query) in cache.localResults)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const verifyEmailLogic = kea<verifyEmailLogicType>([
{
validateEmailToken: async ({ uuid, token }: { uuid: string; token: string }, breakpoint) => {
try {
await api.create(`api/users/${uuid}/verify_email/`, { token, uuid })
await api.create(`api/users/verify_email/`, { token, uuid })
actions.setView('success')
await breakpoint(2000)
window.location.href = '/'
Expand All @@ -48,7 +48,7 @@ export const verifyEmailLogic = kea<verifyEmailLogicType>([
{
requestVerificationLink: async ({ uuid }: { uuid: string }) => {
try {
await api.create(`api/users/${uuid}/request_email_verification/`, { uuid })
await api.create(`api/users/request_email_verification/`, { uuid })
lemonToast.success(
'A new verification link has been sent to the associated email address. Please check your inbox.'
)
Expand Down
188 changes: 119 additions & 69 deletions frontend/src/scenes/data-warehouse/editor/OutputPane.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import 'react-data-grid/lib/styles.css'

import { IconGear } from '@posthog/icons'
import { LemonButton, LemonTabs, Spinner } from '@posthog/lemon-ui'
import { LemonButton, LemonTabs } from '@posthog/lemon-ui'
import clsx from 'clsx'
import { useActions, useValues } from 'kea'
import { AnimationType } from 'lib/animations/animations'
import { Animation } from 'lib/components/Animation/Animation'
import { ExportButton } from 'lib/components/ExportButton/ExportButton'
import { useMemo } from 'react'
import DataGrid from 'react-data-grid'
import { InsightErrorState } from 'scenes/insights/EmptyStates'
import { InsightErrorState, StatelessInsightLoadingState } from 'scenes/insights/EmptyStates'
import { HogQLBoldNumber } from 'scenes/insights/views/BoldNumber/BoldNumber'

import { KeyboardShortcut } from '~/layout/navigation-3000/components/KeyboardShortcut'
import { themeLogic } from '~/layout/navigation-3000/themeLogic'
import { dataNodeLogic } from '~/queries/nodes/DataNode/dataNodeLogic'
import { ElapsedTime } from '~/queries/nodes/DataNode/ElapsedTime'
import { LineGraph } from '~/queries/nodes/DataVisualization/Components/Charts/LineGraph'
import { SideBar } from '~/queries/nodes/DataVisualization/Components/SideBar'
import { Table } from '~/queries/nodes/DataVisualization/Components/Table'
Expand All @@ -39,12 +40,12 @@ export function OutputPane(): JSX.Element {
const { editingView, sourceQuery, exportContext, isValidView, error } = useValues(multitabEditorLogic)
const { saveAsInsight, saveAsView, setSourceQuery, runQuery } = useActions(multitabEditorLogic)
const { isDarkModeOn } = useValues(themeLogic)
const { response, responseLoading, responseError } = useValues(dataNodeLogic)
const { response, responseLoading, responseError, queryId, pollResponse } = useValues(dataNodeLogic)
const { dataWarehouseSavedQueriesLoading } = useValues(dataWarehouseViewsLogic)
const { updateDataWarehouseSavedQuery } = useActions(dataWarehouseViewsLogic)
const { visualizationType, queryCancelled } = useValues(dataVisualizationLogic)

const vizKey = `SQLEditorScene`
const vizKey = useMemo(() => `SQLEditorScene`, [])

const columns = useMemo(() => {
return (
Expand All @@ -69,70 +70,6 @@ export function OutputPane(): JSX.Element {
})
}, [response])

const ErrorState = useMemo((): JSX.Element | null => {
return (
<div className={clsx('flex-1 absolute top-0 left-0 right-0 bottom-0 overflow-scroll')}>
<InsightErrorState
query={sourceQuery}
excludeDetail
title={
queryCancelled
? 'The query was cancelled'
: response && 'error' in response
? (response as any).error
: responseError
}
/>
</div>
)
}, [responseError, sourceQuery, queryCancelled, response])

const Content = (): JSX.Element | null => {
if (activeTab === OutputTab.Results) {
if (responseError) {
return ErrorState
}

return responseLoading ? (
<Spinner className="text-3xl" />
) : !response ? (
<span className="text-muted mt-3">Query results will appear here</span>
) : (
<div className="flex-1 absolute top-0 left-0 right-0 bottom-0">
<DataGrid
className={isDarkModeOn ? 'rdg-dark h-full' : 'rdg-light h-full'}
columns={columns}
rows={rows}
/>
</div>
)
}

if (activeTab === OutputTab.Visualization) {
if (responseError) {
return ErrorState
}

return !response ? (
<span className="text-muted mt-3">Query be results will be visualized here</span>
) : (
<div className="flex-1 absolute top-0 left-0 right-0 bottom-0 px-4 py-1 hide-scrollbar">
<InternalDataTableVisualization
uniqueKey={vizKey}
query={sourceQuery}
setQuery={setSourceQuery}
context={{}}
cachedResults={undefined}
exportContext={exportContext}
onSaveInsight={saveAsInsight}
/>
</div>
)
}

return null
}

return (
<div className="flex flex-col w-full flex-1 bg-bg-3000">
{variablesForInsight.length > 0 && (
Expand Down Expand Up @@ -215,7 +152,26 @@ export function OutputPane(): JSX.Element {
</div>
</div>
<div className="flex flex-1 relative bg-dark justify-center items-center">
<Content />
<Content
activeTab={activeTab}
responseError={responseError}
responseLoading={responseLoading}
response={response}
sourceQuery={sourceQuery}
queryCancelled={queryCancelled}
columns={columns}
rows={rows}
isDarkModeOn={isDarkModeOn}
vizKey={vizKey}
setSourceQuery={setSourceQuery}
exportContext={exportContext}
saveAsInsight={saveAsInsight}
queryId={queryId}
pollResponse={pollResponse}
/>
</div>
<div className="flex justify-end pr-2 border-t">
<ElapsedTime />
</div>
</div>
)
Expand Down Expand Up @@ -303,3 +259,97 @@ function InternalDataTableVisualization(
</div>
)
}

const ErrorState = ({ responseError, sourceQuery, queryCancelled, response }: any): JSX.Element | null => {
return (
<div className={clsx('flex-1 absolute top-0 left-0 right-0 bottom-0 overflow-scroll')}>
<InsightErrorState
query={sourceQuery}
excludeDetail
title={
queryCancelled
? 'The query was cancelled'
: response && 'error' in response
? response.error
: responseError
}
/>
</div>
)
}

const Content = ({
activeTab,
responseError,
responseLoading,
response,
sourceQuery,
queryCancelled,
columns,
rows,
isDarkModeOn,
vizKey,
setSourceQuery,
exportContext,
saveAsInsight,
queryId,
pollResponse,
}: any): JSX.Element | null => {
if (activeTab === OutputTab.Results) {
if (responseError) {
return (
<ErrorState
responseError={responseError}
sourceQuery={sourceQuery}
queryCancelled={queryCancelled}
response={response}
/>
)
}

return responseLoading ? (
<StatelessInsightLoadingState queryId={queryId} pollResponse={pollResponse} />
) : !response ? (
<span className="text-muted mt-3">Query results will appear here</span>
) : (
<div className="flex-1 absolute top-0 left-0 right-0 bottom-0">
<DataGrid
className={isDarkModeOn ? 'rdg-dark h-full' : 'rdg-light h-full'}
columns={columns}
rows={rows}
/>
</div>
)
}

if (activeTab === OutputTab.Visualization) {
if (responseError) {
return (
<ErrorState
responseError={responseError}
sourceQuery={sourceQuery}
queryCancelled={queryCancelled}
response={response}
/>
)
}

return !response ? (
<span className="text-muted mt-3">Query be results will be visualized here</span>
) : (
<div className="flex-1 absolute top-0 left-0 right-0 bottom-0 px-4 py-1 hide-scrollbar">
<InternalDataTableVisualization
uniqueKey={vizKey}
query={sourceQuery}
setQuery={setSourceQuery}
context={{}}
cachedResults={undefined}
exportContext={exportContext}
onSaveInsight={saveAsInsight}
/>
</div>
)
}

return null
}
2 changes: 1 addition & 1 deletion frontend/src/scenes/data-warehouse/editor/QueryTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface QueryTabsProps {

export function QueryTabs({ models, onClear, onClick, onAdd, activeModelUri }: QueryTabsProps): JSX.Element {
return (
<div className="flex flex-row overflow-scroll hide-scrollbar h-10">
<div className="flex flex-row w-full overflow-scroll hide-scrollbar h-10">
{models.map((model: QueryTab) => (
<QueryTabComponent
key={model.uri.path}
Expand Down
28 changes: 13 additions & 15 deletions frontend/src/scenes/data-warehouse/editor/QueryWindow.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Monaco } from '@monaco-editor/react'
import { Spinner } from '@posthog/lemon-ui'
import { BindLogic, useActions, useValues } from 'kea'
import { router } from 'kea-router'
import type { editor as importedEditor } from 'monaco-editor'
Expand Down Expand Up @@ -40,14 +39,16 @@ export function QueryWindow(): JSX.Element {
const { selectTab, deleteTab, createTab, setQueryInput, runQuery, setError, setIsValidView } = useActions(logic)

return (
<div className="flex flex-1 flex-col h-full">
<QueryTabs
models={allTabs}
onClick={selectTab}
onClear={deleteTab}
onAdd={createTab}
activeModelUri={activeModelUri}
/>
<div className="flex flex-1 flex-col h-full overflow-hidden">
<div className="overflow-x-auto">
<QueryTabs
models={allTabs}
onClick={selectTab}
onClear={deleteTab}
onAdd={createTab}
activeModelUri={activeModelUri}
/>
</div>
{editingView && (
<div className="h-7 bg-warning-highlight p-1">
<span> Editing view "{editingView.name}"</span>
Expand Down Expand Up @@ -85,16 +86,13 @@ export function QueryWindow(): JSX.Element {
)
}

function InternalQueryWindow(): JSX.Element {
function InternalQueryWindow(): JSX.Element | null {
const { cacheLoading, sourceQuery, queryInput } = useValues(multitabEditorLogic)
const { setSourceQuery } = useActions(multitabEditorLogic)

// NOTE: hacky way to avoid flicker loading
if (cacheLoading) {
return (
<div className="flex-1 flex justify-center items-center">
<Spinner className="text-3xl" />
</div>
)
return null
}

const dataVisualizationLogicProps: DataVisualizationLogicProps = {
Expand Down
Loading

0 comments on commit e0e0b75

Please sign in to comment.