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

feat: add notebook preview #18813

Merged
merged 9 commits into from
Nov 27, 2023
Merged
13 changes: 11 additions & 2 deletions frontend/src/lib/components/CommandBar/SearchResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { LemonSkeleton } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { useLayoutEffect, useRef } from 'react'
import { summarizeInsight } from 'scenes/insights/summarizeInsight'
import { Notebook } from 'scenes/notebooks/Notebook/Notebook'
import { JSONContent } from 'scenes/notebooks/Notebook/utils'
import { mathsLogic } from 'scenes/trends/mathsLogic'

import { cohortsModel } from '~/models/cohortsModel'
Expand Down Expand Up @@ -120,15 +122,22 @@ export const ResultName = ({ result }: ResultNameProps): JSX.Element | null => {
}

export const ResultDescription = ({ result }: ResultNameProps): JSX.Element | null => {
const { type, extra_fields } = result
const { result_id, type, extra_fields } = result
if (type === 'feature_flag') {
return extra_fields.name && extra_fields.name !== extra_fields.key ? (
<span>{extra_fields.name}</span>
) : (
<i>No description.</i>
)
} else if (type === 'notebook') {
return <span className="whitespace-pre">{extra_fields.text_content}</span>
return (
<Notebook
shortId={result_id}
mode="notebook"
editable={false}
initialContent={extra_fields.content as JSONContent}
/>
)
} else {
return extra_fields.description ? <span>{extra_fields.description}</span> : <i>No description.</i>
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/components/CommandBar/SearchResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const SearchResults = (): JSX.Element => {
/>
))}
</div>
<div className="w-1/2 p-2">
<div className="w-1/2 p-2 overflow-y-auto">
<SearchResultPreview />
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions posthog/api/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"notebook": {
"klass": Notebook,
"search_fields": {"title": "A", "text_content": "C"},
"extra_fields": ["title", "text_content"],
"extra_fields": ["title", "content"],
},
"action": {
"klass": Action,
Expand Down Expand Up @@ -92,7 +92,7 @@ def list(self, request: Request, **kw) -> HttpResponse:
team=self.team,
query=query,
search_fields=entity_meta.get("search_fields"), # type: ignore
extra_fields=entity_meta.get("extra_fields"),
extra_fields=entity_meta.get("extra_fields"), # type: ignore
)
qs = qs.union(klass_qs)
counts[entity_name] = klass_qs.count()
Expand Down
65 changes: 42 additions & 23 deletions posthog/api/test/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from posthog.api.search import process_query
from posthog.test.base import APIBaseTest

from posthog.models import Dashboard, FeatureFlag, Team, Insight
from posthog.models import Dashboard, FeatureFlag, Team, Insight, Notebook


class TestSearch(APIBaseTest):
Expand All @@ -27,55 +27,74 @@ def setUp(self):
FeatureFlag.objects.create(name="second feature flag", key="b", team=self.team, created_by=self.user)
FeatureFlag.objects.create(name="third feature flag", key="c", team=self.team, created_by=self.user)

Notebook.objects.create(team=self.team, created_by=self.user, short_id="01234", title="first notebook")
self.notebook_1 = Notebook.objects.create(
team=self.team, created_by=self.user, short_id="56789", title="second notebook"
)

def test_search(self):
response = self.client.get("/api/projects/@current/search?q=sec")

self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()["results"]), 3)
self.assertEqual(len(response.json()["results"]), 4)
self.assertEqual(response.json()["counts"]["action"], 0)
self.assertEqual(response.json()["counts"]["dashboard"], 1)
self.assertEqual(response.json()["counts"]["feature_flag"], 1)
self.assertEqual(response.json()["counts"]["insight"], 1)
self.assertEqual(response.json()["counts"]["notebook"], 1)

def test_search_without_query(self):
response = self.client.get("/api/projects/@current/search")

self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()["results"]), 9)
self.assertEqual(len(response.json()["results"]), 11)
self.assertEqual(response.json()["counts"]["action"], 0)
self.assertEqual(response.json()["counts"]["dashboard"], 3)
self.assertEqual(response.json()["counts"]["feature_flag"], 3)
self.assertEqual(response.json()["counts"]["insight"], 3)
self.assertEqual(response.json()["counts"]["notebook"], 2)

def test_search_filtered_by_entity(self):
response = self.client.get("/api/projects/@current/search?q=sec&entities=insight&entities=dashboard")
response = self.client.get(
"/api/projects/@current/search?q=sec&entities=insight&entities=dashboard&entities=notebook"
)

self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()["results"]), 2)
self.assertEqual(len(response.json()["results"]), 3)
self.assertEqual(response.json()["counts"]["dashboard"], 1)
self.assertEqual(response.json()["counts"]["insight"], 1)
self.assertEqual(response.json()["counts"]["notebook"], 1)

def test_response_format_and_ids(self):
response = self.client.get("/api/projects/@current/search?q=sec&entities=insight&entities=dashboard")
response = self.client.get(
"/api/projects/@current/search?q=sec&entities=insight&entities=dashboard&entities=notebook"
)

sorted_results = sorted(response.json()["results"], key=lambda entity: entity["type"])

self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json()["results"][0],
{
"rank": response.json()["results"][0]["rank"],
"type": "dashboard",
"result_id": str(self.dashboard_1.id),
"extra_fields": {"description": "", "name": "second dashboard"},
},
)
self.assertEqual(
response.json()["results"][1],
{
"rank": response.json()["results"][1]["rank"],
"type": "insight",
"result_id": self.insight_1.short_id,
"extra_fields": {"name": "second insight", "description": None, "filters": {}, "query": None},
},
sorted_results,
[
{
"rank": sorted_results[0]["rank"],
"type": "dashboard",
"result_id": str(self.dashboard_1.id),
"extra_fields": {"description": "", "name": "second dashboard"},
},
{
"rank": sorted_results[1]["rank"],
"type": "insight",
"result_id": self.insight_1.short_id,
"extra_fields": {"name": "second insight", "description": None, "filters": {}, "query": None},
},
{
"rank": sorted_results[2]["rank"],
"type": "notebook",
"result_id": self.notebook_1.short_id,
"extra_fields": {"title": "second notebook", "content": None},
},
],
)

def test_extra_fields(self):
Expand All @@ -91,7 +110,7 @@ def test_search_with_fully_invalid_query(self):
response = self.client.get("/api/projects/@current/search?q=%3E")

self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()["results"]), 9)
self.assertEqual(len(response.json()["results"]), 11)
self.assertEqual(response.json()["counts"]["action"], 0)
self.assertEqual(response.json()["counts"]["dashboard"], 3)
self.assertEqual(response.json()["counts"]["feature_flag"], 3)
Expand Down
2 changes: 2 additions & 0 deletions posthog/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from .instance_setting import InstanceSetting
from .integration import Integration
from .messaging import MessagingRecord
from .notebook import Notebook
from .organization import Organization, OrganizationInvite, OrganizationMembership
from .organization_domain import OrganizationDomain
from .person import Person, PersonDistinctId, PersonOverride, PersonOverrideMapping
Expand Down Expand Up @@ -102,6 +103,7 @@
"InstanceSetting",
"Integration",
"MessagingRecord",
"Notebook",
"MigrationStatus",
"NotificationViewed",
"Organization",
Expand Down
1 change: 1 addition & 0 deletions posthog/models/notebook/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .notebook import *
Loading