Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create date range picker #94

Open
wants to merge 4 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions source/Ui/DateRangePicker.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
module Ui.DateRangePicker exposing (WhichDatePicker(..), Model, Msg, init, update, view, onSecondDatePickerChange, onFirstDatePickerChange, setCalendarValue, setValue, closeWhichOnSelect, disableWhich, disable)

import Html exposing (..)
import Time
import Ui.Container
import Ui.DatePicker
import Ui.Calendar


type alias Model =
{ datePicker1 : Ui.DatePicker.Model
, datePicker2 : Ui.DatePicker.Model
}


type WhichDatePicker
= First
| Second


{-| Msg is messaging that's been contextualized per date picker
-}
type Msg
= DatePicker1 Ui.DatePicker.Msg
| DatePicker2 Ui.DatePicker.Msg


init : () -> Model
init _ =
{ datePicker1 = Ui.DatePicker.init ()
, datePicker2 = Ui.DatePicker.init ()
}


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
DatePicker1 calendarMsg ->
let
( updatedModel, effect ) =
Ui.DatePicker.update calendarMsg model.datePicker1
in
( { model | datePicker1 = updatedModel }, Cmd.map DatePicker1 effect )

DatePicker2 calendarMsg ->
let
( updatedModel, effect ) =
Ui.DatePicker.update calendarMsg model.datePicker2
in
( { model | datePicker2 = updatedModel }, Cmd.map DatePicker2 effect )


view : String -> Model -> Html Msg
view locale model =
Ui.Container.row []
[ Html.map DatePicker1 (Ui.DatePicker.view locale model.datePicker1)
, Html.map DatePicker2 (Ui.DatePicker.view locale model.datePicker2)
]


{-| Subscribe to the changes of an individual date picker.

e.g.

subscriptions =
Ui.DateRangePicker.onSecondDatePickerChange DateRangePickerChanged datePicker

-}
onSecondDatePickerChange : (Time.Time -> msg) -> Model -> Sub msg
onSecondDatePickerChange msg model =
Ui.DatePicker.onChange msg model.datePicker2


onFirstDatePickerChange : (Time.Time -> msg) -> Model -> Sub msg
onFirstDatePickerChange msg model =
Ui.DatePicker.onChange msg model.datePicker1



{--
Helpful setters
-}


setCalendarValue : (Ui.Calendar.Model -> Ui.Calendar.Model) -> Ui.DatePicker.Model -> Ui.DatePicker.Model
setCalendarValue setter picker =
{ picker | calendar = setter picker.calendar }


setValue : (Ui.DatePicker.Model -> Ui.DatePicker.Model) -> WhichDatePicker -> Model -> Model
setValue updater which picker =
case which of
First ->
{ datePicker2 = picker.datePicker2
, datePicker1 = updater picker.datePicker1
}

Second ->
{ datePicker2 = updater picker.datePicker2
, datePicker1 = picker.datePicker1
}


closeWhichOnSelect : Bool -> WhichDatePicker -> Model -> Model
closeWhichOnSelect value which model =
setValue (\d -> Ui.DatePicker.closeOnSelect value d) which model


disableWhich : WhichDatePicker -> Model -> Model
disableWhich which picker =
setValue (\d -> { d | disabled = True }) which picker


disable : Model -> Model
disable picker =
let
disabler =
(\d -> { d | disabled = True })
in
setValue disabler First picker
|> setValue disabler Second
141 changes: 141 additions & 0 deletions spec/Ui/DateRangePickerSpec.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
module Main exposing (..)

import Spec exposing (..)
import Steps exposing (..)
import Task
import Json.Encode as Json
import Ui.Native.Uid as Uid
import Date.Extra.Format exposing (isoDateFormat, format)
import Date
import Ext.Date
import Ui.DateRangePicker as DRP exposing (setCalendarValue, setValue, WhichDatePicker(..), disableWhich)
import Ui.DatePicker
import Html exposing (..)
import Html.Attributes exposing (class)


type alias Model =
{ simple : DRP.Model
, oneDisabled : DRP.Model
, withPreselectedDates : DRP.Model
, readOnly : DRP.Model
}


type Msg
= Simple DRP.Msg
| OneDisabled DRP.Msg
| WithPreselectedDates DRP.Msg
| ReadOnly DRP.Msg


init : () -> Model
init _ =
let
firstDatePicker =
Ui.DatePicker.init ()

secondDatePicker =
Ui.DatePicker.init ()

firstCalendar =
firstDatePicker.calendar

secondCalendar =
secondDatePicker.calendar
in
({ simple = DRP.init ()
, oneDisabled =
disableWhich First (DRP.init ())
, withPreselectedDates =
setValue (setCalendarValue (\c -> { c | value = (Ext.Date.createDate 2018 5 20), date = (Ext.Date.createDate 2018 5 20) })) First (DRP.init ())
|> setValue (setCalendarValue (\c -> { c | value = (Ext.Date.createDate 2018 5 28), date = (Ext.Date.createDate 2018 5 28) })) Second
, readOnly =
setValue (setCalendarValue (\c -> { c | readonly = True, value = (Ext.Date.createDate 2018 5 20), date = (Ext.Date.createDate 2018 5 20) })) First (DRP.init ())
|> setValue (setCalendarValue (\c -> { c | readonly = True, value = (Ext.Date.createDate 2018 5 28), date = (Ext.Date.createDate 2018 5 28) })) Second
}
)


update : Msg -> Model -> ( Model, Cmd Msg )
update msg_ model =
case msg_ of
Simple msg ->
let
( updatedModel, cmd ) =
DRP.update msg model.simple
in
( { model | simple = updatedModel }, Cmd.none )

OneDisabled msg ->
let
( updatedModel, cmd ) =
DRP.update msg model.oneDisabled
in
( { model | oneDisabled = updatedModel }, Cmd.none )

WithPreselectedDates msg ->
let
( updatedModel, cmd ) =
DRP.update msg model.withPreselectedDates
in
( { model | withPreselectedDates = updatedModel }, Cmd.none )

ReadOnly msg ->
let
( updatedModel, cmd ) =
DRP.update msg model.readOnly
in
( { model | readOnly = updatedModel }, Cmd.none )


uiSnapshot : String -> String -> Html Msg -> Html Msg
uiSnapshot title key ui =
div [ class key ]
[ text title
, ui
]


view : Model -> Html.Html Msg
view model =
div []
[ uiSnapshot "Without Presets" "without-presets" (Html.map Simple (DRP.view "en_us" model.simple))
, uiSnapshot "With One Disabled Date Picker" "one-disabled" (Html.map OneDisabled (DRP.view "en_us" model.oneDisabled))
, uiSnapshot "With Preselected Dates" "preselected" (Html.map WithPreselectedDates (DRP.view "en_us" model.withPreselectedDates))
, uiSnapshot "With A Readonly Date Picker" "readonly" (Html.map ReadOnly (DRP.view "en_us" model.readOnly))
]


specs : Node
specs =
describe "Ui.DateRangePicker"
[ it "displays two calendars"
[ assert.elementPresent ".without-presets ui-picker:nth-child(1)"
, assert.elementPresent ".without-presets ui-picker:nth-child(2)"
]
, it "should be disableable"
[ assert.elementPresent ".one-disabled ui-picker[disabled]"
, assert.elementPresent ".one-disabled ui-picker"
]
, it
"should allow preselection of dates"
[ assert.containsText { selector = ".preselected ui-picker:nth-child(1)", text = "2018-05-20" }
, assert.containsText { selector = ".preselected ui-picker:nth-child(2)", text = "2018-05-28" }
]
, it
"should be able to set calendars to be read only"
[ assert.elementPresent ".readonly ui-picker:nth-child(1) ui-calendar[readonly]"
, assert.elementPresent ".readonly ui-picker:nth-child(2) ui-calendar[readonly]"
]
]


main =
runWithProgram
{ subscriptions = \_ -> Sub.none
, update = update
, init = init
, view = view
}
specs
Loading