Skip to content

Commit dec1e55

Browse files
authored
feat: add databases behind feature flag (#12323)
1 parent ffb22db commit dec1e55

37 files changed

+1285
-48
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,14 @@
165165
"@tiptap/extension-details": "3.9.1",
166166
"@tiptap/extension-document": "3.9.1",
167167
"@tiptap/extension-drag-handle": "3.9.1",
168+
"@tiptap/extension-heading": "^3.9.0",
168169
"@tiptap/extension-image": "3.9.1",
169170
"@tiptap/extension-link": "3.9.1",
170171
"@tiptap/extension-list": "3.9.1",
171172
"@tiptap/extension-mention": "3.9.1",
172173
"@tiptap/extension-node-range": "3.9.1",
173174
"@tiptap/extension-table": "3.9.1",
175+
"@tiptap/extension-text": "^3.9.0",
174176
"@tiptap/extensions": "3.9.1",
175177
"@tiptap/html": "3.9.1",
176178
"@tiptap/pm": "3.9.1",

packages/client/components/DashNavList/LeftNavPageLink.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import StorageIcon from '@mui/icons-material/Storage'
12
import graphql from 'babel-plugin-relay/macro'
23
import {useState} from 'react'
34
import {useFragment} from 'react-relay'
@@ -61,6 +62,7 @@ export const LeftNavPageLink = (props: Props) => {
6162
currentPageAncestorDepth
6263
userSortOrder
6364
sortOrder # used implicityly in store traversal by useDraggingPage
65+
isDatabase
6466
}
6567
`,
6668
pageRef
@@ -74,7 +76,8 @@ export const LeftNavPageLink = (props: Props) => {
7476
isDraggingLastChild,
7577
teamId,
7678
isPrivate,
77-
currentPageAncestorDepth
79+
currentPageAncestorDepth,
80+
isDatabase
7881
} = page
7982
const {viewer: viewerAccess} = access
8083

@@ -165,11 +168,17 @@ export const LeftNavPageLink = (props: Props) => {
165168
}
166169
}}
167170
>
168-
<ExpandPageChildrenButton
169-
showChildren={showChildren}
170-
expandChildPages={expandChildPages}
171-
draggingPageId={isSelf ? null : draggingPageId}
172-
/>
171+
{isDatabase ? (
172+
<div className='flex size-6 shrink-0 items-center justify-center rounded-sm bg-slate-200 text-slate-600 group-data-highlighted:bg-slate-300'>
173+
<StorageIcon className='size-5' />
174+
</div>
175+
) : (
176+
<ExpandPageChildrenButton
177+
showChildren={showChildren}
178+
expandChildPages={expandChildPages}
179+
draggingPageId={isSelf ? null : draggingPageId}
180+
/>
181+
)}
173182
<LeftNavItem>
174183
<span className='pl-1'>{title || '<Untitled>'}</span>
175184
</LeftNavItem>

packages/client/components/DashNavList/PageActions.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ export const PageActions = (props: Props) => {
3232
access {
3333
viewer
3434
}
35+
isDatabase
3536
}
3637
`,
3738
pageRef
3839
)
39-
const {id: pageId, access} = page
40+
const {id: pageId, access, isDatabase} = page
4041
const {viewer: viewerAccess} = access
4142
const history = useHistory()
4243
const [executeArchive] = useArchivePageMutation()
@@ -122,7 +123,9 @@ export const PageActions = (props: Props) => {
122123
</Menu>
123124
</div>
124125
)}
125-
<LeftNavItemButton Icon={AddIcon} onClick={addChildPage} tooltip='Add a page inside' />
126+
{!isDatabase && (
127+
<LeftNavItemButton Icon={AddIcon} onClick={addChildPage} tooltip='Add a page inside' />
128+
)}
126129
</LeftNavItemButtons>
127130
)
128131
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type {HocuspocusProvider} from '@hocuspocus/provider'
2+
import Collaboration from '@tiptap/extension-collaboration'
3+
import {Document} from '@tiptap/extension-document'
4+
import Heading from '@tiptap/extension-heading'
5+
import Text from '@tiptap/extension-text'
6+
import {useEditor} from '@tiptap/react'
7+
import {useRef} from 'react'
8+
import {Database} from '../tiptap/extensions/database/Database'
9+
import {usePageLinkPlaceholder} from './usePageLinkPlaceholder'
10+
11+
export const useTipTapDatabaseEditor = (provider: HocuspocusProvider) => {
12+
const placeholderRef = useRef<string | undefined>(undefined)
13+
14+
const editor = useEditor(
15+
{
16+
content: '',
17+
extensions: [
18+
Document.extend({
19+
content: 'heading database'
20+
}),
21+
Collaboration.configure({
22+
document: provider?.document
23+
}),
24+
Text,
25+
Heading.configure({
26+
levels: [1]
27+
}),
28+
Database.configure({
29+
document: provider?.document
30+
})
31+
],
32+
autofocus: true,
33+
editable: true
34+
},
35+
[provider]
36+
)
37+
38+
usePageLinkPlaceholder(editor!, placeholderRef)
39+
40+
return {editor}
41+
}

packages/client/hooks/useTipTapPageEditor.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,15 @@ export const useTipTapPageEditor = (
5858
graphql`
5959
fragment useTipTapPageEditor_viewer on User @inline {
6060
preferredName
61+
organizations {
62+
hasDatabases: featureFlag(featureName: "Databases")
63+
}
6164
}
6265
`,
6366
viewerRef
6467
)
6568
const preferredName = user?.preferredName
69+
const hasDatabases = !!user?.organizations?.find((org) => org?.hasDatabases)
6670
const atmosphere = useAtmosphere()
6771
const placeholderRef = useRef<string | undefined>(undefined)
6872
const editor = useEditor(
@@ -95,7 +99,9 @@ export const useTipTapPageEditor = (
9599
TaskItem.configure({
96100
nested: true
97101
}),
98-
SlashCommand.configure({}),
102+
SlashCommand.configure({
103+
Database: hasDatabases
104+
}),
99105
Focus,
100106
ImageUpload.configure({
101107
editorWidth: ElementWidth.REFLECTION_CARD - 16 * 2,

packages/client/hooks/useTipTapReflectionEditor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ export const useTipTapReflectionEditor = (
5252
Insights: false,
5353
Table: false,
5454
Details: false,
55-
'Create page': false
55+
'Create page': false,
56+
Database: false
5657
}),
5758
ClearOnSubmit,
5859
Focus,
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type {HocuspocusProvider} from '@hocuspocus/provider'
2+
import {useEffect} from 'react'
3+
import type {useTipTapPageEditor_viewer$key} from '../../__generated__/useTipTapPageEditor_viewer.graphql'
4+
import {TipTapEditor} from '../../components/promptResponse/TipTapEditor'
5+
import {useTipTapDatabaseEditor} from '../../hooks/useTipTapDatabaseEditor'
6+
import {cn} from '../../ui/cn'
7+
8+
interface Props {
9+
provider: HocuspocusProvider
10+
isEditable: boolean
11+
viewerRef: useTipTapPageEditor_viewer$key | null
12+
}
13+
14+
export const DatabaseEditor = (props: Props) => {
15+
const {provider, isEditable} = props
16+
const {editor} = useTipTapDatabaseEditor(provider)
17+
useEffect(() => {
18+
editor?.setEditable(isEditable)
19+
}, [editor, isEditable])
20+
if (!editor) return <div>No editor</div>
21+
return (
22+
<>
23+
<TipTapEditor editor={editor} className={cn('page-editor flex w-full px-6 delay-300')} />
24+
</>
25+
)
26+
}

packages/client/modules/pages/Page.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type {Page_page$key} from '../../__generated__/Page_page.graphql'
44
import type {useTipTapPageEditor_viewer$key} from '../../__generated__/useTipTapPageEditor_viewer.graphql'
55
import useAtmosphere from '../../hooks/useAtmosphere'
66
import {usePageProvider} from '../../hooks/usePageProvider'
7+
import {DatabaseEditor} from './DatabaseEditor'
78
import {PageEditor} from './PageEditor'
89
import {PageHeader} from './PageHeader'
910
import {PageHeaderPublic} from './PageHeaderPublic'
@@ -26,12 +27,13 @@ export const Page = (props: Props) => {
2627
viewer
2728
public
2829
}
30+
isDatabase
2931
}
3032
`,
3133
pageRef
3234
)
3335

34-
const {id: pageId, access} = page
36+
const {id: pageId, access, isDatabase} = page
3537
const {viewer: viewerAccess, public: publicAccess} = access
3638
const {provider, synced} = usePageProvider(pageId)
3739
const atmosphere = useAtmosphere()
@@ -44,7 +46,12 @@ export const Page = (props: Props) => {
4446
<div className='relative flex w-full flex-col items-center bg-white'>
4547
{isPublic ? <PageHeaderPublic /> : <PageHeader pageRef={page} />}
4648
<div className='relative flex min-h-screen w-full max-w-[960px] justify-center bg-white pt-28 pb-10'>
47-
{synced && <PageEditor viewerRef={viewerRef} isEditable={isEditable} provider={provider} />}
49+
{synced &&
50+
(isDatabase ? (
51+
<DatabaseEditor viewerRef={viewerRef} isEditable={isEditable} provider={provider} />
52+
) : (
53+
<PageEditor viewerRef={viewerRef} isEditable={isEditable} provider={provider} />
54+
))}
4855
</div>
4956
</div>
5057
)

packages/client/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"@sereneinserenade/tiptap-search-and-replace": "^0.1.1",
7272
"@stripe/react-stripe-js": "^1.16.5",
7373
"@stripe/stripe-js": "^4.0.0",
74+
"@tanstack/react-table": "^8.21.3",
7475
"@types/history": "^4.7.0",
7576
"cleave.js": "^1.6.0",
7677
"clsx": "^1.2.1",

packages/client/shared/tiptap/extensions/PageLinkBlockBase.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export type PageLinkBlockAttributes = {
55
title: string
66
canonical?: boolean
77
isMoving?: boolean
8+
database?: boolean
89
}
910
declare module '@tiptap/core' {
1011
interface Commands<ReturnType> {
@@ -49,6 +50,16 @@ export const PageLinkBlockBase = Node.create({
4950
'data-canonical': attributes.canonical ? '' : undefined
5051
}
5152
}
53+
},
54+
database: {
55+
parseHTML: (element) => {
56+
return element.getAttribute('data-database') === '' ? true : false
57+
},
58+
renderHTML: (attributes) => {
59+
return {
60+
'data-database': attributes.database ? '' : undefined
61+
}
62+
}
5263
}
5364
}
5465
},

0 commit comments

Comments
 (0)