Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
68daf79f
Commit
68daf79f
authored
Jun 09, 2023
by
StyleZhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: notion-page-selector
parent
cca2ba95
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
298 additions
and
78 deletions
+298
-78
check.svg
web/app/components/base/checkbox/assets/check.svg
+3
-0
index.module.css
web/app/components/base/checkbox/index.module.css
+9
-0
index.tsx
web/app/components/base/checkbox/index.tsx
+2
-1
index.tsx
web/app/components/base/notion-icon/index.tsx
+9
-10
base.tsx
web/app/components/base/notion-page-selector/base.tsx
+22
-2
index.tsx
...notion-page-selector/notion-page-selector-modal/index.tsx
+16
-2
index.module.css
.../base/notion-page-selector/page-selector/index.module.css
+3
-2
index.tsx
...ponents/base/notion-page-selector/page-selector/index.tsx
+181
-24
index.tsx
...ts/base/notion-page-selector/workspace-selector/index.tsx
+1
-1
index.tsx
...unt-setting/data-source-page/data-source-notion/index.tsx
+44
-35
common.en.ts
web/i18n/lang/common.en.ts
+1
-0
common.zh.ts
web/i18n/lang/common.zh.ts
+1
-0
common.ts
web/models/common.ts
+6
-1
No files found.
web/app/components/base/checkbox/assets/check.svg
0 → 100644
View file @
68daf79f
<svg
width=
"12"
height=
"12"
viewBox=
"0 0 12 12"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
d=
"M10 3L4.5 8.5L2 6"
stroke=
"white"
stroke-width=
"2"
stroke-linecap=
"round"
stroke-linejoin=
"round"
/>
</svg>
web/app/components/base/checkbox/index.module.css
View file @
68daf79f
.wrapper
{
border-color
:
#d0d5dd
;
}
.checked
{
background
:
#155eef
url(./assets/check.svg)
center
center
no-repeat
;
background-size
:
12px
12px
;
border-color
:
#155eef
;
}
\ No newline at end of file
web/app/components/base/checkbox/index.tsx
View file @
68daf79f
import
cn
from
'classnames'
import
s
from
'./index.module.css'
type
CheckboxProps
=
{
checked
?:
boolean
...
...
@@ -9,7 +10,7 @@ type CheckboxProps = {
const
Checkbox
=
({
checked
,
onCheck
,
className
}:
CheckboxProps
)
=>
{
return
(
<
div
className=
{
cn
(
'w-4 h-4 border rounded'
,
checked
?
'border-primary-600 bg-primary-600'
:
'
border-gray-300'
,
className
)
}
className=
{
cn
(
s
.
wrapper
,
checked
&&
s
.
checked
,
'w-4 h-4 border rounded
border-gray-300'
,
className
)
}
onClick=
{
onCheck
}
/>
)
...
...
web/app/components/base/notion-icon/index.tsx
View file @
68daf79f
...
...
@@ -35,16 +35,15 @@ const NotionIcon = ({
}
if
(
src
)
{
return
(
<
img
alt=
'workspace icon'
src=
{
src
}
className=
{
cn
(
'block object-cover w-5 h-5'
,
className
)
}
/>
)
}
if
(
name
)
{
if
(
src
.
includes
(
'https://'
))
{
return
(
<
img
alt=
'page icon'
src=
{
src
}
className=
{
cn
(
'block object-cover w-5 h-5'
,
className
)
}
/>
)
}
return
(
<
div
className=
{
cn
(
'flex items-center justify-center w-5 h-5'
,
className
)
}
>
{
src
}
</
div
>
)
...
...
web/app/components/base/notion-page-selector/base.tsx
View file @
68daf79f
...
...
@@ -6,8 +6,19 @@ import WorkspaceSelector from './workspace-selector'
import
SearchInput
from
'./search-input'
import
PageSelector
from
'./page-selector'
import
{
fetchDataSource
}
from
'@/service/common'
import
type
{
DataSourceNotionPage
}
from
'@/models/common'
const
NotionPageSelector
=
()
=>
{
type
NotionPageSelectorProps
=
{
onSelect
:
(
selectedPages
:
DataSourceNotionPage
[])
=>
void
canPreview
?:
boolean
onPreview
?:
(
selectedPage
:
DataSourceNotionPage
)
=>
void
}
const
NotionPageSelector
=
({
onSelect
,
canPreview
,
onPreview
,
}:
NotionPageSelectorProps
)
=>
{
const
[
searchValue
,
setSearchValue
]
=
useState
(
''
)
const
{
data
}
=
useSWR
({
url
:
'data-source/integrates'
},
fetchDataSource
)
const
notionWorkspaces
=
data
?.
data
.
filter
(
item
=>
item
.
provider
===
'notion'
)
||
[]
...
...
@@ -42,7 +53,16 @@ const NotionPageSelector = () => {
/>
</
div
>
<
div
className=
'rounded-b-xl overflow-hidden'
>
<
PageSelector
list=
{
currentWorkspace
?.
source_info
.
pages
||
[]
}
/>
{
currentWorkspace
?.
source_info
.
pages
.
length
&&
(
<
PageSelector
list=
{
currentWorkspace
?.
source_info
.
pages
}
onSelect=
{
onSelect
}
canPreview=
{
canPreview
}
onPreview=
{
onPreview
}
/>
)
}
</
div
>
</
div
>
)
...
...
web/app/components/base/notion-page-selector/notion-page-selector-modal/index.tsx
View file @
68daf79f
import
{
useState
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
cn
from
'classnames'
import
{
XMarkIcon
}
from
'@heroicons/react/24/outline'
import
NotionPageSelector
from
'../base'
import
s
from
'./index.module.css'
import
Modal
from
'@/app/components/base/modal'
import
type
{
DataSourceNotionPage
}
from
'@/models/common'
type
NotionPageSelectorModalProps
=
{
isShow
:
boolean
onClose
:
()
=>
void
onSave
:
(
selectedPages
:
DataSourceNotionPage
[])
=>
void
}
const
NotionPageSelectorModal
=
({
isShow
,
onClose
,
onSave
,
}:
NotionPageSelectorModalProps
)
=>
{
const
{
t
}
=
useTranslation
()
const
[
selectedPages
,
setSelectedPages
]
=
useState
<
DataSourceNotionPage
[]
>
([])
const
handleClose
=
()
=>
{
onClose
()
}
const
handleSelectPage
=
(
newSelectedPages
:
DataSourceNotionPage
[])
=>
{
setSelectedPages
(
newSelectedPages
)
}
const
handleSave
=
()
=>
{
onSave
(
selectedPages
)
}
return
(
<
Modal
...
...
@@ -33,10 +44,13 @@ const NotionPageSelectorModal = ({
<
XMarkIcon
className=
'w-4 h-4'
/>
</
div
>
</
div
>
<
NotionPageSelector
/>
<
NotionPageSelector
onSelect=
{
handleSelectPage
}
canPreview=
{
false
}
/>
<
div
className=
'mt-8 flex justify-end'
>
<
div
className=
{
s
.
operate
}
onClick=
{
handleClose
}
>
{
t
(
'common.operation.cancel'
)
}
</
div
>
<
div
className=
{
cn
(
s
.
operate
,
s
[
'operate-save'
])
}
>
{
t
(
'common.operation.save'
)
}
</
div
>
<
div
className=
{
cn
(
s
.
operate
,
s
[
'operate-save'
])
}
onClick=
{
handleSave
}
>
{
t
(
'common.operation.save'
)
}
</
div
>
</
div
>
</
Modal
>
)
...
...
web/app/components/base/notion-page-selector/page-selector/index.module.css
View file @
68daf79f
...
...
@@ -3,8 +3,9 @@
height
:
20px
;
background
:
url(../assets/down-arrow.svg)
center
center
no-repeat
;
background-size
:
16px
16px
;
transform
:
rotate
(
-90deg
);
}
.arrow-
collapse
{
transform
:
rotate
(
-90deg
);
.arrow-
expand
{
transform
:
rotate
(
0
);
}
\ No newline at end of file
web/app/components/base/notion-page-selector/page-selector/index.tsx
View file @
68daf79f
import
{
memo
}
from
'react'
import
{
memo
,
useState
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
{
FixedSizeList
as
List
,
areEqual
}
from
'react-window'
import
type
{
ListChildComponentProps
}
from
'react-window'
import
cn
from
'classnames'
...
...
@@ -7,60 +8,216 @@ import NotionIcon from '../../notion-icon'
import
s
from
'./index.module.css'
import
type
{
DataSourceNotionPage
}
from
'@/models/common'
const
Item
=
memo
(({
index
,
style
,
data
}:
ListChildComponentProps
<
{
list
:
DataSourceNotionPage
[]
}
>
)
=>
{
const
current
=
data
.
list
[
index
]
let
src
,
name
type
PageSelectorProps
=
{
list
:
DataSourceNotionPage
[]
onSelect
:
(
selectedPages
:
DataSourceNotionPage
[])
=>
void
canPreview
?:
boolean
onPreview
?:
(
selectedPage
:
DataSourceNotionPage
)
=>
void
}
type
NotionPageMap
=
Record
<
string
,
DataSourceNotionPage
>
type
NotionPageTreeItem
=
{
children
:
Set
<
string
>
descendants
:
Set
<
string
>
deepth
:
number
}
&
DataSourceNotionPage
type
NotionPageTreeMap
=
Record
<
string
,
NotionPageTreeItem
>
type
NotionPageItem
=
{
expand
:
boolean
deepth
:
number
}
&
DataSourceNotionPage
if
(
current
.
page_icon
)
{
try
{
const
icon
=
JSON
.
parse
(
current
.
page_icon
)
const
recursivePushInParentDescendants
=
(
listMap
:
Record
<
string
,
DataSourceNotionPage
>
,
listTreeMap
:
NotionPageTreeMap
,
current
:
NotionPageTreeItem
,
leafItem
:
NotionPageTreeItem
,
)
=>
{
const
parentId
=
current
.
parent_id
const
pageId
=
current
.
page_id
if
(
icon
?.
type
===
'emoji'
)
name
=
icon
?.
emoji
if
(
parentId
!==
'root'
)
{
if
(
!
listTreeMap
[
parentId
])
{
const
children
=
new
Set
([
pageId
])
const
descendants
=
new
Set
([
pageId
,
leafItem
.
page_id
])
if
(
icon
?.
type
===
'external'
)
src
=
icon
?.
external
?.
url
listTreeMap
[
parentId
]
=
{
...
listMap
[
parentId
],
children
,
descendants
,
deepth
:
0
,
}
}
catch
(
e
:
any
)
{}
else
{
listTreeMap
[
parentId
].
children
.
add
(
pageId
)
listTreeMap
[
parentId
].
descendants
.
add
(
pageId
)
listTreeMap
[
parentId
].
descendants
.
add
(
leafItem
.
page_id
)
}
leafItem
.
deepth
++
if
(
listTreeMap
[
parentId
].
parent_id
!==
'root'
)
recursivePushInParentDescendants
(
listMap
,
listTreeMap
,
listTreeMap
[
parentId
],
leafItem
)
}
}
const
Item
=
memo
(({
index
,
style
,
data
}:
ListChildComponentProps
<
{
dataList
:
NotionPageItem
[]
handleToggle
:
(
index
:
number
)
=>
void
checkedIds
:
Set
<
string
>
handleCheck
:
(
index
:
number
)
=>
void
canPreview
?:
boolean
handlePreview
:
(
index
:
number
)
=>
void
}
>
)
=>
{
const
{
t
}
=
useTranslation
()
const
{
dataList
,
handleToggle
,
checkedIds
,
handleCheck
,
canPreview
,
handlePreview
}
=
data
const
current
=
dataList
[
index
]
let
iconSrc
if
(
current
.
page_icon
&&
current
.
page_icon
.
type
===
'url'
)
iconSrc
=
current
.
page_icon
.
url
if
(
current
.
page_icon
&&
current
.
page_icon
.
type
===
'emoji'
)
iconSrc
=
current
.
page_icon
.
emoji
return
(
<
div
className=
'group flex items-center p
x-2
rounded-md hover:bg-gray-100 cursor-pointer'
className=
'group flex items-center p
l-2 pr-[2px]
rounded-md hover:bg-gray-100 cursor-pointer'
style=
{
{
...
style
,
top
:
style
.
top
as
number
+
8
,
left
:
8
,
right
:
8
,
width
:
'calc(100% - 16px)'
}
}
>
<
Checkbox
className=
'shrink-0 mr-2 group-hover:border-primary-600 group-hover:border-[2px]'
/>
<
div
className=
{
cn
(
s
.
arrow
,
s
[
'arrow-collapse'
],
'shrink-0 mr-1 w-5 h-5 hover:bg-gray-200 rounded-md'
)
}
/>
<
Checkbox
className=
'shrink-0 mr-2 group-hover:border-primary-600 group-hover:border-[2px]'
checked=
{
checkedIds
.
has
(
current
.
page_id
)
}
onCheck=
{
()
=>
handleCheck
(
index
)
}
/>
<
div
className=
{
cn
(
s
.
arrow
,
current
.
expand
&&
s
[
'arrow-expand'
],
'shrink-0 mr-1 w-5 h-5 hover:bg-gray-200 rounded-md'
)
}
style=
{
{
marginLeft
:
current
.
deepth
*
8
}
}
onClick=
{
()
=>
handleToggle
(
index
)
}
/>
<
NotionIcon
className=
'shrink-0 mr-1'
type=
'page'
src=
{
src
}
name=
{
name
}
src=
{
iconSrc
}
/>
<
div
className=
'text-sm font-medium text-gray-700 truncate'
className=
'
grow
text-sm font-medium text-gray-700 truncate'
title=
{
current
.
page_name
}
>
{
current
.
page_name
}
</
div
>
{
canPreview
&&
(
<
div
className=
'shrink-0 hidden group-hover:flex items-center ml-4 px-2 h-6 rounded-md text-xs font-medium text-gray-700 cursor-pointer hover:bg-gray-50'
onClick=
{
()
=>
handlePreview
(
index
)
}
>
{
t
(
'common.dataSource.notion.selector.preview'
)
}
</
div
>
)
}
</
div
>
)
},
areEqual
)
type
PageSelectorProps
=
{
list
:
DataSourceNotionPage
[]
}
const
PageSelector
=
({
list
,
onSelect
,
canPreview
,
onPreview
,
}:
PageSelectorProps
)
=>
{
const
[
dataList
,
setDataList
]
=
useState
<
NotionPageItem
[]
>
(
list
.
filter
(
item
=>
item
.
parent_id
===
'root'
).
map
((
item
)
=>
{
return
{
...
item
,
expand
:
false
,
deepth
:
0
,
}
}),
)
const
[
checkedIds
,
setCheckedIds
]
=
useState
<
Set
<
string
>>
(
new
Set
())
const
listMap
=
list
.
reduce
((
prev
:
NotionPageMap
,
next
:
DataSourceNotionPage
)
=>
{
prev
[
next
.
page_id
]
=
next
return
prev
},
{})
const
listMapWithChildrenAndDescendants
=
list
.
reduce
((
prev
:
NotionPageTreeMap
,
next
:
DataSourceNotionPage
)
=>
{
const
pageId
=
next
.
page_id
if
(
!
prev
[
pageId
])
prev
[
pageId
]
=
{
...
next
,
children
:
new
Set
(),
descendants
:
new
Set
(),
deepth
:
0
}
recursivePushInParentDescendants
(
listMap
,
prev
,
prev
[
pageId
],
prev
[
pageId
])
return
prev
},
{})
const
handleToggle
=
(
index
:
number
)
=>
{
const
current
=
dataList
[
index
]
const
pageId
=
current
.
page_id
const
currentWithChildrenAndDescendants
=
listMapWithChildrenAndDescendants
[
pageId
]
const
descendantsIds
=
Array
.
from
(
currentWithChildrenAndDescendants
.
descendants
)
const
childrenIds
=
Array
.
from
(
currentWithChildrenAndDescendants
.
children
)
let
newDataList
=
[]
if
(
current
.
expand
)
{
current
.
expand
=
false
newDataList
=
[...
dataList
.
filter
(
item
=>
!
descendantsIds
.
includes
(
item
.
page_id
))]
}
else
{
current
.
expand
=
true
newDataList
=
[
...
dataList
.
slice
(
0
,
index
+
1
),
...
childrenIds
.
map
(
item
=>
({
...
listMap
[
item
],
expand
:
false
,
deepth
:
listMapWithChildrenAndDescendants
[
item
].
deepth
,
})),
...
dataList
.
slice
(
index
+
1
)]
}
setDataList
(
newDataList
)
}
const
handleCheck
=
(
index
:
number
)
=>
{
const
current
=
dataList
[
index
]
const
pageId
=
current
.
page_id
const
currentWithChildrenAndDescendants
=
listMapWithChildrenAndDescendants
[
pageId
]
if
(
checkedIds
.
has
(
pageId
))
{
for
(
const
item
of
currentWithChildrenAndDescendants
.
descendants
)
checkedIds
.
delete
(
item
)
checkedIds
.
delete
(
pageId
)
}
else
{
for
(
const
item
of
currentWithChildrenAndDescendants
.
descendants
)
checkedIds
.
add
(
item
)
checkedIds
.
add
(
pageId
)
}
setCheckedIds
(
new
Set
([...
checkedIds
]))
onSelect
([...
checkedIds
].
map
(
item
=>
listMap
[
item
]))
}
const
handlePreview
=
(
index
:
number
)
=>
{
if
(
onPreview
)
{
const
current
=
dataList
[
index
]
const
pageId
=
current
.
page_id
onPreview
(
listMap
[
pageId
])
}
}
return
(
<
List
className=
'py-2'
height=
{
296
}
itemCount=
{
l
ist
.
length
}
itemCount=
{
dataL
ist
.
length
}
itemSize=
{
28
}
width=
'100%'
itemData=
{
{
list
}
}
itemData=
{
{
dataList
,
handleToggle
,
checkedIds
,
handleCheck
,
canPreview
,
handlePreview
,
}
}
>
{
Item
}
</
List
>
...
...
web/app/components/base/notion-page-selector/workspace-selector/index.tsx
View file @
68daf79f
...
...
@@ -32,7 +32,7 @@ export default function WorkspaceSelector({
name=
{
currentWorkspace
?.
workspace_name
}
/>
<
div
className=
'mr-1 w-[90px] text-left text-sm font-medium text-gray-700 truncate'
title=
{
currentWorkspace
?.
workspace_name
}
>
{
currentWorkspace
?.
workspace_name
}
</
div
>
<
div
className=
'mr-1
w-5
h-[18px] bg-primary-50 rounded-lg text-xs font-medium text-primary-600'
>
{
currentWorkspace
?.
total
}
</
div
>
<
div
className=
'mr-1
px-1
h-[18px] bg-primary-50 rounded-lg text-xs font-medium text-primary-600'
>
{
currentWorkspace
?.
total
}
</
div
>
<
div
className=
{
cn
(
s
[
'down-arrow'
],
'mr-2 w-3 h-3'
)
}
/>
</
Menu
.
Button
>
<
Transition
...
...
web/app/components/header/account-setting/data-source-page/data-source-notion/index.tsx
View file @
68daf79f
...
...
@@ -16,6 +16,7 @@ const DataSourceNotion = ({
workspaces
,
}:
DataSourceNotionProps
)
=>
{
const
{
t
}
=
useTranslation
()
const
connected
=
!!
workspaces
.
length
return
(
<
div
className=
'mb-2 border-[0.5px] border-gray-200 bg-gray-50 rounded-xl'
>
...
...
@@ -26,7 +27,7 @@ const DataSourceNotion = ({
{
t
(
'common.dataSource.notion.title'
)
}
</
div
>
{
!
workspaces
.
length
&&
(
!
connected
&&
(
<
div
className=
'leading-5 text-xs text-gray-500'
>
{
t
(
'common.dataSource.notion.description'
)
}
</
div
>
...
...
@@ -34,7 +35,7 @@ const DataSourceNotion = ({
}
</
div
>
{
!
workspaces
.
length
!
connected
?
(
<
Link
className=
'flex items-center ml-3 px-3 h-7 bg-white border border-gray-200 rounded-md text-xs font-medium text-gray-700 cursor-pointer'
...
...
@@ -52,40 +53,48 @@ const DataSourceNotion = ({
)
}
</
div
>
<
div
className=
'flex items-center px-3 h-[18px]'
>
<
div
className=
'text-xs font-medium text-gray-500'
>
{
t
(
'common.dataSource.notion.connectedWorkspace'
)
}
</
div
>
<
div
className=
'grow ml-3 border-t border-t-gray-100'
/>
</
div
>
<
div
className=
'px-3 pt-2 pb-3'
>
{
workspaces
.
map
(
workspace
=>
(
<
div
className=
{
cn
(
s
[
'workspace-item'
],
'flex items-center mb-1 py-1 pr-1 bg-white rounded-lg'
)
}
key=
{
workspace
.
id
}
>
<
NotionIcon
className=
'ml-3 mr-[6px]'
src=
{
workspace
.
source_info
.
workspace_icon
||
''
}
name=
{
workspace
.
source_info
.
workspace_name
}
/>
<
div
className=
'grow py-[7px] leading-[18px] text-[13px] font-medium text-gray-700'
>
{
workspace
.
source_info
.
workspace_name
}
</
div
>
{
workspace
.
is_bound
?
<
Indicator
className=
'mr-[6px]'
/>
:
<
Indicator
className=
'mr-[6px]'
color=
'yellow'
/>
}
<
div
className=
'mr-3 text-xs font-medium'
>
{
workspace
.
is_bound
?
t
(
'common.dataSource.notion.connected'
)
:
t
(
'common.dataSource.notion.disconnected'
)
}
</
div
>
<
div
className=
'mr-2 w-[1px] h-3 bg-gray-100'
/>
<
Operate
workspace=
{
workspace
}
/>
{
connected
&&
(
<
div
className=
'flex items-center px-3 h-[18px]'
>
<
div
className=
'text-xs font-medium text-gray-500'
>
{
t
(
'common.dataSource.notion.connectedWorkspace'
)
}
</
div
>
))
}
</
div
>
<
div
className=
'grow ml-3 border-t border-t-gray-100'
/>
</
div
>
)
}
{
connected
&&
(
<
div
className=
'px-3 pt-2 pb-3'
>
{
workspaces
.
map
(
workspace
=>
(
<
div
className=
{
cn
(
s
[
'workspace-item'
],
'flex items-center mb-1 py-1 pr-1 bg-white rounded-lg'
)
}
key=
{
workspace
.
id
}
>
<
NotionIcon
className=
'ml-3 mr-[6px]'
src=
{
workspace
.
source_info
.
workspace_icon
||
''
}
name=
{
workspace
.
source_info
.
workspace_name
}
/>
<
div
className=
'grow py-[7px] leading-[18px] text-[13px] font-medium text-gray-700'
>
{
workspace
.
source_info
.
workspace_name
}
</
div
>
{
workspace
.
is_bound
?
<
Indicator
className=
'mr-[6px]'
/>
:
<
Indicator
className=
'mr-[6px]'
color=
'yellow'
/>
}
<
div
className=
'mr-3 text-xs font-medium'
>
{
workspace
.
is_bound
?
t
(
'common.dataSource.notion.connected'
)
:
t
(
'common.dataSource.notion.disconnected'
)
}
</
div
>
<
div
className=
'mr-2 w-[1px] h-3 bg-gray-100'
/>
<
Operate
workspace=
{
workspace
}
/>
</
div
>
))
}
</
div
>
)
}
</
div
>
)
}
...
...
web/i18n/lang/common.en.ts
View file @
68daf79f
...
...
@@ -192,6 +192,7 @@ const translation = {
searchPages
:
'Search pages...'
,
noSerachResult
:
'No search resluts'
,
addPages
:
'Add pages'
,
preview
:
'PREVIEW'
,
},
},
},
...
...
web/i18n/lang/common.zh.ts
View file @
68daf79f
...
...
@@ -193,6 +193,7 @@ const translation = {
searchPages
:
'搜索页面...'
,
noSerachResult
:
'无搜索结果'
,
addPages
:
'添加页面'
,
preview
:
'预览'
,
},
},
},
...
...
web/models/common.ts
View file @
68daf79f
...
...
@@ -101,9 +101,14 @@ export type IWorkspace = {
}
export
type
DataSourceNotionPage
=
{
page_icon
:
string
|
null
page_icon
:
null
|
{
type
:
string
|
null
url
:
string
|
null
emoji
:
string
|
null
}
page_id
:
string
page_name
:
string
parent_id
:
string
}
export
type
DataSourceNotionWorkspace
=
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment