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
ab8e3473
Unverified
Commit
ab8e3473
authored
Nov 29, 2022
by
Zeng1998
Committed by
GitHub
Nov 29, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: support resources reuse (#620)
* feat: support resource reuse * update * update * update * update
parent
eba23c4f
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
312 additions
and
52 deletions
+312
-52
MemoEditor.tsx
web/src/components/MemoEditor.tsx
+25
-45
ResourcesSelectorDialog.tsx
web/src/components/ResourcesSelectorDialog.tsx
+155
-0
memo-editor.less
web/src/less/memo-editor.less
+24
-0
resources-selector-dialog.less
web/src/less/resources-selector-dialog.less
+75
-0
en.json
web/src/locales/en.json
+3
-1
fr.json
web/src/locales/fr.json
+3
-1
vi.json
web/src/locales/vi.json
+3
-1
zh.json
web/src/locales/zh.json
+3
-1
editorStateService.ts
web/src/services/editorStateService.ts
+9
-1
editor.ts
web/src/store/modules/editor.ts
+12
-2
No files found.
web/src/components/MemoEditor.tsx
View file @
ab8e3473
...
@@ -13,6 +13,7 @@ import Selector from "./common/Selector";
...
@@ -13,6 +13,7 @@ import Selector from "./common/Selector";
import
Editor
,
{
EditorRefActions
}
from
"./Editor/Editor"
;
import
Editor
,
{
EditorRefActions
}
from
"./Editor/Editor"
;
import
EmojiPicker
from
"./Editor/EmojiPicker"
;
import
EmojiPicker
from
"./Editor/EmojiPicker"
;
import
ResourceIcon
from
"./ResourceIcon"
;
import
ResourceIcon
from
"./ResourceIcon"
;
import
showResourcesSelectorDialog
from
"./ResourcesSelectorDialog"
;
import
"../less/memo-editor.less"
;
import
"../less/memo-editor.less"
;
const
getEditorContentCache
=
():
string
=>
{
const
getEditorContentCache
=
():
string
=>
{
...
@@ -34,7 +35,6 @@ const setEditingMemoVisibilityCache = (visibility: Visibility) => {
...
@@ -34,7 +35,6 @@ const setEditingMemoVisibilityCache = (visibility: Visibility) => {
interface
State
{
interface
State
{
fullscreen
:
boolean
;
fullscreen
:
boolean
;
isUploadingResource
:
boolean
;
isUploadingResource
:
boolean
;
resourceList
:
Resource
[];
shouldShowEmojiPicker
:
boolean
;
shouldShowEmojiPicker
:
boolean
;
}
}
...
@@ -48,7 +48,6 @@ const MemoEditor = () => {
...
@@ -48,7 +48,6 @@ const MemoEditor = () => {
isUploadingResource
:
false
,
isUploadingResource
:
false
,
fullscreen
:
false
,
fullscreen
:
false
,
shouldShowEmojiPicker
:
false
,
shouldShowEmojiPicker
:
false
,
resourceList
:
[],
});
});
const
[
allowSave
,
setAllowSave
]
=
useState
<
boolean
>
(
false
);
const
[
allowSave
,
setAllowSave
]
=
useState
<
boolean
>
(
false
);
const
prevGlobalStateRef
=
useRef
(
editorState
);
const
prevGlobalStateRef
=
useRef
(
editorState
);
...
@@ -79,13 +78,8 @@ const MemoEditor = () => {
...
@@ -79,13 +78,8 @@ const MemoEditor = () => {
if
(
memo
)
{
if
(
memo
)
{
handleEditorFocus
();
handleEditorFocus
();
editorStateService
.
setMemoVisibility
(
memo
.
visibility
);
editorStateService
.
setMemoVisibility
(
memo
.
visibility
);
editorStateService
.
setResourceList
(
memo
.
resourceList
);
editorRef
.
current
?.
setContent
(
memo
.
content
??
""
);
editorRef
.
current
?.
setContent
(
memo
.
content
??
""
);
setState
((
state
)
=>
{
return
{
...
state
,
resourceList
:
memo
.
resourceList
,
};
});
}
}
});
});
storage
.
set
({
storage
.
set
({
...
@@ -148,12 +142,7 @@ const MemoEditor = () => {
...
@@ -148,12 +142,7 @@ const MemoEditor = () => {
}
}
}
}
}
}
setState
((
state
)
=>
{
editorStateService
.
setResourceList
([...
editorState
.
resourceList
,
...
resourceList
]);
return
{
...
state
,
resourceList
:
[...
state
.
resourceList
,
...
resourceList
],
};
});
}
}
};
};
...
@@ -163,12 +152,7 @@ const MemoEditor = () => {
...
@@ -163,12 +152,7 @@ const MemoEditor = () => {
const
file
=
event
.
clipboardData
.
files
[
0
];
const
file
=
event
.
clipboardData
.
files
[
0
];
const
resource
=
await
handleUploadResource
(
file
);
const
resource
=
await
handleUploadResource
(
file
);
if
(
resource
)
{
if
(
resource
)
{
setState
((
state
)
=>
{
editorStateService
.
setResourceList
([...
editorState
.
resourceList
,
resource
]);
return
{
...
state
,
resourceList
:
[...
state
.
resourceList
,
resource
],
};
});
}
}
}
}
};
};
...
@@ -216,7 +200,7 @@ const MemoEditor = () => {
...
@@ -216,7 +200,7 @@ const MemoEditor = () => {
id
:
prevMemo
.
id
,
id
:
prevMemo
.
id
,
content
,
content
,
visibility
:
editorState
.
memoVisibility
,
visibility
:
editorState
.
memoVisibility
,
resourceIdList
:
s
tate
.
resourceList
.
map
((
resource
)
=>
resource
.
id
),
resourceIdList
:
editorS
tate
.
resourceList
.
map
((
resource
)
=>
resource
.
id
),
});
});
}
}
editorStateService
.
clearEditMemo
();
editorStateService
.
clearEditMemo
();
...
@@ -224,7 +208,7 @@ const MemoEditor = () => {
...
@@ -224,7 +208,7 @@ const MemoEditor = () => {
await
memoService
.
createMemo
({
await
memoService
.
createMemo
({
content
,
content
,
visibility
:
editorState
.
memoVisibility
,
visibility
:
editorState
.
memoVisibility
,
resourceIdList
:
s
tate
.
resourceList
.
map
((
resource
)
=>
resource
.
id
),
resourceIdList
:
editorS
tate
.
resourceList
.
map
((
resource
)
=>
resource
.
id
),
});
});
locationService
.
clearQuery
();
locationService
.
clearQuery
();
}
}
...
@@ -237,20 +221,17 @@ const MemoEditor = () => {
...
@@ -237,20 +221,17 @@ const MemoEditor = () => {
return
{
return
{
...
state
,
...
state
,
fullscreen
:
false
,
fullscreen
:
false
,
resourceList
:
[],
};
};
});
});
editorStateService
.
clearResourceList
();
setEditorContentCache
(
""
);
setEditorContentCache
(
""
);
storage
.
remove
([
"editingMemoVisibilityCache"
]);
storage
.
remove
([
"editingMemoVisibilityCache"
]);
editorRef
.
current
?.
setContent
(
""
);
editorRef
.
current
?.
setContent
(
""
);
};
};
const
handleCancelEdit
=
()
=>
{
const
handleCancelEdit
=
()
=>
{
setState
({
...
state
,
resourceList
:
[],
});
editorStateService
.
clearEditMemo
();
editorStateService
.
clearEditMemo
();
editorStateService
.
clearResourceList
();
editorRef
.
current
?.
setContent
(
""
);
editorRef
.
current
?.
setContent
(
""
);
setEditorContentCache
(
""
);
setEditorContentCache
(
""
);
storage
.
remove
([
"editingMemoVisibilityCache"
]);
storage
.
remove
([
"editingMemoVisibilityCache"
]);
...
@@ -317,12 +298,7 @@ const MemoEditor = () => {
...
@@ -317,12 +298,7 @@ const MemoEditor = () => {
}
}
}
}
}
}
setState
((
state
)
=>
{
editorStateService
.
setResourceList
([...
editorState
.
resourceList
,
...
resourceList
]);
return
{
...
state
,
resourceList
:
[...
state
.
resourceList
,
...
resourceList
],
};
});
document
.
body
.
removeChild
(
inputEl
);
document
.
body
.
removeChild
(
inputEl
);
};
};
inputEl
.
click
();
inputEl
.
click
();
...
@@ -361,13 +337,7 @@ const MemoEditor = () => {
...
@@ -361,13 +337,7 @@ const MemoEditor = () => {
};
};
const
handleDeleteResource
=
async
(
resourceId
:
ResourceId
)
=>
{
const
handleDeleteResource
=
async
(
resourceId
:
ResourceId
)
=>
{
setState
((
state
)
=>
{
editorStateService
.
setResourceList
(
editorState
.
resourceList
.
filter
((
resource
)
=>
resource
.
id
!==
resourceId
));
return
{
...
state
,
resourceList
:
state
.
resourceList
.
filter
((
resource
)
=>
resource
.
id
!==
resourceId
),
};
});
if
(
editorState
.
editMemoId
)
{
if
(
editorState
.
editMemoId
)
{
await
deleteMemoResource
(
editorState
.
editMemoId
,
resourceId
);
await
deleteMemoResource
(
editorState
.
editMemoId
,
resourceId
);
}
}
...
@@ -440,10 +410,20 @@ const MemoEditor = () => {
...
@@ -440,10 +410,20 @@ const MemoEditor = () => {
<
button
className=
"action-btn"
>
<
button
className=
"action-btn"
>
<
Icon
.
Code
className=
"icon-img"
onClick=
{
handleCodeBlockBtnClick
}
/>
<
Icon
.
Code
className=
"icon-img"
onClick=
{
handleCodeBlockBtnClick
}
/>
</
button
>
</
button
>
<
button
className=
"action
-btn"
>
<
div
className=
"action-btn resource
-btn"
>
<
Icon
.
FileText
className=
"icon-img"
onClick=
{
handleUploadFileBtnClick
}
/>
<
Icon
.
FileText
className=
"icon-img"
/>
<
span
className=
{
`tip-text ${state.isUploadingResource ? "!block" : ""}`
}
>
Uploading
</
span
>
<
span
className=
{
`tip-text ${state.isUploadingResource ? "!block" : ""}`
}
>
Uploading
</
span
>
</
button
>
<
div
className=
"resource-action-list"
>
<
div
className=
"resource-action-item"
onClick=
{
handleUploadFileBtnClick
}
>
<
Icon
.
Upload
className=
"icon-img"
/>
<
span
>
{
t
(
"editor.local"
)
}
</
span
>
</
div
>
<
div
className=
"resource-action-item"
onClick=
{
showResourcesSelectorDialog
}
>
<
Icon
.
Database
className=
"icon-img"
/>
<
span
>
{
t
(
"editor.resources"
)
}
</
span
>
</
div
>
</
div
>
</
div
>
<
button
className=
"action-btn"
onClick=
{
handleFullscreenBtnClick
}
>
<
button
className=
"action-btn"
onClick=
{
handleFullscreenBtnClick
}
>
{
state
.
fullscreen
?
<
Icon
.
Minimize
className=
"icon-img"
/>
:
<
Icon
.
Maximize
className=
"icon-img"
/>
}
{
state
.
fullscreen
?
<
Icon
.
Minimize
className=
"icon-img"
/>
:
<
Icon
.
Maximize
className=
"icon-img"
/>
}
</
button
>
</
button
>
...
@@ -454,9 +434,9 @@ const MemoEditor = () => {
...
@@ -454,9 +434,9 @@ const MemoEditor = () => {
/>
/>
</
div
>
</
div
>
</
div
>
</
div
>
{
s
tate
.
resourceList
.
length
>
0
&&
(
{
editorState
.
resourceList
&&
editorS
tate
.
resourceList
.
length
>
0
&&
(
<
div
className=
"resource-list-wrapper"
>
<
div
className=
"resource-list-wrapper"
>
{
s
tate
.
resourceList
.
map
((
resource
)
=>
{
{
editorS
tate
.
resourceList
.
map
((
resource
)
=>
{
return
(
return
(
<
div
key=
{
resource
.
id
}
className=
"resource-container"
>
<
div
key=
{
resource
.
id
}
className=
"resource-container"
>
<
ResourceIcon
resourceType=
"resource.type"
className=
"icon-img"
/>
<
ResourceIcon
resourceType=
"resource.type"
className=
"icon-img"
/>
...
...
web/src/components/ResourcesSelectorDialog.tsx
0 → 100644
View file @
ab8e3473
import
{
Checkbox
,
Tooltip
}
from
"@mui/joy"
;
import
{
useCallback
,
useEffect
,
useState
}
from
"react"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
useLoading
from
"../hooks/useLoading"
;
import
{
editorStateService
,
resourceService
}
from
"../services"
;
import
{
useAppSelector
}
from
"../store"
;
import
Icon
from
"./Icon"
;
import
toastHelper
from
"./Toast"
;
import
{
generateDialog
}
from
"./Dialog"
;
import
showPreviewImageDialog
from
"./PreviewImageDialog"
;
import
"../less/resources-selector-dialog.less"
;
type
Props
=
DialogProps
;
interface
State
{
checkedArray
:
boolean
[];
}
const
ResourcesSelectorDialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
destroy
}
=
props
;
const
{
t
}
=
useTranslation
();
const
loadingState
=
useLoading
();
const
{
resources
}
=
useAppSelector
((
state
)
=>
state
.
resource
);
const
editorState
=
useAppSelector
((
state
)
=>
state
.
editor
);
const
[
state
,
setState
]
=
useState
<
State
>
({
checkedArray
:
[],
});
useEffect
(()
=>
{
resourceService
.
fetchResourceList
()
.
catch
((
error
)
=>
{
console
.
error
(
error
);
toastHelper
.
error
(
error
.
response
.
data
.
message
);
})
.
finally
(()
=>
{
loadingState
.
setFinish
();
});
},
[]);
useEffect
(()
=>
{
const
checkedResourceIdArray
=
editorState
.
resourceList
.
map
((
resource
)
=>
resource
.
id
);
setState
({
checkedArray
:
resources
.
map
((
resource
)
=>
{
return
checkedResourceIdArray
.
includes
(
resource
.
id
);
}),
});
},
[
resources
]);
const
getResourceUrl
=
useCallback
((
resource
:
Resource
)
=>
{
return
`
${
window
.
location
.
origin
}
/o/r/
${
resource
.
id
}
/
${
resource
.
filename
}
`
;
},
[]);
const
handlePreviewBtnClick
=
(
resource
:
Resource
)
=>
{
const
resourceUrl
=
getResourceUrl
(
resource
);
if
(
resource
.
type
.
startsWith
(
"image"
))
{
showPreviewImageDialog
(
resources
.
filter
((
r
)
=>
r
.
type
.
startsWith
(
"image"
)).
map
((
r
)
=>
getResourceUrl
(
r
)),
resources
.
findIndex
((
r
)
=>
r
.
id
===
resource
.
id
)
);
}
else
{
window
.
open
(
resourceUrl
);
}
};
const
handleCheckboxChange
=
(
index
:
number
)
=>
{
const
newCheckedArr
=
state
.
checkedArray
;
newCheckedArr
[
index
]
=
!
newCheckedArr
[
index
];
setState
({
checkedArray
:
newCheckedArr
,
});
};
const
handleConfirmBtnClick
=
()
=>
{
const
resourceList
=
resources
.
filter
((
_
,
index
)
=>
{
return
state
.
checkedArray
[
index
];
});
editorStateService
.
setResourceList
(
resourceList
);
destroy
();
};
return
(
<>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
<
span
className=
"icon-text"
>
🌄
</
span
>
{
t
(
"sidebar.resources"
)
}
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
destroy
}
>
<
Icon
.
X
className=
"icon-img"
/>
</
button
>
</
div
>
<
div
className=
"dialog-content-container"
>
{
loadingState
.
isLoading
?
(
<
div
className=
"loading-text-container"
>
<
p
className=
"tip-text"
>
{
t
(
"resources.fetching-data"
)
}
</
p
>
</
div
>
)
:
(
<
div
className=
"resource-table-container"
>
<
div
className=
"fields-container"
>
<
span
className=
"field-text id-text"
>
ID
</
span
>
<
span
className=
"field-text name-text"
>
NAME
</
span
>
<
span
></
span
>
</
div
>
{
resources
.
length
===
0
?
(
<
p
className=
"tip-text"
>
{
t
(
"resources.no-resources"
)
}
</
p
>
)
:
(
resources
.
map
((
resource
,
index
)
=>
(
<
div
key=
{
resource
.
id
}
className=
"resource-container"
>
<
span
className=
"field-text id-text"
>
{
resource
.
id
}
</
span
>
<
Tooltip
title=
{
resource
.
filename
}
>
<
span
className=
"field-text name-text"
>
{
resource
.
filename
}
</
span
>
</
Tooltip
>
<
div
className=
"flex justify-end"
>
<
Icon
.
Eye
className=
" text-left text-sm leading-6 px-1 mr-2 cursor-pointer hover:bg-gray-100"
onClick=
{
()
=>
handlePreviewBtnClick
(
resource
)
}
>
{
t
(
"resources.preview"
)
}
</
Icon
.
Eye
>
<
Checkbox
checked=
{
state
.
checkedArray
[
index
]
}
onChange=
{
()
=>
handleCheckboxChange
(
index
)
}
/>
</
div
>
</
div
>
))
)
}
</
div
>
)
}
<
div
className=
"flex justify-between w-full mt-2 px-2"
>
<
span
className=
"text-sm font-mono text-gray-500 leading-8"
>
{
t
(
"message.count-selected-resources"
)
}
:
{
state
.
checkedArray
.
filter
((
checked
)
=>
checked
).
length
}
</
span
>
<
div
className=
"flex flex-row justify-start items-center"
>
<
div
className=
"text-sm cursor-pointer px-3 py-1 rounded flex flex-row justify-center items-center border border-blue-600 text-blue-600 bg-blue-50 hover:opacity-80"
onClick=
{
handleConfirmBtnClick
}
>
<
Icon
.
PlusSquare
className=
" w-4 h-auto mr-1"
/>
<
span
>
{
t
(
"common.confirm"
)
}
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
</>
);
};
export
default
function
showResourcesSelectorDialog
()
{
generateDialog
(
{
className
:
"resources-selector-dialog"
,
},
ResourcesSelectorDialog
,
{}
);
}
web/src/less/memo-editor.less
View file @
ab8e3473
...
@@ -67,6 +67,30 @@
...
@@ -67,6 +67,30 @@
}
}
}
}
&.resource-btn{
@apply relative ;
&:hover {
> .resource-action-list {
@apply flex;
}
}
>.resource-action-list{
@apply hidden flex-col justify-start items-start absolute top-6 left-0 mt-1 p-1 z-1 rounded w-36 max-h-52 overflow-auto font-mono bg-zinc-100;
>.resource-action-item{
@apply w-full flex text-black cursor-pointer rounded text-sm leading-6 px-2 truncate hover:bg-zinc-300 shrink-0;
>.icon-img{
@apply w-4 mr-2;
}
}
}
}
> .icon-img {
> .icon-img {
@apply w-5 h-5 mx-auto flex flex-row justify-center items-center;
@apply w-5 h-5 mx-auto flex flex-row justify-center items-center;
}
}
...
...
web/src/less/resources-selector-dialog.less
0 → 100644
View file @
ab8e3473
.resources-selector-dialog {
@apply px-4;
> .dialog-container {
@apply w-112 max-w-full mb-8;
> .dialog-content-container {
@apply flex flex-col justify-start items-start w-full;
> .action-buttons-container {
@apply w-full flex flex-row justify-between items-center mb-2;
> .buttons-wrapper {
@apply flex flex-row justify-start items-center;
> .upload-resource-btn {
@apply text-sm cursor-pointer px-3 py-1 rounded flex flex-row justify-center items-center border border-blue-600 text-blue-600 bg-blue-50 hover:opacity-80;
> .icon-img {
@apply w-4 h-auto mr-1;
}
}
> .delete-unused-resource-btn {
@apply text-sm cursor-pointer px-3 py-1 rounded flex flex-row justify-center items-center border border-red-600 text-red-600 bg-red-100 hover:opacity-80;
> .icon-img {
@apply w-4 h-auto mr-1;
}
}
}
}
> .loading-text-container {
@apply flex flex-col justify-center items-center w-full h-32;
}
> .resource-table-container {
@apply flex flex-col justify-start items-start w-full;
> .fields-container {
@apply px-2 py-2 w-full grid grid-cols-7 border-b;
> .field-text {
@apply font-mono text-gray-400;
}
}
> .tip-text {
@apply w-full text-center text-base my-6 mt-8;
}
> .resource-container {
@apply px-2 py-2 w-full grid grid-cols-7;
> .buttons-container {
@apply w-full flex flex-row justify-end items-center;
}
}
.field-text {
@apply w-full truncate text-base pr-2 last:pr-0;
&.id-text {
@apply col-span-2;
}
&.name-text {
@apply col-span-4;
}
}
}
}
}
}
web/src/locales/en.json
View file @
ab8e3473
...
@@ -88,7 +88,9 @@
...
@@ -88,7 +88,9 @@
"save"
:
"Save"
,
"save"
:
"Save"
,
"placeholder"
:
"Any thoughts..."
,
"placeholder"
:
"Any thoughts..."
,
"only-image-supported"
:
"Only image file supported."
,
"only-image-supported"
:
"Only image file supported."
,
"cant-empty"
:
"Content can't be empty"
"cant-empty"
:
"Content can't be empty"
,
"local"
:
"Local"
,
"resources"
:
"Resources"
},
},
"memo"
:
{
"memo"
:
{
"view-detail"
:
"View Detail"
,
"view-detail"
:
"View Detail"
,
...
...
web/src/locales/fr.json
View file @
ab8e3473
...
@@ -88,7 +88,9 @@
...
@@ -88,7 +88,9 @@
"save"
:
"Sauvegarder"
,
"save"
:
"Sauvegarder"
,
"placeholder"
:
"Une idée..."
,
"placeholder"
:
"Une idée..."
,
"only-image-supported"
:
"Seul le fichier image est pris en charge."
,
"only-image-supported"
:
"Seul le fichier image est pris en charge."
,
"cant-empty"
:
"Le contenu ne doit pas être vide"
"cant-empty"
:
"Le contenu ne doit pas être vide"
,
"local"
:
"Local"
,
"resources"
:
"Resources"
},
},
"memo"
:
{
"memo"
:
{
"view-detail"
:
"Voir le détail"
,
"view-detail"
:
"Voir le détail"
,
...
...
web/src/locales/vi.json
View file @
ab8e3473
...
@@ -88,7 +88,9 @@
...
@@ -88,7 +88,9 @@
"save"
:
"Lưu"
,
"save"
:
"Lưu"
,
"placeholder"
:
"Bất cứ gì bạn đang nghĩ..."
,
"placeholder"
:
"Bất cứ gì bạn đang nghĩ..."
,
"only-image-supported"
:
"Chỉ hỗ trợ hình ảnh."
,
"only-image-supported"
:
"Chỉ hỗ trợ hình ảnh."
,
"cant-empty"
:
"Nội dung không thể trống"
"cant-empty"
:
"Nội dung không thể trống"
,
"local"
:
"Local"
,
"resources"
:
"Resources"
},
},
"memo"
:
{
"memo"
:
{
"view-detail"
:
"Xem chi tiết"
,
"view-detail"
:
"Xem chi tiết"
,
...
...
web/src/locales/zh.json
View file @
ab8e3473
...
@@ -88,7 +88,9 @@
...
@@ -88,7 +88,9 @@
"save"
:
"记下"
,
"save"
:
"记下"
,
"placeholder"
:
"现在的想法是..."
,
"placeholder"
:
"现在的想法是..."
,
"only-image-supported"
:
"仅支持图片文件。"
,
"only-image-supported"
:
"仅支持图片文件。"
,
"cant-empty"
:
"内容不能为空"
"cant-empty"
:
"内容不能为空"
,
"local"
:
"本地上传"
,
"resources"
:
"资源库"
},
},
"memo"
:
{
"memo"
:
{
"view-detail"
:
"查看详情"
,
"view-detail"
:
"查看详情"
,
...
...
web/src/services/editorStateService.ts
View file @
ab8e3473
import
store
from
"../store"
;
import
store
from
"../store"
;
import
{
setEditMemoId
,
setMemoVisibility
}
from
"../store/modules/editor"
;
import
{
setEditMemoId
,
setMemoVisibility
,
setResourceList
}
from
"../store/modules/editor"
;
const
editorStateService
=
{
const
editorStateService
=
{
getState
:
()
=>
{
getState
:
()
=>
{
...
@@ -17,6 +17,14 @@ const editorStateService = {
...
@@ -17,6 +17,14 @@ const editorStateService = {
setMemoVisibility
:
(
memoVisibility
:
Visibility
)
=>
{
setMemoVisibility
:
(
memoVisibility
:
Visibility
)
=>
{
store
.
dispatch
(
setMemoVisibility
(
memoVisibility
));
store
.
dispatch
(
setMemoVisibility
(
memoVisibility
));
},
},
setResourceList
:
(
resourceList
:
Resource
[])
=>
{
store
.
dispatch
(
setResourceList
(
resourceList
));
},
clearResourceList
:
()
=>
{
store
.
dispatch
(
setResourceList
([]));
},
};
};
export
default
editorStateService
;
export
default
editorStateService
;
web/src/store/modules/editor.ts
View file @
ab8e3473
...
@@ -3,11 +3,15 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
...
@@ -3,11 +3,15 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
interface
State
{
interface
State
{
editMemoId
?:
MemoId
;
editMemoId
?:
MemoId
;
memoVisibility
:
Visibility
;
memoVisibility
:
Visibility
;
resourceList
:
Resource
[];
}
}
const
editorSlice
=
createSlice
({
const
editorSlice
=
createSlice
({
name
:
"editor"
,
name
:
"editor"
,
initialState
:
{}
as
State
,
initialState
:
{
memoVisibility
:
"PRIVATE"
,
resourceList
:
[],
}
as
State
,
reducers
:
{
reducers
:
{
setEditMemoId
:
(
state
,
action
:
PayloadAction
<
Option
<
MemoId
>>
)
=>
{
setEditMemoId
:
(
state
,
action
:
PayloadAction
<
Option
<
MemoId
>>
)
=>
{
return
{
return
{
...
@@ -21,9 +25,15 @@ const editorSlice = createSlice({
...
@@ -21,9 +25,15 @@ const editorSlice = createSlice({
memoVisibility
:
action
.
payload
,
memoVisibility
:
action
.
payload
,
};
};
},
},
setResourceList
:
(
state
,
action
:
PayloadAction
<
Resource
[]
>
)
=>
{
return
{
...
state
,
resourceList
:
action
.
payload
,
};
},
},
},
});
});
export
const
{
setEditMemoId
,
setMemoVisibility
}
=
editorSlice
.
actions
;
export
const
{
setEditMemoId
,
setMemoVisibility
,
setResourceList
}
=
editorSlice
.
actions
;
export
default
editorSlice
.
reducer
;
export
default
editorSlice
.
reducer
;
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