Skip to content

Commit

Permalink
inputWithDebounce refactoring (#2302)
Browse files Browse the repository at this point in the history
### What's done:
 * inputWithDebounce now suggests elements with custom divs
  • Loading branch information
sanyavertolet authored Jul 7, 2023
1 parent 76f8595 commit 96d20b6
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,24 @@ package com.saveourtool.save.frontend.components.basic
import com.saveourtool.save.domain.Role
import com.saveourtool.save.domain.Role.OWNER
import com.saveourtool.save.frontend.components.inputform.inputWithDebounceForUserInfo
import com.saveourtool.save.frontend.components.inputform.renderUserWithAvatar
import com.saveourtool.save.frontend.externals.fontawesome.*
import com.saveourtool.save.frontend.utils.*
import com.saveourtool.save.info.UserInfo
import com.saveourtool.save.permission.SetRoleRequest
import com.saveourtool.save.utils.getHighestRole
import com.saveourtool.save.v1

import js.core.jso
import react.*
import react.dom.html.ReactHTML.button
import react.dom.html.ReactHTML.div
import react.dom.html.ReactHTML.img
import react.dom.html.ReactHTML.option
import react.dom.html.ReactHTML.select
import web.cssom.ClassName
import web.cssom.Height
import web.cssom.Width
import web.html.ButtonType

import kotlinx.serialization.encodeToString
Expand Down Expand Up @@ -125,117 +131,95 @@ private fun manageUserRoleCardComponent() = FC<ManageUserRoleCardProps> { props
headers = jsonHeaders,
loadingHandler = ::loadingHandler,
)
.unsafeMap {
it.decodeFromJsonString<String>()
}
.unsafeMap { it.decodeFromJsonString<String>() }
.toRole()
if (role.isLowerThan(OWNER) && props.selfUserInfo.isSuperAdmin()) {
showGlobalRoleConfirmation()
}
setSelfRole(getHighestRole(role, props.selfUserInfo.globalRole))
}

useOnce {
getUsersFromGroup()
}
useOnce { getUsersFromGroup() }

div {
className = ClassName("card card-body mt-0 pt-0 pr-0 pl-0")
div {
className = ClassName("row mt-0 ml-0 mr-0 shadow-sm rounded")
div {
className = ClassName("input-group")
inputWithDebounceForUserInfo {
getOptionFromString = { UserInfo(it) }
selectedOption = userToAdd
setSelectedOption = { setUserToAdd(it) }
getUrlForOptions = { prefix -> "$apiUrl/${props.groupType}s/${props.groupPath}/users/not-from?prefix=$prefix" }
getString = { it.name }
placeholder = "username"
decodeListFromJsonString = { it.decodeFromJsonString() }
getHTMLDataListElementFromOption = { childrenBuilder, userInfo ->
with(childrenBuilder) {
option {
value = userInfo.name
label = userInfo.source
}
}
}
}
div {
className = ClassName("input-group-append")
button {
type = ButtonType.button
className = ClassName("btn btn-sm btn-outline-success")
onClick = {
addUserToGroup()
}
disabled = userToAdd.name.isBlank()
+"Add user"
}
inputWithDebounceForUserInfo {
selectedOption = userToAdd
setSelectedOption = { setUserToAdd(it) }
onOptionClick = {
setUserToAdd(it)
addUserToGroup()
}
getUrlForOptionsFetch = { prefix -> "$apiUrl/${props.groupType}s/${props.groupPath}/users/not-from?prefix=$prefix" }
placeholder = "Input name..."
renderOption = ::renderUserWithAvatar
}
}
for (user in usersFromGroup) {
val userName = user.name
val userRole = props.getUserGroups(user)[props.groupPath] ?: Role.VIEWER
val userIndex = usersFromGroup.indexOf(user)
div {
className = ClassName("row mt-2 mr-0 justify-content-between align-items-center")
div {
for (user in usersFromGroup) {
val userName = user.name
val userRole = props.getUserGroups(user)[props.groupPath] ?: Role.VIEWER
val userIndex = usersFromGroup.indexOf(user)
div {
className = ClassName("col-7 d-flex justify-content-start align-items-center")
div {
className = ClassName("col-2 align-items-center")
fontAwesomeIcon(
when (user.source) {
"github" -> faGithub
"codehub" -> faCopyright
else -> faHome
},
classes = "h-75 w-75"
)
}
className = ClassName("row mt-2 mr-0 justify-content-between align-items-center")
div {
className = ClassName("col-7 text-left align-self-center pl-0")
+userName
}
}
div {
className = ClassName("col-5 align-self-right d-flex align-items-center justify-content-end")
button {
type = ButtonType.button
className = ClassName("btn col-2 align-items-center mr-2")
fontAwesomeIcon(icon = faTimesCircle)
val canDelete = selfRole.isSuperAdmin() ||
selfRole == OWNER && !isSelfRecord(props.selfUserInfo, user) ||
userRole.isLowerThan(selfRole)
id = "remove-user-$userIndex"
hidden = !canDelete
onClick = {
setUserToDelete(usersFromGroup[userIndex])
deleteUser()
className = ClassName("col-7 d-flex justify-content-start align-items-center")
div {
className = ClassName("col-2 align-items-center")
img {
className = ClassName("avatar avatar-user border color-bg-default rounded-circle pl-0")
src = user.avatar?.let { "/api/$v1/avatar$it" }
?: "img/undraw_profile.svg"
style = jso {
width = "2rem".unsafeCast<Width>()
height = "2rem".unsafeCast<Height>()
}
}
}
div {
className = ClassName("col-7 text-left align-self-center pl-0")
+userName
}
}
select {
className = ClassName("custom-select col-9")
onChange = { event ->
setRoleChange { SetRoleRequest(userName, event.target.value.toRole()) }
updatePermissions()
div {
className = ClassName("col-5 align-self-right d-flex align-items-center justify-content-end")
button {
type = ButtonType.button
className = ClassName("btn col-2 align-items-center mr-2")
fontAwesomeIcon(icon = faTimesCircle)
val canDelete = selfRole.isSuperAdmin() ||
selfRole == OWNER && !isSelfRecord(props.selfUserInfo, user) ||
userRole.isLowerThan(selfRole)
id = "remove-user-$userIndex"
hidden = !canDelete
onClick = {
setUserToDelete(usersFromGroup[userIndex])
deleteUser()
}
}
value = userRole.formattedName
id = "role-$userIndex"
rolesAssignableBy(selfRole)
.sortedByDescending {
it.priority
select {
className = ClassName("custom-select col-9")
onChange = { event ->
setRoleChange { SetRoleRequest(userName, event.target.value.toRole()) }
updatePermissions()
}
.map {
option {
value = it.formattedName
+it.formattedName
value = userRole.formattedName
id = "role-$userIndex"
rolesAssignableBy(selfRole)
.sortedByDescending {
it.priority
}
}
disabled = (selfRole == OWNER && isSelfRecord(props.selfUserInfo, user)) ||
!(selfRole.isHigherOrEqualThan(OWNER) || userRole.isLowerThan(selfRole))
.map {
option {
value = it.formattedName
+it.formattedName
}
}
disabled = (selfRole == OWNER && isSelfRecord(props.selfUserInfo, user)) ||
!(selfRole.isHigherOrEqualThan(OWNER) || userRole.isLowerThan(selfRole))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import com.saveourtool.save.testsuite.TestSuiteVersioned

import react.*
import react.dom.html.ReactHTML.div
import react.dom.html.ReactHTML.h5
import react.dom.html.ReactHTML.input
import react.dom.html.ReactHTML.label
import react.dom.html.ReactHTML.option
import web.cssom.ClassName
import web.html.InputType

Expand Down Expand Up @@ -112,15 +112,10 @@ private fun ChildrenBuilder.displayPermissionManager(
inputWithDebounceForString {
selectedOption = organizationName
setSelectedOption = { setOrganizationName(it) }
getOptionFromString = { it }
getString = { it }
getUrlForOptions = { prefix -> "$apiUrl/organizations/get/by-prefix?prefix=$prefix" }
getUrlForOptionsFetch = { prefix -> "$apiUrl/organizations/get/by-prefix?prefix=$prefix" }
placeholder = "Start typing organization name..."
decodeListFromJsonString = { it.decodeFromJsonString() }
getHTMLDataListElementFromOption = { childrenBuilder, organizationName ->
with(childrenBuilder) {
option { value = organizationName }
}
renderOption = { childrenBuilder, organizationName ->
with(childrenBuilder) { h5 { +organizationName } }
}
}
}
Expand Down
Loading

0 comments on commit 96d20b6

Please sign in to comment.