Skip to content

Commit

Permalink
Merge pull request #4166 from gemini-hlsw/sc-3506-copy-paste-to-diffe…
Browse files Browse the repository at this point in the history
…rent-group

Copy observations into groups
  • Loading branch information
rpiaggio authored Sep 23, 2024
2 parents 63b8252 + d2f9519 commit 3a4f16a
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 33 deletions.
13 changes: 9 additions & 4 deletions explore/src/main/scala/explore/observationtree/ObsList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,25 @@ case class ObsList(
clipboardObsContents: Option[ObsIdSet],
readonly: Boolean
) extends ReactFnProps(ObsList.component):
private val activeGroup: Option[Group.Id] = focusedGroup.orElse:
focusedObs.flatMap(obsId => observations.get.getValue(obsId).flatMap(_.groupId))

private val copyDisabled: Boolean = focusedObs.isEmpty
private val pasteDisabled: Boolean = clipboardObsContents.isEmpty
private val deleteDisabled: Boolean = focusedObs.isEmpty && focusedGroup.isEmpty

private def observationText(obsId: Observation.Id): String = s"observation $obsId"
private def groupText(groupId: Group.Id): String = s"group $groupId"

private val copyText: Option[String] = focusedObs.map(observationText)
private val pasteText: Option[String] =
private val copyText: Option[String] = focusedObs.map(observationText)
private val selectedText: Option[String] =
clipboardObsContents.map: obdIdSet =>
obdIdSet.idSet.size match
case 1 => s"observation ${obdIdSet.idSet.head}"
case more => s"$more observations"
private val deleteText: Option[String] =
private val pasteText: Option[String] =
selectedText.map(_ + activeGroup.map(gid => s" into ${groupText(gid)}").orEmpty)
private val deleteText: Option[String] =
focusedObs.map(observationText).orElse(focusedGroup.map(groupText))

object ObsList:
Expand Down Expand Up @@ -304,7 +309,7 @@ object ObsList:
cloneCB = cloneObs(
props.programId,
id,
props.observations.get.length,
obs.groupId, // Clone to the same group
props.observations,
ctx,
adding.async.set(AddingObservation(true)),
Expand Down
11 changes: 6 additions & 5 deletions explore/src/main/scala/explore/observationtree/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def setGroup[F[_]](
def cloneObs(
programId: Program.Id,
obsId: Observation.Id,
pos: NonNegInt,
newGroupId: Option[Group.Id],
observations: UndoSetter[ObservationList],
ctx: AppContext[IO],
before: IO[Unit] = IO.unit,
Expand All @@ -68,10 +68,11 @@ def cloneObs(
import ctx.given

before >>
cloneObservation[IO](obsId)
.flatMap: obs =>
obsExistence(obs.id, o => setObs(programId, o.some, ctx))
.mod(observations)(obsListMod.upsert(obs, pos))
cloneObservation[IO](obsId, newGroupId)
.flatMap: newObs =>
obsExistence(newObs.id, o => setObs(programId, o.some, ctx))
.mod(observations): // Convert NonNegShort => NonNegInt
obsListMod.upsert(newObs, NonNegInt.unsafeFrom(newObs.groupIndex.value))
.toAsync
.guarantee(after)

Expand Down
44 changes: 22 additions & 22 deletions explore/src/main/scala/explore/tabs/ObsTabContents.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import explore.model.ProgramSummaries
import explore.model.enums.AppTab
import explore.model.enums.GridLayoutSection
import explore.model.enums.SelectedPanel
import explore.model.reusability.given
import explore.modes.SpectroscopyModesMatrix
import explore.observationtree.*
import explore.shortcuts.*
Expand Down Expand Up @@ -81,6 +82,8 @@ case class ObsTabContents(
private val focusedGroup: Option[Group.Id] = focused.group
private val observations: UndoSetter[ObservationList] =
programSummaries.zoom(ProgramSummaries.observations)
private val activeGroup: Option[Group.Id] = focusedGroup.orElse:
focusedObs.flatMap(obsId => observations.get.getValue(obsId).flatMap(_.groupId))
private val obsExecutions: ObservationExecutionMap = programSummaries.get.obsExecutionPots
private val groupTimeRanges: GroupTimeRangeMap = programSummaries.get.groupTimeRangePots
private val groups: UndoSetter[GroupTree] = programSummaries.zoom(ProgramSummaries.groups)
Expand Down Expand Up @@ -127,29 +130,26 @@ object ObsTabContents extends TwoPanels:
.withToast(s"Copied obs $id")
.orUnit
.runAsync
.useCallbackWithDepsBy((props, _, _, _, _, _) => (props.observationIds, props.readonly)): // PASTE Action Callback
(props, ctx, _, _, _, _) =>
(observationIds, readonly) =>
import ctx.given
.useCallbackWithDepsBy((props, _, _, _, _, _) => // PASTE Action Callback
(Reusable.explicitly(props.observations)(Reusability.by(_.get)),
props.activeGroup,
props.readonly
)
): (props, ctx, _, _, _, _) =>
(observations, activeGroup, readonly) =>
import ctx.given

ExploreClipboard.get
.flatMap:
case LocalClipboard.CopiedObservations(idSet) =>
idSet.idSet.toList
.traverse(oid =>
cloneObs(
props.programId,
oid,
NonNegInt.unsafeFrom(observationIds.length),
props.observations,
ctx
)
)
.void
.withToast(s"Duplicating obs ${idSet.idSet.mkString_(", ")}")
case _ => IO.unit
.runAsync
.unless_(readonly)
ExploreClipboard.get
.flatMap:
case LocalClipboard.CopiedObservations(obsIdSet) =>
obsIdSet.idSet.toList
.traverse: oid =>
cloneObs(props.programId, oid, activeGroup, observations, ctx)
.void
.withToast(s"Duplicating obs ${obsIdSet.idSet.mkString_(", ")}")
case _ => IO.unit
.runAsync
.unless_(readonly)
.useGlobalHotkeysWithDepsBy((props, _, _, _, _, copyCallback, pasteCallback) =>
(copyCallback, pasteCallback, props.focusedObs, props.observationIdsWithIndices)
): (props, ctx, _, _, _, _, _) =>
Expand Down
9 changes: 7 additions & 2 deletions explore/src/main/scala/queries/schemas/odb/ObsQueries.scala
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,17 @@ object ObsQueries:
.map(_.createObservation.observation)

def cloneObservation[F[_]: Async](
obsId: Observation.Id
obsId: Observation.Id,
newGroupId: Option[Group.Id]
)(using
FetchClient[F, ObservationDB]
): F[Observation] =
CloneObservationMutation[F]
.execute(CloneObservationInput(observationId = obsId.assign))
.execute:
CloneObservationInput(
observationId = obsId.assign,
SET = ObservationPropertiesInput(groupId = newGroupId.orUnassign).assign
)
.map(_.cloneObservation.newObservation)

def applyObservation[F[_]: Async](
Expand Down

0 comments on commit 3a4f16a

Please sign in to comment.