From 42c98edad311da42078a48cd4d1a904ec2b1262f Mon Sep 17 00:00:00 2001 From: niole Date: Sun, 7 Jan 2018 16:55:03 -0800 Subject: [PATCH 1/4] Creates initial daterangepicker and test --- source/Ui/DateRangePicker.elm | 53 ++ spec/Ui/DateRangePickerSpec.elm | 60 ++ yarn.lock | 1186 ++----------------------------- 3 files changed, 166 insertions(+), 1133 deletions(-) create mode 100644 source/Ui/DateRangePicker.elm create mode 100644 spec/Ui/DateRangePickerSpec.elm diff --git a/source/Ui/DateRangePicker.elm b/source/Ui/DateRangePicker.elm new file mode 100644 index 0000000..b4559e6 --- /dev/null +++ b/source/Ui/DateRangePicker.elm @@ -0,0 +1,53 @@ +module Ui.DateRangePicker exposing (..) + +import Html exposing (..) +import Time +import Ui.DatePicker +import Ui.Helpers.Picker as Picker +import Ui.Calendar + + +type alias Model = + { datePicker1 : Ui.DatePicker.Model + , datePicker2 : Ui.DatePicker.Model + } + + +{-| Msg is messaging that's been contextualized per date picker +-} +type Msg + = Calendar1 Ui.DatePicker.Msg + | Calendar2 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 + Calendar1 calendarMsg -> + let + ( updatedModel, effect ) = + Ui.DatePicker.update calendarMsg model.datePicker1 + in + ( { model | datePicker1 = updatedModel }, Cmd.map Calendar1 effect ) + + Calendar2 calendarMsg -> + let + ( updatedModel, effect ) = + Ui.DatePicker.update calendarMsg model.datePicker2 + in + ( { model | datePicker2 = updatedModel }, Cmd.map Calendar2 effect ) + + +view : String -> Model -> Html Msg +view locale model = + div [] + [ Html.map Calendar1 (Ui.DatePicker.view locale model.datePicker1) + , Html.map Calendar2 (Ui.DatePicker.view locale model.datePicker2) + ] diff --git a/spec/Ui/DateRangePickerSpec.elm b/spec/Ui/DateRangePickerSpec.elm new file mode 100644 index 0000000..53fa32e --- /dev/null +++ b/spec/Ui/DateRangePickerSpec.elm @@ -0,0 +1,60 @@ +module Main exposing (..) + +import Spec exposing (..) +import Steps exposing (..) +import Json.Encode as Json +import Ui.DateRangePicker +import Ui.DatePicker +import Html exposing (..) + + +type alias Model = + { one : Ui.DateRangePicker.Model + } + + +type Msg + = One Ui.DateRangePicker.Msg + + +init : () -> Model +init _ = + { one = Ui.DateRangePicker.init () } + + +update : Msg -> Model -> ( Model, Cmd Msg ) +update msg_ model = + case msg_ of + One msg -> + let + ( updatedModel, cmd ) = + Ui.DateRangePicker.update msg model.one + in + ( { model | one = updatedModel }, Cmd.none ) + + +view : Model -> Html.Html Msg +view model = + div [] + [ Html.map One (Ui.DateRangePicker.view "en_us" model.one) + ] + + +specs : Node +specs = + describe "Ui.DateRangePicker" + [ it "displays two calendars" + [ assert.elementPresent "ui-picker:nth-child(1)" + , assert.elementPresent "ui-picker:nth-child(2)" + ] + ] + + +main = + runWithProgram + { subscriptions = \_ -> Sub.none + , update = update + , init = init + , view = view + } + specs diff --git a/yarn.lock b/yarn.lock index 623b3db..1415ed7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,1133 +1,53 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -abab@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d" - -acorn-globals@^1.0.4: - version "1.0.9" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf" - dependencies: - acorn "^2.1.0" - -acorn@^2.1.0, acorn@^2.4.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7" - -adm-zip@^0.4.7: - version "0.4.7" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - -ansi-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.0.0.tgz#c5061b6e0ef8a81775e50f5d66151bf6bf371107" - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -array-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - -asap@~2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f" - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - -assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -async@^2.0.1, async@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" - dependencies: - lodash "^4.14.0" - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - -aws4@^1.2.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755" - -balanced-match@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" - -bcrypt-pbkdf@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz#3ca76b85241c7170bf7d9703e7b9aa74630040d4" - dependencies: - tweetnacl "^0.14.3" - -bl@^1.0.0, bl@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.1.2.tgz#fdca871a99713aa00d19e3bbba41c44787a65398" - dependencies: - readable-stream "~2.0.5" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - dependencies: - inherits "~2.0.0" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - -brace-expansion@^1.0.0: - version "1.1.6" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" - dependencies: - balanced-match "^0.4.1" - concat-map "0.0.1" - -builtin-modules@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - -camelcase@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.0.0.tgz#8b0f90d44be5e281b903b9887349b92595ef07f2" - -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - -chalk@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - -colors@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - dependencies: - delayed-stream "~1.0.0" - -commander@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - dependencies: - graceful-readlink ">= 1.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -content-type-parser@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.1.tgz#c3e56988c53c65127fb46d4032a3a900246fdc94" - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - -cssom@0.3.x, "cssom@>= 0.3.0 < 0.4.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.1.tgz#c9e37ef2490e64f6d1baa10fda852257082c25d3" - -"cssstyle@>= 0.2.36 < 0.3.0", cssstyle@^0.2.37: - version "0.2.37" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-0.2.37.tgz#541097234cb2513c83ceed3acddc27ff27987d54" - dependencies: - cssom "0.3.x" - -dashdash@^1.12.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.0.tgz#29e486c5418bf0f356034a993d51686a33e84141" - dependencies: - assert-plus "^1.0.0" - -decamelize@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - dependencies: - jsbn "~0.1.0" - -elm-github-install@^1.0.0, elm-github-install@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/elm-github-install/-/elm-github-install-1.0.1.tgz#8be5847f5d586078c0d3f658f56dc4fad4f988ff" - dependencies: - adm-zip "^0.4.7" - request "2.74.0" - shelljs "0.7.5" - tar-fs "1.15.0" - tmp "^0.0.31" - -elm-spec@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/elm-spec/-/elm-spec-1.1.1.tgz#eff5cbdca32f0a81d449eec9176436d07fc99a59" - dependencies: - async "^2.1.4" - camelcase "^4.0.0" - colors "^1.1.2" - cssstyle "^0.2.37" - elm "^0.18.0" - elm-github-install "^1.0.1" - globby "^6.1.0" - indent-string "^3.0.0" - jsdom "^9.9.1" - node-localstorage "^1.3.0" - npm-which "^3.0.1" - pad "^1.0.2" - temp "^0.8.3" - yargs "^6.6.0" - -elm@^0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/elm/-/elm-0.18.0.tgz#919b8309cd939dfe2ff9d252d961b6c89509b970" - dependencies: - mkdirp "0.5.1" - promise "7.1.1" - request "2.74.0" - tar "2.2.1" - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.1.0.tgz#e9353258baa9108965efc41cb0ef8ade2f3cfb07" - dependencies: - once "~1.3.0" - -error-ex@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.0.tgz#e67b43f3e82c96ea3a584ffee0b9fc3325d802d9" - dependencies: - is-arrayish "^0.2.1" - -escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -escodegen@^1.6.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - -esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - -esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - -extend@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" - -extsprintf@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" - -fast-levenshtein@~2.0.4: - version "2.0.5" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.5.tgz#bd33145744519ab1c36c3ee9f31f08e9079b67f2" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -form-data@~1.0.0-rc4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-1.0.1.tgz#ae315db9a4907fa065502304a66d7733475ee37c" - dependencies: - async "^2.0.1" - combined-stream "^1.0.5" - mime-types "^2.1.11" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -fstream@^1.0.2: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.10.tgz#604e8a92fe26ffd9f6fae30399d4984e1ab22822" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - -get-caller-file@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" - -getpass@^0.1.1: - version "0.1.6" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" - dependencies: - assert-plus "^1.0.0" - -glob@^7.0.0, glob@^7.0.3: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -graceful-fs@^4.1.11: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -graceful-fs@^4.1.2: - version "4.1.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.10.tgz#f2d720c22092f743228775c75e3612632501f131" - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -hosted-git-info@^2.1.4: - version "2.1.5" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.1.5.tgz#0ba81d90da2e25ab34a332e6ec77936e1598118b" - -html-encoding-sniffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz#79bf7a785ea495fe66165e734153f363ff5437da" - dependencies: - whatwg-encoding "^1.0.1" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -iconv-lite@0.4.13: - version "0.4.13" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" - -iconv-lite@^0.4.13: - version "0.4.15" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - -indent-string@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.0.0.tgz#ddab23d32113ef04b67ab4cf4a0951c1a85fd60c" - dependencies: - repeating "^3.0.0" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@~2.0.0, inherits@~2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -interpret@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - dependencies: - builtin-modules "^1.0.0" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - dependencies: - number-is-nan "^1.0.0" - -is-my-json-valid@^2.12.4: - version "2.15.0" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isexe@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -jodid25519@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" - dependencies: - jsbn "~0.1.0" - -jsbn@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd" - -jsdom@^9.9.1: - version "9.9.1" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.9.1.tgz#84f3972ad394ab963233af8725211bce4d01bfd5" - dependencies: - abab "^1.0.0" - acorn "^2.4.0" - acorn-globals "^1.0.4" - array-equal "^1.0.0" - content-type-parser "^1.0.1" - cssom ">= 0.3.0 < 0.4.0" - cssstyle ">= 0.2.36 < 0.3.0" - escodegen "^1.6.1" - html-encoding-sniffer "^1.0.1" - iconv-lite "^0.4.13" - nwmatcher ">= 1.3.9 < 2.0.0" - parse5 "^1.5.1" - request "^2.55.0" - sax "^1.1.4" - symbol-tree ">= 3.1.0 < 4.0.0" - tough-cookie "^2.3.1" - webidl-conversions "^3.0.1" - whatwg-encoding "^1.0.1" - whatwg-url "^4.1.0" - xml-name-validator ">= 2.0.1 < 3.0.0" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -jsonpointer@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.0.tgz#6661e161d2fc445f19f98430231343722e1fcbd5" - -jsprim@^1.2.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.3.1.tgz#2a7256f70412a29ee3670aaca625994c4dcff252" - dependencies: - extsprintf "1.0.2" - json-schema "0.2.3" - verror "1.3.6" - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - dependencies: - invert-kv "^1.0.0" - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -lodash@^4.14.0: - version "4.17.0" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.0.tgz#93f4466e5ab73e5a1f1216c34eea11535f0a8df5" - -mime-db@~1.24.0: - version "1.24.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.24.0.tgz#e2d13f939f0016c6e4e9ad25a8652f126c467f0c" - -mime-types@^2.1.11, mime-types@~2.1.7: - version "2.1.12" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.12.tgz#152ba256777020dd4663f54c2e7bc26381e71729" - dependencies: - mime-db "~1.24.0" - -minimatch@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" - dependencies: - brace-expansion "^1.0.0" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -node-localstorage@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/node-localstorage/-/node-localstorage-1.3.0.tgz#2e436aae8dcc9ace97b43c65c16c0d577be0a55c" - dependencies: - write-file-atomic "^1.1.4" - -node-uuid@~1.4.7: - version "1.4.7" - resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.7.tgz#6da5a17668c4b3dd59623bda11cf7fa4c1f60a6f" - -normalize-package-data@^2.3.2: - version "2.3.5" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.5.tgz#8d924f142960e1777e7ffe170543631cc7cb02df" - dependencies: - hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -npm-path@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.2.tgz#6462f098bb38e21e335a8c6f42d21d7b57f098c8" - dependencies: - which "^1.2.10" - -npm-which@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" - dependencies: - commander "^2.9.0" - npm-path "^2.0.2" - which "^1.2.10" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -"nwmatcher@>= 1.3.9 < 2.0.0": - version "1.3.9" - resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.3.9.tgz#8bab486ff7fa3dfd086656bbe8b17116d3692d2a" - -oauth-sign@~0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - -object-assign@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - -once@^1.3.0, once@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -once@~1.3.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" - dependencies: - wrappy "1" - -optionator@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - dependencies: - lcid "^1.0.0" - -os-tmpdir@^1.0.0, os-tmpdir@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - -pad@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pad/-/pad-1.0.2.tgz#f6e36ff3ceb468e4ae2ed33ad5ecf25ace920960" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - dependencies: - error-ex "^1.2.0" - -parse5@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - dependencies: - pinkie-promise "^2.0.0" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - -promise@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf" - dependencies: - asap "~2.0.3" - -pump@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.2.tgz#3b3ee6512f94f0e575538c17995f9f16990a5d51" - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -qs@~6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.1.tgz#ce03c5ff0935bc1d9d69a9f14cbd18e568d67625" - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -readable-stream@^2.0.0, readable-stream@~2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~0.10.x" - util-deprecate "~1.0.1" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - dependencies: - resolve "^1.1.6" - -repeating@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-3.0.0.tgz#f4c376fdd2015761f6f96f4303b1224d581e802f" - -request@2.74.0, request@^2.55.0: - version "2.74.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.74.0.tgz#7693ca768bbb0ea5c8ce08c084a45efa05b892ab" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - bl "~1.1.2" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~1.0.0-rc4" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - node-uuid "~1.4.7" - oauth-sign "~0.8.1" - qs "~6.2.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - -resolve@^1.1.6: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - -rimraf@2, rimraf@~2.2.6: - version "2.2.8" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" - -sax@^1.1.4: - version "1.2.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" - -"semver@2 || 3 || 4 || 5": - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - -shelljs@0.7.5: - version "0.7.5" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.5.tgz#2eef7a50a21e1ccf37da00df767ec69e30ad0675" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -slide@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - dependencies: - amdefine ">=0.0.4" - -spdx-correct@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" - dependencies: - spdx-license-ids "^1.0.2" - -spdx-expression-parse@~1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" - -spdx-license-ids@^1.0.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" - -sshpk@^1.7.0: - version "1.10.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.10.1.tgz#30e1a5d329244974a1af61511339d595af6638b0" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jodid25519 "^1.0.0" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -stringstream@~0.0.4: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - dependencies: - is-utf8 "^0.2.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -"symbol-tree@>= 3.1.0 < 4.0.0": - version "3.2.1" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.1.tgz#8549dd1d01fa9f893c18cc9ab0b106b4d9b168cb" - -tar-fs@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.15.0.tgz#74c97dc773737c2aeacbfff246c654d6528a5315" - dependencies: - mkdirp "^0.5.0" - pump "^1.0.0" - tar-stream "^1.1.2" - -tar-stream@^1.1.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.2.tgz#fbc6c6e83c1a19d4cb48c7d96171fc248effc7bf" - dependencies: - bl "^1.0.0" - end-of-stream "^1.0.0" - readable-stream "^2.0.0" - xtend "^4.0.0" - -tar@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -temp@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59" - dependencies: - os-tmpdir "^1.0.0" - rimraf "~2.2.6" - -tmp@^0.0.31: - version "0.0.31" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" - dependencies: - os-tmpdir "~1.0.1" - -tough-cookie@^2.3.1, tough-cookie@~2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" - dependencies: - punycode "^1.4.1" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - -tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.3" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.3.tgz#3da382f670f25ded78d7b3d1792119bca0b7132d" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - dependencies: - prelude-ls "~1.1.2" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -validate-npm-package-license@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" - dependencies: - spdx-correct "~1.0.0" - spdx-expression-parse "~1.0.0" - -verror@1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" - dependencies: - extsprintf "1.0.2" - -webidl-conversions@^3.0.0, webidl-conversions@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - -whatwg-encoding@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz#3c6c451a198ee7aec55b1ec61d0920c67801a5f4" - dependencies: - iconv-lite "0.4.13" - -whatwg-url@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.3.0.tgz#92aaee21f4f2a642074357d70ef8500a7cbb171a" - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - -which@^1.2.10: - version "1.2.12" - resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192" - dependencies: - isexe "^1.1.1" - -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -write-file-atomic@^1.1.4: - version "1.3.1" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.1.tgz#7d45ba32316328dd1ec7d90f60ebc0d845bb759a" - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - slide "^1.1.5" - -"xml-name-validator@>= 2.0.1 < 3.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" - -xtend@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - -yargs-parser@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" - dependencies: - camelcase "^3.0.0" - -yargs@^6.6.0: - version "6.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^4.2.0" +module Ui.DateRangePicker exposing (..) + +import Html exposing (..) +import Time +import Ui.DatePicker +import Ui.Helpers.Picker as Picker +import Ui.Calendar + + +type alias Model = + { datePicker1 : Ui.DatePicker.Model + , datePicker2 : Ui.DatePicker.Model + } + + +{-| Msg is messaging that's been contextualized per date picker +-} +type Msg + = Calendar1 Ui.DatePicker.Msg + | Calendar2 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 + Calendar1 calendarMsg -> + let + ( updatedModel, effect ) = + Ui.DatePicker.update calendarMsg model.datePicker1 + in + ( { model | datePicker1 = updatedModel }, Cmd (Calendar1 effect) ) + + Calendar2 calendarMsg -> + let + ( updatedModel, effect ) = + Ui.DatePicker.update calendarMsg model.datePicker1 + in + ( { model | datePicker2 = updatedModel }, Cmd (Calendar2 effect) ) + + +view : String -> Model -> Html Ui.DatePicker.Msg +view locale model = + div [] + [ Ui.DatePicker.view locale model.datePicker1 + , Ui.DatePicker.view locale model.datePicker2 + ] From 553570adbfaf2f13fe76764862ec04954e8d1cc8 Mon Sep 17 00:00:00 2001 From: niole Date: Sun, 7 Jan 2018 18:52:13 -0800 Subject: [PATCH 2/4] Add rest of UI examples in Ui spec --- source/Ui/DatePicker.elm | 238 ++++++++++++++++++-------------- source/Ui/DateRangePicker.elm | 1 - spec/Ui/DateRangePickerSpec.elm | 92 +++++++++++- 3 files changed, 220 insertions(+), 111 deletions(-) diff --git a/source/Ui/DatePicker.elm b/source/Ui/DatePicker.elm index 610226a..68d3932 100644 --- a/source/Ui/DatePicker.elm +++ b/source/Ui/DatePicker.elm @@ -1,46 +1,66 @@ -module Ui.DatePicker exposing - ( Model, Msg, init, update, subscriptions, onChange, view, render, setValue - , closeOnSelect ) +module Ui.DatePicker + exposing + ( Model + , Msg + , init + , update + , subscriptions + , onChange + , view + , render + , setValue + , closeOnSelect + ) {-| An input component that displays a **Calendar** (in a dropdown) when focused, allowing the user to manipulate the selected date. + # Model + @docs Model, Msg, init, subscriptions, update + # DSL + @docs closeOnSelect + # Events + @docs onChange + # View + @docs view, render -# Functions @docs setValue + + +# Functions + -} import Html.Events.Extra exposing (onPreventDefault) import Html exposing (node, text) import Html.Lazy - import Date.Extra.Format exposing (isoDateFormat, format) import Date.Extra.Config.Configs as DateConfigs import Time import Date - import Ui.Helpers.Dropdown as Dropdown exposing (Dropdown) import Ui.Helpers.Picker as Picker import Ui.Native.Uid as Uid import Ui.Calendar import Ui.Icons import Ui - import Ui.Styles.DatePicker exposing (defaultStyle) import Ui.Styles + {-| Representation of a date picker: + - **closeOnSelect** - Whether or not to close the dropdown after selecting - **format** - The format of the date to render in the input - **readonly** - Whether or not the date picker is readonly @@ -48,165 +68,177 @@ import Ui.Styles - **uid** - The unique identifier of the date picker - **calendar** - The model of the calendar - **dropdown** - The model of the dropdown + -} type alias Model = - { calendar : Ui.Calendar.Model - , closeOnSelect : Bool - , dropdown : Dropdown - , format : String - , disabled : Bool - , readonly : Bool - , uid : String - } + { calendar : Ui.Calendar.Model + , closeOnSelect : Bool + , dropdown : Dropdown + , format : String + , disabled : Bool + , readonly : Bool + , uid : String + } {-| Messages that a date picker can receive. -} type Msg - = Calendar Ui.Calendar.Msg - | Picker Picker.Msg - | Select Time.Time - | Increment - | Decrement - | NoOp + = Calendar Ui.Calendar.Msg + | Picker Picker.Msg + | Select Time.Time + | Increment + | Decrement + | NoOp {-| Initializes a date picker with the given date. datePicker = - Ui.DatePicker.init () - |> Ui.DatePicker.closeOnSelect true + Ui.DatePicker.init () + |> Ui.DatePicker.closeOnSelect true + -} init : () -> Model init _ = - { calendar = Ui.Calendar.init () - , dropdown = Dropdown.init - , format = isoDateFormat - , closeOnSelect = False - , disabled = False - , readonly = False - , uid = Uid.uid () - } - |> Dropdown.offset 5 + { calendar = Ui.Calendar.init () + , dropdown = Dropdown.init + , format = isoDateFormat + , closeOnSelect = False + , disabled = False + , readonly = False + , uid = Uid.uid () + } + |> Dropdown.offset 5 {-| Subscribe to the changes of a date picker. - subscriptions = Ui.DatePicker.onChange DatePickerChanged datePicker + subscriptions = + Ui.DatePicker.onChange DatePickerChanged datePicker + -} onChange : (Time.Time -> msg) -> Model -> Sub msg onChange msg model = - Ui.Calendar.onChange msg model.calendar + Ui.Calendar.onChange msg model.calendar {-| Subscriptions for a date picker. - subscriptions = Sub.map DatePicker (Ui.DatePicker.subscriptions datePicker) + subscriptions = + Sub.map DatePicker (Ui.DatePicker.subscriptions datePicker) + -} subscriptions : Model -> Sub Msg subscriptions model = - Sub.batch - [ Ui.Calendar.onChange Select model.calendar - , Sub.map Picker (Picker.subscriptions model) - ] + Sub.batch + [ Ui.Calendar.onChange Select model.calendar + , Sub.map Picker (Picker.subscriptions model) + ] {-| Sets whether or not to close the dropdown when selecting an other date. -} closeOnSelect : Bool -> Model -> Model closeOnSelect value model = - { model | closeOnSelect = value } + { model | closeOnSelect = value } {-| Updates a date picker. - ( updatedDatePicker, cmd ) = Ui.DatePicker.update msg datePicker + ( updatedDatePicker, cmd ) = + Ui.DatePicker.update msg datePicker + -} update : Msg -> Model -> ( Model, Cmd Msg ) update action model = - case action of - NoOp -> - ( model, Cmd.none ) - - Calendar act -> - let - ( calendar, effect ) = - Ui.Calendar.update act model.calendar - in - ( { model | calendar = calendar }, Cmd.map Calendar effect ) - - Select time -> - let - updatedModel = - if model.closeOnSelect then - Dropdown.close model - else - model - in - ( updatedModel, Cmd.none ) - - Picker act -> - ( Picker.update act model, Cmd.none ) - - Decrement -> - ( { model | calendar = Ui.Calendar.previousDay model.calendar } - |> Dropdown.open - , Cmd.none - ) - - Increment -> - ( { model | calendar = Ui.Calendar.nextDay model.calendar } - |> Dropdown.open - , Cmd.none - ) + case action of + NoOp -> + ( model, Cmd.none ) + + Calendar act -> + let + ( calendar, effect ) = + Ui.Calendar.update act model.calendar + in + ( { model | calendar = calendar }, Cmd.map Calendar effect ) + + Select time -> + let + updatedModel = + if model.closeOnSelect then + Dropdown.close model + else + model + in + ( updatedModel, Cmd.none ) + + Picker act -> + ( Picker.update act model, Cmd.none ) + + Decrement -> + ( { model | calendar = Ui.Calendar.previousDay model.calendar } + |> Dropdown.open + , Cmd.none + ) + + Increment -> + ( { model | calendar = Ui.Calendar.nextDay model.calendar } + |> Dropdown.open + , Cmd.none + ) {-| Lazily renders a date picker in the given locale. Ui.DatePicker.view "en_us" model + -} view : String -> Model -> Html.Html Msg view locale model = - Html.Lazy.lazy2 render locale model + Html.Lazy.lazy2 render locale model {-| Renders a date picker in the given locale. Ui.DatePicker.render "en_us" model + -} render : String -> Model -> Html.Html Msg render locale model = - let - dateText = - (format (DateConfigs.getConfig locale) model.format model.calendar.value) - in - Picker.view - { attributes = Ui.Styles.apply defaultStyle - , address = Picker - , keyActions = - [ ( 40, Increment ) - , ( 38, Decrement ) - , ( 39, Increment ) - , ( 37, Decrement ) - ] - , contents = - [ node "ui-date-picker-content" [] [ text dateText ] - , Ui.Icons.calendar [] - ] - , dropdownContents = - [ node "ui-date-picker-calendar" - [ onPreventDefault "mousedown" NoOp ] - [ Html.map Calendar (Ui.Calendar.view locale model.calendar) - ] - ] - } model + let + dateText = + (format (DateConfigs.getConfig locale) model.format model.calendar.value) + in + Picker.view + { attributes = Ui.Styles.apply defaultStyle + , address = Picker + , keyActions = + [ ( 40, Increment ) + , ( 38, Decrement ) + , ( 39, Increment ) + , ( 37, Decrement ) + ] + , contents = + [ node "ui-date-picker-content" [] [ text dateText ] + , Ui.Icons.calendar [] + ] + , dropdownContents = + [ node "ui-date-picker-calendar" + [ onPreventDefault "mousedown" NoOp ] + [ Html.map Calendar (Ui.Calendar.view locale model.calendar) + ] + ] + } + model {-| Sets the value of a date picker ( updatedDatePicker, cmd ) = - Ui.DatePicker.setValue (Ext.Date.create 1980 5 17) datePicker + Ui.DatePicker.setValue (Ext.Date.create 1980 5 17) datePicker + -} setValue : Date.Date -> Model -> Model setValue date model = - { model | calendar = Ui.Calendar.setValue date model.calendar } + { model | calendar = Ui.Calendar.setValue date model.calendar } diff --git a/source/Ui/DateRangePicker.elm b/source/Ui/DateRangePicker.elm index b4559e6..964abe7 100644 --- a/source/Ui/DateRangePicker.elm +++ b/source/Ui/DateRangePicker.elm @@ -3,7 +3,6 @@ module Ui.DateRangePicker exposing (..) import Html exposing (..) import Time import Ui.DatePicker -import Ui.Helpers.Picker as Picker import Ui.Calendar diff --git a/spec/Ui/DateRangePickerSpec.elm b/spec/Ui/DateRangePickerSpec.elm index 53fa32e..e61d711 100644 --- a/spec/Ui/DateRangePickerSpec.elm +++ b/spec/Ui/DateRangePickerSpec.elm @@ -2,41 +2,119 @@ 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 import Ui.DatePicker +import Ui.Calendar exposing (..) import Html exposing (..) +import Ui.Helpers.Dropdown as Dropdown exposing (Dropdown) type alias Model = - { one : Ui.DateRangePicker.Model + { simple : Ui.DateRangePicker.Model + , oneDisabled : Ui.DateRangePicker.Model + , withPreselectedDates : Ui.DateRangePicker.Model + , readOnly : Ui.DateRangePicker.Model } type Msg - = One Ui.DateRangePicker.Msg + = Simple Ui.DateRangePicker.Msg + | OneDisabled Ui.DateRangePicker.Msg + | WithPreselectedDates Ui.DateRangePicker.Msg + | ReadOnly Ui.DateRangePicker.Msg init : () -> Model init _ = - { one = Ui.DateRangePicker.init () } + let + firstDatePicker = + Ui.DatePicker.init () + + secondDatePicker = + Ui.DatePicker.init () + + firstCalendar = + firstDatePicker.calendar + + secondCalendar = + secondDatePicker.calendar + in + ({ simple = Ui.DateRangePicker.init () + , oneDisabled = + { datePicker1 = { firstDatePicker | disabled = True } + , datePicker2 = secondDatePicker + } + , withPreselectedDates = + let + updatedCalendar1 = + { firstCalendar | value = (Ext.Date.createDate 2018 5 20), date = (Ext.Date.createDate 2018 5 20) } + + updatedCalendar2 = + { secondCalendar | value = (Ext.Date.createDate 2018 5 28), date = (Ext.Date.createDate 2018 5 28) } + in + { datePicker1 = { firstDatePicker | calendar = updatedCalendar1 } + , datePicker2 = { secondDatePicker | calendar = updatedCalendar2 } + } + , readOnly = + let + updatedCalendar1 = + { firstCalendar | readonly = True } + + updatedCalendar2 = + { secondCalendar | readonly = True } + in + { datePicker1 = { firstDatePicker | calendar = updatedCalendar1 } + , datePicker2 = { secondDatePicker | calendar = updatedCalendar2 } + } + } + ) update : Msg -> Model -> ( Model, Cmd Msg ) update msg_ model = case msg_ of - One msg -> + Simple msg -> + let + ( updatedModel, cmd ) = + Ui.DateRangePicker.update msg model.simple + in + ( { model | simple = updatedModel }, Cmd.none ) + + OneDisabled msg -> + let + ( updatedModel, cmd ) = + Ui.DateRangePicker.update msg model.oneDisabled + in + ( { model | oneDisabled = updatedModel }, Cmd.none ) + + WithPreselectedDates msg -> + let + ( updatedModel, cmd ) = + Ui.DateRangePicker.update msg model.withPreselectedDates + in + ( { model | withPreselectedDates = updatedModel }, Cmd.none ) + + ReadOnly msg -> let ( updatedModel, cmd ) = - Ui.DateRangePicker.update msg model.one + Ui.DateRangePicker.update msg model.readOnly in - ( { model | one = updatedModel }, Cmd.none ) + ( { model | readOnly = updatedModel }, Cmd.none ) view : Model -> Html.Html Msg view model = div [] - [ Html.map One (Ui.DateRangePicker.view "en_us" model.one) + [ Html.map Simple (Ui.DateRangePicker.view "en_us" model.simple) + , Html.map OneDisabled (Ui.DateRangePicker.view "en_us" model.oneDisabled) + , Html.map WithPreselectedDates (Ui.DateRangePicker.view "en_us" model.withPreselectedDates) + , Html.map ReadOnly (Ui.DateRangePicker.view "en_us" model.readOnly) ] From 76410e470c15532a4de73d3201bba941b6fbe7a0 Mon Sep 17 00:00:00 2001 From: niole Date: Sun, 7 Jan 2018 19:04:27 -0800 Subject: [PATCH 3/4] Adds helper with titles snapshots and wraps with classed container --- spec/Ui/DateRangePickerSpec.elm | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/spec/Ui/DateRangePickerSpec.elm b/spec/Ui/DateRangePickerSpec.elm index e61d711..e63fb3e 100644 --- a/spec/Ui/DateRangePickerSpec.elm +++ b/spec/Ui/DateRangePickerSpec.elm @@ -12,6 +12,7 @@ import Ui.DateRangePicker import Ui.DatePicker import Ui.Calendar exposing (..) import Html exposing (..) +import Html.Attributes exposing (class) import Ui.Helpers.Dropdown as Dropdown exposing (Dropdown) @@ -108,13 +109,21 @@ update msg_ model = ( { 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 [] - [ Html.map Simple (Ui.DateRangePicker.view "en_us" model.simple) - , Html.map OneDisabled (Ui.DateRangePicker.view "en_us" model.oneDisabled) - , Html.map WithPreselectedDates (Ui.DateRangePicker.view "en_us" model.withPreselectedDates) - , Html.map ReadOnly (Ui.DateRangePicker.view "en_us" model.readOnly) + [ uiSnapshot "Without Presets" "without-presets" (Html.map Simple (Ui.DateRangePicker.view "en_us" model.simple)) + , uiSnapshot "With One Disabled Date Picker" "one-disabled" (Html.map OneDisabled (Ui.DateRangePicker.view "en_us" model.oneDisabled)) + , uiSnapshot "With Preselected Dates" "preselected" (Html.map WithPreselectedDates (Ui.DateRangePicker.view "en_us" model.withPreselectedDates)) + , uiSnapshot "With A Readonly Date Picker" "readonly" (Html.map ReadOnly (Ui.DateRangePicker.view "en_us" model.readOnly)) ] From 9c8a41292af520022d4b5bbb293dd6aefd8be78a Mon Sep 17 00:00:00 2001 From: niole Date: Sun, 7 Jan 2018 20:12:50 -0800 Subject: [PATCH 4/4] Adds unit test cases Add some helper methods Reset Calendar and DatePicker --- source/Ui/DatePicker.elm | 238 ++++++++++++++------------------ source/Ui/DateRangePicker.elm | 89 ++++++++++-- spec/Ui/DateRangePickerSpec.elm | 84 ++++++----- 3 files changed, 221 insertions(+), 190 deletions(-) diff --git a/source/Ui/DatePicker.elm b/source/Ui/DatePicker.elm index 68d3932..610226a 100644 --- a/source/Ui/DatePicker.elm +++ b/source/Ui/DatePicker.elm @@ -1,66 +1,46 @@ -module Ui.DatePicker - exposing - ( Model - , Msg - , init - , update - , subscriptions - , onChange - , view - , render - , setValue - , closeOnSelect - ) +module Ui.DatePicker exposing + ( Model, Msg, init, update, subscriptions, onChange, view, render, setValue + , closeOnSelect ) {-| An input component that displays a **Calendar** (in a dropdown) when focused, allowing the user to manipulate the selected date. - # Model - @docs Model, Msg, init, subscriptions, update - # DSL - @docs closeOnSelect - # Events - @docs onChange - # View - @docs view, render -@docs setValue - - # Functions - +@docs setValue -} import Html.Events.Extra exposing (onPreventDefault) import Html exposing (node, text) import Html.Lazy + import Date.Extra.Format exposing (isoDateFormat, format) import Date.Extra.Config.Configs as DateConfigs import Time import Date + import Ui.Helpers.Dropdown as Dropdown exposing (Dropdown) import Ui.Helpers.Picker as Picker import Ui.Native.Uid as Uid import Ui.Calendar import Ui.Icons import Ui + import Ui.Styles.DatePicker exposing (defaultStyle) import Ui.Styles - {-| Representation of a date picker: - - **closeOnSelect** - Whether or not to close the dropdown after selecting - **format** - The format of the date to render in the input - **readonly** - Whether or not the date picker is readonly @@ -68,177 +48,165 @@ import Ui.Styles - **uid** - The unique identifier of the date picker - **calendar** - The model of the calendar - **dropdown** - The model of the dropdown - -} type alias Model = - { calendar : Ui.Calendar.Model - , closeOnSelect : Bool - , dropdown : Dropdown - , format : String - , disabled : Bool - , readonly : Bool - , uid : String - } + { calendar : Ui.Calendar.Model + , closeOnSelect : Bool + , dropdown : Dropdown + , format : String + , disabled : Bool + , readonly : Bool + , uid : String + } {-| Messages that a date picker can receive. -} type Msg - = Calendar Ui.Calendar.Msg - | Picker Picker.Msg - | Select Time.Time - | Increment - | Decrement - | NoOp + = Calendar Ui.Calendar.Msg + | Picker Picker.Msg + | Select Time.Time + | Increment + | Decrement + | NoOp {-| Initializes a date picker with the given date. datePicker = - Ui.DatePicker.init () - |> Ui.DatePicker.closeOnSelect true - + Ui.DatePicker.init () + |> Ui.DatePicker.closeOnSelect true -} init : () -> Model init _ = - { calendar = Ui.Calendar.init () - , dropdown = Dropdown.init - , format = isoDateFormat - , closeOnSelect = False - , disabled = False - , readonly = False - , uid = Uid.uid () - } - |> Dropdown.offset 5 + { calendar = Ui.Calendar.init () + , dropdown = Dropdown.init + , format = isoDateFormat + , closeOnSelect = False + , disabled = False + , readonly = False + , uid = Uid.uid () + } + |> Dropdown.offset 5 {-| Subscribe to the changes of a date picker. - subscriptions = - Ui.DatePicker.onChange DatePickerChanged datePicker - + subscriptions = Ui.DatePicker.onChange DatePickerChanged datePicker -} onChange : (Time.Time -> msg) -> Model -> Sub msg onChange msg model = - Ui.Calendar.onChange msg model.calendar + Ui.Calendar.onChange msg model.calendar {-| Subscriptions for a date picker. - subscriptions = - Sub.map DatePicker (Ui.DatePicker.subscriptions datePicker) - + subscriptions = Sub.map DatePicker (Ui.DatePicker.subscriptions datePicker) -} subscriptions : Model -> Sub Msg subscriptions model = - Sub.batch - [ Ui.Calendar.onChange Select model.calendar - , Sub.map Picker (Picker.subscriptions model) - ] + Sub.batch + [ Ui.Calendar.onChange Select model.calendar + , Sub.map Picker (Picker.subscriptions model) + ] {-| Sets whether or not to close the dropdown when selecting an other date. -} closeOnSelect : Bool -> Model -> Model closeOnSelect value model = - { model | closeOnSelect = value } + { model | closeOnSelect = value } {-| Updates a date picker. - ( updatedDatePicker, cmd ) = - Ui.DatePicker.update msg datePicker - + ( updatedDatePicker, cmd ) = Ui.DatePicker.update msg datePicker -} update : Msg -> Model -> ( Model, Cmd Msg ) update action model = - case action of - NoOp -> - ( model, Cmd.none ) - - Calendar act -> - let - ( calendar, effect ) = - Ui.Calendar.update act model.calendar - in - ( { model | calendar = calendar }, Cmd.map Calendar effect ) - - Select time -> - let - updatedModel = - if model.closeOnSelect then - Dropdown.close model - else - model - in - ( updatedModel, Cmd.none ) - - Picker act -> - ( Picker.update act model, Cmd.none ) - - Decrement -> - ( { model | calendar = Ui.Calendar.previousDay model.calendar } - |> Dropdown.open - , Cmd.none - ) - - Increment -> - ( { model | calendar = Ui.Calendar.nextDay model.calendar } - |> Dropdown.open - , Cmd.none - ) + case action of + NoOp -> + ( model, Cmd.none ) + + Calendar act -> + let + ( calendar, effect ) = + Ui.Calendar.update act model.calendar + in + ( { model | calendar = calendar }, Cmd.map Calendar effect ) + + Select time -> + let + updatedModel = + if model.closeOnSelect then + Dropdown.close model + else + model + in + ( updatedModel, Cmd.none ) + + Picker act -> + ( Picker.update act model, Cmd.none ) + + Decrement -> + ( { model | calendar = Ui.Calendar.previousDay model.calendar } + |> Dropdown.open + , Cmd.none + ) + + Increment -> + ( { model | calendar = Ui.Calendar.nextDay model.calendar } + |> Dropdown.open + , Cmd.none + ) {-| Lazily renders a date picker in the given locale. Ui.DatePicker.view "en_us" model - -} view : String -> Model -> Html.Html Msg view locale model = - Html.Lazy.lazy2 render locale model + Html.Lazy.lazy2 render locale model {-| Renders a date picker in the given locale. Ui.DatePicker.render "en_us" model - -} render : String -> Model -> Html.Html Msg render locale model = - let - dateText = - (format (DateConfigs.getConfig locale) model.format model.calendar.value) - in - Picker.view - { attributes = Ui.Styles.apply defaultStyle - , address = Picker - , keyActions = - [ ( 40, Increment ) - , ( 38, Decrement ) - , ( 39, Increment ) - , ( 37, Decrement ) - ] - , contents = - [ node "ui-date-picker-content" [] [ text dateText ] - , Ui.Icons.calendar [] - ] - , dropdownContents = - [ node "ui-date-picker-calendar" - [ onPreventDefault "mousedown" NoOp ] - [ Html.map Calendar (Ui.Calendar.view locale model.calendar) - ] - ] - } - model + let + dateText = + (format (DateConfigs.getConfig locale) model.format model.calendar.value) + in + Picker.view + { attributes = Ui.Styles.apply defaultStyle + , address = Picker + , keyActions = + [ ( 40, Increment ) + , ( 38, Decrement ) + , ( 39, Increment ) + , ( 37, Decrement ) + ] + , contents = + [ node "ui-date-picker-content" [] [ text dateText ] + , Ui.Icons.calendar [] + ] + , dropdownContents = + [ node "ui-date-picker-calendar" + [ onPreventDefault "mousedown" NoOp ] + [ Html.map Calendar (Ui.Calendar.view locale model.calendar) + ] + ] + } model {-| Sets the value of a date picker ( updatedDatePicker, cmd ) = - Ui.DatePicker.setValue (Ext.Date.create 1980 5 17) datePicker - + Ui.DatePicker.setValue (Ext.Date.create 1980 5 17) datePicker -} setValue : Date.Date -> Model -> Model setValue date model = - { model | calendar = Ui.Calendar.setValue date model.calendar } + { model | calendar = Ui.Calendar.setValue date model.calendar } diff --git a/source/Ui/DateRangePicker.elm b/source/Ui/DateRangePicker.elm index 964abe7..8a6e7d3 100644 --- a/source/Ui/DateRangePicker.elm +++ b/source/Ui/DateRangePicker.elm @@ -1,7 +1,8 @@ -module Ui.DateRangePicker exposing (..) +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 @@ -12,11 +13,16 @@ type alias Model = } +type WhichDatePicker + = First + | Second + + {-| Msg is messaging that's been contextualized per date picker -} type Msg - = Calendar1 Ui.DatePicker.Msg - | Calendar2 Ui.DatePicker.Msg + = DatePicker1 Ui.DatePicker.Msg + | DatePicker2 Ui.DatePicker.Msg init : () -> Model @@ -29,24 +35,87 @@ init _ = update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of - Calendar1 calendarMsg -> + DatePicker1 calendarMsg -> let ( updatedModel, effect ) = Ui.DatePicker.update calendarMsg model.datePicker1 in - ( { model | datePicker1 = updatedModel }, Cmd.map Calendar1 effect ) + ( { model | datePicker1 = updatedModel }, Cmd.map DatePicker1 effect ) - Calendar2 calendarMsg -> + DatePicker2 calendarMsg -> let ( updatedModel, effect ) = Ui.DatePicker.update calendarMsg model.datePicker2 in - ( { model | datePicker2 = updatedModel }, Cmd.map Calendar2 effect ) + ( { model | datePicker2 = updatedModel }, Cmd.map DatePicker2 effect ) view : String -> Model -> Html Msg view locale model = - div [] - [ Html.map Calendar1 (Ui.DatePicker.view locale model.datePicker1) - , Html.map Calendar2 (Ui.DatePicker.view locale model.datePicker2) + 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 diff --git a/spec/Ui/DateRangePickerSpec.elm b/spec/Ui/DateRangePickerSpec.elm index e63fb3e..e005f71 100644 --- a/spec/Ui/DateRangePickerSpec.elm +++ b/spec/Ui/DateRangePickerSpec.elm @@ -8,27 +8,25 @@ import Ui.Native.Uid as Uid import Date.Extra.Format exposing (isoDateFormat, format) import Date import Ext.Date -import Ui.DateRangePicker +import Ui.DateRangePicker as DRP exposing (setCalendarValue, setValue, WhichDatePicker(..), disableWhich) import Ui.DatePicker -import Ui.Calendar exposing (..) import Html exposing (..) import Html.Attributes exposing (class) -import Ui.Helpers.Dropdown as Dropdown exposing (Dropdown) type alias Model = - { simple : Ui.DateRangePicker.Model - , oneDisabled : Ui.DateRangePicker.Model - , withPreselectedDates : Ui.DateRangePicker.Model - , readOnly : Ui.DateRangePicker.Model + { simple : DRP.Model + , oneDisabled : DRP.Model + , withPreselectedDates : DRP.Model + , readOnly : DRP.Model } type Msg - = Simple Ui.DateRangePicker.Msg - | OneDisabled Ui.DateRangePicker.Msg - | WithPreselectedDates Ui.DateRangePicker.Msg - | ReadOnly Ui.DateRangePicker.Msg + = Simple DRP.Msg + | OneDisabled DRP.Msg + | WithPreselectedDates DRP.Msg + | ReadOnly DRP.Msg init : () -> Model @@ -46,33 +44,15 @@ init _ = secondCalendar = secondDatePicker.calendar in - ({ simple = Ui.DateRangePicker.init () + ({ simple = DRP.init () , oneDisabled = - { datePicker1 = { firstDatePicker | disabled = True } - , datePicker2 = secondDatePicker - } + disableWhich First (DRP.init ()) , withPreselectedDates = - let - updatedCalendar1 = - { firstCalendar | value = (Ext.Date.createDate 2018 5 20), date = (Ext.Date.createDate 2018 5 20) } - - updatedCalendar2 = - { secondCalendar | value = (Ext.Date.createDate 2018 5 28), date = (Ext.Date.createDate 2018 5 28) } - in - { datePicker1 = { firstDatePicker | calendar = updatedCalendar1 } - , datePicker2 = { secondDatePicker | calendar = updatedCalendar2 } - } + 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 = - let - updatedCalendar1 = - { firstCalendar | readonly = True } - - updatedCalendar2 = - { secondCalendar | readonly = True } - in - { datePicker1 = { firstDatePicker | calendar = updatedCalendar1 } - , datePicker2 = { secondDatePicker | calendar = updatedCalendar2 } - } + 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 } ) @@ -83,28 +63,28 @@ update msg_ model = Simple msg -> let ( updatedModel, cmd ) = - Ui.DateRangePicker.update msg model.simple + DRP.update msg model.simple in ( { model | simple = updatedModel }, Cmd.none ) OneDisabled msg -> let ( updatedModel, cmd ) = - Ui.DateRangePicker.update msg model.oneDisabled + DRP.update msg model.oneDisabled in ( { model | oneDisabled = updatedModel }, Cmd.none ) WithPreselectedDates msg -> let ( updatedModel, cmd ) = - Ui.DateRangePicker.update msg model.withPreselectedDates + DRP.update msg model.withPreselectedDates in ( { model | withPreselectedDates = updatedModel }, Cmd.none ) ReadOnly msg -> let ( updatedModel, cmd ) = - Ui.DateRangePicker.update msg model.readOnly + DRP.update msg model.readOnly in ( { model | readOnly = updatedModel }, Cmd.none ) @@ -120,10 +100,10 @@ uiSnapshot title key ui = view : Model -> Html.Html Msg view model = div [] - [ uiSnapshot "Without Presets" "without-presets" (Html.map Simple (Ui.DateRangePicker.view "en_us" model.simple)) - , uiSnapshot "With One Disabled Date Picker" "one-disabled" (Html.map OneDisabled (Ui.DateRangePicker.view "en_us" model.oneDisabled)) - , uiSnapshot "With Preselected Dates" "preselected" (Html.map WithPreselectedDates (Ui.DateRangePicker.view "en_us" model.withPreselectedDates)) - , uiSnapshot "With A Readonly Date Picker" "readonly" (Html.map ReadOnly (Ui.DateRangePicker.view "en_us" model.readOnly)) + [ 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)) ] @@ -131,8 +111,22 @@ specs : Node specs = describe "Ui.DateRangePicker" [ it "displays two calendars" - [ assert.elementPresent "ui-picker:nth-child(1)" - , assert.elementPresent "ui-picker:nth-child(2)" + [ 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]" ] ]