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
06fc29ae
Commit
06fc29ae
authored
Jul 02, 2022
by
boojack
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: rename delete to archive
parent
53662700
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
135 additions
and
103 deletions
+135
-103
ArchivedMemo.tsx
web/src/components/ArchivedMemo.tsx
+8
-9
ArchivedMemoDialog.tsx
web/src/components/ArchivedMemoDialog.tsx
+73
-0
Memo.tsx
web/src/components/Memo.tsx
+13
-25
Sidebar.tsx
web/src/components/Sidebar.tsx
+5
-5
TagList.tsx
web/src/components/TagList.tsx
+1
-1
archived-memo-dialog.less
web/src/less/archived-memo-dialog.less
+2
-2
memo.less
web/src/less/memo.less
+4
-8
shortcut-list.less
web/src/less/shortcut-list.less
+17
-29
tag-list.less
web/src/less/tag-list.less
+9
-21
memoService.ts
web/src/services/memoService.ts
+3
-3
No files found.
web/src/components/
Delet
edMemo.tsx
→
web/src/components/
Archiv
edMemo.tsx
View file @
06fc29ae
...
...
@@ -10,15 +10,14 @@ import "../less/memo.less";
interface
Props
{
memo
:
Memo
;
handleDeletedMemoAction
:
(
memoId
:
MemoId
)
=>
void
;
}
const
Delet
edMemo
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
memo
:
propsMemo
,
handleDeletedMemoAction
}
=
props
;
const
Archiv
edMemo
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
memo
:
propsMemo
}
=
props
;
const
memo
=
{
...
propsMemo
,
createdAtStr
:
utils
.
getDateTimeString
(
propsMemo
.
createdTs
),
delet
edAtStr
:
utils
.
getDateTimeString
(
propsMemo
.
updatedTs
??
Date
.
now
()),
archiv
edAtStr
:
utils
.
getDateTimeString
(
propsMemo
.
updatedTs
??
Date
.
now
()),
};
const
[
showConfirmDeleteBtn
,
toggleConfirmDeleteBtn
]
=
useToggle
(
false
);
const
imageUrls
=
Array
.
from
(
memo
.
content
.
match
(
IMAGE_URL_REG
)
??
[]).
map
((
s
)
=>
s
.
replace
(
IMAGE_URL_REG
,
"$1"
));
...
...
@@ -27,7 +26,7 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
if
(
showConfirmDeleteBtn
)
{
try
{
await
memoService
.
deleteMemoById
(
memo
.
id
);
handleDeletedMemoAction
(
memo
.
id
);
await
memoService
.
fetchAllMemos
(
);
}
catch
(
error
:
any
)
{
toastHelper
.
error
(
error
.
message
);
}
...
...
@@ -42,7 +41,7 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
id
:
memo
.
id
,
rowStatus
:
"NORMAL"
,
});
handleDeletedMemoAction
(
memo
.
id
);
await
memoService
.
fetchAllMemos
(
);
toastHelper
.
info
(
"Restored successfully"
);
}
catch
(
error
:
any
)
{
toastHelper
.
error
(
error
.
message
);
...
...
@@ -56,9 +55,9 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
};
return
(
<
div
className=
{
`memo-wrapper
delet
ed-memo ${"memos-" + memo.id}`
}
onMouseLeave=
{
handleMouseLeaveMemoWrapper
}
>
<
div
className=
{
`memo-wrapper
archiv
ed-memo ${"memos-" + memo.id}`
}
onMouseLeave=
{
handleMouseLeaveMemoWrapper
}
>
<
div
className=
"memo-top-wrapper"
>
<
span
className=
"time-text"
>
Deleted at
{
memo
.
delet
edAtStr
}
</
span
>
<
span
className=
"time-text"
>
Archived at
{
memo
.
archiv
edAtStr
}
</
span
>
<
div
className=
"btns-container"
>
<
span
className=
"btn restore-btn"
onClick=
{
handleRestoreMemoClick
}
>
Restore
...
...
@@ -80,4 +79,4 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
);
};
export
default
Delet
edMemo
;
export
default
Archiv
edMemo
;
web/src/components/
MemoTrash
Dialog.tsx
→
web/src/components/
ArchivedMemo
Dialog.tsx
View file @
06fc29ae
import
{
use
Callback
,
use
Effect
,
useState
}
from
"react"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
useLoading
from
"../hooks/useLoading"
;
import
{
locationService
,
memoService
}
from
"../services"
;
import
{
memoService
}
from
"../services"
;
import
{
useAppSelector
}
from
"../store"
;
import
{
showDialog
}
from
"./Dialog"
;
import
toastHelper
from
"./Toast"
;
import
DeletedMemo
from
"./Delet
edMemo"
;
import
"../less/
memo-trash
-dialog.less"
;
import
ArchivedMemo
from
"./Archiv
edMemo"
;
import
"../less/
archived-memo
-dialog.less"
;
interface
Props
extends
DialogProps
{}
const
MemoTrash
Dialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
ArchivedMemo
Dialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
destroy
}
=
props
;
const
memos
=
useAppSelector
((
state
)
=>
state
.
memo
.
memos
);
const
loadingState
=
useLoading
();
const
[
deletedMemos
,
setDelet
edMemos
]
=
useState
<
Memo
[]
>
([]);
const
[
archivedMemos
,
setArchiv
edMemos
]
=
useState
<
Memo
[]
>
([]);
useEffect
(()
=>
{
memoService
.
fetch
Delet
edMemos
()
.
fetch
Archiv
edMemos
()
.
then
((
result
)
=>
{
set
Delet
edMemos
(
result
);
set
Archiv
edMemos
(
result
);
})
.
catch
((
error
)
=>
{
toastHelper
.
error
(
"Failed to fetch
delet
ed memos: "
,
error
);
toastHelper
.
error
(
"Failed to fetch
archiv
ed memos: "
,
error
);
})
.
finally
(()
=>
{
loadingState
.
setFinish
();
});
locationService
.
clearQuery
();
},
[]);
const
handleDeletedMemoAction
=
useCallback
(
async
(
memoId
:
MemoId
)
=>
{
setDeletedMemos
((
deletedMemos
)
=>
deletedMemos
.
filter
((
memo
)
=>
memo
.
id
!==
memoId
));
await
memoService
.
fetchAllMemos
();
},
[]);
},
[
memos
]);
return
(
<>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
<
span
className=
"icon-text"
>
🗑️
</
span
>
Recycle Bin
<
span
className=
"icon-text"
>
🗂
</
span
>
Archived Memos
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
destroy
}
>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
...
...
@@ -49,14 +45,14 @@ const MemoTrashDialog: React.FC<Props> = (props: Props) => {
<
div
className=
"tip-text-container"
>
<
p
className=
"tip-text"
>
fetching data...
</
p
>
</
div
>
)
:
delet
edMemos
.
length
===
0
?
(
)
:
archiv
edMemos
.
length
===
0
?
(
<
div
className=
"tip-text-container"
>
<
p
className=
"tip-text"
>
Here is No Zettels.
</
p
>
</
div
>
)
:
(
<
div
className=
"
delet
ed-memos-container"
>
{
delet
edMemos
.
map
((
memo
)
=>
(
<
DeletedMemo
key=
{
`${memo.id}-${memo.updatedTs}`
}
memo=
{
memo
}
handleDeletedMemoAction=
{
handleDeletedMemoAction
}
/>
<
div
className=
"
archiv
ed-memos-container"
>
{
archiv
edMemos
.
map
((
memo
)
=>
(
<
ArchivedMemo
key=
{
`${memo.id}-${memo.updatedTs}`
}
memo=
{
memo
}
/>
))
}
</
div
>
)
}
...
...
@@ -65,13 +61,13 @@ const MemoTrashDialog: React.FC<Props> = (props: Props) => {
);
};
export
default
function
show
MemoTrashDialog
():
void
{
export
default
function
show
ArchivedMemo
():
void
{
showDialog
(
{
className
:
"
memo-trash
-dialog"
,
className
:
"
archived-memo
-dialog"
,
useAppContext
:
true
,
},
MemoTrash
Dialog
,
ArchivedMemo
Dialog
,
{}
);
}
web/src/components/Memo.tsx
View file @
06fc29ae
...
...
@@ -3,7 +3,6 @@ import { escape, indexOf } from "lodash-es";
import
{
IMAGE_URL_REG
,
LINK_REG
,
MEMO_LINK_REG
,
TAG_REG
,
UNKNOWN_ID
}
from
"../helpers/consts"
;
import
{
DONE_BLOCK_REG
,
parseMarkedToHtml
,
TODO_BLOCK_REG
}
from
"../helpers/marked"
;
import
*
as
utils
from
"../helpers/utils"
;
import
useToggle
from
"../hooks/useToggle"
;
import
{
editorStateService
,
locationService
,
memoService
}
from
"../services"
;
import
Only
from
"./common/OnlyWhen"
;
import
Image
from
"./Image"
;
...
...
@@ -34,7 +33,6 @@ const Memo: React.FC<Props> = (props: Props) => {
expandButtonStatus
:
-
1
,
});
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
[
showConfirmDeleteBtn
,
toggleConfirmDeleteBtn
]
=
useToggle
(
false
);
const
imageUrls
=
Array
.
from
(
memo
.
content
.
match
(
IMAGE_URL_REG
)
??
[]).
map
((
s
)
=>
s
.
replace
(
IMAGE_URL_REG
,
"$1"
));
useEffect
(()
=>
{
...
...
@@ -74,28 +72,18 @@ const Memo: React.FC<Props> = (props: Props) => {
editorStateService
.
setEditMemoWithId
(
memo
.
id
);
};
const
handleDeleteMemoClick
=
async
()
=>
{
if
(
showConfirmDeleteBtn
)
{
try
{
await
memoService
.
patchMemo
({
id
:
memo
.
id
,
rowStatus
:
"ARCHIVED"
,
});
}
catch
(
error
:
any
)
{
toastHelper
.
error
(
error
.
message
);
}
if
(
editorStateService
.
getState
().
editMemoId
===
memo
.
id
)
{
editorStateService
.
clearEditMemo
();
}
}
else
{
toggleConfirmDeleteBtn
();
const
handleArchiveMemoClick
=
async
()
=>
{
try
{
await
memoService
.
patchMemo
({
id
:
memo
.
id
,
rowStatus
:
"ARCHIVED"
,
});
}
catch
(
error
:
any
)
{
toastHelper
.
error
(
error
.
message
);
}
};
const
handleMouseLeaveMemoWrapper
=
()
=>
{
if
(
showConfirmDeleteBtn
)
{
toggleConfirmDeleteBtn
(
false
);
if
(
editorStateService
.
getState
().
editMemoId
===
memo
.
id
)
{
editorStateService
.
clearEditMemo
();
}
};
...
...
@@ -162,7 +150,7 @@ const Memo: React.FC<Props> = (props: Props) => {
};
return
(
<
div
className=
{
`memo-wrapper ${"memos-" + memo.id} ${memo.pinned ? "pinned" : ""}`
}
onMouseLeave=
{
handleMouseLeaveMemoWrapper
}
>
<
div
className=
{
`memo-wrapper ${"memos-" + memo.id} ${memo.pinned ? "pinned" : ""}`
}
>
<
div
className=
"memo-top-wrapper"
>
<
span
className=
"time-text"
onClick=
{
handleShowMemoStoryDialog
}
>
{
memo
.
createdAtStr
}
...
...
@@ -196,8 +184,8 @@ const Memo: React.FC<Props> = (props: Props) => {
<
span
className=
"btn"
onClick=
{
handleShowMemoStoryDialog
}
>
View Story
</
span
>
<
span
className=
{
`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`
}
onClick=
{
handleDelet
eMemoClick
}
>
{
showConfirmDeleteBtn
?
"Delete!"
:
"Delete"
}
<
span
className=
"btn archive-btn"
onClick=
{
handleArchiv
eMemoClick
}
>
Archive
</
span
>
</
div
>
</
div
>
...
...
web/src/components/Sidebar.tsx
View file @
06fc29ae
...
...
@@ -2,7 +2,7 @@ import { useAppSelector } from "../store";
import
*
as
utils
from
"../helpers/utils"
;
import
showDailyReviewDialog
from
"./DailyReviewDialog"
;
import
showSettingDialog
from
"./SettingDialog"
;
import
show
MemoTrashDialog
from
"./MemoTrash
Dialog"
;
import
show
ArchivedMemoDialog
from
"./ArchivedMemo
Dialog"
;
import
UserBanner
from
"./UserBanner"
;
import
UsageHeatMap
from
"./UsageHeatMap"
;
import
ShortcutList
from
"./ShortcutList"
;
...
...
@@ -21,8 +21,8 @@ const Sidebar: React.FC<Props> = () => {
showSettingDialog
();
};
const
handle
MemosTrash
BtnClick
=
()
=>
{
show
MemoTrash
Dialog
();
const
handle
Archived
BtnClick
=
()
=>
{
show
ArchivedMemo
Dialog
();
};
return
(
...
...
@@ -55,8 +55,8 @@ const Sidebar: React.FC<Props> = () => {
<
button
className=
"btn action-btn"
onClick=
{
handleMyAccountBtnClick
}
>
<
span
className=
"icon"
>
⚙️
</
span
>
Setting
</
button
>
<
button
className=
"btn action-btn"
onClick=
{
handle
MemosTrash
BtnClick
}
>
<
span
className=
"icon"
>
🗑️
</
span
>
Recycle Bin
<
button
className=
"btn action-btn"
onClick=
{
handle
Archived
BtnClick
}
>
<
span
className=
"icon"
>
🗂
</
span
>
Archived
</
button
>
</
div
>
<
ShortcutList
/>
...
...
web/src/components/TagList.tsx
View file @
06fc29ae
...
...
@@ -126,7 +126,7 @@ const TagItemContainer: React.FC<TagItemContainerProps> = (props: TagItemContain
</
div
>
{
hasSubTags
?
(
<
div
className=
{
`subtags-container ${showSubTags ? "" : "hidden"}`
}
>
<
div
className=
{
`subtags-container ${showSubTags ? "" : "
!
hidden"}`
}
>
{
tag
.
subTags
.
map
((
st
,
idx
)
=>
(
<
TagItemContainer
key=
{
st
.
text
+
"-"
+
idx
}
tag=
{
st
}
tagQuery=
{
tagQuery
}
/>
))
}
...
...
web/src/less/
memo-trash
-dialog.less
→
web/src/less/
archived-memo
-dialog.less
View file @
06fc29ae
@import "./mixin.less";
.
memo-trash
-dialog {
.
archived-memo
-dialog {
@apply px-4;
> .dialog-container {
...
...
@@ -15,7 +15,7 @@
.flex(column, center, center);
}
> .
delet
ed-memos-container {
> .
archiv
ed-memos-container {
.flex(column, flex-start, flex-start);
@apply w-full;
}
...
...
web/src/less/memo.less
View file @
06fc29ae
...
...
@@ -4,7 +4,7 @@
.memo-wrapper {
@apply flex flex-col justify-start items-start w-full max-w-full p-4 pt-3 mt-2 bg-white rounded-lg border border-white hover:border-gray-200;
&.
delet
ed-memo {
&.
archiv
ed-memo {
@apply border-gray-200;
}
...
...
@@ -50,14 +50,10 @@
}
> .btn {
@apply w-full
py-2
px-3 rounded justify-start;
@apply w-full
text-sm leading-6 py-1
px-3 rounded justify-start;
&.delete-btn {
@apply text-red-600;
&.final-confirm {
@apply font-bold;
}
&.archive-btn {
@apply text-orange-600;
}
}
}
...
...
web/src/less/shortcut-list.less
View file @
06fc29ae
@import "./mixin.less";
.shortcuts-wrapper {
.flex(column, flex-start, flex-start);
@apply w-full py-0 px-2 mt-2 h-auto shrink-0 flex-nowrap;
@apply flex flex-col justify-start items-start w-full py-0 px-2 mt-2 h-auto shrink-0 flex-nowrap;
.hide-scroll-bar();
> .title-text {
.flex(row, flex-start, center);
@apply w-full px-4;
@apply flex flex-row justify-start items-center w-full px-4;
> .normal-text {
@apply text-
xs
leading-6 font-mono text-gray-400;
@apply text-
sm
leading-6 font-mono text-gray-400;
}
> .btn {
.flex(column, center, center);
@apply w-5 h-5 bg-gray-200 rounded ml-2 shadow hover:opacity-80;
@apply flex flex-col justify-center items-center w-5 h-5 bg-gray-200 rounded ml-2 shadow hover:opacity-80;
> img {
@apply w-4 h-4 opacity-80;
...
...
@@ -24,8 +21,7 @@
}
> .create-shortcut-btn-container {
.flex(row, flex-start, center);
@apply w-full mt-4 mb-2 ml-4;
@apply flex flex-row justify-start items-center w-full mt-4 mb-2 ml-4;
> .btn {
@apply flex p-2 px-4 rounded-lg text-sm border border-dashed border-blue-600;
...
...
@@ -37,23 +33,19 @@
}
> .shortcuts-container {
.flex(column, flex-start, flex-start);
@apply relative w-full h-auto flex-nowrap mb-2;
@apply flex flex-col justify-start items-start relative w-full h-auto flex-nowrap mb-2;
> .shortcut-container {
.flex(row, space-between, center);
@apply w-full h-10 py-0 px-4 mt-px first:mt-2 rounded-lg text-base cursor-pointer select-none shrink-0;
@apply flex flex-row justify-between items-center w-full h-10 py-0 px-4 mt-px first:mt-2 rounded-lg text-base cursor-pointer select-none shrink-0 hover:bg-gray-200;
&:hover {
background-color: @bg-gray;
> .btns-container {
@apply flex;
}
}
&.active {
background-color: @text-green !important
;
@apply bg-green-600
;
> .shortcut-text-container {
> * {
...
...
@@ -63,8 +55,7 @@
}
> .shortcut-text-container {
.flex(row, flex-start, center);
@apply truncate shrink leading-5 mr-1;
@apply flex flex-row justify-start items-center truncate shrink leading-5 mr-1;
color: @text-black;
> .icon-text {
...
...
@@ -77,8 +68,7 @@
}
> .btns-container {
.flex(row, flex-end, center);
@apply hidden shrink-0;
@apply flex-row justify-end items-center hidden shrink-0;
> .action-btn {
.flex(row, center, center);
...
...
@@ -91,35 +81,33 @@
&.toggle-btn {
&:hover {
& + .action-btns-wrapper {
display:
flex;
@apply
flex;
}
}
}
}
> .action-btns-wrapper {
.flex(column, flex-start, flex-start);
@apply absolute right-0 w-auto h-auto px-4 pt-3 translate-y-16 hidden z-10;
@apply flex-col justify-start items-start absolute top-6 right-0 w-auto h-auto px-4 pt-3 hidden z-10;
> .action-btns-container {
.flex(column, flex-start, flex-start);
@apply w-24 h-auto p-1 whitespace-nowrap rounded-md bg-white shadow;
@apply flex flex-col justify-start items-start w-24 h-auto p-1 whitespace-nowrap rounded-md bg-white shadow;
> .btn {
@apply w-full
py-2 px-3 rounded text-sm
text-left hover:bg-gray-100;
@apply w-full
text-sm leading-6 py-1 px-3 rounded
text-left hover:bg-gray-100;
&.delete-btn {
color: @text-red
;
@apply text-orange-600
;
&.final-confirm {
font-weight: bold
;
@apply font-black
;
}
}
}
}
&:hover {
display:
flex;
@apply
flex;
}
}
}
...
...
web/src/less/tag-list.less
View file @
06fc29ae
@import "./mixin.less";
.tags-wrapper {
.flex(column, flex-start, flex-start);
@apply px-2 w-full h-auto flex-nowrap pb-4 mt-2 grow;
@apply flex flex-col justify-start items-start px-2 w-full h-auto flex-nowrap pb-4 mt-2 grow;
.hide-scroll-bar();
> .title-text {
@apply w-full p
y-1 px-4 text-xs
font-mono text-gray-400;
@apply w-full p
x-4 text-sm leading-6
font-mono text-gray-400;
}
> .tags-container {
.flex(column, flex-start, flex-start);
@apply relative w-full h-auto flex-nowrap mb-2 mt-1;
@apply flex flex-col justify-start items-start relative w-full h-auto flex-nowrap mb-2 mt-1;
.subtags-container {
.flex(column, flex-start, flex-start);
@apply h-auto mt-1 ml-4 pl-1;
@apply flex flex-col justify-start items-start h-auto mt-1 ml-4 pl-1;
width: calc(100% - 18px);
min-width: 80px;
border-left: 2px solid @bg-gray;
...
...
@@ -26,27 +23,19 @@
}
.tag-item-container {
.flex(row, space-between, center);
@apply w-full h-10 py-0 px-4 rounded-lg text-base shrink-0 select-none cursor-pointer;
&:hover {
background-color: @bg-gray;
}
@apply flex flex-row justify-between items-center w-full h-10 py-0 px-4 rounded-lg text-base shrink-0 select-none cursor-pointer hover:bg-gray-200;
&.active {
> .tag-text-container {
> * {
@apply font-bold;
color: @text-green;
@apply text-green-600;
}
}
}
> .tag-text-container {
.flex(row, flex-start, center);
@apply overflow-hidden text-ellipsis shrink-0 leading-5;
@apply flex flex-row justify-start items-center overflow-hidden text-ellipsis shrink-0 leading-5 text-black;
max-width: calc(100% - 24px);
color: @text-black;
> .icon-text {
@apply block w-4 shrink-0;
...
...
@@ -58,11 +47,10 @@
}
> .btns-container {
.flex(row, flex-end, center)
;
@apply flex flex-row justify-end items-center
;
> .action-btn {
.flex(row, center, center);
@apply w-6 h-6 shrink-0 transition-all rotate-0;
@apply flex flex-row justify-center items-center w-6 h-6 shrink-0 transition-all rotate-0;
> .icon-img {
@apply w-5 h-5 opacity-80;
...
...
web/src/services/memoService.ts
View file @
06fc29ae
...
...
@@ -23,12 +23,12 @@ const memoService = {
return
memos
;
},
fetch
Delet
edMemos
:
async
()
=>
{
fetch
Archiv
edMemos
:
async
()
=>
{
const
{
data
}
=
(
await
api
.
getArchivedMemoList
()).
data
;
const
delet
edMemos
=
data
.
map
((
m
)
=>
{
const
archiv
edMemos
=
data
.
map
((
m
)
=>
{
return
convertResponseModelMemo
(
m
);
});
return
delet
edMemos
;
return
archiv
edMemos
;
},
getMemoById
:
(
memoId
:
MemoId
)
=>
{
...
...
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