Skip to content

Commit

Permalink
Merge pull request #1214 from gemini-hlsw/timespan-short-units
Browse files Browse the repository at this point in the history
Option of short units in time format
  • Loading branch information
rpiaggio authored Jul 17, 2024
2 parents c049418 + 2f74eff commit 9dfaf68
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 21 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import org.scalajs.linker.interface.ModuleSplitStyle

ThisBuild / tlBaseVersion := "0.109"
ThisBuild / tlBaseVersion := "0.110"
ThisBuild / tlCiReleaseBranches := Seq("master")

val Versions = new {
Expand Down
44 changes: 34 additions & 10 deletions modules/tests/src/test/scala/lucuma/ui/syntax/SyntaxSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package lucuma.ui.syntax

import lucuma.core.util.TimeSpan
import lucuma.ui.TimeUnitsFormat
import lucuma.ui.syntax.time.*

import java.time.Duration
Expand All @@ -12,21 +13,44 @@ class SyntaxSuite extends munit.FunSuite:

test("toHoursMinutes should format a TimeSpan"):
assertEquals(TimeSpan.Zero.toHoursMinutes, "0mins")
assertEquals(TimeSpan.Zero.toHoursMinutes(TimeUnitsFormat.Letter), "0m")
assertEquals(TimeSpan.unsafeFromDuration(Duration.ofHours(1)).toHoursMinutes, "1hrs")
assertEquals(
TimeSpan.unsafeFromDuration(Duration.ofHours(1)).toHoursMinutes(TimeUnitsFormat.Letter),
"1h"
)
assertEquals(TimeSpan.unsafeFromDuration(Duration.ofMinutes(30)).toHoursMinutes, "30mins")
assertEquals(TimeSpan.unsafeFromDuration(Duration.ofHours(1).plusMinutes(30)).toHoursMinutes,
"1hrs 30mins"
assertEquals(
TimeSpan
.unsafeFromDuration(Duration.ofHours(1).plusMinutes(30))
.toHoursMinutes(TimeUnitsFormat.Abbreviation),
"1hrs 30mins"
)
assertEquals(
TimeSpan
.unsafeFromDuration(Duration.ofHours(1).plusMinutes(30))
.toHoursMinutes(TimeUnitsFormat.Letter),
"1h 30m"
)

test("toHoursMinutes should round to the nearest minute"):
assertEquals(TimeSpan.unsafeFromDuration(Duration.ofMinutes(30).plusSeconds(30)).toHoursMinutes,
"31mins"
assertEquals(
TimeSpan.unsafeFromDuration(Duration.ofMinutes(30).plusSeconds(30)).toHoursMinutes,
"31mins"
)
assertEquals(
TimeSpan.unsafeFromDuration(Duration.ofMinutes(30).plusSeconds(29)).toHoursMinutes,
"30mins"
)
assertEquals(TimeSpan.unsafeFromDuration(Duration.ofMinutes(30).plusSeconds(29)).toHoursMinutes,
"30mins"
assertEquals(
TimeSpan
.unsafeFromDuration(Duration.ofHours(1).plusMinutes(30).plusSeconds(30))
.toHoursMinutes,
"1hrs 31mins"
)
assertEquals(TimeSpan
.unsafeFromDuration(Duration.ofHours(1).plusMinutes(30).plusSeconds(30))
.toHoursMinutes,
"1hrs 31mins"
assertEquals(
TimeSpan
.unsafeFromDuration(Duration.ofHours(1).plusMinutes(30).plusSeconds(30))
.toHoursMinutes(TimeUnitsFormat.Letter),
"1h 31m"
)
8 changes: 8 additions & 0 deletions modules/ui/src/main/scala/lucuma/ui/TimeUnitsFormat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// 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

enum TimeUnitsFormat(val hours: String, val minutes: String):
case Letter extends TimeUnitsFormat("h", "m")
case Abbreviation extends TimeUnitsFormat("hrs", "mins")
16 changes: 11 additions & 5 deletions modules/ui/src/main/scala/lucuma/ui/components/TimeSpanView.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,31 @@ import japgolly.scalajs.react.*
import japgolly.scalajs.react.vdom.html_<^.*
import lucuma.core.util.TimeSpan
import lucuma.react.common.ReactFnProps
import lucuma.ui.TimeUnitsFormat
import lucuma.ui.syntax.time.*

/**
* A view of a TimeSpan that shows hours and minutes.
*
* Hovering over the view will show the full (unrounded) TimeSpan in hours, minutes, and seconds.
*/
case class TimeSpanView(timespan: TimeSpan, modifiers: Seq[TagMod] = Seq.empty)
extends ReactFnProps(TimeSpanView.component):
case class TimeSpanView(
timespan: TimeSpan,
unitsFormat: TimeUnitsFormat = TimeUnitsFormat.Abbreviation,
modifiers: Seq[TagMod] = Seq.empty
) extends ReactFnProps(TimeSpanView.component):
def addModifiers(modifiers: Seq[TagMod]) = copy(modifiers = this.modifiers ++ modifiers)
def withMods(mods: TagMod*) = addModifiers(mods)

object TimeSpanView:
private type Props = TimeSpanView

def component = ScalaFnComponent[TimeSpanView]: props =>
private val component = ScalaFnComponent[Props]: props =>
val ts = props.timespan

<.span(
props.modifiers.toTagMod,
^.title := s"${ts.toHoursPart} hours, ${ts.toMinutesPart} minutes, ${ts.toSecondsPart} seconds",
ts.toHoursMinutes
^.title := s"${ts.toHoursPart} hours, ${ts.toMinutesPart} minutes, ${ts.toSecondsPart} seconds"
)(
ts.toHoursMinutes(props.unitsFormat)
)
19 changes: 14 additions & 5 deletions modules/ui/src/main/scala/lucuma/ui/syntax/time.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,28 @@ package lucuma.ui.syntax

import cats.syntax.eq.*
import lucuma.core.util.TimeSpan
import lucuma.ui.TimeUnitsFormat

trait time:
extension (timespan: TimeSpan)
/**
* Format a timespan in the format `${hh}hrs ${mm}mins`
*/
def toHoursMinutes: String =
val hours = timespan.toHoursPart
toHoursMinutes(TimeUnitsFormat.Abbreviation)

/**
* Format a timespan in the format `${hh}hrs ${mm}mins` or `${hh}h ${mm}m`
*/
def toHoursMinutes(unitsFormat: TimeUnitsFormat): String =
val hours = timespan.toHoursPart
def hourStr = s"$hours${unitsFormat.hours}"
// Remaining minutes, rounded to the nearest minute
val minutes = timespan.toMinutes.setScale(0, BigDecimal.RoundingMode.HALF_UP) % 60
val minutes = timespan.toMinutes.setScale(0, BigDecimal.RoundingMode.HALF_UP) % 60
def minuteStr = s"$minutes${unitsFormat.minutes}"

if hours === 0 then s"${minutes}mins"
else if minutes === 0 then s"${hours}hrs"
else s"${hours}hrs ${minutes}mins"
if hours === 0 then minuteStr
else if minutes === 0 then hourStr
else s"$hourStr $minuteStr"

object time extends time

0 comments on commit 9dfaf68

Please sign in to comment.