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
6d5e1def
Commit
6d5e1def
authored
Jan 25, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: update member section
parent
a5bc2d0e
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
84 additions
and
33 deletions
+84
-33
CreateMemoRelationDialog.tsx
web/src/components/CreateMemoRelationDialog.tsx
+3
-3
MemberSection.tsx
web/src/components/Settings/MemberSection.tsx
+68
-28
en.json
web/src/locales/en.json
+2
-1
user.ts
web/src/store/v1/user.ts
+11
-1
No files found.
web/src/components/CreateMemoRelationDialog.tsx
View file @
6d5e1def
...
...
@@ -88,13 +88,13 @@ const CreateMemoRelationDialog: React.FC<Props> = (props: Props) => {
return
(
<>
<
div
className=
"dialog-header-container"
>
<
div
className=
"dialog-header-container
!w-96
"
>
<
p
className=
"title-text"
>
{
"Add references"
}
</
p
>
<
IconButton
size=
"sm"
onClick=
{
()
=>
destroy
()
}
>
<
Icon
.
X
className=
"w-5 h-auto"
/>
</
IconButton
>
</
div
>
<
div
className=
"dialog-content-container
!w-80
"
>
<
div
className=
"dialog-content-container
max-w-[24rem]
"
>
<
Autocomplete
className=
"w-full"
size=
"md"
...
...
@@ -133,7 +133,7 @@ const CreateMemoRelationDialog: React.FC<Props> = (props: Props) => {
}
onChange=
{
(
_
,
value
)
=>
setSelectedMemos
(
value
)
}
/>
<
div
className=
"mt-
2
w-full flex flex-row justify-end items-center space-x-1"
>
<
div
className=
"mt-
4
w-full flex flex-row justify-end items-center space-x-1"
>
<
Button
variant=
"plain"
color=
"neutral"
onClick=
{
handleCloseDialog
}
>
{
t
(
"common.cancel"
)
}
</
Button
>
...
...
web/src/components/Settings/MemberSection.tsx
View file @
6d5e1def
import
{
Button
,
Dropdown
,
Input
,
Menu
,
MenuButton
}
from
"@mui/joy"
;
import
{
Button
,
Dropdown
,
Input
,
Menu
,
MenuButton
,
Radio
,
RadioGroup
}
from
"@mui/joy"
;
import
{
sortBy
}
from
"lodash-es"
;
import
React
,
{
useEffect
,
useState
}
from
"react"
;
import
{
toast
}
from
"react-hot-toast"
;
import
{
userServiceClient
}
from
"@/grpcweb"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
UserNamePrefix
,
useUserStore
}
from
"@/store/v1"
;
import
{
UserNamePrefix
,
stringifyUserRole
,
useUserStore
}
from
"@/store/v1"
;
import
{
RowStatus
}
from
"@/types/proto/api/v2/common"
;
import
{
User
,
User_Role
}
from
"@/types/proto/api/v2/user_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
...
...
@@ -12,8 +13,7 @@ import { showCommonDialog } from "../Dialog/CommonDialog";
import
Icon
from
"../Icon"
;
interface
State
{
createUserUsername
:
string
;
createUserPassword
:
string
;
creatingUser
:
User
;
}
const
MemberSection
=
()
=>
{
...
...
@@ -21,36 +21,56 @@ const MemberSection = () => {
const
currentUser
=
useCurrentUser
();
const
userStore
=
useUserStore
();
const
[
state
,
setState
]
=
useState
<
State
>
({
createUserUsername
:
""
,
createUserPassword
:
""
,
creatingUser
:
User
.
fromPartial
({
username
:
""
,
password
:
""
,
role
:
User_Role
.
USER
,
}),
});
const
[
userList
,
setUserList
]
=
useState
<
User
[]
>
([]);
const
[
users
,
setUsers
]
=
useState
<
User
[]
>
([]);
const
sortedUsers
=
sortBy
(
users
,
"id"
);
useEffect
(()
=>
{
fetchUser
List
();
fetchUser
s
();
},
[]);
const
fetchUser
List
=
async
()
=>
{
const
fetchUser
s
=
async
()
=>
{
const
users
=
await
userStore
.
fetchUsers
();
setUser
List
(
users
);
setUser
s
(
users
);
};
const
handleUsernameInputChange
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
setState
({
...
state
,
createUserUsername
:
event
.
target
.
value
,
creatingUser
:
{
...
state
.
creatingUser
,
username
:
event
.
target
.
value
,
},
});
};
const
handlePasswordInputChange
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
setState
({
...
state
,
createUserPassword
:
event
.
target
.
value
,
creatingUser
:
{
...
state
.
creatingUser
,
password
:
event
.
target
.
value
,
},
});
};
const
handleUserRoleInputChange
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
setState
({
...
state
,
creatingUser
:
{
...
state
.
creatingUser
,
role
:
Number
(
event
.
target
.
value
)
as
User_Role
,
},
});
};
const
handleCreateUserBtnClick
=
async
()
=>
{
if
(
state
.
creat
eUserUsername
===
""
||
state
.
createUserP
assword
===
""
)
{
if
(
state
.
creat
ingUser
.
username
===
""
||
state
.
creatingUser
.
p
assword
===
""
)
{
toast
.
error
(
t
(
"message.fill-form"
));
return
;
}
...
...
@@ -58,18 +78,22 @@ const MemberSection = () => {
try
{
await
userServiceClient
.
createUser
({
user
:
{
name
:
`
${
UserNamePrefix
}${
state
.
creat
eUserU
sername
}
`
,
password
:
state
.
creat
eUserP
assword
,
role
:
User_Role
.
USER
,
name
:
`
${
UserNamePrefix
}${
state
.
creat
ingUser
.
u
sername
}
`
,
password
:
state
.
creat
ingUser
.
p
assword
,
role
:
state
.
creatingUser
.
role
,
},
});
}
catch
(
error
:
any
)
{
toast
.
error
(
error
.
details
);
}
await
fetchUser
List
();
await
fetchUser
s
();
setState
({
createUserUsername
:
""
,
createUserPassword
:
""
,
...
state
,
creatingUser
:
User
.
fromPartial
({
username
:
""
,
password
:
""
,
role
:
User_Role
.
USER
,
}),
});
};
...
...
@@ -91,7 +115,7 @@ const MemberSection = () => {
},
updateMask
:
[
"row_status"
],
});
fetchUser
List
();
fetchUser
s
();
},
});
};
...
...
@@ -104,7 +128,7 @@ const MemberSection = () => {
},
updateMask
:
[
"row_status"
],
});
fetchUser
List
();
fetchUser
s
();
};
const
handleDeleteUserClick
=
(
user
:
User
)
=>
{
...
...
@@ -115,7 +139,7 @@ const MemberSection = () => {
dialogName
:
"delete-user-dialog"
,
onConfirm
:
async
()
=>
{
await
userStore
.
deleteUser
(
user
.
name
);
fetchUser
List
();
fetchUser
s
();
},
});
};
...
...
@@ -126,13 +150,25 @@ const MemberSection = () => {
<
div
className=
"w-full flex flex-col justify-start items-start gap-2"
>
<
div
className=
"flex flex-col justify-start items-start gap-1"
>
<
span
className=
"text-sm"
>
{
t
(
"common.username"
)
}
</
span
>
<
Input
type=
"text"
placeholder=
{
t
(
"common.username"
)
}
value=
{
state
.
creat
eUserU
sername
}
onChange=
{
handleUsernameInputChange
}
/>
<
Input
type=
"text"
placeholder=
{
t
(
"common.username"
)
}
value=
{
state
.
creat
ingUser
.
u
sername
}
onChange=
{
handleUsernameInputChange
}
/>
</
div
>
<
div
className=
"flex flex-col justify-start items-start gap-1"
>
<
span
className=
"text-sm"
>
{
t
(
"common.password"
)
}
</
span
>
<
Input
type=
"password"
placeholder=
{
t
(
"common.password"
)
}
value=
{
state
.
createUserPassword
}
onChange=
{
handlePasswordInputChange
}
/>
<
Input
type=
"password"
placeholder=
{
t
(
"common.password"
)
}
value=
{
state
.
creatingUser
.
password
}
onChange=
{
handlePasswordInputChange
}
/>
</
div
>
<
div
className=
"flex flex-col justify-start items-start gap-1"
>
<
span
className=
"text-sm"
>
{
t
(
"common.role"
)
}
</
span
>
<
RadioGroup
size=
"sm"
orientation=
"horizontal"
defaultValue=
{
User_Role
.
USER
}
onChange=
{
handleUserRoleInputChange
}
>
<
Radio
value=
{
User_Role
.
USER
}
label=
"User"
/>
<
Radio
value=
{
User_Role
.
ADMIN
}
label=
"Admin"
/>
</
RadioGroup
>
</
div
>
<
div
className=
"
btns-container
"
>
<
div
className=
"
mt-2
"
>
<
Button
onClick=
{
handleCreateUserBtnClick
}
>
{
t
(
"common.create"
)
}
</
Button
>
</
div
>
</
div
>
...
...
@@ -144,9 +180,12 @@ const MemberSection = () => {
<
table
className=
"min-w-full divide-y divide-gray-300 dark:divide-zinc-600"
>
<
thead
>
<
tr
className=
"text-sm font-semibold text-left text-gray-900 dark:text-gray-400"
>
<
th
scope=
"col"
className=
"p
y-2 pl-4 pr-3
"
>
<
th
scope=
"col"
className=
"p
x-3 py-2
"
>
ID
</
th
>
<
th
scope=
"col"
className=
"px-3 py-2"
>
{
t
(
"common.role"
)
}
</
th
>
<
th
scope=
"col"
className=
"px-3 py-2"
>
{
t
(
"common.username"
)
}
</
th
>
...
...
@@ -160,9 +199,10 @@ const MemberSection = () => {
</
tr
>
</
thead
>
<
tbody
className=
"divide-y divide-gray-200 dark:divide-zinc-600"
>
{
userList
.
map
((
user
)
=>
(
{
sortedUsers
.
map
((
user
)
=>
(
<
tr
key=
{
user
.
id
}
>
<
td
className=
"whitespace-nowrap py-2 pl-4 pr-3 text-sm text-gray-900 dark:text-gray-400"
>
{
user
.
id
}
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-gray-900 dark:text-gray-400"
>
{
user
.
id
}
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-gray-500 dark:text-gray-400"
>
{
stringifyUserRole
(
user
.
role
)
}
</
td
>
<
td
className=
"whitespace-nowrap px-3 py-2 text-sm text-gray-500 dark:text-gray-400"
>
{
user
.
username
}
<
span
className=
"ml-1 italic"
>
{
user
.
rowStatus
===
RowStatus
.
ARCHIVED
&&
"(Archived)"
}
</
span
>
...
...
web/src/locales/en.json
View file @
6d5e1def
...
...
@@ -64,7 +64,8 @@
"mark"
:
"Mark"
,
"profile"
:
"Profile"
,
"inbox"
:
"Inbox"
,
"search"
:
"Search"
"search"
:
"Search"
,
"role"
:
"Role"
},
"router"
:
{
"go-to-home"
:
"Go to Home"
,
...
...
web/src/store/v1/user.ts
View file @
6d5e1def
import
{
create
}
from
"zustand"
;
import
{
combine
}
from
"zustand/middleware"
;
import
{
authServiceClient
,
userServiceClient
}
from
"@/grpcweb"
;
import
{
User
,
UserSetting
}
from
"@/types/proto/api/v2/user_service"
;
import
{
User
,
UserSetting
,
User_Role
}
from
"@/types/proto/api/v2/user_service"
;
import
{
UserNamePrefix
,
extractUsernameFromName
}
from
"./resourceName"
;
interface
State
{
...
...
@@ -125,3 +125,13 @@ export const useUserStore = create(
},
}))
);
export
const
stringifyUserRole
=
(
role
:
User_Role
)
=>
{
if
(
role
===
User_Role
.
HOST
)
{
return
"Host"
;
}
else
if
(
role
===
User_Role
.
ADMIN
)
{
return
"Admin"
;
}
else
{
return
"User"
;
}
};
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