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
21c70e79
Commit
21c70e79
authored
Oct 18, 2023
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: update memo relations dialog
parent
22d331d6
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
190 additions
and
15 deletions
+190
-15
memo.go
api/v1/memo.go
+3
-3
CreateMemoRelationDialog.tsx
web/src/components/CreateMemoRelationDialog.tsx
+134
-0
BaseDialog.tsx
web/src/components/Dialog/BaseDialog.tsx
+5
-3
Header.tsx
web/src/components/Header.tsx
+2
-2
Memo.tsx
web/src/components/Memo.tsx
+9
-2
MemoEditorDialog.tsx
web/src/components/MemoEditor/MemoEditorDialog.tsx
+8
-1
index.tsx
web/src/components/MemoEditor/index.tsx
+23
-2
MemoList.tsx
web/src/components/MemoList.tsx
+1
-1
base-dialog.less
web/src/less/base-dialog.less
+1
-1
MemoDetail.tsx
web/src/pages/MemoDetail.tsx
+4
-0
No files found.
api/v1/memo.go
View file @
21c70e79
...
@@ -194,9 +194,9 @@ func (s *APIV1Service) GetMemoList(c echo.Context) error {
...
@@ -194,9 +194,9 @@ func (s *APIV1Service) GetMemoList(c echo.Context) error {
if
tag
!=
""
{
if
tag
!=
""
{
contentSearch
=
append
(
contentSearch
,
"#"
+
tag
)
contentSearch
=
append
(
contentSearch
,
"#"
+
tag
)
}
}
content
Slice
:=
c
.
QueryParams
()[
"content"
]
content
:=
c
.
QueryParam
(
"content"
)
if
len
(
contentSlice
)
>
0
{
if
content
!=
""
{
contentSearch
=
append
(
contentSearch
,
content
Slice
...
)
contentSearch
=
append
(
contentSearch
,
content
)
}
}
findMemoMessage
.
ContentSearch
=
contentSearch
findMemoMessage
.
ContentSearch
=
contentSearch
...
...
web/src/components/CreateMemoRelationDialog.tsx
0 → 100644
View file @
21c70e79
import
{
Button
,
Input
}
from
"@mui/joy"
;
import
{
isNaN
,
unionBy
}
from
"lodash-es"
;
import
React
,
{
useState
}
from
"react"
;
import
{
toast
}
from
"react-hot-toast"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
{
Memo
}
from
"@/types/proto/api/v2/memo_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
generateDialog
}
from
"./Dialog"
;
import
Icon
from
"./Icon"
;
interface
Props
extends
DialogProps
{
onCancel
?:
()
=>
void
;
onConfirm
?:
(
memoIdList
:
number
[])
=>
void
;
}
const
CreateMemoRelationDialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
destroy
,
onCancel
,
onConfirm
}
=
props
;
const
t
=
useTranslate
();
const
[
memoId
,
setMemoId
]
=
useState
<
string
>
(
""
);
const
[
memoList
,
setMemoList
]
=
useState
<
Memo
[]
>
([]);
const
handleMemoIdInputKeyDown
=
(
event
:
React
.
KeyboardEvent
)
=>
{
if
(
event
.
key
===
"Enter"
)
{
handleSaveBtnClick
();
}
};
const
handleMemoIdChanged
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
memoId
=
event
.
target
.
value
;
setMemoId
(
memoId
.
trim
());
};
const
handleSaveBtnClick
=
async
()
=>
{
const
id
=
Number
(
memoId
);
if
(
isNaN
(
id
))
{
toast
.
error
(
"Invalid memo id"
);
return
;
}
try
{
const
{
memo
}
=
await
memoServiceClient
.
getMemo
({
id
,
});
if
(
!
memo
)
{
toast
.
error
(
"Not found memo"
);
return
;
}
setMemoId
(
""
);
setMemoList
(
unionBy
([
memo
,
...
memoList
],
"id"
));
}
catch
(
error
:
any
)
{
console
.
error
(
error
);
toast
.
error
(
error
.
response
.
data
.
message
);
}
};
const
handleDeleteMemoRelation
=
async
(
memo
:
Memo
)
=>
{
setMemoList
(
memoList
.
filter
((
m
)
=>
m
!==
memo
));
};
const
handleCloseDialog
=
()
=>
{
if
(
onCancel
)
{
onCancel
();
}
destroy
();
};
const
handleConfirmBtnClick
=
async
()
=>
{
if
(
onConfirm
)
{
onConfirm
(
memoList
.
map
((
memo
)
=>
memo
.
id
));
}
destroy
();
};
return
(
<>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
{
"Relations"
}
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
()
=>
destroy
()
}
>
<
Icon
.
X
/>
</
button
>
</
div
>
<
div
className=
"dialog-content-container !w-80"
>
<
Input
className=
"mb-2"
size=
"md"
placeholder=
{
"Memo ID. e.g. 286"
}
value=
{
memoId
}
onChange=
{
handleMemoIdChanged
}
onKeyDown=
{
handleMemoIdInputKeyDown
}
fullWidth
endDecorator=
{
<
Icon
.
Check
onClick=
{
handleSaveBtnClick
}
className=
"w-4 h-auto cursor-pointer hover:opacity-80"
/>
}
/>
{
memoList
.
length
>
0
&&
(
<>
<
div
className=
"w-full flex flex-row justify-start items-start flex-wrap gap-x-2 gap-y-1"
>
{
memoList
.
map
((
memo
)
=>
(
<
div
className=
"max-w-[120px] text-sm mr-2 mt-1 cursor-pointer truncate opacity-80 dark:text-gray-300 hover:opacity-60 hover:line-through"
key=
{
memo
.
id
}
onClick=
{
()
=>
handleDeleteMemoRelation
(
memo
)
}
>
<
span
className=
"font-mono mr-1"
>
#
{
memo
.
id
}
</
span
>
<
span
className=
"opacity-80"
>
{
memo
.
content
}
</
span
>
</
div
>
))
}
</
div
>
</>
)
}
<
div
className=
"mt-2 w-full flex flex-row justify-end items-center space-x-1"
>
<
Button
variant=
"plain"
color=
"neutral"
onClick=
{
handleCloseDialog
}
>
{
t
(
"common.cancel"
)
}
</
Button
>
<
Button
onClick=
{
handleConfirmBtnClick
}
disabled=
{
memoList
.
length
===
0
}
>
{
t
(
"common.confirm"
)
}
</
Button
>
</
div
>
</
div
>
</>
);
};
function
showCreateMemoRelationDialog
(
props
:
Omit
<
Props
,
"destroy"
|
"hide"
>
)
{
generateDialog
(
{
className
:
"create-memo-relation-dialog"
,
dialogName
:
"create-memo-relation-dialog"
,
},
CreateMemoRelationDialog
,
props
);
}
export
default
showCreateMemoRelationDialog
;
web/src/components/Dialog/BaseDialog.tsx
View file @
21c70e79
import
{
CssVarsProvider
}
from
"@mui/joy"
;
import
{
CssVarsProvider
}
from
"@mui/joy"
;
import
classNames
from
"classnames"
;
import
{
useEffect
,
useRef
}
from
"react"
;
import
{
useEffect
,
useRef
}
from
"react"
;
import
{
createRoot
}
from
"react-dom/client"
;
import
{
createRoot
}
from
"react-dom/client"
;
import
{
Provider
}
from
"react-redux"
;
import
{
Provider
}
from
"react-redux"
;
...
@@ -11,6 +12,7 @@ import "@/less/base-dialog.less";
...
@@ -11,6 +12,7 @@ import "@/less/base-dialog.less";
interface
DialogConfig
{
interface
DialogConfig
{
dialogName
:
string
;
dialogName
:
string
;
className
?:
string
;
className
?:
string
;
containerClassName
?:
string
;
clickSpaceDestroy
?:
boolean
;
clickSpaceDestroy
?:
boolean
;
}
}
...
@@ -19,7 +21,7 @@ interface Props extends DialogConfig, DialogProps {
...
@@ -19,7 +21,7 @@ interface Props extends DialogConfig, DialogProps {
}
}
const
BaseDialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
BaseDialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
children
,
className
,
clickSpaceDestroy
,
dialogName
,
destroy
}
=
props
;
const
{
children
,
className
,
c
ontainerClassName
,
c
lickSpaceDestroy
,
dialogName
,
destroy
}
=
props
;
const
dialogStore
=
useDialogStore
();
const
dialogStore
=
useDialogStore
();
const
dialogContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
dialogContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
dialogIndex
=
dialogStore
.
state
.
dialogStack
.
findIndex
((
item
)
=>
item
===
dialogName
);
const
dialogIndex
=
dialogStore
.
state
.
dialogStack
.
findIndex
((
item
)
=>
item
===
dialogName
);
...
@@ -55,8 +57,8 @@ const BaseDialog: React.FC<Props> = (props: Props) => {
...
@@ -55,8 +57,8 @@ const BaseDialog: React.FC<Props> = (props: Props) => {
};
};
return
(
return
(
<
div
className=
{
`dialog-wrapper ${className ?? ""}`
}
onMouseDown=
{
handleSpaceClicked
}
>
<
div
className=
{
classNames
(
"dialog-wrapper"
,
className
)
}
onMouseDown=
{
handleSpaceClicked
}
>
<
div
ref=
{
dialogContainerRef
}
className=
"dialog-container"
onMouseDown=
{
(
e
)
=>
e
.
stopPropagation
()
}
>
<
div
ref=
{
dialogContainerRef
}
className=
{
classNames
(
"dialog-container"
,
containerClassName
)
}
onMouseDown=
{
(
e
)
=>
e
.
stopPropagation
()
}
>
{
children
}
{
children
}
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/components/Header.tsx
View file @
21c70e79
...
@@ -83,12 +83,12 @@ const Header = () => {
...
@@ -83,12 +83,12 @@ const Header = () => {
return
(
return
(
<
div
<
div
className=
{
`fixed sm:sticky top-0 left-0 w-full sm:w-56 h-
full
shrink-0 pointer-events-none sm:pointer-events-auto z-10 ${
className=
{
`fixed sm:sticky top-0 left-0 w-full sm:w-56 h-
screen
shrink-0 pointer-events-none sm:pointer-events-auto z-10 ${
showHeader && "pointer-events-auto"
showHeader && "pointer-events-auto"
}`
}
}`
}
>
>
<
div
<
div
className=
{
`fixed top-0 left-0 w-full h-full opacity-0 pointer-events-none transition-opacity duration-300 sm:!hidden ${
className=
{
`fixed top-0 left-0 w-full h-full
max-h-screen
opacity-0 pointer-events-none transition-opacity duration-300 sm:!hidden ${
showHeader && "opacity-60 pointer-events-auto"
showHeader && "opacity-60 pointer-events-auto"
}`
}
}`
}
onClick=
{
()
=>
layoutStore
.
setHeaderStatus
(
false
)
}
onClick=
{
()
=>
layoutStore
.
setHeaderStatus
(
false
)
}
...
...
web/src/components/Memo.tsx
View file @
21c70e79
...
@@ -25,6 +25,7 @@ import "@/less/memo.less";
...
@@ -25,6 +25,7 @@ import "@/less/memo.less";
interface
Props
{
interface
Props
{
memo
:
Memo
;
memo
:
Memo
;
showVisibility
?:
boolean
;
showVisibility
?:
boolean
;
showPinnedStyle
?:
boolean
;
lazyRendering
?:
boolean
;
lazyRendering
?:
boolean
;
}
}
...
@@ -229,7 +230,7 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -229,7 +230,7 @@ const Memo: React.FC<Props> = (props: Props) => {
return
(
return
(
<>
<>
<
div
className=
{
`memo-wrapper ${"memos-" + memo.id} ${memo.pinned &&
!readonly
? "pinned" : ""}`
}
ref=
{
memoContainerRef
}
>
<
div
className=
{
`memo-wrapper ${"memos-" + memo.id} ${memo.pinned &&
props.showPinnedStyle
? "pinned" : ""}`
}
ref=
{
memoContainerRef
}
>
<
div
className=
"memo-top-wrapper"
>
<
div
className=
"memo-top-wrapper"
>
<
div
className=
"w-full max-w-[calc(100%-20px)] flex flex-row justify-start items-center mr-1"
>
<
div
className=
"w-full max-w-[calc(100%-20px)] flex flex-row justify-start items-center mr-1"
>
<
span
className=
"text-sm text-gray-400 select-none"
onClick=
{
handleGotoMemoDetailPage
}
>
<
span
className=
"text-sm text-gray-400 select-none"
onClick=
{
handleGotoMemoDetailPage
}
>
...
@@ -290,6 +291,12 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -290,6 +291,12 @@ const Memo: React.FC<Props> = (props: Props) => {
<
div
className=
"flex flex-row justify-start items-center"
>
<
div
className=
"flex flex-row justify-start items-center"
>
{
creator
&&
(
{
creator
&&
(
<>
<>
<
Link
className=
"flex flex-row justify-start items-center"
to=
{
`/m/${memo.id}`
}
>
<
Tooltip
title=
{
"Identifier"
}
placement=
"top"
>
<
span
className=
"text-sm text-gray-500 dark:text-gray-400"
>
#
{
memo
.
id
}
</
span
>
</
Tooltip
>
</
Link
>
<
Icon
.
Dot
className=
"w-4 h-auto text-gray-400 dark:text-zinc-400"
/>
<
Link
to=
{
`/u/${encodeURIComponent(memo.creatorUsername)}`
}
>
<
Link
to=
{
`/u/${encodeURIComponent(memo.creatorUsername)}`
}
>
<
Tooltip
title=
{
"Creator"
}
placement=
"top"
>
<
Tooltip
title=
{
"Creator"
}
placement=
"top"
>
<
span
className=
"flex flex-row justify-start items-center"
>
<
span
className=
"flex flex-row justify-start items-center"
>
...
@@ -298,7 +305,7 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -298,7 +305,7 @@ const Memo: React.FC<Props> = (props: Props) => {
</
span
>
</
span
>
</
Tooltip
>
</
Tooltip
>
</
Link
>
</
Link
>
{
memo
.
pinned
&&
(
{
memo
.
pinned
&&
props
.
showPinnedStyle
&&
(
<>
<>
<
Icon
.
Dot
className=
"w-4 h-auto text-gray-400 dark:text-zinc-400"
/>
<
Icon
.
Dot
className=
"w-4 h-auto text-gray-400 dark:text-zinc-400"
/>
<
Tooltip
title=
{
"Pinned"
}
placement=
"top"
>
<
Tooltip
title=
{
"Pinned"
}
placement=
"top"
>
...
...
web/src/components/MemoEditor/MemoEditorDialog.tsx
View file @
21c70e79
...
@@ -31,7 +31,13 @@ const MemoEditorDialog: React.FC<Props> = ({ memoId, relationList, destroy }: Pr
...
@@ -31,7 +31,13 @@ const MemoEditorDialog: React.FC<Props> = ({ memoId, relationList, destroy }: Pr
</
button
>
</
button
>
</
div
>
</
div
>
<
div
className=
"flex flex-col justify-start items-start max-w-full w-[36rem]"
>
<
div
className=
"flex flex-col justify-start items-start max-w-full w-[36rem]"
>
<
MemoEditor
cacheKey=
{
`memo-editor-${memoId}`
}
memoId=
{
memoId
}
relationList=
{
relationList
}
onConfirm=
{
handleCloseBtnClick
}
/>
<
MemoEditor
className=
"border-none !p-0 -mb-2"
cacheKey=
{
`memo-editor-${memoId}`
}
memoId=
{
memoId
}
relationList=
{
relationList
}
onConfirm=
{
handleCloseBtnClick
}
/>
</
div
>
</
div
>
</>
</>
);
);
...
@@ -42,6 +48,7 @@ export default function showMemoEditorDialog(props: Pick<Props, "memoId" | "rela
...
@@ -42,6 +48,7 @@ export default function showMemoEditorDialog(props: Pick<Props, "memoId" | "rela
{
{
className
:
"memo-editor-dialog"
,
className
:
"memo-editor-dialog"
,
dialogName
:
"memo-editor-dialog"
,
dialogName
:
"memo-editor-dialog"
,
containerClassName
:
"dark:!bg-zinc-700"
,
},
},
MemoEditorDialog
,
MemoEditorDialog
,
props
props
...
...
web/src/components/MemoEditor/index.tsx
View file @
21c70e79
import
{
Select
,
Option
,
Button
}
from
"@mui/joy"
;
import
{
Select
,
Option
,
Button
}
from
"@mui/joy"
;
import
{
isNumber
,
last
,
uniq
}
from
"lodash-es"
;
import
{
isNumber
,
last
,
uniq
,
uniqBy
}
from
"lodash-es"
;
import
React
,
{
useCallback
,
useEffect
,
useMemo
,
useRef
,
useState
}
from
"react"
;
import
React
,
{
useCallback
,
useEffect
,
useMemo
,
useRef
,
useState
}
from
"react"
;
import
{
toast
}
from
"react-hot-toast"
;
import
{
toast
}
from
"react-hot-toast"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
useTranslation
}
from
"react-i18next"
;
...
@@ -10,6 +10,7 @@ import { getMatchedNodes } from "@/labs/marked";
...
@@ -10,6 +10,7 @@ import { getMatchedNodes } from "@/labs/marked";
import
{
useFilterStore
,
useGlobalStore
,
useMemoStore
,
useResourceStore
,
useTagStore
,
useUserStore
}
from
"@/store/module"
;
import
{
useFilterStore
,
useGlobalStore
,
useMemoStore
,
useResourceStore
,
useTagStore
,
useUserStore
}
from
"@/store/module"
;
import
{
Resource
}
from
"@/types/proto/api/v2/resource_service"
;
import
{
Resource
}
from
"@/types/proto/api/v2/resource_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
showCreateMemoRelationDialog
from
"../CreateMemoRelationDialog"
;
import
showCreateResourceDialog
from
"../CreateResourceDialog"
;
import
showCreateResourceDialog
from
"../CreateResourceDialog"
;
import
Icon
from
"../Icon"
;
import
Icon
from
"../Icon"
;
import
VisibilityIcon
from
"../VisibilityIcon"
;
import
VisibilityIcon
from
"../VisibilityIcon"
;
...
@@ -181,6 +182,23 @@ const MemoEditor = (props: Props) => {
...
@@ -181,6 +182,23 @@ const MemoEditor = (props: Props) => {
});
});
};
};
const
handleAddMemoRelationBtnClick
=
()
=>
{
showCreateMemoRelationDialog
({
onConfirm
:
(
memoIdList
)
=>
{
setState
((
prevState
)
=>
({
...
prevState
,
relationList
:
uniqBy
(
[
...
memoIdList
.
map
((
id
)
=>
({
memoId
:
memoId
||
UNKNOWN_ID
,
relatedMemoId
:
id
,
type
:
"REFERENCE"
as
MemoRelationType
})),
...
state
.
relationList
,
].
filter
((
relation
)
=>
relation
.
relatedMemoId
!==
(
memoId
||
UNKNOWN_ID
)),
"relatedMemoId"
),
}));
},
});
};
const
handleSetResourceList
=
(
resourceList
:
Resource
[])
=>
{
const
handleSetResourceList
=
(
resourceList
:
Resource
[])
=>
{
setState
((
prevState
)
=>
({
setState
((
prevState
)
=>
({
...
prevState
,
...
prevState
,
...
@@ -406,7 +424,10 @@ const MemoEditor = (props: Props) => {
...
@@ -406,7 +424,10 @@ const MemoEditor = (props: Props) => {
<
div
className=
"flex flex-row justify-start items-center"
>
<
div
className=
"flex flex-row justify-start items-center"
>
<
TagSelector
onTagSelectorClick=
{
(
tag
)
=>
handleTagSelectorClick
(
tag
)
}
/>
<
TagSelector
onTagSelectorClick=
{
(
tag
)
=>
handleTagSelectorClick
(
tag
)
}
/>
<
button
className=
"flex flex-row justify-center items-center p-1 w-auto h-auto mr-1 select-none rounded cursor-pointer text-gray-600 dark:text-gray-400 hover:bg-gray-300 dark:hover:bg-zinc-800 hover:shadow"
>
<
button
className=
"flex flex-row justify-center items-center p-1 w-auto h-auto mr-1 select-none rounded cursor-pointer text-gray-600 dark:text-gray-400 hover:bg-gray-300 dark:hover:bg-zinc-800 hover:shadow"
>
<
Icon
.
Paperclip
className=
"w-5 h-5 mx-auto"
onClick=
{
handleUploadFileBtnClick
}
/>
<
Icon
.
Image
className=
"w-5 h-5 mx-auto"
onClick=
{
handleUploadFileBtnClick
}
/>
</
button
>
<
button
className=
"flex flex-row justify-center items-center p-1 w-auto h-auto mr-1 select-none rounded cursor-pointer text-gray-600 dark:text-gray-400 hover:bg-gray-300 dark:hover:bg-zinc-800 hover:shadow"
>
<
Icon
.
Link
className=
"w-5 h-5 mx-auto"
onClick=
{
handleAddMemoRelationBtnClick
}
/>
</
button
>
</
button
>
<
button
className=
"flex flex-row justify-center items-center p-1 w-auto h-auto mr-1 select-none rounded cursor-pointer text-gray-600 dark:text-gray-400 hover:bg-gray-300 dark:hover:bg-zinc-800 hover:shadow"
>
<
button
className=
"flex flex-row justify-center items-center p-1 w-auto h-auto mr-1 select-none rounded cursor-pointer text-gray-600 dark:text-gray-400 hover:bg-gray-300 dark:hover:bg-zinc-800 hover:shadow"
>
<
Icon
.
CheckSquare
className=
"w-5 h-5 mx-auto"
onClick=
{
handleCheckBoxBtnClick
}
/>
<
Icon
.
CheckSquare
className=
"w-5 h-5 mx-auto"
onClick=
{
handleCheckBoxBtnClick
}
/>
...
...
web/src/components/MemoList.tsx
View file @
21c70e79
...
@@ -132,7 +132,7 @@ const MemoList: React.FC = () => {
...
@@ -132,7 +132,7 @@ const MemoList: React.FC = () => {
return (
return (
<
div
className=
"flex flex-col justify-start items-start w-full max-w-full overflow-y-scroll pb-28 hide-scrollbar"
>
<
div
className=
"flex flex-col justify-start items-start w-full max-w-full overflow-y-scroll pb-28 hide-scrollbar"
>
{
sortedMemos
.
map
((
memo
)
=>
(
{
sortedMemos
.
map
((
memo
)
=>
(
<
Memo
key=
{
`${memo.id}-${memo.displayTs}`
}
memo=
{
memo
}
lazyRendering
showVisibility
/>
<
Memo
key=
{
`${memo.id}-${memo.displayTs}`
}
memo=
{
memo
}
lazyRendering
showVisibility
showPinnedStyle
/>
))
}
))
}
{
isFetching
?
(
{
isFetching
?
(
<
div
className=
"flex flex-col justify-start items-center w-full mt-2 mb-1"
>
<
div
className=
"flex flex-col justify-start items-center w-full mt-2 mb-1"
>
...
...
web/src/less/base-dialog.less
View file @
21c70e79
...
@@ -22,7 +22,7 @@
...
@@ -22,7 +22,7 @@
}
}
.btn {
.btn {
@apply flex flex-col justify-center items-center w-6 h-6 rounded hover:bg-gray-100 dark:hover:bg-zinc-
7
00 hover:shadow;
@apply flex flex-col justify-center items-center w-6 h-6 rounded hover:bg-gray-100 dark:hover:bg-zinc-
9
00 hover:shadow;
}
}
}
}
...
...
web/src/pages/MemoDetail.tsx
View file @
21c70e79
...
@@ -132,6 +132,10 @@ const MemoDetail = () => {
...
@@ -132,6 +132,10 @@ const MemoDetail = () => {
<
MemoRelationListView
relationList=
{
referenceRelations
}
/>
<
MemoRelationListView
relationList=
{
referenceRelations
}
/>
<
div
className=
"w-full mt-4 flex flex-col sm:flex-row justify-start sm:justify-between sm:items-center gap-2"
>
<
div
className=
"w-full mt-4 flex flex-col sm:flex-row justify-start sm:justify-between sm:items-center gap-2"
>
<
div
className=
"flex flex-row justify-start items-center"
>
<
div
className=
"flex flex-row justify-start items-center"
>
<
Tooltip
title=
{
"Identifier"
}
placement=
"top"
>
<
span
className=
"text-sm text-gray-500 dark:text-gray-400"
>
#
{
memo
.
id
}
</
span
>
</
Tooltip
>
<
Icon
.
Dot
className=
"w-4 h-auto text-gray-400 dark:text-zinc-400"
/>
<
Link
to=
{
`/u/${encodeURIComponent(memo.creatorUsername)}`
}
>
<
Link
to=
{
`/u/${encodeURIComponent(memo.creatorUsername)}`
}
>
<
Tooltip
title=
{
"Creator"
}
placement=
"top"
>
<
Tooltip
title=
{
"Creator"
}
placement=
"top"
>
<
span
className=
"flex flex-row justify-start items-center"
>
<
span
className=
"flex flex-row justify-start items-center"
>
...
...
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