All Downloads are FREE. Search and download functionalities are using the official Maven repository.

lucuma.ui.sequence.SequenceColumns.scala Maven / Gradle / Ivy

There is a newer version: 0.125.0
Show newest version
// 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 lucuma.ui.sequence

import cats.syntax.all.*
import japgolly.scalajs.react.*
import japgolly.scalajs.react.vdom.html_<^.*
import lucuma.react.common.*
import lucuma.react.syntax.*
import lucuma.react.table.*
import lucuma.ui.syntax.all.*
import lucuma.ui.table.*
import lucuma.ui.table.ColumnSize.*
import lucuma.ui.utils.formatSN

import SequenceRowFormatters.*

object SequenceColumns:
  val IndexAndTypeColumnId: ColumnId = ColumnId("stepType")
  val ExposureColumnId: ColumnId     = ColumnId("exposure")
  val GuideColumnId: ColumnId        = ColumnId("guide")
  val PColumnId: ColumnId            = ColumnId("p")
  val QColumnId: ColumnId            = ColumnId("q")
  val WavelengthColumnId: ColumnId   = ColumnId("lambda")
  val FPUColumnId: ColumnId          = ColumnId("fpu")
  val GratingColumnId: ColumnId      = ColumnId("grating")
  val FilterColumnId: ColumnId       = ColumnId("filter")
  val XBinColumnId: ColumnId         = ColumnId("xbin")
  val YBinColumnId: ColumnId         = ColumnId("Ybin")
  val ROIColumnId: ColumnId          = ColumnId("roi")
  val SNColumnId: ColumnId           = ColumnId("sn")

  val BaseColumnSizes: Map[ColumnId, ColumnSize] = Map(
    IndexAndTypeColumnId -> FixedSize(60.toPx),
    ExposureColumnId     -> Resizable(77.toPx, min = 77.toPx, max = 130.toPx),
    GuideColumnId        -> FixedSize(33.toPx),
    PColumnId            -> FixedSize(75.toPx),
    QColumnId            -> FixedSize(75.toPx),
    WavelengthColumnId   -> Resizable(75.toPx, min = 75.toPx, max = 130.toPx),
    FPUColumnId          -> Resizable(132.toPx, min = 132.toPx),
    GratingColumnId      -> Resizable(120.toPx, min = 120.toPx),
    FilterColumnId       -> Resizable(90.toPx, min = 90.toPx),
    XBinColumnId         -> FixedSize(60.toPx),
    YBinColumnId         -> FixedSize(60.toPx),
    ROIColumnId          -> Resizable(75.toPx, min = 75.toPx),
    SNColumnId           -> Resizable(75.toPx, min = 75.toPx, max = 130.toPx)
  )

  // The order in which they are removed by overflow. The ones at the beginning go first.
  // Missing columns are not removed by overflow. (We declare them in reverse order)
  val BaseColumnPriorities: List[ColumnId] = List(
    PColumnId,
    QColumnId,
    GuideColumnId,
    ExposureColumnId,
    SNColumnId,
    ROIColumnId,
    XBinColumnId,
    YBinColumnId,
    FilterColumnId,
    GratingColumnId,
    FPUColumnId
  ).reverse

  def headerCell[T, R, TM](
    colId:  ColumnId,
    colDef: ColumnDef.Applied[Expandable[HeaderOrRow[T]], TM]
  ): ColumnDef.Single.WithTableMeta[Expandable[HeaderOrRow[T]], Option[VdomNode], TM] =
    colDef(
      colId,
      _.value.left.toOption.map(_.content),
      header = "",
      cell = cell =>
        cell.value
          .map: header =>
            <.span(
              SequenceStyles.TableHeader,
              TagMod(
                SequenceStyles.TableHeaderExpandable,
                ^.onClick ==>
                  (_.stopPropagationCB >> cell.row.getToggleExpandedHandler()),
                <.span(
                  TableStyles.ExpanderChevron,
                  TableStyles.ExpanderChevronOpen.when(cell.row.getIsExpanded())
                )(TableIcons.ChevronRight.withFixedWidth())
              ).when(cell.row.getCanExpand()),
              <.span(SequenceStyles.TableHeaderContent)(header)
            ),
      enableResizing = false
    )

  // `T` is the actual type of the table row, from which we extract an `R` using `getStep`.
  // `D` is the `DynamicConfig`.
  // `TM` is the type of the table meta.
  def gmosColumns[D, T, R <: SequenceRow[D], TM](
    colDef:   ColumnDef.Applied[Expandable[HeaderOrRow[T]], TM],
    getStep:  T => Option[R],
    getIndex: T => Option[StepIndex]
  ): List[ColumnDef.Single.WithTableMeta[Expandable[HeaderOrRow[T]], ?, TM]] =
    List(
      colDef(
        IndexAndTypeColumnId,
        _.value.toOption
          .map(row => (getIndex(row), getStep(row).flatMap(_.stepTypeDisplay)))
          .getOrElse((none, none)),
        header = "Step",
        cell = c =>
          React.Fragment(
            c.value._1.map(_.value.value),
            c.value._2.map(_.renderVdom)
          )
      ),
      colDef(
        ExposureColumnId,
        _.value.toOption.flatMap(row => getStep(row).flatMap(_.exposureTime)),
        header = _ => "Exp (sec)",
        cell = c =>
          (c.value, c.row.original.value.toOption.flatMap(getStep).flatMap(_.instrument)).mapN:
            (e, i) => FormatExposureTime(i)(e).value
      ),
      colDef(
        GuideColumnId,
        _.value.toOption.flatMap(row => getStep(row).map(_.hasGuiding)),
        header = "",
        cell = _.value
          .filter(identity) // Only render on Some(true)
          .map(_ => SequenceIcons.Crosshairs.withClass(SequenceStyles.StepGuided))
      ),
      colDef(
        PColumnId,
        _.value.toOption.map(row => getStep(row).flatMap(_.p)),
        header = _ => "p",
        cell = _.value.map(_.map(FormatOffsetP(_).value)).orEmpty
      ),
      colDef(
        QColumnId,
        _.value.toOption.map(row => getStep(row).flatMap(_.q)),
        header = _ => "q",
        cell = _.value.map(_.map(FormatOffsetQ(_).value)).orEmpty
      ),
      colDef(
        WavelengthColumnId,
        _.value.toOption.map(row => getStep(row).flatMap(_.wavelength)),
        header = _ => "λ (nm)",
        cell = _.value.map(_.map(FormatWavelength(_).value).getOrElse("-")).orEmpty
      ),
      colDef(
        FPUColumnId,
        _.value.toOption.map(row => getStep(row).flatMap(_.fpuName).getOrElse("None")),
        header = _ => "FPU",
        cell = _.value.orEmpty
      ),
      colDef(
        GratingColumnId,
        _.value.toOption.map(row => getStep(row).flatMap(_.gratingName).getOrElse("None")),
        header = "Grating",
        cell = _.value.orEmpty
      ),
      colDef(
        FilterColumnId,
        _.value.toOption.map(row => getStep(row).flatMap(_.filterName).getOrElse("None")),
        header = "Filter",
        cell = _.value.orEmpty
      ),
      colDef(
        XBinColumnId,
        _.value.toOption.flatMap(row => getStep(row).flatMap(_.readoutXBin)),
        header = _ => "Xbin",
        cell = _.value.orEmpty
      ),
      colDef(
        YBinColumnId,
        _.value.toOption.flatMap(row => getStep(row).flatMap(_.readoutYBin)),
        header = _ => "Ybin",
        cell = _.value.orEmpty
      ),
      colDef(
        ROIColumnId,
        _.value.toOption.flatMap(row => getStep(row).flatMap(_.roi)),
        header = "ROI",
        cell = _.value.orEmpty
      ),
      colDef(
        SNColumnId,
        _.value.toOption.flatMap(row => getStep(row).flatMap(_.signalToNoise)),
        header = "S/N",
        cell = _.value.map(formatSN).orEmpty
      )
    )




© 2015 - 2025 Weber Informatics LLC | Privacy Policy