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
c4a24bea
Commit
c4a24bea
authored
Jul 19, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore(frontend): tweak memo relations
parent
d264f459
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
97 additions
and
41 deletions
+97
-41
CreateMemoRelationDialog.tsx
web/src/components/CreateMemoRelationDialog.tsx
+3
-1
AddMemoRelationButton.tsx
...ponents/MemoEditor/ActionButton/AddMemoRelationButton.tsx
+3
-0
MemoRelationListView.tsx
web/src/components/MemoRelationListView.tsx
+91
-18
memo.ts
web/src/store/v1/memo.ts
+0
-11
resource.ts
web/src/store/v1/resource.ts
+0
-11
No files found.
web/src/components/CreateMemoRelationDialog.tsx
View file @
c4a24bea
...
@@ -13,6 +13,8 @@ import Icon from "./Icon";
...
@@ -13,6 +13,8 @@ import Icon from "./Icon";
interface
Props
extends
DialogProps
{
interface
Props
extends
DialogProps
{
onConfirm
:
(
memos
:
Memo
[],
embedded
?:
boolean
)
=>
void
;
onConfirm
:
(
memos
:
Memo
[],
embedded
?:
boolean
)
=>
void
;
// Custom filter function for filtering memos.
filter
?:
(
memo
:
Memo
)
=>
boolean
;
}
}
const
CreateMemoRelationDialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
CreateMemoRelationDialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
...
@@ -24,7 +26,7 @@ const CreateMemoRelationDialog: React.FC<Props> = (props: Props) => {
...
@@ -24,7 +26,7 @@ const CreateMemoRelationDialog: React.FC<Props> = (props: Props) => {
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
>
(
true
);
const
[
embedded
,
setEmbedded
]
=
useState
<
boolean
>
(
true
);
const
filteredMemos
=
fetchedMemos
.
filter
((
memo
)
=>
!
selectedMemos
.
includes
(
memo
));
const
filteredMemos
=
fetchedMemos
.
filter
((
memo
)
=>
!
selectedMemos
.
includes
(
memo
)
&&
(
!
props
.
filter
||
props
.
filter
(
memo
))
);
useDebounce
(
useDebounce
(
async
()
=>
{
async
()
=>
{
...
...
web/src/components/MemoEditor/ActionButton/AddMemoRelationButton.tsx
View file @
c4a24bea
...
@@ -5,6 +5,7 @@ import toast from "react-hot-toast";
...
@@ -5,6 +5,7 @@ import toast from "react-hot-toast";
import
showCreateMemoRelationDialog
from
"@/components/CreateMemoRelationDialog"
;
import
showCreateMemoRelationDialog
from
"@/components/CreateMemoRelationDialog"
;
import
Icon
from
"@/components/Icon"
;
import
Icon
from
"@/components/Icon"
;
import
{
MemoRelation_Type
}
from
"@/types/proto/api/v1/memo_relation_service"
;
import
{
MemoRelation_Type
}
from
"@/types/proto/api/v1/memo_relation_service"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
EditorRefActions
}
from
"../Editor"
;
import
{
EditorRefActions
}
from
"../Editor"
;
import
{
MemoEditorContext
}
from
"../types"
;
import
{
MemoEditorContext
}
from
"../types"
;
...
@@ -55,6 +56,8 @@ const AddMemoRelationButton = (props: Props) => {
...
@@ -55,6 +56,8 @@ const AddMemoRelationButton = (props: Props) => {
),
),
);
);
},
},
filter
:
(
memo
:
Memo
)
=>
memo
.
name
!==
context
.
memoName
&&
!
context
.
relationList
.
some
((
relation
)
=>
relation
.
relatedMemo
===
memo
.
name
),
});
});
};
};
...
...
web/src/components/MemoRelationListView.tsx
View file @
c4a24bea
import
{
memo
,
useEffect
,
useState
}
from
"react"
;
import
clsx
from
"clsx"
;
import
{
memo
,
useState
}
from
"react"
;
import
{
Link
}
from
"react-router-dom"
;
import
useAsyncEffect
from
"@/hooks/useAsyncEffect"
;
import
{
useMemoStore
}
from
"@/store/v1"
;
import
{
useMemoStore
}
from
"@/store/v1"
;
import
{
MemoRelation
}
from
"@/types/proto/api/v1/memo_relation_service"
;
import
{
MemoRelation
}
from
"@/types/proto/api/v1/memo_relation_service"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Memo
}
from
"@/types/proto/api/v1/memo_service"
;
import
EmbeddedContent
from
"./MemoContent/EmbeddedContent
"
;
import
Icon
from
"./Icon
"
;
interface
Props
{
interface
Props
{
memo
:
Memo
;
memo
:
Memo
;
...
@@ -13,26 +16,96 @@ const MemoRelationListView = (props: Props) => {
...
@@ -13,26 +16,96 @@ const MemoRelationListView = (props: Props) => {
const
{
memo
,
relations
:
relationList
}
=
props
;
const
{
memo
,
relations
:
relationList
}
=
props
;
const
memoStore
=
useMemoStore
();
const
memoStore
=
useMemoStore
();
const
[
referencingMemoList
,
setReferencingMemoList
]
=
useState
<
Memo
[]
>
([]);
const
[
referencingMemoList
,
setReferencingMemoList
]
=
useState
<
Memo
[]
>
([]);
const
[
referencedMemoList
,
setReferencedMemoList
]
=
useState
<
Memo
[]
>
([]);
const
[
selectedTab
,
setSelectedTab
]
=
useState
<
"referencing"
|
"referenced"
>
(
"referencing"
);
useEffect
(()
=>
{
useAsyncEffect
(
async
()
=>
{
(
async
()
=>
{
const
referencingMemoList
=
await
Promise
.
all
(
const
referencingMemoList
=
await
Promise
.
all
(
relationList
relationList
.
filter
((
relation
)
=>
relation
.
memo
===
memo
.
name
&&
relation
.
relatedMemo
!==
memo
.
name
)
.
filter
((
relation
)
=>
relation
.
memo
===
memo
.
name
&&
relation
.
relatedMemo
!==
memo
.
name
)
.
map
((
relation
)
=>
memoStore
.
getOrFetchMemoByName
(
relation
.
relatedMemo
,
{
skipStore
:
true
})),
.
map
((
relation
)
=>
memoStore
.
getOrFetchMemoByName
(
relation
.
relatedMemo
,
{
skipStore
:
true
})),
);
);
setReferencingMemoList
(
referencingMemoList
);
setReferencingMemoList
(
referencingMemoList
);
})();
const
referencedMemoList
=
await
Promise
.
all
(
},
[
memo
,
relationList
]);
relationList
.
filter
((
relation
)
=>
relation
.
memo
!==
memo
.
name
&&
relation
.
relatedMemo
===
memo
.
name
)
.
map
((
relation
)
=>
memoStore
.
getOrFetchMemoByName
(
relation
.
memo
,
{
skipStore
:
true
})),
);
setReferencedMemoList
(
referencedMemoList
);
if
(
referencingMemoList
.
length
===
0
)
{
setSelectedTab
(
"referenced"
);
}
else
{
setSelectedTab
(
"referencing"
);
}
},
[
memo
.
name
,
relationList
]);
if
(
referencingMemoList
.
length
+
referencedMemoList
.
length
===
0
)
{
return
null
;
}
return
(
return
(
referencingMemoList
.
length
>
0
&&
(
<
div
className=
"relative flex flex-col justify-start items-start w-full px-2 pt-2 pb-1 bg-zinc-50 dark:bg-zinc-900 rounded-lg border border-gray-200 dark:border-zinc-700"
>
<
div
className=
"w-full flex flex-row justify-start items-center flex-wrap gap-2"
>
<
div
className=
"w-full flex flex-row justify-start items-center mb-1 gap-3 opacity-60"
>
{
referencingMemoList
.
length
>
0
&&
(
<
button
className=
{
clsx
(
"w-auto flex flex-row justify-start items-center text-xs gap-0.5 text-gray-500"
,
selectedTab
===
"referencing"
&&
"text-gray-800 dark:text-gray-400"
,
)
}
onClick=
{
()
=>
setSelectedTab
(
"referencing"
)
}
>
<
Icon
.
Link
className=
"w-3 h-auto shrink-0 opacity-70"
/>
<
span
>
Referencing
</
span
>
</
button
>
)
}
{
referencedMemoList
.
length
>
0
&&
(
<
button
className=
{
clsx
(
"w-auto flex flex-row justify-start items-center text-xs gap-0.5 text-gray-500"
,
selectedTab
===
"referenced"
&&
"text-gray-800 dark:text-gray-400"
,
)
}
onClick=
{
()
=>
setSelectedTab
(
"referenced"
)
}
>
<
Icon
.
Milestone
className=
"w-3 h-auto shrink-0 opacity-70"
/>
<
span
>
Referenced by
</
span
>
</
button
>
)
}
</
div
>
{
selectedTab
===
"referencing"
&&
referencingMemoList
.
length
>
0
&&
(
<
div
className=
"w-full flex flex-col justify-start items-start"
>
{
referencingMemoList
.
map
((
memo
)
=>
{
{
referencingMemoList
.
map
((
memo
)
=>
{
return
<
EmbeddedContent
key=
{
memo
.
uid
}
resourceName=
{
`memos/${memo.uid}`
}
params=
{
"snippet"
}
/>;
return
(
<
Link
key=
{
memo
.
name
}
className=
"w-auto max-w-full flex flex-row justify-start items-center text-sm leading-5 text-gray-600 dark:text-gray-400 dark:border-zinc-700 dark:bg-zinc-900 hover:underline"
to=
{
`/m/${memo.uid}`
}
unstable_viewTransition
>
<
Icon
.
Dot
className=
"shrink-0 -ml-1 opacity-60"
/>
<
span
className=
"truncate"
>
{
memo
.
snippet
}
</
span
>
</
Link
>
);
})
}
})
}
</
div
>
</
div
>
)
)
}
{
selectedTab
===
"referenced"
&&
referencedMemoList
.
length
>
0
&&
(
<
div
className=
"w-full flex flex-col justify-start items-start"
>
{
referencedMemoList
.
map
((
memo
)
=>
{
return
(
<
Link
key=
{
memo
.
name
}
className=
"w-auto max-w-full flex flex-row justify-start items-center text-sm leading-5 text-gray-600 dark:text-gray-400 dark:border-zinc-700 dark:bg-zinc-900 hover:underline"
to=
{
`/m/${memo.uid}`
}
unstable_viewTransition
>
<
Icon
.
Dot
className=
"shrink-0 -ml-1 opacity-60"
/>
<
span
className=
"truncate"
>
{
memo
.
snippet
}
</
span
>
</
Link
>
);
})
}
</
div
>
)
}
</
div
>
);
);
};
};
...
...
web/src/store/v1/memo.ts
View file @
c4a24bea
...
@@ -48,17 +48,6 @@ export const useMemoStore = create(
...
@@ -48,17 +48,6 @@ export const useMemoStore = create(
getMemoByName
:
(
name
:
string
)
=>
{
getMemoByName
:
(
name
:
string
)
=>
{
return
get
().
memoMapByName
[
name
];
return
get
().
memoMapByName
[
name
];
},
},
searchMemos
:
async
(
filter
:
string
)
=>
{
const
{
memos
}
=
await
memoServiceClient
.
searchMemos
({
filter
,
});
const
memoMap
=
get
().
memoMapByName
;
for
(
const
memo
of
memos
)
{
memoMap
[
memo
.
name
]
=
memo
;
}
set
({
stateId
:
uniqueId
(),
memoMapByName
:
memoMap
});
return
memos
;
},
fetchMemoByUid
:
async
(
uid
:
string
)
=>
{
fetchMemoByUid
:
async
(
uid
:
string
)
=>
{
const
memo
=
await
memoServiceClient
.
getMemoByUid
({
const
memo
=
await
memoServiceClient
.
getMemoByUid
({
uid
,
uid
,
...
...
web/src/store/v1/resource.ts
View file @
c4a24bea
...
@@ -15,17 +15,6 @@ export const useResourceStore = create(
...
@@ -15,17 +15,6 @@ export const useResourceStore = create(
combine
(
getDefaultState
(),
(
set
,
get
)
=>
({
combine
(
getDefaultState
(),
(
set
,
get
)
=>
({
setState
:
(
state
:
State
)
=>
set
(
state
),
setState
:
(
state
:
State
)
=>
set
(
state
),
getState
:
()
=>
get
(),
getState
:
()
=>
get
(),
searchResources
:
async
(
filter
:
string
)
=>
{
const
{
resources
}
=
await
resourceServiceClient
.
searchResources
({
filter
,
});
const
resourceMap
=
get
().
resourceMapByName
;
for
(
const
resource
of
resources
)
{
resourceMap
[
resource
.
name
]
=
resource
;
}
set
({
resourceMapByName
:
resourceMap
});
return
resources
;
},
fetchResourceByUID
:
async
(
uid
:
string
)
=>
{
fetchResourceByUID
:
async
(
uid
:
string
)
=>
{
const
resource
=
await
resourceServiceClient
.
getResourceByUid
({
const
resource
=
await
resourceServiceClient
.
getResourceByUid
({
uid
,
uid
,
...
...
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