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
e0e59c58
Unverified
Commit
e0e59c58
authored
May 27, 2023
by
boojack
Committed by
GitHub
May 27, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: display memo with updated ts (#1760)
parent
826541a7
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
82 additions
and
47 deletions
+82
-47
memo.go
api/memo.go
+1
-0
system.go
api/system.go
+3
-1
system_setting.go
api/system_setting.go
+9
-15
memo.go
server/memo.go
+21
-1
system.go
server/system.go
+5
-11
DailyMemo.tsx
web/src/components/DailyMemo.tsx
+2
-2
Memo.tsx
web/src/components/Memo.tsx
+3
-3
MemoList.tsx
web/src/components/MemoList.tsx
+3
-3
SystemSection.tsx
web/src/components/Settings/SystemSection.tsx
+19
-0
ShareMemoDialog.tsx
web/src/components/ShareMemoDialog.tsx
+2
-2
filter.ts
web/src/helpers/filter.ts
+2
-2
DailyReview.tsx
web/src/pages/DailyReview.tsx
+5
-5
EmbedMemo.tsx
web/src/pages/EmbedMemo.tsx
+1
-1
Explore.tsx
web/src/pages/Explore.tsx
+1
-1
global.ts
web/src/store/module/global.ts
+1
-0
memo.ts
web/src/store/module/memo.ts
+1
-0
global.ts
web/src/store/reducer/global.ts
+1
-0
memo.d.ts
web/src/types/modules/memo.d.ts
+1
-0
system.d.ts
web/src/types/modules/system.d.ts
+1
-0
No files found.
api/memo.go
View file @
e0e59c58
...
@@ -34,6 +34,7 @@ type MemoResponse struct {
...
@@ -34,6 +34,7 @@ type MemoResponse struct {
UpdatedTs
int64
`json:"updatedTs"`
UpdatedTs
int64
`json:"updatedTs"`
// Domain specific fields
// Domain specific fields
DisplayTs
int64
`json:"displayTs"`
Content
string
`json:"content"`
Content
string
`json:"content"`
Visibility
Visibility
`json:"visibility"`
Visibility
Visibility
`json:"visibility"`
Pinned
bool
`json:"pinned"`
Pinned
bool
`json:"pinned"`
...
...
api/system.go
View file @
e0e59c58
...
@@ -24,6 +24,8 @@ type SystemStatus struct {
...
@@ -24,6 +24,8 @@ type SystemStatus struct {
CustomizedProfile
CustomizedProfile
`json:"customizedProfile"`
CustomizedProfile
CustomizedProfile
`json:"customizedProfile"`
// Storage service ID.
// Storage service ID.
StorageServiceID
int
`json:"storageServiceId"`
StorageServiceID
int
`json:"storageServiceId"`
// Local storage path
// Local storage path
.
LocalStoragePath
string
`json:"localStoragePath"`
LocalStoragePath
string
`json:"localStoragePath"`
// Memo display with updated timestamp.
MemoDisplayWithUpdatedTs
bool
`json:"memoDisplayWithUpdatedTs"`
}
}
api/system_setting.go
View file @
e0e59c58
...
@@ -37,6 +37,7 @@ const (
...
@@ -37,6 +37,7 @@ const (
SystemSettingOpenAIConfigName
SystemSettingName
=
"openai-config"
SystemSettingOpenAIConfigName
SystemSettingName
=
"openai-config"
// SystemSettingTelegramRobotToken is the name of Telegram Robot Token.
// SystemSettingTelegramRobotToken is the name of Telegram Robot Token.
SystemSettingTelegramRobotTokenName
SystemSettingName
=
"telegram-robot-token"
SystemSettingTelegramRobotTokenName
SystemSettingName
=
"telegram-robot-token"
SystemSettingMemoDisplayWithUpdatedTsName
SystemSettingName
=
"memo-display-with-updated-ts"
)
)
// CustomizedProfile is the struct definition for SystemSettingCustomizedProfileName system setting item.
// CustomizedProfile is the struct definition for SystemSettingCustomizedProfileName system setting item.
...
@@ -88,6 +89,8 @@ func (key SystemSettingName) String() string {
...
@@ -88,6 +89,8 @@ func (key SystemSettingName) String() string {
return
"openai-config"
return
"openai-config"
case
SystemSettingTelegramRobotTokenName
:
case
SystemSettingTelegramRobotTokenName
:
return
"telegram-robot-token"
return
"telegram-robot-token"
case
SystemSettingMemoDisplayWithUpdatedTsName
:
return
"memo-display-with-updated-ts"
}
}
return
""
return
""
}
}
...
@@ -111,43 +114,36 @@ func (upsert SystemSettingUpsert) Validate() error {
...
@@ -111,43 +114,36 @@ func (upsert SystemSettingUpsert) Validate() error {
switch
settingName
:=
upsert
.
Name
;
settingName
{
switch
settingName
:=
upsert
.
Name
;
settingName
{
case
SystemSettingServerIDName
:
case
SystemSettingServerIDName
:
return
fmt
.
Errorf
(
"updating %v is not allowed"
,
settingName
)
return
fmt
.
Errorf
(
"updating %v is not allowed"
,
settingName
)
case
SystemSettingAllowSignUpName
:
case
SystemSettingAllowSignUpName
:
var
value
bool
var
value
bool
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
case
SystemSettingIgnoreUpgradeName
:
case
SystemSettingIgnoreUpgradeName
:
var
value
bool
var
value
bool
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
case
SystemSettingDisablePublicMemosName
:
case
SystemSettingDisablePublicMemosName
:
var
value
bool
var
value
bool
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
case
SystemSettingMaxUploadSizeMiBName
:
case
SystemSettingMaxUploadSizeMiBName
:
var
value
int
var
value
int
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
case
SystemSettingAdditionalStyleName
:
case
SystemSettingAdditionalStyleName
:
var
value
string
var
value
string
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
case
SystemSettingAdditionalScriptName
:
case
SystemSettingAdditionalScriptName
:
var
value
string
var
value
string
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
case
SystemSettingCustomizedProfileName
:
case
SystemSettingCustomizedProfileName
:
customizedProfile
:=
CustomizedProfile
{
customizedProfile
:=
CustomizedProfile
{
Name
:
"memos"
,
Name
:
"memos"
,
...
@@ -157,7 +153,6 @@ func (upsert SystemSettingUpsert) Validate() error {
...
@@ -157,7 +153,6 @@ func (upsert SystemSettingUpsert) Validate() error {
Appearance
:
"system"
,
Appearance
:
"system"
,
ExternalURL
:
""
,
ExternalURL
:
""
,
}
}
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
customizedProfile
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
customizedProfile
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
...
@@ -167,26 +162,22 @@ func (upsert SystemSettingUpsert) Validate() error {
...
@@ -167,26 +162,22 @@ func (upsert SystemSettingUpsert) Validate() error {
if
!
slices
.
Contains
(
UserSettingAppearanceValue
,
customizedProfile
.
Appearance
)
{
if
!
slices
.
Contains
(
UserSettingAppearanceValue
,
customizedProfile
.
Appearance
)
{
return
fmt
.
Errorf
(
`invalid appearance value for system setting "%v"`
,
settingName
)
return
fmt
.
Errorf
(
`invalid appearance value for system setting "%v"`
,
settingName
)
}
}
case
SystemSettingStorageServiceIDName
:
case
SystemSettingStorageServiceIDName
:
value
:=
DatabaseStorage
value
:=
DatabaseStorage
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
return
nil
return
nil
case
SystemSettingLocalStoragePathName
:
case
SystemSettingLocalStoragePathName
:
value
:=
""
value
:=
""
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
case
SystemSettingOpenAIConfigName
:
case
SystemSettingOpenAIConfigName
:
value
:=
OpenAIConfig
{}
value
:=
OpenAIConfig
{}
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
case
SystemSettingTelegramRobotTokenName
:
case
SystemSettingTelegramRobotTokenName
:
if
upsert
.
Value
==
""
{
if
upsert
.
Value
==
""
{
return
nil
return
nil
...
@@ -195,11 +186,14 @@ func (upsert SystemSettingUpsert) Validate() error {
...
@@ -195,11 +186,14 @@ func (upsert SystemSettingUpsert) Validate() error {
if
len
(
fragments
)
!=
2
{
if
len
(
fragments
)
!=
2
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
}
case
SystemSettingMemoDisplayWithUpdatedTsName
:
var
value
bool
if
err
:=
json
.
Unmarshal
([]
byte
(
upsert
.
Value
),
&
value
);
err
!=
nil
{
return
fmt
.
Errorf
(
systemSettingUnmarshalError
,
settingName
)
}
default
:
default
:
return
fmt
.
Errorf
(
"invalid system setting name"
)
return
fmt
.
Errorf
(
"invalid system setting name"
)
}
}
return
nil
return
nil
}
}
...
...
server/memo.go
View file @
e0e59c58
...
@@ -609,19 +609,39 @@ func (s *Server) composeMemoMessageToMemoResponse(ctx context.Context, memoMessa
...
@@ -609,19 +609,39 @@ func (s *Server) composeMemoMessageToMemoResponse(ctx context.Context, memoMessa
Pinned
:
memoMessage
.
Pinned
,
Pinned
:
memoMessage
.
Pinned
,
}
}
// Compose creator name.
user
,
err
:=
s
.
Store
.
FindUser
(
ctx
,
&
api
.
UserFind
{
user
,
err
:=
s
.
Store
.
FindUser
(
ctx
,
&
api
.
UserFind
{
ID
:
&
memoResponse
.
CreatorID
,
ID
:
&
memoResponse
.
CreatorID
,
})
})
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
if
user
.
Nickname
!=
""
{
if
user
.
Nickname
!=
""
{
memoResponse
.
CreatorName
=
user
.
Nickname
memoResponse
.
CreatorName
=
user
.
Nickname
}
else
{
}
else
{
memoResponse
.
CreatorName
=
user
.
Username
memoResponse
.
CreatorName
=
user
.
Username
}
}
// Compose display ts.
memoResponse
.
DisplayTs
=
memoResponse
.
CreatedTs
// Find memo display with updated ts setting.
memoDisplayWithUpdatedTsSetting
,
err
:=
s
.
Store
.
FindSystemSetting
(
ctx
,
&
api
.
SystemSettingFind
{
Name
:
api
.
SystemSettingMemoDisplayWithUpdatedTsName
,
})
if
err
!=
nil
&&
common
.
ErrorCode
(
err
)
!=
common
.
NotFound
{
return
nil
,
errors
.
Wrap
(
err
,
"failed to find system setting"
)
}
if
memoDisplayWithUpdatedTsSetting
!=
nil
{
memoDisplayWithUpdatedTs
:=
false
err
=
json
.
Unmarshal
([]
byte
(
memoDisplayWithUpdatedTsSetting
.
Value
),
&
memoDisplayWithUpdatedTs
)
if
err
!=
nil
{
return
nil
,
errors
.
Wrap
(
err
,
"failed to unmarshal system setting value"
)
}
if
memoDisplayWithUpdatedTs
{
memoResponse
.
DisplayTs
=
memoResponse
.
UpdatedTs
}
}
relationList
:=
[]
*
api
.
MemoRelation
{}
relationList
:=
[]
*
api
.
MemoRelation
{}
for
_
,
relation
:=
range
memoMessage
.
RelationList
{
for
_
,
relation
:=
range
memoMessage
.
RelationList
{
relationList
=
append
(
relationList
,
convertMemoRelationMessageToMemoRelation
(
relation
))
relationList
=
append
(
relationList
,
convertMemoRelationMessageToMemoRelation
(
relation
))
...
...
server/system.go
View file @
e0e59c58
...
@@ -57,6 +57,7 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
...
@@ -57,6 +57,7 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
},
},
StorageServiceID
:
api
.
DatabaseStorage
,
StorageServiceID
:
api
.
DatabaseStorage
,
LocalStoragePath
:
"assets/{timestamp}_{filename}"
,
LocalStoragePath
:
"assets/{timestamp}_{filename}"
,
MemoDisplayWithUpdatedTs
:
false
,
}
}
systemSettingList
,
err
:=
s
.
Store
.
FindSystemSettingList
(
ctx
,
&
api
.
SystemSettingFind
{})
systemSettingList
,
err
:=
s
.
Store
.
FindSystemSettingList
(
ctx
,
&
api
.
SystemSettingFind
{})
...
@@ -78,35 +79,28 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
...
@@ -78,35 +79,28 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
switch
systemSetting
.
Name
{
switch
systemSetting
.
Name
{
case
api
.
SystemSettingAllowSignUpName
:
case
api
.
SystemSettingAllowSignUpName
:
systemStatus
.
AllowSignUp
=
baseValue
.
(
bool
)
systemStatus
.
AllowSignUp
=
baseValue
.
(
bool
)
case
api
.
SystemSettingIgnoreUpgradeName
:
case
api
.
SystemSettingIgnoreUpgradeName
:
systemStatus
.
IgnoreUpgrade
=
baseValue
.
(
bool
)
systemStatus
.
IgnoreUpgrade
=
baseValue
.
(
bool
)
case
api
.
SystemSettingDisablePublicMemosName
:
case
api
.
SystemSettingDisablePublicMemosName
:
systemStatus
.
DisablePublicMemos
=
baseValue
.
(
bool
)
systemStatus
.
DisablePublicMemos
=
baseValue
.
(
bool
)
case
api
.
SystemSettingMaxUploadSizeMiBName
:
case
api
.
SystemSettingMaxUploadSizeMiBName
:
systemStatus
.
MaxUploadSizeMiB
=
int
(
baseValue
.
(
float64
))
systemStatus
.
MaxUploadSizeMiB
=
int
(
baseValue
.
(
float64
))
case
api
.
SystemSettingAdditionalStyleName
:
case
api
.
SystemSettingAdditionalStyleName
:
systemStatus
.
AdditionalStyle
=
baseValue
.
(
string
)
systemStatus
.
AdditionalStyle
=
baseValue
.
(
string
)
case
api
.
SystemSettingAdditionalScriptName
:
case
api
.
SystemSettingAdditionalScriptName
:
systemStatus
.
AdditionalScript
=
baseValue
.
(
string
)
systemStatus
.
AdditionalScript
=
baseValue
.
(
string
)
case
api
.
SystemSettingCustomizedProfileName
:
case
api
.
SystemSettingCustomizedProfileName
:
customizedProfile
:=
api
.
CustomizedProfile
{}
customizedProfile
:=
api
.
CustomizedProfile
{}
if
err
:=
json
.
Unmarshal
([]
byte
(
systemSetting
.
Value
),
&
customizedProfile
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
([]
byte
(
systemSetting
.
Value
),
&
customizedProfile
);
err
!=
nil
{
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to unmarshal system setting customized profile value"
)
.
SetInternal
(
err
)
return
echo
.
NewHTTPError
(
http
.
StatusInternalServerError
,
"Failed to unmarshal system setting customized profile value"
)
.
SetInternal
(
err
)
}
}
systemStatus
.
CustomizedProfile
=
customizedProfile
systemStatus
.
CustomizedProfile
=
customizedProfile
case
api
.
SystemSettingStorageServiceIDName
:
case
api
.
SystemSettingStorageServiceIDName
:
systemStatus
.
StorageServiceID
=
int
(
baseValue
.
(
float64
))
systemStatus
.
StorageServiceID
=
int
(
baseValue
.
(
float64
))
case
api
.
SystemSettingLocalStoragePathName
:
case
api
.
SystemSettingLocalStoragePathName
:
systemStatus
.
LocalStoragePath
=
baseValue
.
(
string
)
systemStatus
.
LocalStoragePath
=
baseValue
.
(
string
)
case
api
.
SystemSettingMemoDisplayWithUpdatedTsName
:
systemStatus
.
MemoDisplayWithUpdatedTs
=
baseValue
.
(
bool
)
default
:
default
:
log
.
Warn
(
"Unknown system setting name"
,
zap
.
String
(
"setting name"
,
systemSetting
.
Name
.
String
()))
log
.
Warn
(
"Unknown system setting name"
,
zap
.
String
(
"setting name"
,
systemSetting
.
Name
.
String
()))
}
}
...
...
web/src/components/DailyMemo.tsx
View file @
e0e59c58
...
@@ -9,12 +9,12 @@ interface Props {
...
@@ -9,12 +9,12 @@ interface Props {
const
DailyMemo
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
DailyMemo
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
memo
}
=
props
;
const
{
memo
}
=
props
;
const
createdTimeStr
=
getTimeString
(
memo
.
created
Ts
);
const
displayTimeStr
=
getTimeString
(
memo
.
display
Ts
);
return
(
return
(
<
div
className=
"daily-memo-wrapper"
>
<
div
className=
"daily-memo-wrapper"
>
<
div
className=
"time-wrapper"
>
<
div
className=
"time-wrapper"
>
<
span
className=
"normal-text"
>
{
created
TimeStr
}
</
span
>
<
span
className=
"normal-text"
>
{
display
TimeStr
}
</
span
>
</
div
>
</
div
>
<
div
className=
"memo-container"
>
<
div
className=
"memo-container"
>
<
MemoContent
content=
{
memo
.
content
}
showFull=
{
true
}
/>
<
MemoContent
content=
{
memo
.
content
}
showFull=
{
true
}
/>
...
...
web/src/components/Memo.tsx
View file @
e0e59c58
...
@@ -33,7 +33,7 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -33,7 +33,7 @@ const Memo: React.FC<Props> = (props: Props) => {
const
userStore
=
useUserStore
();
const
userStore
=
useUserStore
();
const
memoStore
=
useMemoStore
();
const
memoStore
=
useMemoStore
();
const
memoCacheStore
=
useMemoCacheStore
();
const
memoCacheStore
=
useMemoCacheStore
();
const
[
createdTimeStr
,
setCreatedTimeStr
]
=
useState
<
string
>
(
getRelativeTimeString
(
memo
.
created
Ts
));
const
[
createdTimeStr
,
setCreatedTimeStr
]
=
useState
<
string
>
(
getRelativeTimeString
(
memo
.
display
Ts
));
const
[
relatedMemoList
,
setRelatedMemoList
]
=
useState
<
Memo
[]
>
([]);
const
[
relatedMemoList
,
setRelatedMemoList
]
=
useState
<
Memo
[]
>
([]);
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
isVisitorMode
=
userStore
.
isVisitorMode
()
||
readonly
;
const
isVisitorMode
=
userStore
.
isVisitorMode
()
||
readonly
;
...
@@ -54,9 +54,9 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -54,9 +54,9 @@ const Memo: React.FC<Props> = (props: Props) => {
useEffect
(()
=>
{
useEffect
(()
=>
{
let
intervalFlag
:
any
=
-
1
;
let
intervalFlag
:
any
=
-
1
;
if
(
Date
.
now
()
-
memo
.
created
Ts
<
1000
*
60
*
60
*
24
)
{
if
(
Date
.
now
()
-
memo
.
display
Ts
<
1000
*
60
*
60
*
24
)
{
intervalFlag
=
setInterval
(()
=>
{
intervalFlag
=
setInterval
(()
=>
{
setCreatedTimeStr
(
getRelativeTimeString
(
memo
.
created
Ts
));
setCreatedTimeStr
(
getRelativeTimeString
(
memo
.
display
Ts
));
},
1000
*
1
);
},
1000
*
1
);
}
}
...
...
web/src/components/MemoList.tsx
View file @
e0e59c58
...
@@ -56,7 +56,7 @@ const MemoList = () => {
...
@@ -56,7 +56,7 @@ const MemoList = () => {
if
(
if
(
duration
&&
duration
&&
duration
.
from
<
duration
.
to
&&
duration
.
from
<
duration
.
to
&&
(
getTimeStampByDate
(
memo
.
createdTs
)
<
duration
.
from
||
getTimeStampByDate
(
memo
.
created
Ts
)
>
duration.to)
(
getTimeStampByDate
(
memo
.
displayTs
)
<
duration
.
from
||
getTimeStampByDate
(
memo
.
display
Ts
)
>
duration.to)
)
{
)
{
shouldShow
=
false
;
shouldShow
=
false
;
}
}
...
@@ -82,7 +82,7 @@ const MemoList = () => {
...
@@ -82,7 +82,7 @@ const MemoList = () => {
const pinnedMemos = shownMemos.filter((m) =
>
m.pinned);
const pinnedMemos = shownMemos.filter((m) =
>
m.pinned);
const unpinnedMemos = shownMemos.filter((m) =
>
!m.pinned);
const unpinnedMemos = shownMemos.filter((m) =
>
!m.pinned);
const memoSort = (mi: Memo, mj: Memo) =
>
{
const memoSort = (mi: Memo, mj: Memo) =
>
{
return
mj
.
createdTs
-
mi
.
created
Ts
;
return
mj
.
displayTs
-
mi
.
display
Ts
;
}
;
}
;
pinnedMemos.sort(memoSort);
pinnedMemos.sort(memoSort);
unpinnedMemos.sort(memoSort);
unpinnedMemos.sort(memoSort);
...
@@ -168,7 +168,7 @@ const MemoList = () => {
...
@@ -168,7 +168,7 @@ const MemoList = () => {
return (
return (
<
div
className=
"memo-list-container"
>
<
div
className=
"memo-list-container"
>
{
sortedMemos
.
map
((
memo
)
=>
(
{
sortedMemos
.
map
((
memo
)
=>
(
<
Memo
key=
{
`${memo.id}-${memo.
created
Ts}`
}
memo=
{
memo
}
/>
<
Memo
key=
{
`${memo.id}-${memo.
display
Ts}`
}
memo=
{
memo
}
/>
))
}
))
}
{
isFetching
?
(
{
isFetching
?
(
<
div
className=
"status-text-container fetching-tip"
>
<
div
className=
"status-text-container fetching-tip"
>
...
...
web/src/components/Settings/SystemSection.tsx
View file @
e0e59c58
...
@@ -17,6 +17,7 @@ interface State {
...
@@ -17,6 +17,7 @@ interface State {
additionalStyle
:
string
;
additionalStyle
:
string
;
additionalScript
:
string
;
additionalScript
:
string
;
maxUploadSizeMiB
:
number
;
maxUploadSizeMiB
:
number
;
memoDisplayWithUpdatedTs
:
boolean
;
}
}
const
SystemSection
=
()
=>
{
const
SystemSection
=
()
=>
{
...
@@ -31,6 +32,7 @@ const SystemSection = () => {
...
@@ -31,6 +32,7 @@ const SystemSection = () => {
additionalScript
:
systemStatus
.
additionalScript
,
additionalScript
:
systemStatus
.
additionalScript
,
disablePublicMemos
:
systemStatus
.
disablePublicMemos
,
disablePublicMemos
:
systemStatus
.
disablePublicMemos
,
maxUploadSizeMiB
:
systemStatus
.
maxUploadSizeMiB
,
maxUploadSizeMiB
:
systemStatus
.
maxUploadSizeMiB
,
memoDisplayWithUpdatedTs
:
systemStatus
.
memoDisplayWithUpdatedTs
,
});
});
const
[
telegramRobotToken
,
setTelegramRobotToken
]
=
useState
<
string
>
(
""
);
const
[
telegramRobotToken
,
setTelegramRobotToken
]
=
useState
<
string
>
(
""
);
const
[
openAIConfig
,
setOpenAIConfig
]
=
useState
<
OpenAIConfig
>
({
const
[
openAIConfig
,
setOpenAIConfig
]
=
useState
<
OpenAIConfig
>
({
...
@@ -65,6 +67,7 @@ const SystemSection = () => {
...
@@ -65,6 +67,7 @@ const SystemSection = () => {
additionalScript
:
systemStatus
.
additionalScript
,
additionalScript
:
systemStatus
.
additionalScript
,
disablePublicMemos
:
systemStatus
.
disablePublicMemos
,
disablePublicMemos
:
systemStatus
.
disablePublicMemos
,
maxUploadSizeMiB
:
systemStatus
.
maxUploadSizeMiB
,
maxUploadSizeMiB
:
systemStatus
.
maxUploadSizeMiB
,
memoDisplayWithUpdatedTs
:
systemStatus
.
memoDisplayWithUpdatedTs
,
});
});
},
[
systemStatus
]);
},
[
systemStatus
]);
...
@@ -202,6 +205,18 @@ const SystemSection = () => {
...
@@ -202,6 +205,18 @@ const SystemSection = () => {
});
});
};
};
const
handleMemoDisplayWithUpdatedTs
=
async
(
value
:
boolean
)
=>
{
setState
({
...
state
,
memoDisplayWithUpdatedTs
:
value
,
});
globalStore
.
setSystemStatus
({
disablePublicMemos
:
value
});
await
api
.
upsertSystemSetting
({
name
:
"memo-display-with-updated-ts"
,
value
:
JSON
.
stringify
(
value
),
});
};
const
handleMaxUploadSizeChanged
=
async
(
event
:
React
.
FocusEvent
<
HTMLInputElement
>
)
=>
{
const
handleMaxUploadSizeChanged
=
async
(
event
:
React
.
FocusEvent
<
HTMLInputElement
>
)
=>
{
// fixes cursor skipping position on mobile
// fixes cursor skipping position on mobile
event
.
target
.
selectionEnd
=
event
.
target
.
value
.
length
;
event
.
target
.
selectionEnd
=
event
.
target
.
value
.
length
;
...
@@ -254,6 +269,10 @@ const SystemSection = () => {
...
@@ -254,6 +269,10 @@ const SystemSection = () => {
<
span
className=
"normal-text"
>
{
t
(
"setting.system-section.disable-public-memos"
)
}
</
span
>
<
span
className=
"normal-text"
>
{
t
(
"setting.system-section.disable-public-memos"
)
}
</
span
>
<
Switch
checked=
{
state
.
disablePublicMemos
}
onChange=
{
(
event
)
=>
handleDisablePublicMemosChanged
(
event
.
target
.
checked
)
}
/>
<
Switch
checked=
{
state
.
disablePublicMemos
}
onChange=
{
(
event
)
=>
handleDisablePublicMemosChanged
(
event
.
target
.
checked
)
}
/>
</
div
>
</
div
>
<
div
className=
"form-label"
>
<
span
className=
"normal-text"
>
Display with updated time
</
span
>
<
Switch
checked=
{
state
.
memoDisplayWithUpdatedTs
}
onChange=
{
(
event
)
=>
handleMemoDisplayWithUpdatedTs
(
event
.
target
.
checked
)
}
/>
</
div
>
<
div
className=
"form-label"
>
<
div
className=
"form-label"
>
<
div
className=
"flex flex-row items-center"
>
<
div
className=
"flex flex-row items-center"
>
<
span
className=
"text-sm mr-1"
>
{
t
(
"setting.system-section.max-upload-size"
)
}
</
span
>
<
span
className=
"text-sm mr-1"
>
{
t
(
"setting.system-section.max-upload-size"
)
}
</
span
>
...
...
web/src/components/ShareMemoDialog.tsx
View file @
e0e59c58
...
@@ -46,7 +46,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
...
@@ -46,7 +46,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
const
memoElRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
memoElRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
memo
=
{
const
memo
=
{
...
propsMemo
,
...
propsMemo
,
createdAtStr
:
getDateTimeString
(
propsMemo
.
created
Ts
),
displayTsStr
:
getDateTimeString
(
propsMemo
.
display
Ts
),
};
};
const
createdDays
=
Math
.
ceil
((
Date
.
now
()
-
getTimeStampByDate
(
user
.
createdTs
))
/
1000
/
3600
/
24
);
const
createdDays
=
Math
.
ceil
((
Date
.
now
()
-
getTimeStampByDate
(
user
.
createdTs
))
/
1000
/
3600
/
24
);
...
@@ -174,7 +174,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
...
@@ -174,7 +174,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
className=
"w-full h-auto select-none relative flex flex-col justify-start items-start bg-white dark:bg-zinc-800"
className=
"w-full h-auto select-none relative flex flex-col justify-start items-start bg-white dark:bg-zinc-800"
ref=
{
memoElRef
}
ref=
{
memoElRef
}
>
>
<
span
className=
"w-full px-6 pt-5 pb-2 text-sm text-gray-500"
>
{
memo
.
createdAt
Str
}
</
span
>
<
span
className=
"w-full px-6 pt-5 pb-2 text-sm text-gray-500"
>
{
memo
.
displayTs
Str
}
</
span
>
<
div
className=
"w-full px-6 text-base pb-4"
>
<
div
className=
"w-full px-6 text-base pb-4"
>
<
MemoContent
content=
{
memo
.
content
}
showFull=
{
true
}
/>
<
MemoContent
content=
{
memo
.
content
}
showFull=
{
true
}
/>
<
MemoResourceListView
className=
"!grid-cols-2"
resourceList=
{
memo
.
resourceList
}
/>
<
MemoResourceListView
className=
"!grid-cols-2"
resourceList=
{
memo
.
resourceList
}
/>
...
...
web/src/helpers/filter.ts
View file @
e0e59c58
...
@@ -203,9 +203,9 @@ export const checkShouldShowMemo = (memo: Memo, filter: Filter) => {
...
@@ -203,9 +203,9 @@ export const checkShouldShowMemo = (memo: Memo, filter: Filter) => {
}
}
}
else
if
(
type
===
"DISPLAY_TIME"
)
{
}
else
if
(
type
===
"DISPLAY_TIME"
)
{
if
(
operator
===
"BEFORE"
)
{
if
(
operator
===
"BEFORE"
)
{
return
memo
.
created
Ts
<
getUnixTimeMillis
(
value
);
return
memo
.
display
Ts
<
getUnixTimeMillis
(
value
);
}
else
{
}
else
{
return
memo
.
created
Ts
>=
getUnixTimeMillis
(
value
);
return
memo
.
display
Ts
>=
getUnixTimeMillis
(
value
);
}
}
}
else
if
(
type
===
"VISIBILITY"
)
{
}
else
if
(
type
===
"VISIBILITY"
)
{
let
matched
=
memo
.
visibility
===
value
;
let
matched
=
memo
.
visibility
===
value
;
...
...
web/src/pages/DailyReview.tsx
View file @
e0e59c58
...
@@ -28,15 +28,15 @@ const DailyReview = () => {
...
@@ -28,15 +28,15 @@ const DailyReview = () => {
const
currentDate
=
new
Date
(
currentDateStamp
);
const
currentDate
=
new
Date
(
currentDateStamp
);
const
dailyMemos
=
memos
const
dailyMemos
=
memos
.
filter
((
m
)
=>
{
.
filter
((
m
)
=>
{
const
createdTimestamp
=
getTimeStampByDate
(
m
.
created
Ts
);
const
displayTimestamp
=
getTimeStampByDate
(
m
.
display
Ts
);
const
currentDateStampWithOffset
=
currentDateStamp
+
convertToMillis
(
localSetting
);
const
currentDateStampWithOffset
=
currentDateStamp
+
convertToMillis
(
localSetting
);
return
(
return
(
m
.
rowStatus
===
"NORMAL"
&&
m
.
rowStatus
===
"NORMAL"
&&
created
Timestamp
>=
currentDateStampWithOffset
&&
display
Timestamp
>=
currentDateStampWithOffset
&&
created
Timestamp
<
currentDateStampWithOffset
+
DAILY_TIMESTAMP
display
Timestamp
<
currentDateStampWithOffset
+
DAILY_TIMESTAMP
);
);
})
})
.
sort
((
a
,
b
)
=>
getTimeStampByDate
(
a
.
createdTs
)
-
getTimeStampByDate
(
b
.
created
Ts
));
.
sort
((
a
,
b
)
=>
getTimeStampByDate
(
a
.
displayTs
)
-
getTimeStampByDate
(
b
.
display
Ts
));
useEffect
(()
=>
{
useEffect
(()
=>
{
let
offset
=
0
;
let
offset
=
0
;
...
@@ -46,7 +46,7 @@ const DailyReview = () => {
...
@@ -46,7 +46,7 @@ const DailyReview = () => {
offset
+=
fetchedMemos
.
length
;
offset
+=
fetchedMemos
.
length
;
if
(
fetchedMemos
.
length
===
DEFAULT_MEMO_LIMIT
)
{
if
(
fetchedMemos
.
length
===
DEFAULT_MEMO_LIMIT
)
{
const
lastMemo
=
last
(
fetchedMemos
);
const
lastMemo
=
last
(
fetchedMemos
);
if
(
lastMemo
&&
lastMemo
.
created
Ts
>
currentDateStamp
)
{
if
(
lastMemo
&&
lastMemo
.
display
Ts
>
currentDateStamp
)
{
await
fetchMoreMemos
();
await
fetchMoreMemos
();
}
}
}
}
...
...
web/src/pages/EmbedMemo.tsx
View file @
e0e59c58
...
@@ -45,7 +45,7 @@ const EmbedMemo = () => {
...
@@ -45,7 +45,7 @@ const EmbedMemo = () => {
<
main
className=
"w-full max-w-lg mx-auto my-auto shadow px-4 py-4 rounded-lg"
>
<
main
className=
"w-full max-w-lg mx-auto my-auto shadow px-4 py-4 rounded-lg"
>
<
div
className=
"w-full flex flex-col justify-start items-start"
>
<
div
className=
"w-full flex flex-col justify-start items-start"
>
<
div
className=
"w-full mb-2 flex flex-row justify-start items-center text-sm text-gray-400 dark:text-gray-300"
>
<
div
className=
"w-full mb-2 flex flex-row justify-start items-center text-sm text-gray-400 dark:text-gray-300"
>
<
span
>
{
getDateTimeString
(
state
.
memo
.
created
Ts
)
}
</
span
>
<
span
>
{
getDateTimeString
(
state
.
memo
.
display
Ts
)
}
</
span
>
<
a
className=
"ml-2 hover:underline hover:text-green-600"
href=
{
`/u/${state.memo.creatorId}`
}
>
<
a
className=
"ml-2 hover:underline hover:text-green-600"
href=
{
`/u/${state.memo.creatorId}`
}
>
@
{
state
.
memo
.
creatorName
}
@
{
state
.
memo
.
creatorName
}
</
a
>
</
a
>
...
...
web/src/pages/Explore.tsx
View file @
e0e59c58
...
@@ -90,7 +90,7 @@ const Explore = () => {
...
@@ -90,7 +90,7 @@ const Explore = () => {
<
main
className=
"relative w-full h-auto flex flex-col justify-start items-start -mt-2"
>
<
main
className=
"relative w-full h-auto flex flex-col justify-start items-start -mt-2"
>
<
MemoFilter
/>
<
MemoFilter
/>
{
sortedMemos
.
map
((
memo
)
=>
{
{
sortedMemos
.
map
((
memo
)
=>
{
return
<
Memo
key=
{
`${memo.id}-${memo.
created
Ts}`
}
memo=
{
memo
}
readonly=
{
true
}
/>;
return
<
Memo
key=
{
`${memo.id}-${memo.
display
Ts}`
}
memo=
{
memo
}
readonly=
{
true
}
/>;
})
}
})
}
{
isComplete
?
(
{
isComplete
?
(
state
.
memos
.
length
===
0
?
(
state
.
memos
.
length
===
0
?
(
...
...
web/src/store/module/global.ts
View file @
e0e59c58
...
@@ -16,6 +16,7 @@ export const initialGlobalState = async () => {
...
@@ -16,6 +16,7 @@ export const initialGlobalState = async () => {
maxUploadSizeMiB
:
0
,
maxUploadSizeMiB
:
0
,
additionalStyle
:
""
,
additionalStyle
:
""
,
additionalScript
:
""
,
additionalScript
:
""
,
memoDisplayWithUpdatedTs
:
false
,
customizedProfile
:
{
customizedProfile
:
{
name
:
"memos"
,
name
:
"memos"
,
logoUrl
:
"/logo.webp"
,
logoUrl
:
"/logo.webp"
,
...
...
web/src/store/module/memo.ts
View file @
e0e59c58
...
@@ -11,6 +11,7 @@ export const convertResponseModelMemo = (memo: Memo): Memo => {
...
@@ -11,6 +11,7 @@ export const convertResponseModelMemo = (memo: Memo): Memo => {
...
memo
,
...
memo
,
createdTs
:
memo
.
createdTs
*
1000
,
createdTs
:
memo
.
createdTs
*
1000
,
updatedTs
:
memo
.
updatedTs
*
1000
,
updatedTs
:
memo
.
updatedTs
*
1000
,
displayTs
:
memo
.
displayTs
*
1000
,
};
};
};
};
...
...
web/src/store/reducer/global.ts
View file @
e0e59c58
...
@@ -23,6 +23,7 @@ const globalSlice = createSlice({
...
@@ -23,6 +23,7 @@ const globalSlice = createSlice({
disablePublicMemos
:
false
,
disablePublicMemos
:
false
,
additionalStyle
:
""
,
additionalStyle
:
""
,
additionalScript
:
""
,
additionalScript
:
""
,
memoDisplayWithUpdatedTs
:
false
,
customizedProfile
:
{
customizedProfile
:
{
name
:
"memos"
,
name
:
"memos"
,
logoUrl
:
"/logo.webp"
,
logoUrl
:
"/logo.webp"
,
...
...
web/src/types/modules/memo.d.ts
View file @
e0e59c58
...
@@ -10,6 +10,7 @@ interface Memo {
...
@@ -10,6 +10,7 @@ interface Memo {
updatedTs
:
TimeStamp
;
updatedTs
:
TimeStamp
;
rowStatus
:
RowStatus
;
rowStatus
:
RowStatus
;
displayTs
:
TimeStamp
;
content
:
string
;
content
:
string
;
visibility
:
Visibility
;
visibility
:
Visibility
;
pinned
:
boolean
;
pinned
:
boolean
;
...
...
web/src/types/modules/system.d.ts
View file @
e0e59c58
...
@@ -31,6 +31,7 @@ interface SystemStatus {
...
@@ -31,6 +31,7 @@ interface SystemStatus {
customizedProfile
:
CustomizedProfile
;
customizedProfile
:
CustomizedProfile
;
storageServiceId
:
number
;
storageServiceId
:
number
;
localStoragePath
:
string
;
localStoragePath
:
string
;
memoDisplayWithUpdatedTs
:
boolean
;
}
}
interface
SystemSetting
{
interface
SystemSetting
{
...
...
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