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
82da20e1
Commit
82da20e1
authored
Oct 15, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: implement graph of relations
parent
952428c1
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
236 additions
and
2 deletions
+236
-2
package.json
web/package.json
+1
-0
pnpm-lock.yaml
web/pnpm-lock.yaml
+125
-0
MemoDetailSidebar.tsx
web/src/components/MemoDetailSidebar/MemoDetailSidebar.tsx
+8
-1
AddMemoRelationPopover.tsx
...onents/MemoEditor/ActionButton/AddMemoRelationPopover.tsx
+1
-1
MemoRelationForceGraph.tsx
...ponents/MemoRelationForceGraph/MemoRelationForceGraph.tsx
+50
-0
index.ts
web/src/components/MemoRelationForceGraph/index.ts
+5
-0
types.ts
web/src/components/MemoRelationForceGraph/types.ts
+11
-0
utils.ts
web/src/components/MemoRelationForceGraph/utils.ts
+35
-0
No files found.
web/package.json
View file @
82da20e1
...
@@ -34,6 +34,7 @@
...
@@ -34,6 +34,7 @@
"mermaid"
:
"^11.2.1"
,
"mermaid"
:
"^11.2.1"
,
"react"
:
"^18.3.1"
,
"react"
:
"^18.3.1"
,
"react-dom"
:
"^18.3.1"
,
"react-dom"
:
"^18.3.1"
,
"react-force-graph-2d"
:
"^1.25.6"
,
"react-hot-toast"
:
"^2.4.1"
,
"react-hot-toast"
:
"^2.4.1"
,
"react-i18next"
:
"^15.0.2"
,
"react-i18next"
:
"^15.0.2"
,
"react-leaflet"
:
"^4.2.1"
,
"react-leaflet"
:
"^4.2.1"
,
...
...
web/pnpm-lock.yaml
View file @
82da20e1
This diff is collapsed.
Click to expand it.
web/src/components/MemoDetailSidebar/MemoDetailSidebar.tsx
View file @
82da20e1
...
@@ -3,6 +3,7 @@ import { isEqual } from "lodash-es";
...
@@ -3,6 +3,7 @@ import { isEqual } from "lodash-es";
import
{
CheckCircleIcon
,
Code2Icon
,
HashIcon
,
LinkIcon
}
from
"lucide-react"
;
import
{
CheckCircleIcon
,
Code2Icon
,
HashIcon
,
LinkIcon
}
from
"lucide-react"
;
import
{
Memo
,
MemoProperty
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Memo
,
MemoProperty
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
MemoRelationForceGraph
from
"../MemoRelationForceGraph"
;
interface
Props
{
interface
Props
{
memo
:
Memo
;
memo
:
Memo
;
...
@@ -21,7 +22,13 @@ const MemoDetailSidebar = ({ memo, className }: Props) => {
...
@@ -21,7 +22,13 @@ const MemoDetailSidebar = ({ memo, className }: Props) => {
className
,
className
,
)
}
)
}
>
>
<
div
className=
"flex flex-col justify-start items-start w-full mt-1 px-1 gap-2 h-auto shrink-0 flex-nowrap hide-scrollbar"
>
<
div
className=
"flex flex-col justify-start items-start w-full px-1 gap-2 h-auto shrink-0 flex-nowrap hide-scrollbar"
>
{
memo
.
relations
.
length
>
0
&&
(
<
div
className=
"relative w-full h-36 border rounded-lg bg-zinc-50 dark:bg-zinc-900 dark:border-zinc-800"
>
<
MemoRelationForceGraph
className=
"w-full h-full"
memo=
{
memo
}
/>
<
span
className=
"absolute top-1 left-2 text-xs opacity-60 font-mono"
>
Relations
</
span
>
</
div
>
)
}
<
div
className=
"w-full flex flex-col"
>
<
div
className=
"w-full flex flex-col"
>
<
p
className=
"flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-gray-400 dark:text-gray-500 select-none"
>
<
p
className=
"flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-gray-400 dark:text-gray-500 select-none"
>
<
span
>
Created at
</
span
>
<
span
>
Created at
</
span
>
...
...
web/src/components/MemoEditor/ActionButton/AddMemoRelationPopover.tsx
View file @
82da20e1
...
@@ -27,7 +27,7 @@ const AddMemoRelationPopover = (props: Props) => {
...
@@ -27,7 +27,7 @@ const AddMemoRelationPopover = (props: Props) => {
const
[
isFetching
,
setIsFetching
]
=
useState
<
boolean
>
(
true
);
const
[
isFetching
,
setIsFetching
]
=
useState
<
boolean
>
(
true
);
const
[
fetchedMemos
,
setFetchedMemos
]
=
useState
<
Memo
[]
>
([]);
const
[
fetchedMemos
,
setFetchedMemos
]
=
useState
<
Memo
[]
>
([]);
const
[
selectedMemos
,
setSelectedMemos
]
=
useState
<
Memo
[]
>
([]);
const
[
selectedMemos
,
setSelectedMemos
]
=
useState
<
Memo
[]
>
([]);
const
[
embedded
,
setEmbedded
]
=
useState
<
boolean
>
(
tru
e
);
const
[
embedded
,
setEmbedded
]
=
useState
<
boolean
>
(
fals
e
);
const
[
popoverOpen
,
setPopoverOpen
]
=
useState
<
boolean
>
(
false
);
const
[
popoverOpen
,
setPopoverOpen
]
=
useState
<
boolean
>
(
false
);
const
filteredMemos
=
fetchedMemos
.
filter
(
const
filteredMemos
=
fetchedMemos
.
filter
(
...
...
web/src/components/MemoRelationForceGraph/MemoRelationForceGraph.tsx
0 → 100644
View file @
82da20e1
import
{
useColorScheme
}
from
"@mui/joy"
;
import
clsx
from
"clsx"
;
import
{
useEffect
,
useRef
,
useState
}
from
"react"
;
import
ForceGraph2D
from
"react-force-graph-2d"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
FGMethods
}
from
"./types"
;
import
{
convertMemoRelationsToGraphData
}
from
"./utils"
;
interface
Props
{
memo
:
Memo
;
className
?:
string
;
}
const
MAIN_NODE_COLOR
=
"#14b8a6"
;
const
DEFAULT_NODE_COLOR
=
"#a1a1aa"
;
const
MemoRelationForceGraph
=
({
className
,
memo
}:
Props
)
=>
{
const
{
mode
}
=
useColorScheme
();
const
containerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
graphRef
=
useRef
<
FGMethods
|
undefined
>
(
undefined
);
const
[
graphSize
,
setGraphSize
]
=
useState
({
width
:
0
,
height
:
0
});
useEffect
(()
=>
{
if
(
!
containerRef
.
current
)
return
;
setGraphSize
(
containerRef
.
current
.
getBoundingClientRect
());
},
[]);
const
onNodeClick
=
()
=>
{
// TODO: Handle node click event
};
return
(
<
div
ref=
{
containerRef
}
className=
{
clsx
(
"dark:opacity-80"
,
className
)
}
>
<
ForceGraph2D
ref=
{
graphRef
}
width=
{
graphSize
.
width
}
height=
{
graphSize
.
height
}
enableZoomInteraction
cooldownTicks=
{
0
}
nodeColor=
{
(
node
)
=>
(
node
.
name
===
memo
.
name
?
MAIN_NODE_COLOR
:
DEFAULT_NODE_COLOR
)
}
nodeRelSize=
{
3
}
linkColor=
{
()
=>
(
mode
===
"light"
?
""
:
"#525252"
)
}
graphData=
{
convertMemoRelationsToGraphData
(
memo
.
relations
)
}
onNodeClick=
{
onNodeClick
}
/>
</
div
>
);
};
export
default
MemoRelationForceGraph
;
web/src/components/MemoRelationForceGraph/index.ts
0 → 100644
View file @
82da20e1
import
MemoRelationForceGraph
from
"./MemoRelationForceGraph"
;
export
*
from
"./utils"
;
export
default
MemoRelationForceGraph
;
web/src/components/MemoRelationForceGraph/types.ts
0 → 100644
View file @
82da20e1
import
{
ForceGraphMethods
,
LinkObject
,
NodeObject
}
from
"react-force-graph-2d"
;
export
interface
NodeType
{
name
:
string
;
}
export
interface
LinkType
{
// ...add more additional properties relevant to the link here.
}
export
interface
FGMethods
extends
ForceGraphMethods
<
NodeObject
<
NodeType
>
,
LinkObject
<
NodeType
,
LinkType
>>
{}
web/src/components/MemoRelationForceGraph/utils.ts
0 → 100644
View file @
82da20e1
import
{
GraphData
,
LinkObject
,
NodeObject
}
from
"react-force-graph-2d"
;
import
{
MemoRelation
}
from
"@/types/proto/api/v1/memo_relation_service"
;
import
{
LinkType
,
NodeType
}
from
"./types"
;
export
const
convertMemoRelationsToGraphData
=
(
memoRelations
:
MemoRelation
[]):
GraphData
<
NodeType
,
LinkType
>
=>
{
const
nodesMap
=
new
Map
<
string
,
NodeObject
<
NodeType
>>
();
const
links
:
LinkObject
<
NodeType
,
LinkType
>
[]
=
[];
// Iterate through memoRelations to populate nodes and links.
memoRelations
.
forEach
((
relation
)
=>
{
const
{
memo
,
relatedMemo
,
type
}
=
relation
;
// Add memo node if not already present.
if
(
!
nodesMap
.
has
(
memo
))
{
nodesMap
.
set
(
memo
,
{
id
:
memo
,
name
:
memo
});
}
// Add related_memo node if not already present.
if
(
!
nodesMap
.
has
(
relatedMemo
))
{
nodesMap
.
set
(
relatedMemo
,
{
id
:
relatedMemo
,
name
:
relatedMemo
});
}
// Create link between memo and relatedMemo.
links
.
push
({
source
:
memo
,
target
:
relatedMemo
,
type
,
// Include the type of relation as a property of the link.
});
});
return
{
nodes
:
Array
.
from
(
nodesMap
.
values
()),
links
,
};
};
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