Skip to content

Commit

Permalink
Merge branch 'master' into feat/never-drop-data
Browse files Browse the repository at this point in the history
  • Loading branch information
raquelmsmith committed Sep 13, 2023
2 parents e01830e + a3635b6 commit 77fa9b8
Show file tree
Hide file tree
Showing 43 changed files with 587 additions and 370 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 22 additions & 16 deletions frontend/src/layout/navigation/TopBar/TopBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ export function TopBar(): JSX.Element {
const { hideInviteModal } = useActions(inviteLogic)
const { groupNamesTaxonomicTypes } = useValues(groupsModel)
const { featureFlags } = useValues(featureFlagLogic)

const hasNotebooks = !!featureFlags[FEATURE_FLAGS.NOTEBOOKS]

const groupTypes = [
TaxonomicFilterGroupType.Events,
TaxonomicFilterGroupType.Persons,
TaxonomicFilterGroupType.Actions,
TaxonomicFilterGroupType.Cohorts,
TaxonomicFilterGroupType.Insights,
TaxonomicFilterGroupType.FeatureFlags,
TaxonomicFilterGroupType.Plugins,
TaxonomicFilterGroupType.Experiments,
TaxonomicFilterGroupType.Dashboards,
...groupNamesTaxonomicTypes,
]

if (hasNotebooks) {
groupTypes.push(TaxonomicFilterGroupType.Notebooks)
}

return (
<>
<Announcement />
Expand All @@ -48,26 +68,12 @@ export function TopBar(): JSX.Element {
</Link>

<div className="grow">
<UniversalSearchPopover
groupType={TaxonomicFilterGroupType.Events}
groupTypes={[
TaxonomicFilterGroupType.Events,
TaxonomicFilterGroupType.Persons,
TaxonomicFilterGroupType.Actions,
TaxonomicFilterGroupType.Cohorts,
TaxonomicFilterGroupType.Insights,
TaxonomicFilterGroupType.FeatureFlags,
TaxonomicFilterGroupType.Plugins,
TaxonomicFilterGroupType.Experiments,
TaxonomicFilterGroupType.Dashboards,
...groupNamesTaxonomicTypes,
]}
/>
<UniversalSearchPopover groupType={TaxonomicFilterGroupType.Events} groupTypes={groupTypes} />
</div>
<ActivationSidebarToggle />
</div>
<div className="TopBar__segment TopBar__segment--right">
{!!featureFlags[FEATURE_FLAGS.NOTEBOOKS] && <NotebookButton />}
{hasNotebooks && <NotebookButton />}
<NotificationBell />
<HelpButton />
<SitePopover />
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1321,7 +1321,7 @@ const api = {
},
async update(
notebookId: NotebookType['short_id'],
data: Pick<NotebookType, 'version' | 'content' | 'title'>
data: Pick<NotebookType, 'version' | 'content' | 'text_content' | 'title'>
): Promise<NotebookType> {
return await new ApiRequest().notebook(notebookId).update({ data })
},
Expand All @@ -1348,11 +1348,11 @@ const api = {
q = { ...q, created_by: createdBy }
}
if (search) {
q = { ...q, s: search }
q = { ...q, search: search }
}
return await apiRequest.withQueryString(q).get()
},
async create(data?: Pick<NotebookType, 'content' | 'title'>): Promise<NotebookType> {
async create(data?: Pick<NotebookType, 'content' | 'text_content' | 'title'>): Promise<NotebookType> {
return await new ApiRequest().notebooks().create({ data })
},
async delete(notebookId: NotebookType['short_id']): Promise<NotebookType> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
PersonType,
PluginType,
PropertyDefinition,
NotebookType,
} from '~/types'
import { cohortsModel } from '~/models/cohortsModel'
import { actionsModel } from '~/models/actionsModel'
Expand All @@ -42,6 +43,7 @@ import { groupDisplayId } from 'scenes/persons/GroupActorDisplay'
import { infiniteListLogicType } from 'lib/components/TaxonomicFilter/infiniteListLogicType'
import { updatePropertyDefinitions } from '~/models/propertyDefinitionsModel'
import { InlineHogQLEditor } from './InlineHogQLEditor'
import { FEATURE_FLAGS } from 'lib/constants'

export const eventTaxonomicGroupProps: Pick<TaxonomicFilterGroup, 'getPopoverHeader' | 'getIcon'> = {
getPopoverHeader: (eventDefinition: EventDefinition): string => {
Expand Down Expand Up @@ -77,6 +79,8 @@ export const taxonomicFilterLogic = kea<taxonomicFilterLogicType>({
['groupTypes', 'aggregationLabel'],
groupPropertiesModel,
['allGroupProperties'],
featureFlagsLogic,
['featureFlags'],
],
},
actions: () => ({
Expand Down Expand Up @@ -146,15 +150,17 @@ export const taxonomicFilterLogic = kea<taxonomicFilterLogicType>({
s.groupAnalyticsTaxonomicGroupNames,
s.eventNames,
s.excludedProperties,
s.featureFlags,
],
(
teamId,
groupAnalyticsTaxonomicGroups,
groupAnalyticsTaxonomicGroupNames,
eventNames,
excludedProperties
excludedProperties,
featureFlags
): TaxonomicFilterGroup[] => {
return [
const groups = [
{
name: 'Events',
searchPlaceholder: 'events',
Expand Down Expand Up @@ -209,7 +215,7 @@ export const taxonomicFilterLogic = kea<taxonomicFilterLogicType>({
filter_by_event_names: true,
}).url
: undefined,
expandLabel: ({ count, expandedCount }) =>
expandLabel: ({ count, expandedCount }: { count: number; expandedCount: number }) =>
`Show ${pluralize(expandedCount - count, 'property', 'properties')} that ${pluralize(
eventNames.length,
'has',
Expand Down Expand Up @@ -237,7 +243,7 @@ export const taxonomicFilterLogic = kea<taxonomicFilterLogicType>({
filter_by_event_names: true,
}).url
: undefined,
expandLabel: ({ count, expandedCount }) =>
expandLabel: ({ count, expandedCount }: { count: number; expandedCount: number }) =>
`Show ${pluralize(expandedCount - count, 'property', 'properties')} that ${pluralize(
eventNames.length,
'has',
Expand Down Expand Up @@ -408,8 +414,8 @@ export const taxonomicFilterLogic = kea<taxonomicFilterLogicType>({
value: '$session_duration',
},
],
getName: (option) => option.name,
getValue: (option) => option.value,
getName: (option: any) => option.name,
getValue: (option: any) => option.value,
getPopoverHeader: () => 'Session',
},
{
Expand All @@ -422,6 +428,21 @@ export const taxonomicFilterLogic = kea<taxonomicFilterLogicType>({
...groupAnalyticsTaxonomicGroups,
...groupAnalyticsTaxonomicGroupNames,
]

if (featureFlags[FEATURE_FLAGS.NOTEBOOKS]) {
groups.push({
name: 'Notebooks',
searchPlaceholder: 'notebooks',
type: TaxonomicFilterGroupType.Notebooks,
value: 'notebooks',
endpoint: `api/projects/${teamId}/notebooks/`,
getName: (notebook: NotebookType) => notebook.title || `Notebook ${notebook.short_id}`,
getValue: (notebook: NotebookType) => notebook.short_id,
getPopoverHeader: () => 'Notebooks',
})
}

return groups
},
],
activeTaxonomicGroup: [
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/components/TaxonomicFilter/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export enum TaxonomicFilterGroupType {
GroupNamesPrefix = 'name_groups',
Sessions = 'sessions',
HogQLExpression = 'hogql_expression',
Notebooks = 'notebooks',
}

export interface InfiniteListLogicProps extends TaxonomicFilterLogicProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ function redirectOnSelectItems(
)
} else if (groupType === TaxonomicFilterGroupType.Dashboards) {
router.actions.push(urls.dashboard(value))
} else if (groupType === TaxonomicFilterGroupType.Notebooks) {
router.actions.push(urls.notebook(String(value)))
}
}

Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ export const FEATURE_FLAGS = {
SURVEY_NPS_RESULTS: 'survey-nps-results', // owner: @liyiy
// owner: #team-monitoring
SESSION_RECORDING_ALLOW_V1_SNAPSHOTS: 'session-recording-allow-v1-snapshots',
HOGQL_INSIGHTS: 'hogql-insights', // owner: @mariusandra
} as const
export type FeatureFlagKey = (typeof FEATURE_FLAGS)[keyof typeof FEATURE_FLAGS]

Expand Down
9 changes: 8 additions & 1 deletion frontend/src/queries/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
isTimeToSeeDataSessionsNode,
isHogQLQuery,
isInsightVizNode,
isLifecycleQuery,
} from './utils'
import api, { ApiMethodOptions } from 'lib/api'
import { getCurrentTeamId } from 'lib/utils/logics'
Expand All @@ -27,6 +28,8 @@ import { toParams } from 'lib/utils'
import { queryNodeToFilter } from './nodes/InsightQuery/utils/queryNodeToFilter'
import { now } from 'lib/dayjs'
import { currentSessionId } from 'lib/internalMetrics'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { FEATURE_FLAGS } from 'lib/constants'

const EXPORT_MAX_LIMIT = 10000

Expand Down Expand Up @@ -104,10 +107,14 @@ export async function query<N extends DataNode = DataNode>(
const logParams: Record<string, any> = {}
const startTime = performance.now()

const hogQLInsightsFlagEnabled = Boolean(
featureFlagLogic.findMounted()?.values.featureFlags?.[FEATURE_FLAGS.HOGQL_INSIGHTS]
)

try {
if (isPersonsNode(queryNode)) {
response = await api.get(getPersonsEndpoint(queryNode), methodOptions)
} else if (isInsightQueryNode(queryNode)) {
} else if (isInsightQueryNode(queryNode) && !(hogQLInsightsFlagEnabled && isLifecycleQuery(queryNode))) {
const filters = queryNodeToFilter(queryNode)
const params = {
...filters,
Expand Down
22 changes: 22 additions & 0 deletions frontend/src/queries/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,9 @@
],
"description": "Property filters for all series"
},
"response": {
"$ref": "#/definitions/LifecycleQueryResponse"
},
"samplingFactor": {
"description": "Sampling rate",
"type": ["number", "null"]
Expand All @@ -1433,6 +1436,25 @@
"required": ["kind", "series"],
"type": "object"
},
"LifecycleQueryResponse": {
"additionalProperties": false,
"properties": {
"result": {
"items": {
"type": "object"
},
"type": "array"
},
"timings": {
"items": {
"$ref": "#/definitions/QueryTiming"
},
"type": "array"
}
},
"required": ["result"],
"type": "object"
},
"LifecycleToggle": {
"enum": ["new", "resurrecting", "returning", "dormant"],
"type": "string"
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/queries/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,11 @@ export type LifecycleFilter = Omit<LifecycleFilterType, keyof FilterType> & {
toggledLifecycles?: LifecycleToggle[]
} // using everything except what it inherits from FilterType

export interface LifecycleQueryResponse {
result: Record<string, any>[]
timings?: QueryTiming[]
}

export interface LifecycleQuery extends InsightsQueryBase {
kind: NodeKind.LifecycleQuery
/** Granularity of the response. Can be one of `hour`, `day`, `week` or `month` */
Expand All @@ -448,6 +453,7 @@ export interface LifecycleQuery extends InsightsQueryBase {
series: (EventsNode | ActionsNode)[]
/** Properties specific to the lifecycle insight */
lifecycleFilter?: LifecycleFilter
response?: LifecycleQueryResponse
}

export type InsightQueryNode =
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/scenes/notebooks/Nodes/NodeWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ExtendedRegExpMatchArray,
Attribute,
NodeViewProps,
getExtensionField,
} from '@tiptap/react'
import { ReactNode, useCallback, useRef } from 'react'
import clsx from 'clsx'
Expand Down Expand Up @@ -212,12 +213,14 @@ export type CreatePostHogWidgetNodeOptions<T extends CustomNotebookNodeAttribute
}
attributes: Record<keyof T, Partial<Attribute>>
widgets?: NotebookNodeWidget[]
serializedText?: (attributes: NotebookNodeAttributes<T>) => string
}

export function createPostHogWidgetNode<T extends CustomNotebookNodeAttributes>({
Component,
pasteOptions,
attributes,
serializedText,
...wrapperProps
}: CreatePostHogWidgetNodeOptions<T>): Node {
// NOTE: We use NodeViewProps here as we convert them to NotebookNodeViewProps
Expand Down Expand Up @@ -252,6 +255,19 @@ export function createPostHogWidgetNode<T extends CustomNotebookNodeAttributes>(
atom: true,
draggable: true,

serializedText: serializedText,

extendNodeSchema(extension) {
const context = {
name: extension.name,
options: extension.options,
storage: extension.storage,
}
return {
serializedText: getExtensionField(extension, 'serializedText', context),
}
},

addAttributes() {
return {
height: {},
Expand Down
24 changes: 23 additions & 1 deletion frontend/src/scenes/notebooks/Nodes/NotebookNodeBacklink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@ import { mergeAttributes, Node, NodeViewProps } from '@tiptap/core'
import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react'
import { InsightModel, NotebookNodeType, NotebookTarget } from '~/types'
import { Link } from '@posthog/lemon-ui'
import { IconGauge, IconBarChart, IconFlag, IconExperiment, IconLive, IconPerson, IconCohort } from 'lib/lemon-ui/icons'
import {
IconGauge,
IconBarChart,
IconFlag,
IconExperiment,
IconLive,
IconPerson,
IconCohort,
IconJournal,
} from 'lib/lemon-ui/icons'
import { TaxonomicFilterGroupType } from 'lib/components/TaxonomicFilter/types'
import { urls } from 'scenes/urls'
import clsx from 'clsx'
Expand All @@ -22,6 +31,7 @@ const ICON_MAP = {
events: <IconLive width="1em" height="1em" />,
persons: <IconPerson />,
cohorts: <IconCohort />,
notebooks: <IconJournal />,
}

const Component = (props: NodeViewProps): JSX.Element => {
Expand Down Expand Up @@ -67,6 +77,8 @@ function backlinkHref(id: string, type: TaxonomicFilterGroupType): string {
return urls.experiment(id)
} else if (type === TaxonomicFilterGroupType.Dashboards) {
return urls.dashboard(id)
} else if (type === TaxonomicFilterGroupType.Notebooks) {
return urls.notebook(id)
}
return ''
}
Expand Down Expand Up @@ -139,6 +151,16 @@ export const NotebookNodeBacklink = Node.create({
return { id: id, type: TaxonomicFilterGroupType.Dashboards, title: dashboard.name }
},
}),
posthogNodePasteRule({
find: urls.notebook('(.+)'),
editor: this.editor,
type: this.type,
getAttributes: async (match) => {
const id = match[1]
const notebook = await api.notebooks.get(id)
return { id: id, type: TaxonomicFilterGroupType.Notebooks, title: notebook.title }
},
}),
]
},
})
4 changes: 4 additions & 0 deletions frontend/src/scenes/notebooks/Nodes/NotebookNodeImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ export const NotebookNodeImage = createPostHogWidgetNode<NotebookNodeImageAttrib
nodeType: NotebookNodeType.Image,
title: 'Image',
Component,
serializedText: (attrs) => {
// TODO file is null when this runs... should it be?
return attrs?.file?.name || ''
},
heightEstimate: 400,
minHeight: 100,
resizeable: true,
Expand Down
Loading

0 comments on commit 77fa9b8

Please sign in to comment.