Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
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
Vũ Hoàng Anh
canifa_note
Commits
454cd4e2
Commit
454cd4e2
authored
Jan 05, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: implement switchable task list node
parent
6320d042
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
208 additions
and
38 deletions
+208
-38
markdown_service.go
api/v2/markdown_service.go
+67
-0
memo_service.go
api/v2/memo_service.go
+5
-0
utils.go
plugin/gomark/ast/utils.go
+23
-0
parser.go
plugin/gomark/parser/parser.go
+0
-10
parser_test.go
plugin/gomark/parser/parser_test.go
+5
-0
html.go
plugin/gomark/renderer/html/html.go
+15
-4
string.go
plugin/gomark/renderer/string/string.go
+11
-0
Renderer.tsx
web/src/components/MemoContent/Renderer.tsx
+3
-2
TaskList.tsx
web/src/components/MemoContent/TaskList.tsx
+33
-5
index.tsx
web/src/components/MemoContent/index.tsx
+27
-11
context.ts
web/src/components/MemoContent/types/context.ts
+14
-1
MemoView.tsx
web/src/components/MemoView.tsx
+1
-1
ShareMemoDialog.tsx
web/src/components/ShareMemoDialog.tsx
+1
-1
TimelineMemo.tsx
web/src/components/TimelineMemo.tsx
+1
-1
Archived.tsx
web/src/pages/Archived.tsx
+1
-1
MemoDetail.tsx
web/src/pages/MemoDetail.tsx
+1
-1
No files found.
api/v2/markdown_service.go
View file @
454cd4e2
...
...
@@ -95,6 +95,73 @@ func convertFromASTNode(rawNode ast.Node) *apiv2pb.Node {
return
node
}
func
convertToASTNodes
(
nodes
[]
*
apiv2pb
.
Node
)
[]
ast
.
Node
{
rawNodes
:=
[]
ast
.
Node
{}
for
_
,
node
:=
range
nodes
{
rawNode
:=
convertToASTNode
(
node
)
rawNodes
=
append
(
rawNodes
,
rawNode
)
}
return
rawNodes
}
func
convertToASTNode
(
node
*
apiv2pb
.
Node
)
ast
.
Node
{
switch
n
:=
node
.
Node
.
(
type
)
{
case
*
apiv2pb
.
Node_LineBreakNode
:
return
&
ast
.
LineBreak
{}
case
*
apiv2pb
.
Node_ParagraphNode
:
children
:=
convertToASTNodes
(
n
.
ParagraphNode
.
Children
)
return
&
ast
.
Paragraph
{
Children
:
children
}
case
*
apiv2pb
.
Node_CodeBlockNode
:
return
&
ast
.
CodeBlock
{
Language
:
n
.
CodeBlockNode
.
Language
,
Content
:
n
.
CodeBlockNode
.
Content
}
case
*
apiv2pb
.
Node_HeadingNode
:
children
:=
convertToASTNodes
(
n
.
HeadingNode
.
Children
)
return
&
ast
.
Heading
{
Level
:
int
(
n
.
HeadingNode
.
Level
),
Children
:
children
}
case
*
apiv2pb
.
Node_HorizontalRuleNode
:
return
&
ast
.
HorizontalRule
{
Symbol
:
n
.
HorizontalRuleNode
.
Symbol
}
case
*
apiv2pb
.
Node_BlockquoteNode
:
children
:=
convertToASTNodes
(
n
.
BlockquoteNode
.
Children
)
return
&
ast
.
Blockquote
{
Children
:
children
}
case
*
apiv2pb
.
Node_OrderedListNode
:
children
:=
convertToASTNodes
(
n
.
OrderedListNode
.
Children
)
return
&
ast
.
OrderedList
{
Number
:
n
.
OrderedListNode
.
Number
,
Children
:
children
}
case
*
apiv2pb
.
Node_UnorderedListNode
:
children
:=
convertToASTNodes
(
n
.
UnorderedListNode
.
Children
)
return
&
ast
.
UnorderedList
{
Symbol
:
n
.
UnorderedListNode
.
Symbol
,
Children
:
children
}
case
*
apiv2pb
.
Node_TaskListNode
:
children
:=
convertToASTNodes
(
n
.
TaskListNode
.
Children
)
return
&
ast
.
TaskList
{
Symbol
:
n
.
TaskListNode
.
Symbol
,
Complete
:
n
.
TaskListNode
.
Complete
,
Children
:
children
}
case
*
apiv2pb
.
Node_MathBlockNode
:
return
&
ast
.
MathBlock
{
Content
:
n
.
MathBlockNode
.
Content
}
case
*
apiv2pb
.
Node_TextNode
:
return
&
ast
.
Text
{
Content
:
n
.
TextNode
.
Content
}
case
*
apiv2pb
.
Node_BoldNode
:
children
:=
convertToASTNodes
(
n
.
BoldNode
.
Children
)
return
&
ast
.
Bold
{
Symbol
:
n
.
BoldNode
.
Symbol
,
Children
:
children
}
case
*
apiv2pb
.
Node_ItalicNode
:
return
&
ast
.
Italic
{
Symbol
:
n
.
ItalicNode
.
Symbol
,
Content
:
n
.
ItalicNode
.
Content
}
case
*
apiv2pb
.
Node_BoldItalicNode
:
return
&
ast
.
BoldItalic
{
Symbol
:
n
.
BoldItalicNode
.
Symbol
,
Content
:
n
.
BoldItalicNode
.
Content
}
case
*
apiv2pb
.
Node_CodeNode
:
return
&
ast
.
Code
{
Content
:
n
.
CodeNode
.
Content
}
case
*
apiv2pb
.
Node_ImageNode
:
return
&
ast
.
Image
{
AltText
:
n
.
ImageNode
.
AltText
,
URL
:
n
.
ImageNode
.
Url
}
case
*
apiv2pb
.
Node_LinkNode
:
return
&
ast
.
Link
{
Text
:
n
.
LinkNode
.
Text
,
URL
:
n
.
LinkNode
.
Url
}
case
*
apiv2pb
.
Node_AutoLinkNode
:
return
&
ast
.
AutoLink
{
URL
:
n
.
AutoLinkNode
.
Url
}
case
*
apiv2pb
.
Node_TagNode
:
return
&
ast
.
Tag
{
Content
:
n
.
TagNode
.
Content
}
case
*
apiv2pb
.
Node_StrikethroughNode
:
return
&
ast
.
Strikethrough
{
Content
:
n
.
StrikethroughNode
.
Content
}
case
*
apiv2pb
.
Node_EscapingCharacterNode
:
return
&
ast
.
EscapingCharacter
{
Symbol
:
n
.
EscapingCharacterNode
.
Symbol
}
case
*
apiv2pb
.
Node_MathNode
:
return
&
ast
.
Math
{
Content
:
n
.
MathNode
.
Content
}
default
:
return
&
ast
.
Text
{}
}
}
func
traverseASTNodes
(
nodes
[]
ast
.
Node
,
fn
func
(
ast
.
Node
))
{
for
_
,
node
:=
range
nodes
{
fn
(
node
)
...
...
api/v2/memo_service.go
View file @
454cd4e2
...
...
@@ -19,6 +19,7 @@ import (
"github.com/usememos/memos/plugin/gomark/ast"
"github.com/usememos/memos/plugin/gomark/parser"
"github.com/usememos/memos/plugin/gomark/parser/tokenizer"
"github.com/usememos/memos/plugin/gomark/restore"
"github.com/usememos/memos/plugin/webhook"
apiv2pb
"github.com/usememos/memos/proto/gen/api/v2"
storepb
"github.com/usememos/memos/proto/gen/store"
...
...
@@ -232,6 +233,10 @@ func (s *APIV2Service) UpdateMemo(ctx context.Context, request *apiv2pb.UpdateMe
}
}
})
}
else
if
path
==
"nodes"
{
nodes
:=
convertToASTNodes
(
request
.
Memo
.
Nodes
)
content
:=
restore
.
Restore
(
nodes
)
update
.
Content
=
&
content
}
else
if
path
==
"visibility"
{
visibility
:=
convertVisibilityToStore
(
request
.
Memo
.
Visibility
)
update
.
Visibility
=
&
visibility
...
...
plugin/gomark/ast/utils.go
0 → 100644
View file @
454cd4e2
package
ast
func
FindPrevSiblingExceptLineBreak
(
node
Node
)
Node
{
if
node
==
nil
{
return
nil
}
prev
:=
node
.
PrevSibling
()
if
prev
!=
nil
&&
prev
.
Type
()
==
LineBreakNode
{
return
FindPrevSiblingExceptLineBreak
(
prev
)
}
return
prev
}
func
FindNextSiblingExceptLineBreak
(
node
Node
)
Node
{
if
node
==
nil
{
return
nil
}
next
:=
node
.
NextSibling
()
if
next
!=
nil
&&
next
.
Type
()
==
LineBreakNode
{
return
FindNextSiblingExceptLineBreak
(
next
)
}
return
next
}
plugin/gomark/parser/parser.go
View file @
454cd4e2
...
...
@@ -49,7 +49,6 @@ func ParseBlock(tokens []*tokenizer.Token) ([]ast.Node, error) {
func
ParseBlockWithParsers
(
tokens
[]
*
tokenizer
.
Token
,
blockParsers
[]
BlockParser
)
([]
ast
.
Node
,
error
)
{
nodes
:=
[]
ast
.
Node
{}
var
prevNode
ast
.
Node
var
skipNextLineBreakFlag
bool
for
len
(
tokens
)
>
0
{
for
_
,
blockParser
:=
range
blockParsers
{
size
,
matched
:=
blockParser
.
Match
(
tokens
)
...
...
@@ -59,21 +58,12 @@ func ParseBlockWithParsers(tokens []*tokenizer.Token, blockParsers []BlockParser
return
nil
,
errors
.
New
(
"parse error"
)
}
if
node
.
Type
()
==
ast
.
LineBreakNode
&&
skipNextLineBreakFlag
{
if
prevNode
!=
nil
&&
ast
.
IsBlockNode
(
prevNode
)
{
tokens
=
tokens
[
size
:
]
skipNextLineBreakFlag
=
false
break
}
}
tokens
=
tokens
[
size
:
]
if
prevNode
!=
nil
{
prevNode
.
SetNextSibling
(
node
)
node
.
SetPrevSibling
(
prevNode
)
}
prevNode
=
node
skipNextLineBreakFlag
=
true
nodes
=
append
(
nodes
,
node
)
break
}
...
...
plugin/gomark/parser/parser_test.go
View file @
454cd4e2
...
...
@@ -96,6 +96,7 @@ func TestParser(t *testing.T) {
},
},
},
&
ast
.
LineBreak
{},
&
ast
.
Paragraph
{
Children
:
[]
ast
.
Node
{
&
ast
.
Text
{
...
...
@@ -126,6 +127,7 @@ func TestParser(t *testing.T) {
},
},
},
&
ast
.
LineBreak
{},
&
ast
.
CodeBlock
{
Language
:
"javascript"
,
Content
:
"console.log(
\"
Hello world!
\"
);"
,
...
...
@@ -143,6 +145,7 @@ func TestParser(t *testing.T) {
},
},
&
ast
.
LineBreak
{},
&
ast
.
LineBreak
{},
&
ast
.
Paragraph
{
Children
:
[]
ast
.
Node
{
&
ast
.
Text
{
...
...
@@ -163,6 +166,7 @@ func TestParser(t *testing.T) {
},
},
},
&
ast
.
LineBreak
{},
&
ast
.
TaskList
{
Symbol
:
tokenizer
.
Hyphen
,
Complete
:
false
,
...
...
@@ -186,6 +190,7 @@ func TestParser(t *testing.T) {
},
},
},
&
ast
.
LineBreak
{},
&
ast
.
TaskList
{
Symbol
:
tokenizer
.
Hyphen
,
Complete
:
true
,
...
...
plugin/gomark/renderer/html/html.go
View file @
454cd4e2
...
...
@@ -72,8 +72,19 @@ func (r *HTMLRenderer) RenderNode(node ast.Node) {
// RenderNodes renders a slice of AST nodes to HTML.
func
(
r
*
HTMLRenderer
)
RenderNodes
(
nodes
[]
ast
.
Node
)
{
var
prevNode
ast
.
Node
var
skipNextLineBreakFlag
bool
for
_
,
node
:=
range
nodes
{
if
node
.
Type
()
==
ast
.
LineBreakNode
&&
skipNextLineBreakFlag
{
if
prevNode
!=
nil
&&
ast
.
IsBlockNode
(
prevNode
)
{
skipNextLineBreakFlag
=
false
continue
}
}
r
.
RenderNode
(
node
)
prevNode
=
node
skipNextLineBreakFlag
=
true
}
}
...
...
@@ -111,7 +122,7 @@ func (r *HTMLRenderer) renderHorizontalRule(_ *ast.HorizontalRule) {
}
func
(
r
*
HTMLRenderer
)
renderBlockquote
(
node
*
ast
.
Blockquote
)
{
prevSibling
,
nextSibling
:=
node
.
PrevSibling
(),
node
.
NextSibling
(
)
prevSibling
,
nextSibling
:=
ast
.
FindPrevSiblingExceptLineBreak
(
node
),
ast
.
FindNextSiblingExceptLineBreak
(
node
)
if
prevSibling
==
nil
||
prevSibling
.
Type
()
!=
ast
.
BlockquoteNode
{
r
.
output
.
WriteString
(
"<blockquote>"
)
}
...
...
@@ -122,7 +133,7 @@ func (r *HTMLRenderer) renderBlockquote(node *ast.Blockquote) {
}
func
(
r
*
HTMLRenderer
)
renderTaskList
(
node
*
ast
.
TaskList
)
{
prevSibling
,
nextSibling
:=
node
.
PrevSibling
(),
node
.
NextSibling
(
)
prevSibling
,
nextSibling
:=
ast
.
FindPrevSiblingExceptLineBreak
(
node
),
ast
.
FindNextSiblingExceptLineBreak
(
node
)
if
prevSibling
==
nil
||
prevSibling
.
Type
()
!=
ast
.
TaskListNode
{
r
.
output
.
WriteString
(
"<ul>"
)
}
...
...
@@ -140,7 +151,7 @@ func (r *HTMLRenderer) renderTaskList(node *ast.TaskList) {
}
func
(
r
*
HTMLRenderer
)
renderUnorderedList
(
node
*
ast
.
UnorderedList
)
{
prevSibling
,
nextSibling
:=
node
.
PrevSibling
(),
node
.
NextSibling
(
)
prevSibling
,
nextSibling
:=
ast
.
FindPrevSiblingExceptLineBreak
(
node
),
ast
.
FindNextSiblingExceptLineBreak
(
node
)
if
prevSibling
==
nil
||
prevSibling
.
Type
()
!=
ast
.
UnorderedListNode
{
r
.
output
.
WriteString
(
"<ul>"
)
}
...
...
@@ -153,7 +164,7 @@ func (r *HTMLRenderer) renderUnorderedList(node *ast.UnorderedList) {
}
func
(
r
*
HTMLRenderer
)
renderOrderedList
(
node
*
ast
.
OrderedList
)
{
prevSibling
,
nextSibling
:=
node
.
PrevSibling
(),
node
.
NextSibling
(
)
prevSibling
,
nextSibling
:=
ast
.
FindPrevSiblingExceptLineBreak
(
node
),
ast
.
FindNextSiblingExceptLineBreak
(
node
)
if
prevSibling
==
nil
||
prevSibling
.
Type
()
!=
ast
.
OrderedListNode
{
r
.
output
.
WriteString
(
"<ol>"
)
}
...
...
plugin/gomark/renderer/string/string.go
View file @
454cd4e2
...
...
@@ -72,8 +72,19 @@ func (r *StringRenderer) RenderNode(node ast.Node) {
// RenderNodes renders a slice of AST nodes to raw string.
func
(
r
*
StringRenderer
)
RenderNodes
(
nodes
[]
ast
.
Node
)
{
var
prevNode
ast
.
Node
var
skipNextLineBreakFlag
bool
for
_
,
node
:=
range
nodes
{
if
node
.
Type
()
==
ast
.
LineBreakNode
&&
skipNextLineBreakFlag
{
if
prevNode
!=
nil
&&
ast
.
IsBlockNode
(
prevNode
)
{
skipNextLineBreakFlag
=
false
continue
}
}
r
.
RenderNode
(
node
)
prevNode
=
node
skipNextLineBreakFlag
=
true
}
}
...
...
web/src/components/MemoContent/Renderer.tsx
View file @
454cd4e2
...
...
@@ -44,10 +44,11 @@ import Text from "./Text";
import
UnorderedList
from
"./UnorderedList"
;
interface
Props
{
index
:
string
;
node
:
Node
;
}
const
Renderer
:
React
.
FC
<
Props
>
=
({
node
}:
Props
)
=>
{
const
Renderer
:
React
.
FC
<
Props
>
=
({
index
,
node
}:
Props
)
=>
{
switch
(
node
.
type
)
{
case
NodeType
.
LINE_BREAK
:
return
<
LineBreak
/>;
...
...
@@ -66,7 +67,7 @@ const Renderer: React.FC<Props> = ({ node }: Props) => {
case
NodeType
.
UNORDERED_LIST
:
return
<
UnorderedList
{
...
(
node
.
unorderedListNode
as
UnorderedListNode
)}
/>;
case
NodeType
.
TASK_LIST
:
return
<
TaskList
{
...
(
node
.
taskListNode
as
TaskListNode
)}
/>;
return
<
TaskList
index=
{
index
}
{
...
(
node
.
taskListNode
as
TaskListNode
)}
/>;
case
NodeType
.
MATH_BLOCK
:
return
<
Math
{
...
(
node
.
mathBlockNode
as
MathNode
)}
block=
{
true
}
/>;
case
NodeType
.
TEXT
:
...
...
web/src/components/MemoContent/TaskList.tsx
View file @
454cd4e2
import
{
Checkbox
}
from
"@mui/joy"
;
import
{
Node
}
from
"@/types/proto/api/v2/markdown_service"
;
import
{
useContext
}
from
"react"
;
import
{
useMemoStore
}
from
"@/store/v1"
;
import
{
Node
,
NodeType
}
from
"@/types/proto/api/v2/markdown_service"
;
import
Renderer
from
"./Renderer"
;
import
{
RendererContext
}
from
"./types"
;
interface
Props
{
index
:
string
;
symbol
:
string
;
complete
:
boolean
;
children
:
Node
[];
}
const
TaskList
:
React
.
FC
<
Props
>
=
({
complete
,
children
}:
Props
)
=>
{
const
TaskList
:
React
.
FC
<
Props
>
=
({
index
,
complete
,
children
}:
Props
)
=>
{
const
context
=
useContext
(
RendererContext
);
const
memoStore
=
useMemoStore
();
const
handleCheckboxChange
=
async
(
on
:
boolean
)
=>
{
const
nodeIndex
=
Number
(
index
);
if
(
isNaN
(
nodeIndex
))
{
return
;
}
const
node
=
context
.
nodes
[
nodeIndex
];
if
(
node
.
type
!==
NodeType
.
TASK_LIST
||
!
node
.
taskListNode
)
{
return
;
}
node
.
taskListNode
!
.
complete
=
on
;
await
memoStore
.
updateMemo
(
{
id
:
context
.
memoId
,
nodes
:
context
.
nodes
,
},
[
"nodes"
]
);
};
return
(
<
ul
>
<
li
className=
"grid grid-cols-[24px_1fr] gap-1"
>
<
div
className=
"w-7 h-6 flex justify-center items-center"
>
<
Checkbox
size=
"sm"
checked=
{
complete
}
readOnly
/>
<
Checkbox
size=
"sm"
checked=
{
complete
}
disabled=
{
context
.
readonly
}
onChange=
{
(
e
)
=>
handleCheckboxChange
(
e
.
target
.
checked
)
}
/>
</
div
>
<
div
>
{
children
.
map
((
child
,
i
ndex
)
=>
(
<
Renderer
key=
{
`${child.type}-${
i
ndex}`
}
node=
{
child
}
/>
{
children
.
map
((
child
,
subI
ndex
)
=>
(
<
Renderer
key=
{
`${child.type}-${
subIndex}`
}
index=
{
`${index}-${subI
ndex}`
}
node=
{
child
}
/>
))
}
</
div
>
</
li
>
...
...
web/src/components/MemoContent/index.tsx
View file @
454cd4e2
import
{
useRef
}
from
"react"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useMemoStore
}
from
"@/store/v1"
;
import
{
Node
}
from
"@/types/proto/api/v2/markdown_service"
;
import
Renderer
from
"./Renderer"
;
import
{
RendererContext
}
from
"./types"
;
interface
Props
{
memoId
:
number
;
nodes
:
Node
[];
readonly
?:
boolean
;
className
?:
string
;
onMemoContentClick
?:
(
e
:
React
.
MouseEvent
)
=>
void
;
}
const
MemoContent
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
className
,
onMemoContentClick
}
=
props
;
const
{
className
,
memoId
,
nodes
,
onMemoContentClick
}
=
props
;
const
currentUser
=
useCurrentUser
();
const
memoStore
=
useMemoStore
();
const
memoContentContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
allowEdit
=
currentUser
?.
id
===
memoStore
.
getMemoById
(
memoId
)?.
creatorId
&&
!
props
.
readonly
;
const
handleMemoContentClick
=
async
(
e
:
React
.
MouseEvent
)
=>
{
if
(
onMemoContentClick
)
{
...
...
@@ -19,17 +27,25 @@ const MemoContent: React.FC<Props> = (props: Props) => {
};
return
(
<
RendererContext
.
Provider
value=
{
{
memoId
,
nodes
,
readonly
:
!
allowEdit
,
}
}
>
<
div
className=
{
`w-full flex flex-col justify-start items-start text-gray-800 dark:text-gray-300 ${className || ""}`
}
>
<
div
ref=
{
memoContentContainerRef
}
className=
"w-full max-w-full word-break text-base leading-6 space-y-1"
onClick=
{
handleMemoContentClick
}
>
{
props
.
nodes
.
map
((
node
,
index
)
=>
(
<
Renderer
key=
{
`${node.type}-${index}`
}
node=
{
node
}
/>
{
nodes
.
map
((
node
,
index
)
=>
(
<
Renderer
key=
{
`${node.type}-${index}`
}
index=
{
String
(
index
)
}
node=
{
node
}
/>
))
}
</
div
>
</
div
>
</
RendererContext
.
Provider
>
);
};
...
...
web/src/components/MemoContent/types/context.ts
View file @
454cd4e2
export
interface
RendererContext
{}
import
{
createContext
}
from
"react"
;
import
{
UNKNOWN_ID
}
from
"@/helpers/consts"
;
import
{
Node
}
from
"@/types/proto/api/v2/markdown_service"
;
interface
Context
{
memoId
:
number
;
nodes
:
Node
[];
readonly
?:
boolean
;
}
export
const
RendererContext
=
createContext
<
Context
>
({
memoId
:
UNKNOWN_ID
,
nodes
:
[],
});
web/src/components/MemoView.tsx
View file @
454cd4e2
...
...
@@ -251,7 +251,7 @@ const MemoView: React.FC<Props> = (props: Props) => {
)
}
</
div
>
</
div
>
<
MemoContent
nodes=
{
memo
.
nodes
}
onMemoContentClick=
{
handleMemoContentClick
}
/>
<
MemoContent
memoId=
{
memo
.
id
}
nodes=
{
memo
.
nodes
}
onMemoContentClick=
{
handleMemoContentClick
}
/>
<
MemoResourceListView
resourceList=
{
memo
.
resources
}
/>
<
MemoRelationListView
memo=
{
memo
}
relationList=
{
referenceRelations
}
/>
</
div
>
...
...
web/src/components/ShareMemoDialog.tsx
View file @
454cd4e2
...
...
@@ -100,7 +100,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
>
<
span
className=
"w-full px-6 pt-5 pb-2 text-sm text-gray-500"
>
{
getDateTimeString
(
memo
.
displayTime
)
}
</
span
>
<
div
className=
"w-full px-6 text-base pb-4"
>
<
MemoContent
nodes=
{
memo
.
nodes
}
/>
<
MemoContent
memoId=
{
memo
.
id
}
nodes=
{
memo
.
nodes
}
readonly=
{
true
}
/>
<
MemoResourceListView
resourceList=
{
memo
.
resources
}
/>
</
div
>
<
div
className=
"flex flex-row justify-between items-center w-full bg-gray-100 dark:bg-zinc-900 py-4 px-6"
>
...
...
web/src/components/TimelineMemo.tsx
View file @
454cd4e2
...
...
@@ -18,7 +18,7 @@ const TimelineMemo = (props: Props) => {
<
div
className=
"w-full flex flex-row justify-start items-center mt-0.5 mb-1 text-sm font-mono text-gray-500 dark:text-gray-400"
>
<
span
className=
"opacity-80"
>
{
getTimeString
(
memo
.
displayTime
)
}
</
span
>
</
div
>
<
MemoContent
nodes=
{
memo
.
nodes
}
/>
<
MemoContent
memoId=
{
memo
.
id
}
nodes=
{
memo
.
nodes
}
/>
<
MemoResourceListView
resourceList=
{
memo
.
resources
}
/>
<
MemoRelationListView
memo=
{
memo
}
relationList=
{
relations
}
/>
</
div
>
...
...
web/src/pages/Archived.tsx
View file @
454cd4e2
...
...
@@ -105,7 +105,7 @@ const Archived = () => {
</
Tooltip
>
</
div
>
</
div
>
<
MemoContent
nodes=
{
memo
.
nodes
}
/>
<
MemoContent
memoId=
{
memo
.
id
}
nodes=
{
memo
.
nodes
}
readonly=
{
true
}
/>
</
div
>
))
}
</
div
>
...
...
web/src/pages/MemoDetail.tsx
View file @
454cd4e2
...
...
@@ -139,7 +139,7 @@ const MemoDetail = () => {
</
Link
>
</
div
>
)
}
<
MemoContent
nodes=
{
memo
.
nodes
}
/>
<
MemoContent
memoId=
{
memo
.
id
}
nodes=
{
memo
.
nodes
}
readonly=
{
true
}
/>
<
MemoResourceListView
resourceList=
{
memo
.
resources
}
/>
<
MemoRelationListView
memo=
{
memo
}
relationList=
{
referenceRelations
}
/>
<
div
className=
"w-full mt-3 flex flex-row justify-between items-center gap-2"
>
...
...
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