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
c87b679f
Commit
c87b679f
authored
Oct 19, 2023
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: add memo relation list
parent
e6b20c52
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
83 additions
and
58 deletions
+83
-58
Memo.tsx
web/src/components/Memo.tsx
+2
-4
RelationListView.tsx
web/src/components/MemoEditor/RelationListView.tsx
+16
-23
MemoRelationListView.tsx
web/src/components/MemoRelationListView.tsx
+60
-23
MemoResourceListView.tsx
web/src/components/MemoResourceListView.tsx
+1
-1
MemoDetail.tsx
web/src/pages/MemoDetail.tsx
+4
-7
No files found.
web/src/components/Memo.tsx
View file @
c87b679f
...
@@ -44,9 +44,7 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -44,9 +44,7 @@ const Memo: React.FC<Props> = (props: Props) => {
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
readonly
=
memo
.
creatorUsername
!==
user
?.
username
;
const
readonly
=
memo
.
creatorUsername
!==
user
?.
username
;
const
creator
=
userV1Store
.
getUserByUsername
(
memo
.
creatorUsername
);
const
creator
=
userV1Store
.
getUserByUsername
(
memo
.
creatorUsername
);
const
referenceRelations
=
memo
.
relationList
.
filter
(
const
referenceRelations
=
memo
.
relationList
.
filter
((
relation
)
=>
relation
.
type
===
"REFERENCE"
);
(
relation
)
=>
relation
.
memoId
===
memo
.
id
&&
relation
.
relatedMemoId
!==
memo
.
id
&&
relation
.
type
===
"REFERENCE"
);
const
commentRelations
=
memo
.
relationList
.
filter
((
relation
)
=>
relation
.
relatedMemoId
===
memo
.
id
&&
relation
.
type
===
"COMMENT"
);
const
commentRelations
=
memo
.
relationList
.
filter
((
relation
)
=>
relation
.
relatedMemoId
===
memo
.
id
&&
relation
.
type
===
"COMMENT"
);
// Prepare memo creator.
// Prepare memo creator.
...
@@ -286,7 +284,7 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -286,7 +284,7 @@ const Memo: React.FC<Props> = (props: Props) => {
onMemoContentDoubleClick=
{
handleMemoContentDoubleClick
}
onMemoContentDoubleClick=
{
handleMemoContentDoubleClick
}
/>
/>
<
MemoResourceListView
resourceList=
{
memo
.
resourceList
}
/>
<
MemoResourceListView
resourceList=
{
memo
.
resourceList
}
/>
<
MemoRelationListView
relationList=
{
referenceRelations
}
/>
<
MemoRelationListView
memo=
{
memo
}
relationList=
{
referenceRelations
}
/>
<
div
className=
"mt-4 w-full flex flex-row justify-between items-center gap-2"
>
<
div
className=
"mt-4 w-full flex flex-row justify-between items-center gap-2"
>
<
div
className=
"flex flex-row justify-start items-center"
>
<
div
className=
"flex flex-row justify-start items-center"
>
{
creator
&&
(
{
creator
&&
(
...
...
web/src/components/MemoEditor/RelationListView.tsx
View file @
c87b679f
...
@@ -7,51 +7,44 @@ interface Props {
...
@@ -7,51 +7,44 @@ interface Props {
setRelationList
:
(
relationList
:
MemoRelation
[])
=>
void
;
setRelationList
:
(
relationList
:
MemoRelation
[])
=>
void
;
}
}
interface
FormatedMemoRelation
extends
MemoRelation
{
relatedMemo
:
Memo
;
}
const
RelationListView
=
(
props
:
Props
)
=>
{
const
RelationListView
=
(
props
:
Props
)
=>
{
const
{
relationList
,
setRelationList
}
=
props
;
const
{
relationList
,
setRelationList
}
=
props
;
const
memoCacheStore
=
useMemoCacheStore
();
const
memoCacheStore
=
useMemoCacheStore
();
const
[
formatedMemoRelationList
,
setFormatedMemoRelationList
]
=
useState
<
FormatedMemoRelation
[]
>
([]);
const
[
referencingMemoList
,
setReferencingMemoList
]
=
useState
<
Memo
[]
>
([]);
useEffect
(()
=>
{
useEffect
(()
=>
{
(
async
()
=>
{
(
async
()
=>
{
const
requests
=
relationList
const
requests
=
relationList
.
filter
((
relation
)
=>
relation
.
type
===
"REFERENCE"
)
.
filter
((
relation
)
=>
relation
.
type
===
"REFERENCE"
)
.
map
(
async
(
relation
)
=>
{
.
map
(
async
(
relation
)
=>
{
const
relatedMemo
=
await
memoCacheStore
.
getOrFetchMemoById
(
relation
.
relatedMemoId
);
return
await
memoCacheStore
.
getOrFetchMemoById
(
relation
.
relatedMemoId
);
return
{
...
relation
,
relatedMemo
,
};
});
});
const
list
=
await
Promise
.
all
(
requests
);
const
list
=
await
Promise
.
all
(
requests
);
set
FormatedMemoRelation
List
(
list
);
set
ReferencingMemo
List
(
list
);
})();
})();
},
[
relationList
]);
},
[
relationList
]);
const
handleDeleteRelation
=
async
(
memoRelation
:
FormatedMemoRelation
)
=>
{
const
handleDeleteRelation
=
async
(
memo
:
Memo
)
=>
{
const
newRelationList
=
relationList
.
filter
((
relation
)
=>
relation
.
relatedMemoId
!==
memoRelation
.
relatedMemoId
);
setRelationList
(
relationList
.
filter
((
relation
)
=>
relation
.
relatedMemoId
!==
memo
.
id
));
setRelationList
(
newRelationList
);
};
};
console
.
log
(
"referencingMemoList"
,
referencingMemoList
);
return
(
return
(
<>
<>
{
formatedMemoRelation
List
.
length
>
0
&&
(
{
referencingMemo
List
.
length
>
0
&&
(
<
div
className=
"w-full flex flex-row gap-2 mt-2 flex-wrap"
>
<
div
className=
"w-full flex flex-row gap-2 mt-2 flex-wrap"
>
{
formatedMemoRelationList
.
map
((
memoRelation
)
=>
{
{
referencingMemoList
.
map
((
memo
)
=>
{
return
(
return
(
<
div
<
div
key=
{
memoRelation
.
relatedMemoId
}
key=
{
memo
.
id
}
className=
"w-auto max-w-[50%] overflow-hidden flex flex-row justify-start items-center bg-gray-100 dark:bg-zinc-800 hover:opacity-80 rounded text-sm p-1 px-2 text-gray-500 cursor-pointer"
className=
"w-auto max-w-xs overflow-hidden flex flex-row justify-start items-center bg-gray-100 dark:bg-zinc-800 hover:opacity-80 rounded text-sm p-1 px-2 text-gray-500 cursor-pointer hover:line-through"
onClick=
{
()
=>
handleDeleteRelation
(
memo
)
}
>
>
<
Icon
.
Link
className=
"w-4 h-auto shrink-0"
/>
<
Icon
.
Link
className=
"w-4 h-auto shrink-0 opacity-80"
/>
<
span
className=
"mx-1 max-w-full text-ellipsis font-mono whitespace-nowrap overflow-hidden"
>
<
span
className=
"px-1 shrink-0 opacity-80"
>
#
{
memo
.
id
}
</
span
>
{
memoRelation
.
relatedMemo
.
content
}
<
span
className=
"max-w-full text-ellipsis whitespace-nowrap overflow-hidden"
>
{
memo
.
content
}
</
span
>
</
span
>
<
Icon
.
X
className=
"w-4 h-auto hover:opacity-80 shrink-0 ml-1"
/>
<
Icon
.
X
className=
"w-4 h-auto hover:opacity-80 shrink-0"
onClick=
{
()
=>
handleDeleteRelation
(
memoRelation
)
}
/>
</
div
>
</
div
>
);
);
})
}
})
}
...
...
web/src/components/MemoRelationListView.tsx
View file @
c87b679f
import
{
Tooltip
}
from
"@mui/joy"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
Link
}
from
"react-router-dom"
;
import
{
useMemoCacheStore
}
from
"@/store/v1"
;
import
{
useMemoCacheStore
}
from
"@/store/v1"
;
import
Icon
from
"./Icon"
;
import
Icon
from
"./Icon"
;
interface
Props
{
interface
Props
{
memo
:
Memo
;
relationList
:
MemoRelation
[];
relationList
:
MemoRelation
[];
}
}
const
MemoRelationListView
=
(
props
:
Props
)
=>
{
const
MemoRelationListView
=
(
props
:
Props
)
=>
{
const
{
memo
,
relationList
}
=
props
;
const
memoCacheStore
=
useMemoCacheStore
();
const
memoCacheStore
=
useMemoCacheStore
();
const
[
relatedMemoList
,
setRelatedMemoList
]
=
useState
<
Memo
[]
>
([]);
const
[
referencingMemoList
,
setReferencingMemoList
]
=
useState
<
Memo
[]
>
([]);
const
[
referencedMemoList
,
setReferencedMemoList
]
=
useState
<
Memo
[]
>
([]);
useEffect
(()
=>
{
useEffect
(()
=>
{
(
async
()
=>
{
(
async
()
=>
{
const
memoList
=
await
Promise
.
all
(
props
.
relationList
.
map
((
relation
)
=>
memoCacheStore
.
getOrFetchMemoById
(
relation
.
relatedMemoId
)));
const
referencingMemoList
=
await
Promise
.
all
(
setRelatedMemoList
(
memoList
);
relationList
.
filter
((
relation
)
=>
relation
.
memoId
===
memo
.
id
&&
relation
.
relatedMemoId
!==
memo
.
id
)
.
map
((
relation
)
=>
memoCacheStore
.
getOrFetchMemoById
(
relation
.
relatedMemoId
))
);
setReferencingMemoList
(
referencingMemoList
);
const
referencedMemoList
=
await
Promise
.
all
(
relationList
.
filter
((
relation
)
=>
relation
.
memoId
!==
memo
.
id
&&
relation
.
relatedMemoId
===
memo
.
id
)
.
map
((
relation
)
=>
memoCacheStore
.
getOrFetchMemoById
(
relation
.
memoId
))
);
setReferencedMemoList
(
referencedMemoList
);
})();
})();
},
[
props
.
relationList
]);
},
[
memo
,
relationList
]);
const
handleGotoMemoDetail
=
(
memo
:
Memo
)
=>
{
window
.
open
(
`/m/
${
memo
.
id
}
`
,
"_blank"
);
};
return
(
return
(
<>
<>
{
relatedMemoList
.
length
>
0
&&
(
{
referencingMemoList
.
length
>
0
&&
(
<
div
className=
"w-full max-w-full overflow-hidden grid grid-cols-1 gap-1 mt-2"
>
<
div
className=
"w-full mt-2 flex flex-row justify-start items-start"
>
{
relatedMemoList
.
map
((
memo
)
=>
{
<
Tooltip
title=
"References"
placement=
"top"
>
return
(
<
Icon
.
Link
className=
"w-4 h-auto shrink-0 opacity-70 mt-1.5 mr-1"
/>
<
div
</
Tooltip
>
key=
{
memo
.
id
}
<
div
className=
"w-auto max-w-[calc(100%-2rem)] flex flex-row justify-start items-center flex-wrap gap-2"
>
className=
"w-auto flex flex-row justify-start items-center hover:bg-gray-100 dark:hover:bg-zinc-800 rounded text-sm p-1 text-gray-500 dark:text-gray-400 cursor-pointer"
{
referencingMemoList
.
map
((
memo
)
=>
{
onClick=
{
()
=>
handleGotoMemoDetail
(
memo
)
}
return
(
>
<
div
key=
{
memo
.
id
}
className=
"block w-auto max-w-[50%]"
>
<
div
className=
"w-5 h-5 flex justify-center items-center shrink-0 bg-gray-100 dark:bg-zinc-800 rounded-full"
>
<
Link
<
Icon
.
Link
className=
"w-3 h-auto"
/>
className=
"px-2 border rounded-full w-auto text-sm leading-6 flex flex-row justify-start items-center flex-nowrap text-gray-600 dark:text-gray-300 dark:border-gray-600 hover:shadow hover:opacity-80"
to=
{
`/m/${memo.id}`
}
>
<
span
className=
"opacity-70 mr-1"
>
#
{
memo
.
id
}
</
span
>
<
span
className=
"truncate"
>
{
memo
.
content
}
</
span
>
</
Link
>
</
div
>
);
})
}
</
div
>
</
div
>
)
}
{
referencedMemoList
.
length
>
0
&&
(
<
div
className=
"w-full mt-2 flex flex-row justify-start items-start"
>
<
Tooltip
title=
"Referenced"
placement=
"top"
>
<
Icon
.
Milestone
className=
"w-4 h-auto shrink-0 opacity-70 mt-1.5 mr-1"
/>
</
Tooltip
>
<
div
className=
"grow w-auto max-w-[calc(100%-2rem)] flex flex-row justify-start items-center flex-wrap gap-2"
>
{
referencedMemoList
.
map
((
memo
)
=>
{
return
(
<
div
key=
{
memo
.
id
}
className=
"block w-auto max-w-[50%]"
>
<
Link
className=
"px-2 border rounded-full w-auto text-sm leading-6 flex flex-row justify-start items-center flex-nowrap text-gray-600 dark:text-gray-300 dark:border-gray-600 hover:shadow hover:opacity-80"
to=
{
`/m/${memo.id}`
}
>
<
span
className=
"opacity-70 mr-1"
>
#
{
memo
.
id
}
</
span
>
<
span
className=
"truncate"
>
{
memo
.
content
}
</
span
>
</
Link
>
</
div
>
</
div
>
<
span
className=
"mx-1 w-auto truncate"
>
{
memo
.
content
}
</
span
>
);
</
div
>
})
}
);
</
div
>
})
}
</
div
>
</
div
>
)
}
)
}
</>
</>
...
...
web/src/components/MemoResourceListView.tsx
View file @
c87b679f
...
@@ -78,7 +78,7 @@ const MemoResourceListView: React.FC<Props> = (props: Props) => {
...
@@ -78,7 +78,7 @@ const MemoResourceListView: React.FC<Props> = (props: Props) => {
<
div
className=
{
`w-full flex flex-col justify-start items-start ${className || ""}`
}
>
<
div
className=
{
`w-full flex flex-col justify-start items-start ${className || ""}`
}
>
{
videoResourceList
.
length
>
0
&&
(
{
videoResourceList
.
length
>
0
&&
(
<
div
className=
"w-full grid grid-cols-2 sm:grid-cols-3 gap-2 mt-2
wrapper
"
>
<
div
className=
"w-full grid grid-cols-2 sm:grid-cols-3 gap-2 mt-2"
>
{
videoResourceList
.
map
((
resource
)
=>
{
{
videoResourceList
.
map
((
resource
)
=>
{
const
url
=
getResourceUrl
(
resource
);
const
url
=
getResourceUrl
(
resource
);
return
(
return
(
...
...
web/src/pages/MemoDetail.tsx
View file @
c87b679f
...
@@ -36,10 +36,7 @@ const MemoDetail = () => {
...
@@ -36,10 +36,7 @@ const MemoDetail = () => {
const
memoId
=
Number
(
params
.
memoId
);
const
memoId
=
Number
(
params
.
memoId
);
const
memo
=
memoStore
.
state
.
memos
.
find
((
memo
)
=>
memo
.
id
===
memoId
);
const
memo
=
memoStore
.
state
.
memos
.
find
((
memo
)
=>
memo
.
id
===
memoId
);
const
allowEdit
=
memo
?.
creatorUsername
===
currentUser
?.
username
;
const
allowEdit
=
memo
?.
creatorUsername
===
currentUser
?.
username
;
const
referenceRelations
=
const
referenceRelations
=
memo
?.
relationList
.
filter
((
relation
)
=>
relation
.
type
===
"REFERENCE"
)
||
[];
memo
?.
relationList
.
filter
(
(
relation
)
=>
relation
.
memoId
===
memo
?.
id
&&
relation
.
relatedMemoId
!==
memo
?.
id
&&
relation
.
type
===
"REFERENCE"
)
||
[];
const
commentRelations
=
memo
?.
relationList
.
filter
((
relation
)
=>
relation
.
relatedMemoId
===
memo
.
id
&&
relation
.
type
===
"COMMENT"
)
||
[];
const
commentRelations
=
memo
?.
relationList
.
filter
((
relation
)
=>
relation
.
relatedMemoId
===
memo
.
id
&&
relation
.
type
===
"COMMENT"
)
||
[];
const
comments
=
commentRelations
const
comments
=
commentRelations
.
map
((
relation
)
=>
memoStore
.
state
.
memos
.
find
((
memo
)
=>
memo
.
id
===
relation
.
memoId
))
.
map
((
relation
)
=>
memoStore
.
state
.
memos
.
find
((
memo
)
=>
memo
.
id
===
relation
.
memoId
))
...
@@ -113,9 +110,9 @@ const MemoDetail = () => {
...
@@ -113,9 +110,9 @@ const MemoDetail = () => {
</
div
>
</
div
>
<
div
className=
"relative flex-grow max-w-2xl w-full min-h-full flex flex-col justify-start items-start px-4 pb-6"
>
<
div
className=
"relative flex-grow max-w-2xl w-full min-h-full flex flex-col justify-start items-start px-4 pb-6"
>
{
memo
.
parent
&&
(
{
memo
.
parent
&&
(
<
div
className=
"w-
full
mb-4"
>
<
div
className=
"w-
auto
mb-4"
>
<
Link
<
Link
className=
"px-3 py-1 border rounded-full max-w-xs w-
full
text-sm flex flex-row justify-start items-center flex-nowrap text-gray-600 dark:text-gray-400 dark:border-gray-500 hover:shadow hover:opacity-80"
className=
"px-3 py-1 border rounded-full max-w-xs w-
auto
text-sm flex flex-row justify-start items-center flex-nowrap text-gray-600 dark:text-gray-400 dark:border-gray-500 hover:shadow hover:opacity-80"
to=
{
`/m/${memo.parent.id}`
}
to=
{
`/m/${memo.parent.id}`
}
>
>
<
Icon
.
ArrowUpLeftFromCircle
className=
"w-4 h-auto shrink-0 opacity-60"
/>
<
Icon
.
ArrowUpLeftFromCircle
className=
"w-4 h-auto shrink-0 opacity-60"
/>
...
@@ -129,7 +126,7 @@ const MemoDetail = () => {
...
@@ -129,7 +126,7 @@ const MemoDetail = () => {
</
div
>
</
div
>
<
MemoContent
content=
{
memo
.
content
}
/>
<
MemoContent
content=
{
memo
.
content
}
/>
<
MemoResourceListView
resourceList=
{
memo
.
resourceList
}
/>
<
MemoResourceListView
resourceList=
{
memo
.
resourceList
}
/>
<
MemoRelationListView
relationList=
{
referenceRelations
}
/>
<
MemoRelationListView
memo=
{
memo
}
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"
>
<
Tooltip
title=
{
"Identifier"
}
placement=
"top"
>
...
...
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