diff --git a/explore/src/main/scala/explore/attachments/ObsAttachmentsTableBody.scala b/explore/src/main/scala/explore/attachments/ObsAttachmentsTableBody.scala index 36b0cfd3ba..0c1387336e 100644 --- a/explore/src/main/scala/explore/attachments/ObsAttachmentsTableBody.scala +++ b/explore/src/main/scala/explore/attachments/ObsAttachmentsTableBody.scala @@ -36,6 +36,7 @@ import japgolly.scalajs.react.vdom.html_<^.* import lucuma.core.model.ObsAttachment as ObsAtt import lucuma.core.model.Program import lucuma.core.util.Enumerated +import lucuma.core.util.NewType import lucuma.core.util.Timestamp import lucuma.react.common.ReactFnProps import lucuma.react.common.style.Css @@ -58,7 +59,6 @@ import org.scalajs.dom.File as DomFile import org.typelevel.log4cats.Logger import scala.collection.immutable.SortedSet -import lucuma.core.util.NewType object ObsAttachmentsTableTileState extends NewType[Action]: def apply(): ObsAttachmentsTableTileState = ObsAttachmentsTableTileState(Action.None) @@ -69,10 +69,10 @@ case class ObsAttachmentsTableBody( authToken: NonEmptyString, obsAttachmentAssignments: ObsAttachmentAssignmentMap, obsAttachments: View[ObsAttachmentList], - readOnly: Boolean -)( - val state: View[ObsAttachmentsTableTileState] -) extends ReactFnProps(ObsAttachmentsTableBody.component) + readOnly: Boolean, + tileState: View[ObsAttachmentsTableTileState] +) extends ReactFnProps(ObsAttachmentsTableBody.component): + val action = tileState.zoom(ObsAttachmentsTableTileState.value.asLens) object ObsAttachmentsTableBody extends ObsAttachmentUtils: private type Props = ObsAttachmentsTableBody @@ -183,7 +183,6 @@ object ObsAttachmentsTableBody extends ObsAttachmentUtils: .useMemoBy((_, _, _, _) => ()): (props, ctx, _, _) => _ => import ctx.given - val action = props.state.zoom(ObsAttachmentsTableTileState.value.asLens) def column[V](id: ColumnId, accessor: ObsAttachment => V) : ColumnDef.Single.WithTableMeta[View[ObsAttachment], V, TableMeta] = @@ -206,7 +205,7 @@ object ObsAttachmentsTableBody extends ObsAttachmentUtils: val files = e.target.files.toList (Callback(e.target.value = null) *> updateAttachment(props, meta.client, thisOa, files) - .switching(action.async, Action.Replace, Action.None) + .switching(props.action.async, Action.Replace, Action.None) .runAsync) .when_(files.nonEmpty) @@ -337,9 +336,7 @@ object ObsAttachmentsTableBody extends ObsAttachmentUtils: getRowId = (row, _, _) => RowId(row.get.id.toString), meta = TableMeta(client, props.obsAttachmentAssignments, urlMap.get, props.readOnly) ) - .render: (props, ctx, client, _, _, _, table) => - val action = props.state.zoom(ObsAttachmentsTableTileState.value.asLens) - + .render: (props, _, _, _, _, _, table) => React.Fragment( PrimeTable( table, @@ -351,8 +348,8 @@ object ObsAttachmentsTableBody extends ObsAttachmentUtils: ConfirmPopup(), Dialog( onHide = Callback.empty, - visible = action.get != Action.None, - header = action.get.msg, + visible = props.action.get != Action.None, + header = props.action.get.msg, blockScroll = true, modal = true, dismissableMask = false, @@ -366,10 +363,10 @@ case class ObsAttachmentsTableTitle( pid: Program.Id, authToken: NonEmptyString, obsAttachments: View[ObsAttachmentList], - readOnly: Boolean -)( - val state: View[ObsAttachmentsTableTileState] -) extends ReactFnProps(ObsAttachmentsTableTitle.component) + readOnly: Boolean, + tileState: View[ObsAttachmentsTableTileState] +) extends ReactFnProps(ObsAttachmentsTableTitle.component): + val action = tileState.zoom(ObsAttachmentsTableTileState.value.asLens) object ObsAttachmentsTableTitle extends ObsAttachmentUtils: private type Props = ObsAttachmentsTableTitle @@ -409,7 +406,7 @@ object ObsAttachmentsTableTitle extends ObsAttachmentUtils: props.obsAttachments, newAttType.get, client, - props.state.zoom(ObsAttachmentsTableTileState.value.asLens) + props.action ), ^.id := "attachment-upload", ^.name := "file", diff --git a/explore/src/main/scala/explore/components/ColumnSelectorInTitle.scala b/explore/src/main/scala/explore/components/ColumnSelectorInTitle.scala index 26bdd7a2a8..09b5659923 100644 --- a/explore/src/main/scala/explore/components/ColumnSelectorInTitle.scala +++ b/explore/src/main/scala/explore/components/ColumnSelectorInTitle.scala @@ -3,15 +3,15 @@ package explore.components -import crystal.react.View import cats.syntax.all.* +import crystal.react.View import explore.components.ui.ExploreStyles import japgolly.scalajs.react.* import japgolly.scalajs.react.vdom.html_<^.* import lucuma.react.common.ReactFnProps +import lucuma.react.table.ColumnId import lucuma.react.table.Table import lucuma.ui.table.ColumnSelector -import lucuma.react.table.ColumnId case class ColumnSelectorState[A, B]( table: Option[Table[A, B]] = None diff --git a/explore/src/main/scala/explore/config/sequence/GeneratedSequenceBody.scala b/explore/src/main/scala/explore/config/sequence/GeneratedSequenceBody.scala index d625d29776..bc06a0bfab 100644 --- a/explore/src/main/scala/explore/config/sequence/GeneratedSequenceBody.scala +++ b/explore/src/main/scala/explore/config/sequence/GeneratedSequenceBody.scala @@ -11,10 +11,13 @@ import crystal.react.* import crystal.react.given import crystal.react.hooks.* import explore.* +import explore.components.HelpIcon import explore.components.ui.ExploreStyles import explore.model.AppContext +import explore.model.Execution import explore.model.Observation import explore.model.reusability.given +import explore.syntax.ui.* import japgolly.scalajs.react.* import japgolly.scalajs.react.vdom.html_<^.* import lucuma.core.enums.ObserveClass @@ -22,23 +25,19 @@ import lucuma.core.math.SignalToNoise import lucuma.core.model.Program import lucuma.core.model.Target import lucuma.core.model.sequence.InstrumentExecutionConfig +import lucuma.core.util.TimeSpan import lucuma.react.common.ReactFnProps import lucuma.react.primereact.Message +import lucuma.refined.* import lucuma.schemas.model.ExecutionVisits import lucuma.schemas.odb.SequenceQueriesGQL.* import lucuma.schemas.odb.input.* +import lucuma.ui.components.TimeSpanView import lucuma.ui.syntax.all.* import lucuma.ui.syntax.all.given import queries.common.ObsQueriesGQL import queries.common.TargetQueriesGQL import queries.common.VisitQueriesGQL.* -import explore.model.Execution -import explore.syntax.ui.* -import lucuma.core.util.TimeSpan - -import explore.components.HelpIcon -import lucuma.ui.components.TimeSpanView -import lucuma.refined.* case class GeneratedSequenceBody( programId: Program.Id, diff --git a/explore/src/main/scala/explore/constraints/ConstraintSummaryTile.scala b/explore/src/main/scala/explore/constraints/ConstraintSummaryTile.scala index 5d9c14ea29..75e5115e11 100644 --- a/explore/src/main/scala/explore/constraints/ConstraintSummaryTile.scala +++ b/explore/src/main/scala/explore/constraints/ConstraintSummaryTile.scala @@ -9,8 +9,8 @@ import crystal.react.* import explore.Icons import explore.common.UserPreferencesQueries import explore.common.UserPreferencesQueries.TableStore -import explore.components.ui.ExploreStyles import explore.components.ColumnSelectorState +import explore.components.ui.ExploreStyles import explore.model.AppContext import explore.model.ConstraintGroup import explore.model.ConstraintGroupList @@ -40,9 +40,9 @@ case class ConstraintsSummaryTableBody( userId: Option[User.Id], programId: Program.Id, constraintList: ConstraintGroupList, - expandedIds: View[SortedSet[ObsIdSet]] -)(val state: View[ColumnSelectorState[ConstraintGroup, Nothing]]) - extends ReactFnProps(ConstraintsSummaryTableBody.component) + expandedIds: View[SortedSet[ObsIdSet]], + tileState: View[ColumnSelectorState[ConstraintGroup, Nothing]] +) extends ReactFnProps(ConstraintsSummaryTableBody.component) object ConstraintsSummaryTableBody: private type Props = ConstraintsSummaryTableBody @@ -231,7 +231,7 @@ object ConstraintsSummaryTableBody: TableStore(props.userId, TableId.ConstraintsSummary, cols) ) ) - .useEffectOnMountBy((p, _, _, _, table) => p.state.set(ColumnSelectorState(table.some))) + .useEffectOnMountBy((p, _, _, _, table) => p.tileState.set(ColumnSelectorState(table.some))) .render { (props, _, _, _, table) => <.div( PrimeTable( diff --git a/explore/src/main/scala/explore/findercharts/FinderChartsBody.scala b/explore/src/main/scala/explore/findercharts/FinderChartsBody.scala index 22c22fd60e..1d000494f5 100644 --- a/explore/src/main/scala/explore/findercharts/FinderChartsBody.scala +++ b/explore/src/main/scala/explore/findercharts/FinderChartsBody.scala @@ -31,9 +31,9 @@ import lucuma.ui.components.SolarProgress import lucuma.ui.reusability.given import lucuma.ui.syntax.all.given import lucuma.ui.syntax.pot.* +import monocle.Focus import scala.collection.immutable.SortedSet -import monocle.Focus case class FinderChartsTileState(chartSelector: ChartSelector, selected: Option[ObsAtt.Id]) diff --git a/explore/src/main/scala/explore/itc/ItcPanelTile.scala b/explore/src/main/scala/explore/itc/ItcPanelTile.scala index 3bf5684eaa..f302b69cb4 100644 --- a/explore/src/main/scala/explore/itc/ItcPanelTile.scala +++ b/explore/src/main/scala/explore/itc/ItcPanelTile.scala @@ -19,18 +19,14 @@ import explore.model.itc.* import japgolly.scalajs.react.* import japgolly.scalajs.react.vdom.html_<^.* import lucuma.core.model.User +import lucuma.core.util.NewType import lucuma.react.common.ReactFnProps import lucuma.ui.syntax.all.given -import monocle.Lens -import monocle.Focus -case class ItcPanelTileState( - selectedTarget: Option[ItcTarget] = None -) +object ItcPanelTileState extends NewType[Option[ItcTarget]]: + def apply(): ItcPanelTileState = ItcPanelTileState(None) -object ItcPanelTileState: - val selectedTarget: Lens[ItcPanelTileState, Option[ItcTarget]] = - Focus[ItcPanelTileState](_.selectedTarget) +type ItcPanelTileState = ItcPanelTileState.Type case class ItcPanelBody( uid: User.Id, @@ -39,9 +35,9 @@ case class ItcPanelBody( itcChartResults: Map[ItcTarget, Pot[ItcChartResult]], itcLoading: LoadingState, globalPreferences: View[GlobalPreferences], - state: View[ItcPanelTileState] + tileState: View[ItcPanelTileState] ) extends ReactFnProps(ItcPanelBody.component) { - val selectedTarget = state.zoom(ItcPanelTileState.selectedTarget) + val selectedTarget = tileState.zoom(ItcPanelTileState.value.asLens) } object ItcPanelBody: @@ -69,7 +65,7 @@ object ItcPanelBody: val detailsView = globalPreferences.zoom(GlobalPreferences.itcDetailsOpen) - val selectedTarget = props.state.get.selectedTarget + val selectedTarget = props.selectedTarget.get val isModeSelected = props.itcProps.finalConfig.isDefined val selectMode = "Select a mode to plot".some.filterNot(_ => isModeSelected) @@ -108,7 +104,7 @@ object ItcPanelBody: selectedResult.map(_.charts), error, chartTypeView.get, - props.state.get.selectedTarget.map(_.name.value), + selectedTarget.map(_.name.value), props.itcProps.signalToNoiseAt, props.itcLoading, detailsView.get diff --git a/explore/src/main/scala/explore/itc/ItcPanelTitle.scala b/explore/src/main/scala/explore/itc/ItcPanelTitle.scala index bf0437924c..a8255b32cb 100644 --- a/explore/src/main/scala/explore/itc/ItcPanelTitle.scala +++ b/explore/src/main/scala/explore/itc/ItcPanelTitle.scala @@ -27,9 +27,9 @@ case class ItcPanelTitle( itcPanelProps: ItcProps, itcChartResults: Map[ItcTarget, Pot[ItcChartResult]], itcLoading: LoadingState, - state: View[ItcPanelTileState] + tileState: View[ItcPanelTileState] ) extends ReactFnProps(ItcPanelTitle.component) { - val selectedTarget = state.zoom(ItcPanelTileState.selectedTarget) + val selectedTarget = tileState.zoom(ItcPanelTileState.value.asLens) } object ItcPanelTitle: diff --git a/explore/src/main/scala/explore/notes/NotesTile.scala b/explore/src/main/scala/explore/notes/NotesTile.scala index 96b95eeb9b..99cbabd0c0 100644 --- a/explore/src/main/scala/explore/notes/NotesTile.scala +++ b/explore/src/main/scala/explore/notes/NotesTile.scala @@ -12,6 +12,7 @@ import explore.components.Tile import explore.components.ui.ExploreStyles import explore.model.ObsTabTilesIds import explore.model.Observation +import explore.model.enums.TileSizeState import japgolly.scalajs.react.* import japgolly.scalajs.react.vdom.html_<^.* import lucuma.core.util.NewType @@ -27,7 +28,6 @@ import lucuma.ui.primereact.* import lucuma.ui.primereact.given import monocle.Focus import monocle.Lens -import explore.model.enums.TileSizeState object NotesTile: @@ -38,7 +38,7 @@ object NotesTile: s"Note for Observer", canMinimize = true, bodyClass = ExploreStyles.NotesTile - )(NotesTileBody(obsId, notes), NotesTileTitle(obsId, notes)) + )(NotesTileBody(obsId, notes, _), NotesTileTitle(obsId, notes, _, _)) case class NotesTileState(notes: String, editing: Editing) @@ -48,9 +48,9 @@ object NotesTileState: case class NotesTileBody( obsId: Observation.Id, - notes: View[Option[NonEmptyString]] -)(val state: View[NotesTileState]) - extends ReactFnProps(NotesTileBody.component) + notes: View[Option[NonEmptyString]], + state: View[NotesTileState] +) extends ReactFnProps(NotesTileBody.component) type Editing = Editing.Type object Editing extends NewType[Boolean]: @@ -96,10 +96,11 @@ object NotesTileBody: } case class NotesTileTitle( - obsId: Observation.Id, - notes: View[Option[NonEmptyString]] -)(val state: View[NotesTileState], val tileSize: TileSizeState) - extends ReactFnProps(NotesTileTitle.component) + obsId: Observation.Id, + notes: View[Option[NonEmptyString]], + state: View[NotesTileState], + tileSize: TileSizeState +) extends ReactFnProps(NotesTileTitle.component) object NotesTileTitle: private type Props = NotesTileTitle diff --git a/explore/src/main/scala/explore/observationtree/ObsSummaryTable.scala b/explore/src/main/scala/explore/observationtree/ObsSummaryTable.scala index 2aca837dd8..a9e62e46b1 100644 --- a/explore/src/main/scala/explore/observationtree/ObsSummaryTable.scala +++ b/explore/src/main/scala/explore/observationtree/ObsSummaryTable.scala @@ -14,6 +14,7 @@ import crystal.react.syntax.pot.given import explore.Icons import explore.common.UserPreferencesQueries import explore.common.UserPreferencesQueries.TableStore +import explore.components.ColumnSelectorState import explore.components.ui.ExploreStyles import explore.model.AppContext import explore.model.Asterism @@ -58,16 +59,15 @@ import queries.schemas.odb.ObsQueries.ObservationList import java.time.Instant import java.util.UUID -import explore.components.ColumnSelectorState final case class ObsSummaryTable( userId: Option[User.Id], programId: Program.Id, observations: UndoSetter[ObservationList], obsExecutions: ObservationExecutionMap, - allTargets: TargetList -)(val state: View[ColumnSelectorState[Expandable[ObsSummaryTable.ObsSummaryRow], Nothing]]) - extends ReactFnProps(ObsSummaryTable.component) + allTargets: TargetList, + tileState: View[ColumnSelectorState[Expandable[ObsSummaryTable.ObsSummaryRow], Nothing]] +) extends ReactFnProps(ObsSummaryTable.component) object ObsSummaryTable: import ObsSummaryRow.* @@ -317,7 +317,7 @@ object ObsSummaryTable: ), TableStore(props.userId, TableId.ObservationsSummary, cols) ) - .useEffectOnMountBy((p, _, _, _, table) => p.state.set(ColumnSelectorState(table.some))) + .useEffectOnMountBy((p, _, _, _, table) => p.tileState.set(ColumnSelectorState(table.some))) .useResizeDetector() // adding new observation .useStateView(AddingObservation(false)) diff --git a/explore/src/main/scala/explore/proposal/ProgramUsers.scala b/explore/src/main/scala/explore/proposal/ProgramUsers.scala index 6dd50fa5ba..c39f87113a 100644 --- a/explore/src/main/scala/explore/proposal/ProgramUsers.scala +++ b/explore/src/main/scala/explore/proposal/ProgramUsers.scala @@ -14,19 +14,18 @@ import explore.model.AppContext import explore.model.CoIInvitation import explore.model.ProgramUserWithRole import explore.model.ProposalTabTileIds -import explore.model.enums.TileSizeState import japgolly.scalajs.react.* import japgolly.scalajs.react.vdom.html_<^.* import lucuma.core.enums.InvitationStatus import lucuma.core.model.Program import lucuma.core.util.Enumerated +import lucuma.core.util.NewType import lucuma.react.common.ReactFnProps import lucuma.react.primereact.Button import lucuma.react.primereact.OverlayPanelRef import lucuma.ui.primereact.* import lucuma.ui.syntax.all.given import org.typelevel.log4cats.Logger -import lucuma.core.util.NewType enum CreateInviteProcess(private val tag: String) derives Enumerated: case Idle extends CreateInviteProcess("idle") @@ -41,17 +40,13 @@ case class ProgramUsers( pid: Program.Id, readOnly: Boolean, users: View[List[ProgramUserWithRole]], - invitations: View[List[CoIInvitation]] -)( - val state: View[ProgramUsersState] + invitations: View[List[CoIInvitation]], + state: View[ProgramUsersState] ) extends ReactFnProps(ProgramUsers.component) object ProgramUsers: - def inviteControl(readOnly: Boolean, ref: OverlayPanelRef)( - state: View[ProgramUsersState], - s: TileSizeState - ) = + def inviteControl(readOnly: Boolean, ref: OverlayPanelRef, state: View[ProgramUsersState]) = Button( severity = Button.Severity.Secondary, size = Button.Size.Small, @@ -73,7 +68,7 @@ object ProgramUsers: ProposalTabTileIds.UsersId.id, ProgramUsersState(CreateInviteProcess.Idle), "Investigators" - )(ProgramUsers(pid, readOnly, users, invitations), inviteControl(readOnly, ref)) + )(ProgramUsers(pid, readOnly, users, invitations, _), (s, _) => inviteControl(readOnly, ref, s)) private type Props = ProgramUsers diff --git a/explore/src/main/scala/explore/proposal/ProposalDetailsTile.scala b/explore/src/main/scala/explore/proposal/ProposalDetailsTile.scala index 41bdbab495..7afbc74565 100644 --- a/explore/src/main/scala/explore/proposal/ProposalDetailsTile.scala +++ b/explore/src/main/scala/explore/proposal/ProposalDetailsTile.scala @@ -33,8 +33,9 @@ import explore.model.Proposal import explore.model.ProposalType import explore.model.ProposalType.* import explore.model.display.given -import explore.model.reusability.given +import explore.model.enums.TileSizeState import explore.model.enums.Visible +import explore.model.reusability.given import explore.syntax.ui.* import explore.undo.* import japgolly.scalajs.react.* @@ -62,7 +63,6 @@ import lucuma.ui.syntax.all.given import lucuma.ui.syntax.pot.* import org.typelevel.log4cats.Logger import spire.std.any.* -import explore.model.enums.TileSizeState case class ProposalDetailsBody( proposal: View[Proposal], @@ -516,9 +516,8 @@ object ProposalDetailsBody: splitsList )(using ctx.logger) -case class ProposalDetailsTitle(undoCtx: UndoContext[Proposal])( - val tileSize: TileSizeState -) extends ReactFnProps(ProposalDetailsTitle.component) +case class ProposalDetailsTitle(undoCtx: UndoContext[Proposal], tileSize: TileSizeState) + extends ReactFnProps(ProposalDetailsTitle.component) object ProposalDetailsTitle: private type Props = ProposalDetailsTitle diff --git a/explore/src/main/scala/explore/proposal/ProposalEditor.scala b/explore/src/main/scala/explore/proposal/ProposalEditor.scala index f9e8fdf5f5..04f20ed86f 100644 --- a/explore/src/main/scala/explore/proposal/ProposalEditor.scala +++ b/explore/src/main/scala/explore/proposal/ProposalEditor.scala @@ -100,7 +100,7 @@ object ProposalEditor: props.cfps, props.readonly ), - (_, s) => ProposalDetailsTitle(undoCtx)(s) + (_, s) => ProposalDetailsTitle(undoCtx, s) ) val usersTile = diff --git a/explore/src/main/scala/explore/tabs/AsterismEditorTile.scala b/explore/src/main/scala/explore/tabs/AsterismEditorTile.scala index 02df13a831..c14b13f1d6 100644 --- a/explore/src/main/scala/explore/tabs/AsterismEditorTile.scala +++ b/explore/src/main/scala/explore/tabs/AsterismEditorTile.scala @@ -90,8 +90,9 @@ object AsterismEditorTile: searching, globalPreferences, readonly, - sequenceChanged - )(a) + sequenceChanged, + a + ) ), (s, _) => AsterismEditorTitle(programId, diff --git a/explore/src/main/scala/explore/tabs/ConstraintsTabContents.scala b/explore/src/main/scala/explore/tabs/ConstraintsTabContents.scala index a7229c96ff..0c545be988 100644 --- a/explore/src/main/scala/explore/tabs/ConstraintsTabContents.scala +++ b/explore/src/main/scala/explore/tabs/ConstraintsTabContents.scala @@ -11,10 +11,11 @@ import crystal.react.hooks.* import crystal.react.reuse.* import explore.* import explore.common.TimingWindowsQueries +import explore.components.ColumnSelectorInTitle +import explore.components.ColumnSelectorState import explore.components.FocusedStatus import explore.components.Tile import explore.components.TileController -import explore.components.ColumnSelectorState import explore.constraints.ConstraintsPanel import explore.constraints.ConstraintsSummaryTableBody import explore.data.KeyedIndexedList @@ -53,7 +54,6 @@ import monocle.Iso import scala.collection.immutable.SortedSet import scala.scalajs.LinkingInfo -import explore.components.ColumnSelectorInTitle case class ConstraintsTabContents( userId: Option[User.Id], @@ -124,7 +124,8 @@ object ConstraintsTabContents extends TwoPanels: props.userId, props.programId, props.programSummaries.get.constraintGroups, - props.expandedIds + props.expandedIds, + _ ), (s, _) => ColumnSelectorInTitle(ConstraintsSummaryTableBody.columnNames, s) ) diff --git a/explore/src/main/scala/explore/tabs/FinderChartsTile.scala b/explore/src/main/scala/explore/tabs/FinderChartsTile.scala index 5a6ed4958e..e5521b7c0e 100644 --- a/explore/src/main/scala/explore/tabs/FinderChartsTile.scala +++ b/explore/src/main/scala/explore/tabs/FinderChartsTile.scala @@ -10,8 +10,8 @@ import explore.components.Tile import explore.components.ui.ExploreStyles import explore.findercharts.ChartSelector import explore.findercharts.FinderChartsBody -import explore.findercharts.FinderChartsTitle import explore.findercharts.FinderChartsTileState +import explore.findercharts.FinderChartsTitle import explore.model.ObsAttachmentList import explore.model.ObsTabTilesIds import explore.model.Observation diff --git a/explore/src/main/scala/explore/tabs/ItcTile.scala b/explore/src/main/scala/explore/tabs/ItcTile.scala index 86401c0de2..873749d353 100644 --- a/explore/src/main/scala/explore/tabs/ItcTile.scala +++ b/explore/src/main/scala/explore/tabs/ItcTile.scala @@ -7,8 +7,8 @@ import crystal.Pot import crystal.react.View import explore.components.Tile import explore.itc.ItcPanelBody -import explore.itc.ItcPanelTitle import explore.itc.ItcPanelTileState +import explore.itc.ItcPanelTitle import explore.itc.ItcProps import explore.model.GlobalPreferences import explore.model.LoadingState diff --git a/explore/src/main/scala/explore/tabs/ObsTabContents.scala b/explore/src/main/scala/explore/tabs/ObsTabContents.scala index 060a153948..86ca51ddfa 100644 --- a/explore/src/main/scala/explore/tabs/ObsTabContents.scala +++ b/explore/src/main/scala/explore/tabs/ObsTabContents.scala @@ -11,6 +11,8 @@ import crystal.react.hooks.* import eu.timepit.refined.types.numeric.NonNegInt import explore.* import explore.Icons +import explore.components.ColumnSelectorInTitle +import explore.components.ColumnSelectorState import explore.components.Tile import explore.components.ui.ExploreStyles import explore.data.KeyedIndexedList @@ -43,6 +45,7 @@ import lucuma.react.hotkeys.hooks.* import lucuma.react.primereact.Button import lucuma.react.resizeDetector.* import lucuma.react.resizeDetector.hooks.* +import lucuma.react.table.Expandable import lucuma.refined.* import lucuma.ui.optics.* import lucuma.ui.primereact.* @@ -50,9 +53,6 @@ import lucuma.ui.reusability.given import lucuma.ui.sso.UserVault import lucuma.ui.syntax.all.given import monocle.Iso -import lucuma.react.table.Expandable -import explore.components.ColumnSelectorState -import explore.components.ColumnSelectorInTitle object DeckShown extends NewType[Boolean]: inline def Shown: DeckShown = DeckShown(true) @@ -138,7 +138,8 @@ object ObsTabContents extends TwoPanels: props.programId, props.observations, props.obsExecutions, - props.targets.get + props.targets.get, + _ ), (s, _) => ColumnSelectorInTitle(ObsSummaryTable.columnNames, s) // TODO: elevation view diff --git a/explore/src/main/scala/explore/tabs/OverviewTabContents.scala b/explore/src/main/scala/explore/tabs/OverviewTabContents.scala index 094621f9b7..83c1b6fc80 100644 --- a/explore/src/main/scala/explore/tabs/OverviewTabContents.scala +++ b/explore/src/main/scala/explore/tabs/OverviewTabContents.scala @@ -7,8 +7,8 @@ import cats.effect.IO import cats.syntax.all.* import crystal.react.* import explore.attachments.ObsAttachmentsTableBody -import explore.attachments.ObsAttachmentsTableTitle import explore.attachments.ObsAttachmentsTableTileState +import explore.attachments.ObsAttachmentsTableTitle import explore.components.Tile import explore.components.TileController import explore.model.AppContext @@ -58,7 +58,7 @@ object OverviewTabContents { "Warnings And Errors", none, canMinimize = true - )(ObservationValidationsTableBody(props.programId, props.observations)(_), + )(ObservationValidationsTableBody(props.programId, props.observations, _), ObservationValidationsTableTitle.apply ) @@ -75,14 +75,16 @@ object OverviewTabContents { vault.token, props.obsAttachmentAssignments, props.obsAttachments, - props.readonly + props.readonly, + _ ), (s, _) => ObsAttachmentsTableTitle(props.programId, vault.token, props.obsAttachments, - props.readonly - )(s) + props.readonly, + s + ) ) ) .filterNot(_ => props.userVault.isGuest) diff --git a/explore/src/main/scala/explore/tabs/TargetTabContents.scala b/explore/src/main/scala/explore/tabs/TargetTabContents.scala index f26a81dcf1..a5c12b5773 100644 --- a/explore/src/main/scala/explore/tabs/TargetTabContents.scala +++ b/explore/src/main/scala/explore/tabs/TargetTabContents.scala @@ -11,6 +11,7 @@ import crystal.react.* import crystal.react.hooks.* import eu.timepit.refined.types.string.NonEmptyString import explore.* +import explore.components.ColumnSelectorState import explore.components.FocusedStatus import explore.components.Tile import explore.components.TileController @@ -28,12 +29,12 @@ import explore.model.syntax.all.* import explore.observationtree.AsterismGroupObsList import explore.shortcuts.* import explore.shortcuts.given -import explore.targets.ObservationPasteAction import explore.targets.DeletingTargets +import explore.targets.ObservationPasteAction import explore.targets.TargetPasteAction import explore.targets.TargetSummaryBody -import explore.targets.TargetSummaryTitle import explore.targets.TargetSummaryTileState +import explore.targets.TargetSummaryTitle import explore.undo.* import explore.utils.* import japgolly.scalajs.react.* @@ -62,7 +63,6 @@ import queries.schemas.odb.ObsQueries import java.time.Instant import scala.collection.immutable.SortedSet import scala.scalajs.LinkingInfo -import explore.components.ColumnSelectorState case class TargetTabContents( userId: Option[User.Id], @@ -153,17 +153,18 @@ object TargetTabContents extends TwoPanels: selectTargetOrSummary, selectedTargetIds, props.programSummaries, - props.readonly + props.readonly, + _ ), (s, _) => - TargetSummaryTitle( - props.programId, - props.targets.model, - selectTargetOrSummary, - selectedTargetIds, - props.programSummaries, - props.readonly - )(s) + TargetSummaryTitle(props.programId, + props.targets.model, + selectTargetOrSummary, + selectedTargetIds, + props.programSummaries, + props.readonly, + s + ) ) /** diff --git a/explore/src/main/scala/explore/targeteditor/AsterismEditorBody.scala b/explore/src/main/scala/explore/targeteditor/AsterismEditorBody.scala index 4377ebfef1..aaaef902b5 100644 --- a/explore/src/main/scala/explore/targeteditor/AsterismEditorBody.scala +++ b/explore/src/main/scala/explore/targeteditor/AsterismEditorBody.scala @@ -6,6 +6,8 @@ package explore.targeteditor import cats.syntax.all.* import crystal.react.* import crystal.react.hooks.* +import explore.components.ColumnSelectorInTitle +import explore.components.ColumnSelectorState import explore.components.ui.ExploreStyles import explore.config.ObsTimeEditor import explore.model.AladinFullScreen @@ -30,16 +32,14 @@ import lucuma.core.model.Target import lucuma.core.model.User import lucuma.core.util.NewType import lucuma.react.common.ReactFnProps +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 -import monocle.Lens -import monocle.Focus -import explore.components.ColumnSelectorInTitle -import explore.components.ColumnSelectorState -import lucuma.schemas.model.SiderealTargetWithId case class AsterismTileState( table: ColumnSelectorState[SiderealTargetWithId, TargetTable.TableMeta] = @@ -73,9 +73,9 @@ case class AsterismEditorBody( searching: View[Set[Target.Id]], globalPreferences: View[GlobalPreferences], readonly: Boolean, - sequenceChanged: Callback -)(val state: View[AsterismTileState]) - extends ReactFnProps(AsterismEditorBody.component): + sequenceChanged: Callback, + tileState: View[AsterismTileState] +) extends ReactFnProps(AsterismEditorBody.component): val allTargets: UndoSetter[TargetList] = obsAndTargets.zoom(ObservationsAndTargets.targets) object AreAdding extends NewType[Boolean] @@ -91,7 +91,7 @@ object AsterismEditorBody extends AsterismModifier: ObsIdSetEditInfo.fromObservationList } .useLayoutEffectWithDepsBy((_, obsEditInfo) => obsEditInfo) { (p, _) => obsEditInfo => - p.state.zoom(AsterismTileState.obsEditInfo).set(obsEditInfo.value.some) + p.tileState.zoom(AsterismTileState.obsEditInfo).set(obsEditInfo.value.some) } .useLayoutEffectWithDepsBy((props, obsEditInfo) => (obsEditInfo.asterismIds, props.focusedTargetId) @@ -129,7 +129,7 @@ object AsterismEditorBody extends AsterismModifier: <.div( ExploreStyles.AladinFullScreen.when(fullScreen.get.value), editWarningMsg.map(msg => <.div(ExploreStyles.SharedEditWarning, msg)), - props.state.get + props.tileState.get .unexecutedObs(props.obsIds) .map(unexecutedObs => TargetTable( @@ -143,7 +143,7 @@ object AsterismEditorBody extends AsterismModifier: vizTime, fullScreen.get, props.readonly || obsEditInfo.allAreExecuted - )(props.state.zoom(AsterismTileState.table)) + )(props.tileState.zoom(AsterismTileState.table)) ), // 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. @@ -192,7 +192,7 @@ case class AsterismEditorTitle( onAsterismUpdate: OnAsterismUpdateParams => Callback, readonly: Boolean, vizTimeView: View[Option[Instant]], - state: View[AsterismTileState] + tileState: View[AsterismTileState] ) extends ReactFnProps(AsterismEditorTitle.component) object AsterismEditorTitle extends AsterismModifier: @@ -208,8 +208,8 @@ object AsterismEditorTitle extends AsterismModifier: React.Fragment( // only pass in the unexecuted observations. Will be readonly if there aren't any - (props.state.get.obsEditInfo, - props.state.get + (props.tileState.get.obsEditInfo, + props.tileState.get .unexecutedObs(props.obsIds) ).mapN((obsEditInfo, unexecutedObs) => targetSelectionPopup( @@ -224,5 +224,7 @@ object AsterismEditorTitle extends AsterismModifier: ) ), ObsTimeEditor(props.vizTimeView), - ColumnSelectorInTitle(TargetTable.columnNames, props.state.zoom(AsterismTileState.table)) + ColumnSelectorInTitle(TargetTable.columnNames, + props.tileState.zoom(AsterismTileState.table) + ) ) diff --git a/explore/src/main/scala/explore/targets/TargetSummaryBody.scala b/explore/src/main/scala/explore/targets/TargetSummaryBody.scala index 700de0fbed..3d814d1347 100644 --- a/explore/src/main/scala/explore/targets/TargetSummaryBody.scala +++ b/explore/src/main/scala/explore/targets/TargetSummaryBody.scala @@ -10,6 +10,7 @@ import crystal.react.* import explore.Icons import explore.common.UserPreferencesQueries import explore.common.UserPreferencesQueries.TableStore +import explore.components.ColumnSelectorState import explore.components.HelpIcon import explore.components.ui.ExploreStyles import explore.model.AppContext @@ -45,11 +46,10 @@ import lucuma.ui.reusability.given import lucuma.ui.syntax.all.given import lucuma.ui.table.* import lucuma.ui.table.hooks.* +import monocle.Focus import org.scalajs.dom.File as DOMFile import scala.collection.immutable.SortedSet -import monocle.Focus -import explore.components.ColumnSelectorState case class TargetSummaryTileState( filesToImport: List[DOMFile], @@ -75,12 +75,12 @@ case class TargetSummaryBody( selectTargetOrSummary: Option[Target.Id] => Callback, selectedTargetIds: View[List[Target.Id]], undoCtx: UndoContext[ProgramSummaries], - readonly: Boolean -)(val state: View[TargetSummaryTileState]) - extends ReactFnProps(TargetSummaryBody.component): - val filesToImport = state.zoom(TargetSummaryTileState.filesToImport) - val table = state.zoom(TargetSummaryTileState.table) - val deletingTargets = state.zoom(TargetSummaryTileState.deletingTargets) + readonly: Boolean, + tileState: View[TargetSummaryTileState] +) extends ReactFnProps(TargetSummaryBody.component): + val filesToImport = tileState.zoom(TargetSummaryTileState.filesToImport) + val table = tileState.zoom(TargetSummaryTileState.table) + val deletingTargets = tileState.zoom(TargetSummaryTileState.deletingTargets) object TargetSummaryBody: private type Props = TargetSummaryBody @@ -322,12 +322,12 @@ case class TargetSummaryTitle( selectTargetOrSummary: Option[Target.Id] => Callback, selectedTargetIds: View[List[Target.Id]], undoCtx: UndoContext[ProgramSummaries], - readonly: Boolean -)(val state: View[TargetSummaryTileState]) - extends ReactFnProps(TargetSummaryTitle.component) { - val filesToImport = state.zoom(TargetSummaryTileState.filesToImport) - val table = state.zoom(TargetSummaryTileState.table) - val deletingTargets = state.zoom(TargetSummaryTileState.deletingTargets) + readonly: Boolean, + tileState: View[TargetSummaryTileState] +) extends ReactFnProps(TargetSummaryTitle.component) { + val filesToImport = tileState.zoom(TargetSummaryTileState.filesToImport) + val table = tileState.zoom(TargetSummaryTileState.table) + val deletingTargets = tileState.zoom(TargetSummaryTileState.deletingTargets) } object TargetSummaryTitle: diff --git a/explore/src/main/scala/explore/timingwindows/TimingWindowsTile.scala b/explore/src/main/scala/explore/timingwindows/TimingWindowsTile.scala index 5e3b7bdc39..75018e5d7c 100644 --- a/explore/src/main/scala/explore/timingwindows/TimingWindowsTile.scala +++ b/explore/src/main/scala/explore/timingwindows/TimingWindowsTile.scala @@ -14,6 +14,7 @@ import explore.components.Tile import explore.components.ui.ExploreStyles import explore.model.Constants.BadTimingWindow import explore.model.ObsTabTilesIds +import explore.model.enums.TileSizeState import explore.model.formats.* import explore.model.reusability.given import explore.model.syntax.all.* @@ -26,6 +27,7 @@ import lucuma.core.model.TimingWindow import lucuma.core.model.TimingWindowEnd import lucuma.core.model.TimingWindowRepeat import lucuma.core.syntax.display.given +import lucuma.core.util.NewType import lucuma.core.util.TimeSpan import lucuma.core.util.Timestamp import lucuma.core.validation.InputValidSplitEpi @@ -53,17 +55,16 @@ import java.time.Duration import java.time.Instant import java.time.ZoneOffset import java.time.ZonedDateTime -import explore.model.enums.TileSizeState -case class TimingWindowsTileState( - setRowSelection: RowSelection => Callback = _ => Callback.empty -) +object TimingWindowsTileState extends NewType[RowSelection => Callback]: + def apply(): TimingWindowsTileState = TimingWindowsTileState(_ => Callback.empty) +type TimingWindowsTileState = TimingWindowsTileState.Type case class TimingWindowsBody( - windows: View[List[TimingWindow]], - readOnly: Boolean -)(val state: View[TimingWindowsTileState]) - extends ReactFnProps(TimingWindowsBody.component) + windows: View[List[TimingWindow]], + readOnly: Boolean, + tileState: View[TimingWindowsTileState] +) extends ReactFnProps(TimingWindowsBody.component) object TimingWindowsTile: def timingWindowsPanel( @@ -74,8 +75,8 @@ object TimingWindowsTile: val title = if (timingWindows.get.isEmpty) base else s"$base (${timingWindows.get.length})" Tile(ObsTabTilesIds.TimingWindowsId.id, TimingWindowsTileState(), title)( - TimingWindowsBody(timingWindows, readOnly), - TimingWindowsTitle(timingWindows, readOnly) + TimingWindowsBody(timingWindows, readOnly, _), + TimingWindowsTitle(timingWindows, readOnly, _, _) ) object TimingWindowsBody: @@ -157,7 +158,7 @@ object TimingWindowsBody: ) .useEffectOnMountBy((p, _, _, _, table) => val cb = (a: RowSelection) => table.setRowSelection(a) - p.state.set(TimingWindowsTileState(cb)) + p.tileState.set(TimingWindowsTileState(cb)) ) .render: (props, resize, dbActive, rows, table) => val pos = table.getSelectedRowModel().rows.headOption.map(_.original._2) @@ -424,10 +425,11 @@ object TimingWindowsBody: ) case class TimingWindowsTitle( - windows: View[List[TimingWindow]], - readOnly: Boolean -)(val state: View[TimingWindowsTileState], val tileSize: TileSizeState) - extends ReactFnProps(TimingWindowsTitle.component) + windows: View[List[TimingWindow]], + readOnly: Boolean, + tileState: View[TimingWindowsTileState], + tileSize: TileSizeState +) extends ReactFnProps(TimingWindowsTitle.component) object TimingWindowsTitle: private type Props = TimingWindowsTitle @@ -446,7 +448,7 @@ object TimingWindowsTitle: start = Timestamp.unsafeFromInstantTruncated(Instant.now), end = none ) - ) >> props.state.get.setRowSelection( + ) >> props.tileState.get.value( RowSelection(RowId(props.windows.get.size.toString) -> true) ) ).tiny.compact diff --git a/explore/src/main/scala/explore/validations/ObservationValidationsTableBody.scala b/explore/src/main/scala/explore/validations/ObservationValidationsTableBody.scala index 958c497ec1..742ffba777 100644 --- a/explore/src/main/scala/explore/validations/ObservationValidationsTableBody.scala +++ b/explore/src/main/scala/explore/validations/ObservationValidationsTableBody.scala @@ -3,8 +3,8 @@ package explore.validations -import crystal.react.View import cats.syntax.all.* +import crystal.react.View import explore.Icons import explore.components.ui.ExploreStyles import explore.model.AppContext @@ -12,6 +12,7 @@ import explore.model.Focused import explore.model.Observation import explore.model.ObservationList import explore.model.enums.AppTab +import explore.model.enums.TileSizeState import explore.model.reusability.given import japgolly.scalajs.react.* import japgolly.scalajs.react.ScalaFnComponent @@ -20,6 +21,7 @@ import japgolly.scalajs.react.vdom.html_<^.* import lucuma.core.enums.ObservationValidationCode import lucuma.core.model.ObservationValidation import lucuma.core.model.Program +import lucuma.core.util.NewType import lucuma.react.common.ReactFnProps import lucuma.react.primereact.* import lucuma.react.primereact.tooltip.* @@ -32,14 +34,14 @@ import lucuma.ui.primereact.* import lucuma.ui.table.* import scala.scalajs.js -import lucuma.core.util.NewType -import explore.model.enums.TileSizeState object ObservationValidationsTableTileState extends NewType[Boolean => Callback] type ObservationValidationsTableTileState = ObservationValidationsTableTileState.Type -case class ObservationValidationsTableBody(programId: Program.Id, observations: ObservationList)( - val state: View[ObservationValidationsTableTileState] +case class ObservationValidationsTableBody( + programId: Program.Id, + observations: ObservationList, + tileState: View[ObservationValidationsTableTileState] ) extends ReactFnProps(ObservationValidationsTableBody.component) object ObservationValidationsTableBody { @@ -157,7 +159,7 @@ object ObservationValidationsTableBody { ) .useEffectOnMountBy((p, _, _, _, table) => val cb = (a: Boolean) => table.toggleAllRowsExpanded(a) - p.state.set(ObservationValidationsTableTileState(cb)) + p.tileState.set(ObservationValidationsTableTileState(cb)) ) .useResizeDetector() .render((props, _, rows, _, table, resizer) => @@ -235,8 +237,8 @@ object ObservationValidationsTableBody { } case class ObservationValidationsTableTitle( - state: View[ObservationValidationsTableTileState], - tileSize: TileSizeState + tileState: View[ObservationValidationsTableTileState], + tileSize: TileSizeState ) extends ReactFnProps(ObservationValidationsTableTitle.component) object ObservationValidationsTableTitle: @@ -252,12 +254,12 @@ object ObservationValidationsTableTitle: size = Button.Size.Small, icon = Icons.SquarePlus, tooltip = "Expand All", - onClick = p.state.get.value(true) + onClick = p.tileState.get.value(true) ).compact, Button( size = Button.Size.Small, icon = Icons.SquareMinus, tooltip = "Collapse All", - onClick = p.state.get.value(false) + onClick = p.tileState.get.value(false) ).compact )