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
c6a09d93
Commit
c6a09d93
authored
Jul 26, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: update memo filter styles
parent
cd38ec93
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
59 additions
and
219 deletions
+59
-219
TagsSection.tsx
web/src/components/HomeSidebar/TagsSection.tsx
+10
-10
MemoFilters.tsx
web/src/components/MemoFilters.tsx
+33
-12
SearchBar.tsx
web/src/components/SearchBar.tsx
+1
-0
UserStatisticsView.tsx
web/src/components/UserStatisticsView.tsx
+3
-9
index.ts
web/src/store/index.ts
+0
-4
filter.ts
web/src/store/module/filter.ts
+0
-52
index.ts
web/src/store/module/index.ts
+0
-1
filter.ts
web/src/store/reducer/filter.ts
+0
-65
resource.ts
web/src/store/reducer/resource.ts
+0
-47
memoFilter.ts
web/src/store/v1/memoFilter.ts
+12
-19
No files found.
web/src/components/HomeSidebar/TagsSection.tsx
View file @
c6a09d93
...
...
@@ -6,8 +6,7 @@ import useDebounce from "react-use/lib/useDebounce";
import
useLocalStorage
from
"react-use/lib/useLocalStorage"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useFilterStore
}
from
"@/store/module"
;
import
{
useMemoList
,
useTagStore
}
from
"@/store/v1"
;
import
{
useMemoFilterStore
,
useMemoList
,
useTagStore
}
from
"@/store/v1"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
Icon
from
"../Icon"
;
import
showRenameTagDialog
from
"../RenameTagDialog"
;
...
...
@@ -22,7 +21,7 @@ const TagsSection = (props: Props) => {
const
t
=
useTranslate
();
const
location
=
useLocation
();
const
user
=
useCurrentUser
();
const
filterStore
=
use
FilterStore
();
const
memoFilterStore
=
useMemo
FilterStore
();
const
tagStore
=
useTagStore
();
const
memoList
=
useMemoList
();
const
[
treeMode
,
setTreeMode
]
=
useLocalStorage
<
boolean
>
(
"tag-view-as-tree"
,
false
);
...
...
@@ -37,10 +36,14 @@ const TagsSection = (props: Props) => {
};
const
handleTagClick
=
(
tag
:
string
)
=>
{
if
(
filterStore
.
getState
().
tag
===
tag
)
{
filterStore
.
setTagFilter
(
undefined
);
const
isActive
=
memoFilterStore
.
getFiltersByFactor
(
"tag"
).
some
((
filter
)
=>
filter
.
value
===
tag
);
if
(
isActive
)
{
memoFilterStore
.
removeFilter
((
f
)
=>
f
.
factor
===
"tag"
&&
f
.
value
===
tag
);
}
else
{
filterStore
.
setTagFilter
(
tag
);
memoFilterStore
.
addFilter
({
factor
:
"tag"
,
value
:
tag
,
});
}
};
...
...
@@ -103,10 +106,7 @@ const TagsSection = (props: Props) => {
</
Menu
>
</
Dropdown
>
<
div
className=
{
clsx
(
"inline-flex flex-nowrap ml-0.5 gap-0.5 cursor-pointer max-w-[calc(100%-16px)]"
,
filterStore
.
state
.
tag
===
tag
&&
"text-blue-600 dark:text-blue-400"
,
)
}
className=
{
clsx
(
"inline-flex flex-nowrap ml-0.5 gap-0.5 cursor-pointer max-w-[calc(100%-16px)]"
)
}
onClick=
{
()
=>
handleTagClick
(
tag
)
}
>
<
span
className=
"truncate dark:opacity-80"
>
{
tag
}
</
span
>
...
...
web/src/components/MemoFilters.tsx
View file @
c6a09d93
import
{
isEqual
}
from
"lodash-es"
;
import
{
useMemoFilterStore
}
from
"@/store/v1"
;
import
{
FilterFactor
,
getMemoFilterKey
,
MemoFilter
,
useMemoFilterStore
}
from
"@/store/v1"
;
import
Icon
from
"./Icon"
;
const
MemoFilters
=
()
=>
{
const
memoFilterStore
=
useMemoFilterStore
();
const
filters
=
memoFilterStore
.
filters
;
const
getFilterDisplayText
=
(
filter
:
MemoFilter
)
=>
{
if
(
filter
.
value
)
{
return
filter
.
value
;
}
if
(
filter
.
factor
.
startsWith
(
"property."
))
{
return
filter
.
factor
.
replace
(
"property."
,
""
);
}
return
filter
.
factor
;
};
if
(
filters
.
length
===
0
)
{
return
undefined
;
}
return
(
<
div
className=
"w-full mb-2 flex flex-row justify-start items-start gap-2"
>
<
span
className=
"flex flex-row items-center gap-0.5 text-gray-500 text-sm leading-6"
>
<
span
className=
"flex flex-row items-center gap-0.5 text-gray-500 text-sm leading-6
border border-transparent
"
>
<
Icon
.
Filter
className=
"w-4 h-auto opacity-60 inline"
/>
Filters
</
span
>
<
div
className=
"flex flex-row justify-start items-center flex-wrap gap-2 leading-6"
>
<
div
className=
"flex flex-row justify-start items-center flex-wrap gap-2 leading-6
h-6
"
>
{
filters
.
map
((
filter
)
=>
(
<
div
key=
{
filter
.
factor
}
className=
"flex flex-row items-center gap-1 bg-gray-100 dark:bg-zinc-800 border dark:border-zinc-700 px-1 rounded-md"
key=
{
getMemoFilterKey
(
filter
)
}
className=
"flex flex-row items-center gap-1 bg-white dark:bg-zinc-800 border dark:border-zinc-700 pl-1.5 pr-1 rounded-md hover:line-through cursor-pointer"
onClick=
{
()
=>
memoFilterStore
.
removeFilter
((
f
)
=>
isEqual
(
f
,
filter
))
}
>
<
span
className=
"text-gray-600 dark:text-gray-500 text-sm"
>
{
filter
.
factor
}
</
span
>
{
filter
.
value
&&
<
span
className=
"text-gray-500 dark:text-gray-400 text-sm max-w-12 truncate"
>
{
filter
.
value
}
</
span
>
}
<
button
onClick=
{
()
=>
memoFilterStore
.
removeFilter
((
f
)
=>
isEqual
(
f
,
filter
))
}
className=
"text-gray-500 dark:text-gray-300 opacity-60 hover:opacity-100"
>
<
Icon
.
X
className=
"w-3 h-auto"
/>
<
FactorIcon
className=
"w-4 h-auto text-gray-500 dark:text-gray-400 opacity-60"
factor=
{
filter
.
factor
}
/>
<
span
className=
"text-gray-500 dark:text-gray-400 text-sm max-w-32 truncate"
>
{
getFilterDisplayText
(
filter
)
}
</
span
>
<
button
className=
"text-gray-500 dark:text-gray-300 opacity-60 hover:opacity-100"
>
<
Icon
.
X
className=
"w-4 h-auto"
/>
</
button
>
</
div
>
))
}
...
...
@@ -37,4 +45,17 @@ const MemoFilters = () => {
);
};
const
FactorIcon
=
({
factor
,
className
}:
{
factor
:
FilterFactor
;
className
?:
string
})
=>
{
const
iconMap
=
{
tag
:
<
Icon
.
Tag
className=
{
className
}
/>,
visibility
:
<
Icon
.
Eye
className=
{
className
}
/>,
contentSearch
:
<
Icon
.
Search
className=
{
className
}
/>,
displayTime
:
<
Icon
.
Calendar
className=
{
className
}
/>,
"property.hasLink"
:
<
Icon
.
Link
className
=
{
className
}
/>
,
"property.hasTaskList"
:
<
Icon
.
CheckCircle
className
=
{
className
}
/>
,
"property.hasCode"
:
<
Icon
.
Code
className
=
{
className
}
/>
,
};
return
iconMap
[
factor
as
keyof
typeof
iconMap
]
||
<></>;
};
export
default
MemoFilters
;
web/src/components/SearchBar.tsx
View file @
c6a09d93
...
...
@@ -21,6 +21,7 @@ const SearchBar = () => {
factor
:
"contentSearch"
,
value
:
queryText
,
});
setQueryText
(
""
);
}
}
};
...
...
web/src/components/UserStatisticsView.tsx
View file @
c6a09d93
...
...
@@ -116,9 +116,7 @@ const UserStatisticsView = () => {
<
Divider
className=
"!my-2 opacity-50"
/>
<
div
className=
"w-full flex flex-row justify-start items-center gap-x-2 gap-y-1 flex-wrap"
>
<
div
className=
{
clsx
(
"w-auto border dark:border-zinc-800 pl-1 pr-1.5 rounded-md flex justify-between items-center cursor-pointer hover:shadow"
,
)
}
className=
{
clsx
(
"w-auto border dark:border-zinc-800 pl-1 pr-1.5 rounded-md flex justify-between items-center"
)
}
onClick=
{
()
=>
memoFilterStore
.
addFilter
({
factor
:
"property.hasLink"
,
value
:
""
})
}
>
<
div
className=
"w-auto flex justify-start items-center mr-1"
>
...
...
@@ -128,9 +126,7 @@ const UserStatisticsView = () => {
<
span
className=
"text-sm truncate"
>
{
memoStats
.
link
}
</
span
>
</
div
>
<
div
className=
{
clsx
(
"w-auto border dark:border-zinc-800 pl-1 pr-1.5 rounded-md flex justify-between items-center cursor-pointer hover:shadow"
,
)
}
className=
{
clsx
(
"w-auto border dark:border-zinc-800 pl-1 pr-1.5 rounded-md flex justify-between items-center"
)
}
onClick=
{
()
=>
memoFilterStore
.
addFilter
({
factor
:
"property.hasTaskList"
,
value
:
""
})
}
>
<
div
className=
"w-auto flex justify-start items-center mr-1"
>
...
...
@@ -154,9 +150,7 @@ const UserStatisticsView = () => {
)
}
</
div
>
<
div
className=
{
clsx
(
"w-auto border dark:border-zinc-800 pl-1 pr-1.5 rounded-md flex justify-between items-center cursor-pointer hover:shadow"
,
)
}
className=
{
clsx
(
"w-auto border dark:border-zinc-800 pl-1 pr-1.5 rounded-md flex justify-between items-center"
)
}
onClick=
{
()
=>
memoFilterStore
.
addFilter
({
factor
:
"property.hasCode"
,
value
:
""
})
}
>
<
div
className=
"w-auto flex justify-start items-center mr-1"
>
...
...
web/src/store/index.ts
View file @
c6a09d93
import
{
configureStore
}
from
"@reduxjs/toolkit"
;
import
{
TypedUseSelectorHook
,
useDispatch
,
useSelector
}
from
"react-redux"
;
import
dialogReducer
from
"./reducer/dialog"
;
import
filterReducer
from
"./reducer/filter"
;
import
resourceReducer
from
"./reducer/resource"
;
const
store
=
configureStore
({
reducer
:
{
filter
:
filterReducer
,
resource
:
resourceReducer
,
dialog
:
dialogReducer
,
},
});
...
...
web/src/store/module/filter.ts
deleted
100644 → 0
View file @
cd38ec93
import
{
Visibility
}
from
"@/types/proto/api/v1/memo_service"
;
import
store
,
{
useAppSelector
}
from
".."
;
import
{
MemoPropertyFilter
,
setFilter
,
setMemoPropertyFilter
}
from
"../reducer/filter"
;
export
const
useFilterStore
=
()
=>
{
const
state
=
useAppSelector
((
state
)
=>
state
.
filter
);
return
{
state
,
getState
:
()
=>
{
return
store
.
getState
().
filter
;
},
clearFilter
:
()
=>
{
store
.
dispatch
(
setFilter
({
tag
:
undefined
,
text
:
undefined
,
visibility
:
undefined
,
memoPropertyFilter
:
undefined
,
}),
);
},
setTextFilter
:
(
text
?:
string
)
=>
{
store
.
dispatch
(
setFilter
({
text
:
text
,
}),
);
},
setTagFilter
:
(
tag
?:
string
)
=>
{
store
.
dispatch
(
setFilter
({
tag
:
tag
,
}),
);
},
setMemoVisibilityFilter
:
(
visibility
?:
Visibility
)
=>
{
store
.
dispatch
(
setFilter
({
visibility
:
visibility
,
}),
);
},
setMemoPropertyFilter
:
(
memoPropertyFilter
:
Partial
<
MemoPropertyFilter
>
)
=>
{
store
.
dispatch
(
setMemoPropertyFilter
({
...
memoPropertyFilter
,
}),
);
},
};
};
web/src/store/module/index.ts
View file @
c6a09d93
export
*
from
"./filter"
;
export
*
from
"./dialog"
;
web/src/store/reducer/filter.ts
deleted
100644 → 0
View file @
cd38ec93
import
{
createSlice
,
PayloadAction
}
from
"@reduxjs/toolkit"
;
import
{
Visibility
}
from
"@/types/proto/api/v1/memo_service"
;
interface
State
{
tag
?:
string
;
text
?:
string
;
visibility
?:
Visibility
;
memoPropertyFilter
?:
MemoPropertyFilter
;
}
export
interface
MemoPropertyFilter
{
hasLink
?:
boolean
;
hasTaskList
?:
boolean
;
hasCode
?:
boolean
;
}
export
type
Filter
=
State
;
const
getInitialState
=
():
State
=>
{
const
state
:
State
=
{};
const
urlParams
=
new
URLSearchParams
(
location
.
search
);
const
tag
=
urlParams
.
get
(
"tag"
);
const
text
=
urlParams
.
get
(
"text"
);
if
(
tag
)
{
state
.
tag
=
tag
;
}
if
(
text
)
{
state
.
text
=
text
;
}
return
state
;
};
const
filterSlice
=
createSlice
({
name
:
"filter"
,
initialState
:
getInitialState
(),
reducers
:
{
setFilter
:
(
state
,
action
:
PayloadAction
<
Partial
<
State
>>
)
=>
{
if
(
JSON
.
stringify
(
action
.
payload
)
===
state
)
{
return
state
;
}
return
{
...
state
,
...
action
.
payload
,
};
},
setMemoPropertyFilter
:
(
state
,
action
:
PayloadAction
<
Partial
<
MemoPropertyFilter
>>
)
=>
{
if
(
JSON
.
stringify
(
action
.
payload
)
===
state
.
memoPropertyFilter
)
{
return
state
;
}
return
{
...
state
,
memoPropertyFilter
:
{
...
state
.
memoPropertyFilter
,
...
action
.
payload
,
},
};
},
},
});
export
const
{
setFilter
,
setMemoPropertyFilter
}
=
filterSlice
.
actions
;
export
default
filterSlice
.
reducer
;
web/src/store/reducer/resource.ts
deleted
100644 → 0
View file @
cd38ec93
import
{
createSlice
,
PayloadAction
}
from
"@reduxjs/toolkit"
;
import
{
uniqBy
}
from
"lodash-es"
;
import
{
Resource
}
from
"@/types/proto/api/v1/resource_service"
;
interface
State
{
resources
:
Resource
[];
}
const
resourceSlice
=
createSlice
({
name
:
"resource"
,
initialState
:
{
resources
:
[],
}
as
State
,
reducers
:
{
setResources
:
(
state
,
action
:
PayloadAction
<
Resource
[]
>
)
=>
{
return
{
...
state
,
resources
:
action
.
payload
,
};
},
upsertResources
:
(
state
,
action
:
PayloadAction
<
Resource
[]
>
)
=>
{
return
{
...
state
,
resources
:
uniqBy
([...
action
.
payload
,
...
state
.
resources
],
"name"
),
};
},
patchResource
:
(
state
,
action
:
PayloadAction
<
Partial
<
Resource
>>
)
=>
{
return
{
...
state
,
resources
:
state
.
resources
.
map
((
resource
)
=>
{
if
(
resource
.
name
===
action
.
payload
.
name
)
{
return
{
...
resource
,
...
action
.
payload
,
};
}
else
{
return
resource
;
}
}),
};
},
},
});
export
const
{
setResources
,
upsertResources
,
patchResource
}
=
resourceSlice
.
actions
;
export
default
resourceSlice
.
reducer
;
web/src/store/v1/memoFilter.ts
View file @
c6a09d93
import
{
uniq
}
from
"lodash-es"
;
import
{
uniq
By
}
from
"lodash-es"
;
import
{
create
}
from
"zustand"
;
import
{
combine
,
persist
}
from
"zustand/middleware"
;
import
{
combine
}
from
"zustand/middleware"
;
type
FilterFactor
=
export
type
FilterFactor
=
|
"tag"
|
"visibility"
|
"contentSearch"
...
...
@@ -16,25 +16,18 @@ export interface MemoFilter {
value
:
string
;
}
export
const
getMemoFilterKey
=
(
filter
:
MemoFilter
)
=>
`
${
filter
.
factor
}
:
${
filter
.
value
}
`
;
interface
State
{
filters
:
MemoFilter
[];
}
const
getDefaultState
=
():
State
=>
({
filters
:
[],
});
export
const
useMemoFilterStore
=
create
(
persist
(
combine
(
getDefaultState
(),
(
set
,
get
)
=>
({
setState
:
(
state
:
State
)
=>
set
(
state
),
getState
:
()
=>
get
(),
getFiltersByFactor
:
(
factor
:
FilterFactor
)
=>
get
().
filters
.
filter
((
f
)
=>
f
.
factor
===
factor
),
addFilter
:
(
filter
:
MemoFilter
)
=>
set
((
state
)
=>
({
filters
:
uniq
([...
state
.
filters
,
filter
])
})),
removeFilter
:
(
filterFn
:
(
f
:
MemoFilter
)
=>
boolean
)
=>
set
((
state
)
=>
({
filters
:
state
.
filters
.
filter
((
f
)
=>
!
filterFn
(
f
))
})),
})),
{
name
:
"memo-filter"
,
},
),
combine
((():
State
=>
({
filters
:
[]
}))(),
(
set
,
get
)
=>
({
setState
:
(
state
:
State
)
=>
set
(
state
),
getState
:
()
=>
get
(),
getFiltersByFactor
:
(
factor
:
FilterFactor
)
=>
get
().
filters
.
filter
((
f
)
=>
f
.
factor
===
factor
),
addFilter
:
(
filter
:
MemoFilter
)
=>
set
((
state
)
=>
({
filters
:
uniqBy
([...
state
.
filters
,
filter
],
getMemoFilterKey
)
})),
removeFilter
:
(
filterFn
:
(
f
:
MemoFilter
)
=>
boolean
)
=>
set
((
state
)
=>
({
filters
:
state
.
filters
.
filter
((
f
)
=>
!
filterFn
(
f
))
})),
})),
);
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