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
c25c57ab
Commit
c25c57ab
authored
May 17, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: support updating display time
parent
b0aad6f6
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
65 additions
and
38 deletions
+65
-38
memo_service.go
server/router/api/v1/memo_service.go
+11
-0
BaseDialog.tsx
web/src/components/Dialog/BaseDialog.tsx
+2
-4
ExploreSidebar.tsx
web/src/components/ExploreSidebar/ExploreSidebar.tsx
+1
-1
TagsSection.tsx
web/src/components/HomeSidebar/TagsSection.tsx
+3
-3
Code.tsx
web/src/components/MemoContent/Code.tsx
+1
-1
MemoEditorDialog.tsx
web/src/components/MemoEditor/MemoEditorDialog.tsx
+37
-9
index.tsx
web/src/components/MemoEditor/index.tsx
+8
-9
Home.tsx
web/src/pages/Home.tsx
+2
-11
No files found.
server/router/api/v1/memo_service.go
View file @
c25c57ab
...
...
@@ -277,6 +277,17 @@ func (s *APIV1Service) UpdateMemo(ctx context.Context, request *v1pb.UpdateMemoR
}
else
if
path
==
"created_ts"
{
createdTs
:=
request
.
Memo
.
CreateTime
.
AsTime
()
.
Unix
()
update
.
CreatedTs
=
&
createdTs
}
else
if
path
==
"display_ts"
{
displayTs
:=
request
.
Memo
.
DisplayTime
.
AsTime
()
.
Unix
()
memoRelatedSetting
,
err
:=
s
.
Store
.
GetWorkspaceMemoRelatedSetting
(
ctx
)
if
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed to get workspace memo related setting"
)
}
if
memoRelatedSetting
.
DisplayWithUpdateTime
{
update
.
UpdatedTs
=
&
displayTs
}
else
{
update
.
CreatedTs
=
&
displayTs
}
}
else
if
path
==
"pinned"
{
if
_
,
err
:=
s
.
Store
.
UpsertMemoOrganizer
(
ctx
,
&
store
.
MemoOrganizer
{
MemoID
:
id
,
...
...
web/src/components/Dialog/BaseDialog.tsx
View file @
c25c57ab
...
...
@@ -77,10 +77,8 @@ export function generateDialog<T extends DialogProps>(
const
cbs
:
DialogCallback
=
{
destroy
:
()
=>
{
document
.
body
.
style
.
removeProperty
(
"overflow"
);
setTimeout
(()
=>
{
dialog
.
unmount
();
tempDiv
.
remove
();
});
dialog
.
unmount
();
tempDiv
.
remove
();
},
};
...
...
web/src/components/ExploreSidebar/ExploreSidebar.tsx
View file @
c25c57ab
...
...
@@ -15,7 +15,7 @@ const ExploreSidebar = (props: Props) => {
)
}
>
<
SearchBar
/>
<
TagsSection
hideTips
=
{
true
}
/>
<
TagsSection
readonly
=
{
true
}
/>
</
aside
>
);
};
...
...
web/src/components/HomeSidebar/TagsSection.tsx
View file @
c25c57ab
...
...
@@ -14,7 +14,7 @@ import Icon from "../Icon";
import
showRenameTagDialog
from
"../RenameTagDialog"
;
interface
Props
{
hideTips
?:
boolean
;
readonly
?:
boolean
;
}
const
TagsSection
=
(
props
:
Props
)
=>
{
...
...
@@ -62,7 +62,7 @@ const TagsSection = (props: Props) => {
<
div
className=
"flex flex-col justify-start items-start w-full mt-3 px-1 h-auto shrink-0 flex-nowrap hide-scrollbar"
>
<
div
className=
"group flex flex-row justify-start items-center w-full gap-1 mb-1"
>
<
span
className=
"text-sm leading-6 font-mono text-gray-400 select-none"
>
{
t
(
"common.tags"
)
}
</
span
>
{
!
props
.
hideTips
&&
(
{
!
props
.
readonly
&&
(
<
div
className=
{
clsx
(
"group-hover:block"
,
tagAmounts
.
length
>
0
?
"hidden"
:
""
)
}
>
<
Tooltip
title=
{
"Rebuild"
}
placement=
"top"
>
<
Icon
.
RefreshCcw
...
...
@@ -80,7 +80,7 @@ const TagsSection = (props: Props) => {
))
}
</
div
>
)
:
(
!
props
.
hideTips
&&
(
!
props
.
readonly
&&
(
<
div
className=
"p-2 border border-dashed dark:border-zinc-800 rounded-md flex flex-row justify-start items-start gap-1 text-gray-400 dark:text-gray-500"
>
<
Icon
.
Tags
/>
<
p
className=
"mt-0.5 text-sm leading-snug italic"
>
{
t
(
"tag.create-tags-guide"
)
}
</
p
>
...
...
web/src/components/MemoContent/Code.tsx
View file @
c25c57ab
...
...
@@ -3,7 +3,7 @@ interface Props {
}
const
Code
:
React
.
FC
<
Props
>
=
({
content
}:
Props
)
=>
{
return
<
code
className=
"inline break-all px-1 font-mono
rounded
bg-gray-100 dark:bg-zinc-700"
>
{
content
}
</
code
>;
return
<
code
className=
"inline break-all px-1 font-mono
text-sm rounded opacity-80
bg-gray-100 dark:bg-zinc-700"
>
{
content
}
</
code
>;
};
export
default
Code
;
web/src/components/MemoEditor/MemoEditorDialog.tsx
View file @
c25c57ab
import
{
IconButton
}
from
"@mui/joy"
;
import
{
useEffect
}
from
"react"
;
import
{
useTagStore
}
from
"@/store/v1"
;
import
clsx
from
"clsx"
;
import
{
useEffect
,
useRef
,
useState
}
from
"react"
;
import
{
useMemoStore
,
useTagStore
}
from
"@/store/v1"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
MemoEditor
,
{
Props
as
MemoEditorProps
}
from
"."
;
import
{
generateDialog
}
from
"../Dialog"
;
import
Icon
from
"../Icon"
;
...
...
@@ -8,7 +10,7 @@ import Icon from "../Icon";
interface
Props
extends
DialogProps
,
MemoEditorProps
{}
const
MemoEditorDialog
:
React
.
FC
<
Props
>
=
({
memoName
:
memo
,
memoName
,
parentMemoName
,
placeholder
,
cacheKey
,
...
...
@@ -17,11 +19,21 @@ const MemoEditorDialog: React.FC<Props> = ({
destroy
,
}:
Props
)
=>
{
const
tagStore
=
useTagStore
();
const
memoStore
=
useMemoStore
();
const
[
displayTime
,
setDisplayTime
]
=
useState
<
string
|
undefined
>
(
memoStore
.
getMemoByName
(
memoName
||
""
)?.
displayTime
?.
toISOString
());
const
memoPatchRef
=
useRef
<
Partial
<
Memo
>>
({
displayTime
:
memoStore
.
getMemoByName
(
memoName
||
""
)?.
displayTime
,
});
useEffect
(()
=>
{
tagStore
.
fetchTags
(
undefined
,
{
skipCache
:
false
});
},
[]);
const
updateDisplayTime
=
(
displayTime
:
string
)
=>
{
setDisplayTime
(
displayTime
);
memoPatchRef
.
current
.
displayTime
=
new
Date
(
displayTime
);
};
const
handleCloseBtnClick
=
()
=>
{
destroy
();
};
...
...
@@ -35,10 +47,25 @@ const MemoEditorDialog: React.FC<Props> = ({
return
(
<>
<
div
className=
"w-full flex flex-row justify-between items-center mb-2"
>
<
div
className=
"flex flex-row justify-start items-center"
>
<
img
className=
"w-6 h-auto rounded-full shadow"
src=
{
"/full-logo.webp"
}
alt=
""
/>
<
p
className=
"ml-1 text-lg opacity-80 dark:text-gray-300"
>
Memos
</
p
>
<
div
className=
"w-full flex flex-row justify-between items-center"
>
<
div
className=
{
clsx
(
"flex flex-row justify-start items-center"
,
!
displayTime
&&
"mb-2"
)
}
>
{
displayTime
?
(
<
div
className=
"relative"
>
<
span
className=
"cursor-pointer text-gray-500 dark:text-gray-400"
>
{
new
Date
(
displayTime
).
toLocaleString
()
}
</
span
>
<
input
className=
"inset-0 absolute z-1 opacity-0"
type=
"datetime-local"
value=
{
displayTime
}
onFocus=
{
(
e
:
any
)
=>
e
.
target
.
showPicker
()
}
onChange=
{
(
e
)
=>
updateDisplayTime
(
e
.
target
.
value
)
}
/>
</
div
>
)
:
(
<>
<
img
className=
"w-6 h-auto rounded-full shadow"
src=
{
"/full-logo.webp"
}
alt=
""
/>
<
p
className=
"ml-1 text-lg opacity-80 dark:text-gray-300"
>
Memos
</
p
>
</>
)
}
</
div
>
<
IconButton
size=
"sm"
onClick=
{
handleCloseBtnClick
}
>
<
Icon
.
X
className=
"w-5 h-auto"
/>
...
...
@@ -47,11 +74,12 @@ const MemoEditorDialog: React.FC<Props> = ({
<
div
className=
"flex flex-col justify-start items-start max-w-full w-[36rem]"
>
<
MemoEditor
className=
"border-none !p-0 -mb-2"
cacheKey=
{
`memo-editor-${cacheKey || memo}`
}
memoName=
{
memo
}
cacheKey=
{
`memo-editor-${cacheKey || memo
Name
}`
}
memoName=
{
memo
Name
}
parentMemoName=
{
parentMemoName
}
placeholder=
{
placeholder
}
relationList=
{
relationList
}
memoPatchRef=
{
memoPatchRef
}
onConfirm=
{
handleConfirm
}
autoFocus
/>
...
...
web/src/components/MemoEditor/index.tsx
View file @
c25c57ab
...
...
@@ -9,7 +9,7 @@ import { isValidUrl } from "@/helpers/utils";
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useMemoStore
,
useResourceStore
,
useUserStore
,
useWorkspaceSettingStore
}
from
"@/store/v1"
;
import
{
MemoRelation
,
MemoRelation_Type
}
from
"@/types/proto/api/v1/memo_relation_service"
;
import
{
Visibility
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Memo
,
Visibility
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Resource
}
from
"@/types/proto/api/v1/resource_service"
;
import
{
UserSetting
}
from
"@/types/proto/api/v1/user_service"
;
import
{
WorkspaceMemoRelatedSetting
}
from
"@/types/proto/api/v1/workspace_setting_service"
;
...
...
@@ -36,8 +36,8 @@ export interface Props {
parentMemoName
?:
string
;
relationList
?:
MemoRelation
[];
autoFocus
?:
boolean
;
memoPatchRef
?:
React
.
MutableRefObject
<
Partial
<
Memo
>>
;
onConfirm
?:
(
memoName
:
string
)
=>
void
;
onEditPrevious
?:
()
=>
void
;
}
interface
State
{
...
...
@@ -159,12 +159,6 @@ const MemoEditor = (props: Props) => {
}
return
;
}
if
(
!!
props
.
onEditPrevious
&&
event
.
key
===
"ArrowDown"
&&
!
state
.
isComposing
&&
editorRef
.
current
.
getContent
()
===
""
)
{
event
.
preventDefault
();
props
.
onEditPrevious
();
return
;
}
};
const
handleMemoVisibilityChange
=
(
visibility
:
Visibility
)
=>
{
...
...
@@ -293,13 +287,18 @@ const MemoEditor = (props: Props) => {
if
(
memoName
)
{
const
prevMemo
=
await
memoStore
.
getOrFetchMemoByName
(
memoName
);
if
(
prevMemo
)
{
const
updateMask
=
[
"content"
,
"visibility"
];
if
(
props
.
memoPatchRef
?.
current
?.
displayTime
)
{
updateMask
.
push
(
"display_ts"
);
}
const
memo
=
await
memoStore
.
updateMemo
(
{
name
:
prevMemo
.
name
,
content
,
visibility
:
state
.
memoVisibility
,
...
props
.
memoPatchRef
?.
current
,
},
[
"content"
,
"visibility"
]
,
updateMask
,
);
await
memoServiceClient
.
setMemoResources
({
name
:
memo
.
name
,
...
...
web/src/pages/Home.tsx
View file @
c25c57ab
import
{
Button
}
from
"@mui/joy"
;
import
clsx
from
"clsx"
;
import
{
use
Callback
,
use
Effect
,
useState
}
from
"react"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
Empty
from
"@/components/Empty"
;
import
{
HomeSidebar
,
HomeSidebarDrawer
}
from
"@/components/HomeSidebar"
;
import
Icon
from
"@/components/Icon"
;
import
MemoEditor
from
"@/components/MemoEditor"
;
import
showMemoEditorDialog
from
"@/components/MemoEditor/MemoEditorDialog"
;
import
MemoFilter
from
"@/components/MemoFilter"
;
import
MemoView
from
"@/components/MemoView"
;
import
MobileHeader
from
"@/components/MobileHeader"
;
...
...
@@ -59,14 +58,6 @@ const Home = () => {
setNextPageToken
(
response
.
nextPageToken
);
};
const
handleEditPrevious
=
useCallback
(()
=>
{
const
lastMemo
=
memoList
.
value
[
memoList
.
value
.
length
-
1
];
showMemoEditorDialog
({
memoName
:
lastMemo
.
name
,
cacheKey
:
`
${
lastMemo
.
name
}
-
${
lastMemo
.
displayTime
}
`
,
});
},
[
memoList
]);
return
(
<
section
className=
"@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8"
>
{
!
md
&&
(
...
...
@@ -76,7 +67,7 @@ const Home = () => {
)
}
<
div
className=
{
clsx
(
"w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4"
)
}
>
<
div
className=
{
clsx
(
md
?
"w-[calc(100%-15rem)]"
:
"w-full"
)
}
>
<
MemoEditor
className=
"mb-2"
cacheKey=
"home-memo-editor"
onEditPrevious=
{
handleEditPrevious
}
/>
<
MemoEditor
className=
"mb-2"
cacheKey=
"home-memo-editor"
/>
<
div
className=
"flex flex-col justify-start items-start w-full max-w-full"
>
<
MemoFilter
className=
"px-2 pb-2"
/>
{
sortedMemos
.
map
((
memo
)
=>
(
...
...
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