Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for changing between readonly and full access for CoIs. #4526

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions explore/src/clue/scala/queries/common/ProgramQueriesGQL.scala
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ object ProgramQueriesGQL:
}
"""

@GraphQL
trait ChangeProgramUserRoleMutation extends GraphQLOperation[ObservationDB]:
val document = s"""
mutation($$input: ChangeProgramUserRoleInput!) {
changeProgramUserRole(input: $$input) {
programUser {
role
}
}
}
"""

@GraphQL
trait UpdateConfigurationRequestsMutation extends GraphQLOperation[ObservationDB]:
val document = s"""
Expand Down
9 changes: 9 additions & 0 deletions explore/src/main/scala/explore/common/ProgramQueries.scala
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,15 @@ object ProgramQueries:
)(using FetchClient[F, ObservationDB]): F[Unit] =
updateProgramUsers(puid, ProgramUserPropertiesInput(gender = g.orUnassign))

def changeProgramUserRole[F[_]: Async](puid: ProgramUser.Id, role: ProgramUserRole)(using
FetchClient[F, ObservationDB]
): F[Unit] =
ChangeProgramUserRoleMutation[F]
.execute:
ChangeProgramUserRoleInput(programUserId = puid, newRole = role)
.raiseGraphQLErrors
.void

// Note: If justification is none, it is ignored, not un-set. We
// (currently, at least) do not allow unsetting justifications in explore.
def updateConfigurationRequestStatus[F[_]: Async](
Expand Down
9 changes: 2 additions & 7 deletions explore/src/main/scala/explore/proposal/ProposalEditor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import explore.model.ProposalTabTileIds
import explore.model.enums.GridLayoutSection
import explore.model.layout.LayoutsMap
import explore.undo.*
import explore.users.AddProgramUserButton
import explore.users.AddReadonlyCoiButton
import explore.users.ProgramUsersTable
import japgolly.scalajs.react.*
import japgolly.scalajs.react.vdom.html_<^.*
Expand Down Expand Up @@ -153,12 +153,7 @@ object ProposalEditor:
.unless[VdomNode](props.proposalOrUserIsReadonly):
<.div(
ExploreStyles.AddProgramUserButton,
AddProgramUserButton(props.programId,
ProgramUserRole.CoiRO,
props.users,
icon = Icons.UserMagnifyingGlass
),
AddProgramUserButton(props.programId, ProgramUserRole.Coi, props.users)
AddReadonlyCoiButton(props.programId, props.users)
)
.orEmpty
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ import explore.Icons
import explore.model.AppContext
import explore.model.IsActive
import explore.model.ProgramUser
import explore.model.display.given
import explore.syntax.ui.*
import japgolly.scalajs.react.*
import japgolly.scalajs.react.vdom.html_<^.*
import lucuma.core.enums.ProgramUserRole
import lucuma.core.model.Program
import lucuma.core.syntax.display.*
import lucuma.react.common.ReactFnComponent
import lucuma.react.common.ReactFnProps
import lucuma.react.fa.FontAwesomeIcon
Expand All @@ -26,23 +24,21 @@ import lucuma.schemas.ObservationDB.Types.AddProgramUserInput
import lucuma.ui.primereact.*
import queries.common.ProposalQueriesGQL.*

case class AddProgramUserButton(
case class AddReadonlyCoiButton(
programId: Program.Id,
role: ProgramUserRole,
users: View[List[ProgramUser]],
icon: FontAwesomeIcon = Icons.UserPlus
) extends ReactFnProps(AddProgramUserButton)
users: View[List[ProgramUser]]
) extends ReactFnProps(AddReadonlyCoiButton)

object AddProgramUserButton
extends ReactFnComponent[AddProgramUserButton](props =>
object AddReadonlyCoiButton
extends ReactFnComponent[AddReadonlyCoiButton](props =>
for {
ctx <- useContext(AppContext.ctx)
isActive <- useStateView(IsActive(false))
} yield
import ctx.given

def addProgramUser: IO[Unit] =
val input = AddProgramUserInput(programId = props.programId, role = props.role)
val input = AddProgramUserInput(programId = props.programId, role = ProgramUserRole.CoiRO)
AddProgramUser[IO]
.execute(input)
.raiseGraphQLErrors
Expand All @@ -53,8 +49,8 @@ object AddProgramUserButton
Button(
severity = Button.Severity.Secondary,
loading = isActive.get.value,
icon = props.icon,
tooltip = s"Add ${props.role.longName}",
icon = Icons.UserPlus,
tooltip = "Add Co-Investigator",
onClick = addProgramUser.runAsync
).tiny.compact
)
31 changes: 27 additions & 4 deletions explore/src/main/scala/explore/users/ProgramUsersTable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ object ProgramUsersTable:
case InProgress(message) => <.span(Icons.Info).withTooltip(message)
case Failed(message) => <.span(Icons.ErrorIcon).withTooltip(message)

private val CoIRoles: Set[ProgramUserRole] = Set(ProgramUserRole.Coi, ProgramUserRole.CoiRO)
private val NonCoIRoles: Set[ProgramUserRole] = Enumerated[ProgramUserRole].all.toSet -- CoIRoles

private def columns(using
ctx: AppContext[IO]
): List[ColumnDef.WithTableMeta[View[ProgramUser], ?, TableMeta]] =
Expand Down Expand Up @@ -338,7 +341,7 @@ object ProgramUsersTable:
val canEdit = meta.currentUserCanEdit(cell.get)

EnumDropdownOptionalView(
id = "es".refined,
id = NonEmptyString.unsafeFrom(s"$programUserId-es"),
value = view,
showClear = true,
itemTemplate = _.value.shortName,
Expand All @@ -361,7 +364,7 @@ object ProgramUsersTable:
val canEdit = meta.currentUserCanEdit(cell.get)

Checkbox(
id = "thesis",
id = s"$programUserId-thesis",
checked = view.get.getOrElse(false),
disabled = !canEdit || meta.isActive.get.value,
onChange = r => view.set(r.some)
Expand All @@ -382,7 +385,7 @@ object ProgramUsersTable:
val canEdit = meta.currentUserCanEdit(cell.get)

EnumOptionalDropdown[Gender](
id = "gender".refined,
id = NonEmptyString.unsafeFrom(s"$programUserId-gender"),
value = view.get,
showClear = true,
itemTemplate = _.value.shortName,
Expand All @@ -395,7 +398,27 @@ object ProgramUsersTable:
).sortableBy(_.get.toString),
column(Column.OrcidId, _.get.user.flatMap(_.orcidId).foldMap(_.value)).sortable,
// TODO: Make editable between COI and Readonly COI, if user is not this one
column(Column.Role, _.get.role.shortName).sortable,
// column(Column.Role, _.get.role.shortName).sortable,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented line

ColDef(
Column.Role.id,
_.zoom(ProgramUser.role),
Column.Role.header,
cell = c =>
val currentRole = c.value.get
c.table.options.meta.map: meta =>
if (meta.proposalOrUserIsReadonly || !CoIRoles.contains(currentRole))
currentRole.shortName: VdomNode
else
val programUserId = c.row.original.get.id
val view =
c.value.withOnMod(role => changeProgramUserRole[IO](programUserId, role).runAsync)
EnumDropdownView(
id = NonEmptyString.unsafeFrom(s"$programUserId-role"),
value = view,
exclude = NonCoIRoles,
clazz = ExploreStyles.PartnerSelector
): VdomNode
).sortableBy(_.get.shortName),
ColDef(
Column.Status.id,
_.get.status,
Expand Down
2 changes: 2 additions & 0 deletions model/shared/src/main/scala/explore/model/ProgramUser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ object ProgramUser:
val partnerLink: Lens[ProgramUser, Option[PartnerLink]] =
Focus[ProgramUser](_.partnerLink)

val role: Lens[ProgramUser, ProgramUserRole] = Focus[ProgramUser](_.role)

val educationalStatus: Lens[ProgramUser, Option[EducationalStatus]] =
Focus[ProgramUser](_.educationalStatus)

Expand Down
Loading