Skip to content

Commit

Permalink
checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
rpiaggio committed Nov 4, 2024
1 parent 6524e54 commit fed71cc
Show file tree
Hide file tree
Showing 11 changed files with 290 additions and 303 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object ExploreStyles:
val TileTitle: Css = Css("explore-tile-title")
val TileTitleText: Css = Css("explore-tile-title-text")
val TileTitleMenu: Css = Css("explore-tile-title-menu")
val TileTitleStrip: Css = Css("explore-tile-title-strip")
// val TileTitleStrip: Css = Css("explore-tile-title-strip")
val TileDraggable: Css = Css("explore-tile-draggable")
val TileTitleControlArea: Css = Css("explore-tile-title-control-area")
val JustifiedEndTileControl: Css = Css("justified-end-tile-control")
Expand Down
14 changes: 6 additions & 8 deletions common/src/main/webapp/sass/explore.scss
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,6 @@ thead tr th.sticky-header {
.explore-tile-title-menu {
@include lucumaUICommon.text-ellipsis;

flex: 0 0 min-content;
cursor: move;
padding: 0.5em;
letter-spacing: 2px;
Expand Down Expand Up @@ -824,7 +823,6 @@ thead tr th.sticky-header {

.explore-obs-instant-tile-title {
justify-content: center;
flex-grow: 0;
font-size: smaller;

@include small-tile-title;
Expand Down Expand Up @@ -1056,9 +1054,9 @@ thead tr th.sticky-header {
.explore-tile-title-control-area {
min-width: 60%;

.explore-tile-control {
justify-content: space-between;
}
// .explore-tile-control {
// justify-content: space-between;
// }

.explore-title-select-columns {
display: none;
Expand Down Expand Up @@ -1319,9 +1317,9 @@ $search-preview-margin: 5px;
padding-top: 1em;
}

.explore-tile-control:has(.explore-sequence-tile-title) {
justify-self: stretch;
}
// .explore-tile-control:has(.explore-sequence-tile-title) {
// justify-self: stretch;
// }

.explore-sequence-tile-title {
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,22 @@ import monocle.Focus
object ObsSummaryTable:
private val ObservationIdColumnId = ColumnId("observation_id")
private val GroupColumnId = ColumnId("group")
// private val ValidationCheckColumnId = ColumnId("validation_check")
private val StateColumnId = ColumnId("state")
private val ScienceBandColumnId = ColumnId("science_band")
// private val CompletionColumnId = ColumnId("completion")
private val ExpanderColumnId = ColumnId("expander")
private val TargetTypeColumnId = ColumnId("target_type")
private val TargetColumnId = ColumnId("target")
private val ConstraintsColumnId = ColumnId("constraints")
// private val FindingChartColumnId = ColumnId("finding_chart")
private val ConfigurationColumnId = ColumnId("configuration")
private val DurationColumnId = ColumnId("duration")

private val RAColumnId = ColumnId("ra")
private val DecColumnId = ColumnId("dec")
private val SEDColumnId = ColumnId("sed")
// private val ValidationCheckColumnId = ColumnId("validation_check")
// private val CompletionColumnId = ColumnId("completion")
// private val FindingChartColumnId = ColumnId("finding_chart")
// private val PriorityColumnId = ColumnId("priority")
private val RAColumnId = ColumnId("ra")
private val DecColumnId = ColumnId("dec")
// private val TimingWindowsColumnId = ColumnId("timing_windows")
private val SEDColumnId = ColumnId("sed")
// private val ChargedTimeColumnId = ColumnId("charged_time")

private val ColumnNames: TreeSeqMap[ColumnId, String] =
Expand Down Expand Up @@ -536,17 +535,18 @@ object ObsSummaryTable:
.flatMap(bt => vizTime.fold(bt.baseCoordinates.some)(v => bt.at(v).map(_.value)))
}

case class SharedState(
case class TileState(
columnVisibility: ColumnVisibility,
toggleAllRowsSelected: Option[Boolean => Callback]
)
object SharedState:
val Initial: SharedState = SharedState(DefaultColVisibility, None)

val columnVisibility: Lens[SharedState, ColumnVisibility] =
Focus[SharedState](_.columnVisibility)
val toggleAllRowsSelected: Lens[SharedState, Option[Boolean => Callback]] =
Focus[SharedState](_.toggleAllRowsSelected)
object TileState:
val Initial: TileState = TileState(DefaultColVisibility, None)

val columnVisibility: Lens[TileState, ColumnVisibility] =
Focus[TileState](_.columnVisibility)
val toggleAllRowsSelected: Lens[TileState, Option[Boolean => Callback]] =
Focus[TileState](_.toggleAllRowsSelected)

case class Title(
columnVisibility: View[ColumnVisibility],
Expand Down
6 changes: 3 additions & 3 deletions explore/src/main/scala/explore/tabs/AsterismEditorTile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import explore.model.OnAsterismUpdateParams
import explore.model.OnCloneParameters
import explore.model.TargetEditObsInfo
import explore.model.enums.TileSizeState
import explore.targeteditor.AsterismEditorBody
import explore.targeteditor.Body
import explore.targeteditor.AsterismEditorTitle
import explore.targeteditor.AsterismTileState
import explore.targeteditor.TileState
import explore.undo.UndoSetter
import japgolly.scalajs.react.Callback
import japgolly.scalajs.react.extra.router.SetRouteVia
Expand Down Expand Up @@ -62,7 +62,7 @@ object AsterismEditorTile:
readonly: Boolean,
sequenceChanged: Callback = Callback.empty,
backButton: Option[VdomNode] = None
)(using FetchClient[IO, ObservationDB], Logger[IO]): Tile[AsterismTileState] = {
)(using FetchClient[IO, ObservationDB], Logger[IO]): Tile[TileState] = {
// Save the time here. this works for the obs and target tabs
// It's OK to save the viz time for executed observations, I think.
val vizTimeView =
Expand Down
6 changes: 3 additions & 3 deletions explore/src/main/scala/explore/tabs/ObsTabContents.scala
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ object ObsTabContents extends TwoPanels:
Tile(
ObsSummaryTabTileIds.SummaryId.id,
s"Observations Summary (${props.observations.get.toList.filterNot(_.isCalibration).length})",
ObsSummaryTable.SharedState.Initial,
ObsSummaryTable.TileState.Initial,
backButton.some,
canMinimize = false,
canMaximize = false
Expand All @@ -288,11 +288,11 @@ object ObsTabContents extends TwoPanels:
props.targets.get,
props.programSummaries.get.allocatedScienceBands.size > 1,
s.get.columnVisibility,
cb => s.zoom(ObsSummaryTable.SharedState.toggleAllRowsSelected).set(cb.some)
cb => s.zoom(ObsSummaryTable.TileState.toggleAllRowsSelected).set(cb.some)
),
(s, _) =>
ObsSummaryTable.Title(
s.zoom(ObsSummaryTable.SharedState.columnVisibility),
s.zoom(ObsSummaryTable.TileState.columnVisibility),
s.get.toggleAllRowsSelected
)
)
Expand Down
226 changes: 226 additions & 0 deletions explore/src/main/scala/explore/targeteditor/AsterismEditor.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
// Copyright (c) 2016-2023 Association of Universities for Research in Astronomy, Inc. (AURA)
// For license information see LICENSE or https://opensource.org/licenses/BSD-3-Clause

package explore.targeteditor

import cats.syntax.all.*
import crystal.react.*
import crystal.react.hooks.*
import explore.components.ColumnSelectorInTitle
import explore.components.ui.ExploreStyles
import explore.config.ObsTimeEditor
import explore.model.AladinFullScreen
import explore.model.AppContext
import explore.model.Asterism
import explore.model.GlobalPreferences
import explore.model.GuideStarSelection
import explore.model.ObsConfiguration
import explore.model.ObsIdSet
import explore.model.ObsIdSetEditInfo
import explore.model.ObservationsAndTargets
import explore.model.OnAsterismUpdateParams
import explore.model.OnCloneParameters
import explore.model.TargetEditObsInfo
import explore.model.TargetList
import explore.model.reusability.given
import explore.targets.TargetColumns
import explore.undo.UndoSetter
import japgolly.scalajs.react.*
import japgolly.scalajs.react.extra.router.SetRouteVia
import japgolly.scalajs.react.vdom.html_<^.*
import lucuma.core.model.Program
import lucuma.core.model.Target
import lucuma.core.model.User
import lucuma.core.util.NewType
import lucuma.core.util.TimeSpan
import lucuma.react.common.ReactFnProps
import lucuma.react.table.ColumnVisibility
import lucuma.react.table.Table
import lucuma.schemas.model.SiderealTargetWithId
import lucuma.ui.reusability.given
import lucuma.ui.syntax.all.given
import monocle.Focus
import monocle.Iso
import monocle.Lens

import java.time.Instant

object AsterismEditor:
case class TileState(
columnVisibility: ColumnVisibility,
obsEditInfo: Option[ObsIdSetEditInfo]
)

object TileState:
val Initial: TileState = TileState(TargetColumns.DefaultVisibility, none)

val columnVisibility: Lens[TileState, ColumnVisibility] =
Focus[TileState](_.columnVisibility)
val obsEditInfo: Lens[TileState, Option[ObsIdSetEditInfo]] =
Focus[TileState](_.obsEditInfo)

case class Body(
programId: Program.Id,
userId: User.Id,
obsIds: ObsIdSet,
obsAndTargets: UndoSetter[ObservationsAndTargets],
obsTime: View[Option[Instant]],
configuration: ObsConfiguration,
focusedTargetId: Option[Target.Id],
setTarget: (Option[Target.Id], SetRouteVia) => Callback,
onCloneTarget: OnCloneParameters => Callback,
onAsterismUpdate: OnAsterismUpdateParams => Callback,
obsInfo: Target.Id => TargetEditObsInfo,
searching: View[Set[Target.Id]],
globalPreferences: View[GlobalPreferences],
guideStarSelection: View[GuideStarSelection],
readonly: Boolean,
sequenceChanged: Callback,
columnVisibility: ColumnVisibility,
obsEditInfo: View[Option[ObsIdSetEditInfo]]
) extends ReactFnProps(Body.component):
val allTargets: UndoSetter[TargetList] = obsAndTargets.zoom(ObservationsAndTargets.targets)

object Body extends AsterismModifier:
private type Props = Body

private val component =
ScalaFnComponent
.withHooks[Props]
.useMemoBy(props => (props.obsIds, props.obsAndTargets.get._1)): _ =>
ObsIdSetEditInfo.fromObservationList
.useLayoutEffectWithDepsBy((_, obsEditInfo) => obsEditInfo): (props, _) =>
obsEditInfo => props.obsEditInfo.set(obsEditInfo.value.some)
.useLayoutEffectWithDepsBy((props, obsEditInfo) =>
(obsEditInfo.asterismIds, props.focusedTargetId)
): (props, _) =>
(asterismIds, focusedTargetId) =>
// If the selected targetId is None, or not in the asterism, select the first target (if any).
// Need to replace history here.
focusedTargetId.filter(asterismIds.contains_) match
case None => props.setTarget(asterismIds.headOption, SetRouteVia.HistoryReplace)
case _ => Callback.empty
// full screen aladin
.useStateView(AladinFullScreen.Normal)
.render: (props, obsEditInfo, fullScreen) =>
val selectedTargetView: View[Option[Target.Id]] =
View(
props.focusedTargetId,
(mod, cb) =>
val oldValue = props.focusedTargetId
val newValue = mod(props.focusedTargetId)
props.setTarget(newValue, SetRouteVia.HistoryPush) >> cb(oldValue, newValue)
)

val editWarningMsg: Option[String] =
if (obsEditInfo.allAreExecuted)
if (obsEditInfo.editing.length > 1)
"All of the current observations are executed. Asterism is readonly.".some
else "The current observation has been executed. Asterism is readonly.".some
else if (obsEditInfo.executed.isDefined)
"Adding and removing targets will only affect the unexecuted observations.".some
else none

<.div(ExploreStyles.AladinFullScreen.when(fullScreen.get.value))(
editWarningMsg.map(msg => <.div(ExploreStyles.SharedEditWarning, msg)),
// the 'getOrElse doesn't matter. Controls will be readonly if all are executed
props.obsEditInfo.get
.map(_.unExecuted.getOrElse(props.obsIds))
.map: unexecutedObs =>
TargetTable(
props.userId.some,
props.programId,
unexecutedObs,
obsEditInfo.asterismIds,
props.obsAndTargets,
selectedTargetView,
props.onAsterismUpdate,
props.obsTime.get,
fullScreen.get,
props.readonly || obsEditInfo.allAreExecuted,
props.columnVisibility
),
// it's possible for us to get here without an asterism but with a focused target id. This will get
// corrected, but we need to not render the target editor before it is corrected.
(Asterism.fromIdsAndTargets(obsEditInfo.asterismIds, props.allTargets.get),
props.focusedTargetId
).mapN: (asterism, focusedTargetId) =>
val selectedTargetOpt: Option[UndoSetter[Target.Sidereal]] =
props.allTargets
.zoom(Iso.id[TargetList].index(focusedTargetId).andThen(Target.sidereal))

val obsInfo = props.obsInfo(focusedTargetId)

selectedTargetOpt
.map: siderealTarget =>
<.div(
ExploreStyles.TargetTileEditor,
SiderealTargetEditor(
props.programId,
props.userId,
siderealTarget,
props.obsAndTargets,
asterism.focusOn(focusedTargetId),
props.obsTime.get,
props.configuration.some,
props.searching,
onClone = props.onCloneTarget,
obsInfo = obsInfo,
fullScreen = fullScreen,
globalPreferences = props.globalPreferences,
guideStarSelection = props.guideStarSelection,
readonly = props.readonly,
invalidateSequence = props.sequenceChanged
)
)
.getOrElse[VdomElement]:
<.div("Non-sidereal targets not supported")
)

case class Title(
programId: Program.Id,
obsIds: ObsIdSet,
obsAndTargets: UndoSetter[ObservationsAndTargets],
onAsterismUpdate: OnAsterismUpdateParams => Callback,
readonly: Boolean,
obsTimeView: View[Option[Instant]],
obsDurationView: View[Option[TimeSpan]],
pendingTime: Option[TimeSpan],
columnVisibility: View[ColumnVisibility],
obsEditInfo: Option[ObsIdSetEditInfo]
) extends ReactFnProps(Title.component)

object Title extends AsterismModifier:
private type Props = Title

private val component =
ScalaFnComponent
.withHooks[Props]
.useContext(AppContext.ctx)
.useStateView(AreAdding(false))
.render: (props, ctx, adding) =>
import ctx.given

<.span(
// only pass in the unexecuted observations. Will be readonly if there aren't any
(props.obsEditInfo, props.obsEditInfo.map(_.unExecuted.getOrElse(props.obsIds))).mapN:
(obsEditInfo, unexecutedObs) =>
targetSelectionPopup(
"Add",
props.programId,
unexecutedObs,
props.obsAndTargets,
adding,
props.onAsterismUpdate,
props.readonly || obsEditInfo.allAreExecuted,
ExploreStyles.AddTargetButton
)
,
ObsTimeEditor(
props.obsTimeView,
props.obsDurationView,
props.pendingTime,
props.obsIds.size > 1
),
ColumnSelectorInTitle(TargetColumns.AllColNames.toList, props.columnVisibility)
)
Loading

0 comments on commit fed71cc

Please sign in to comment.