Skip to content

Instantly share code, notes, and snippets.

Created July 13, 2017 18:48
Show Gist options
  • Save anonymous/29e370df7c9284011e15ebcedb5ee13a to your computer and use it in GitHub Desktop.
Save anonymous/29e370df7c9284011e15ebcedb5ee13a to your computer and use it in GitHub Desktop.
Untitled
module Counter exposing (main)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Time.DateTime as DateTime exposing (DateTime, date)
import Json.Decode as Decode exposing (Decoder)
-- Model
type Model
= HelloPage
| ItemFormPage Item
type alias Item =
{ title : String
, duration : Maybe Duration
}
type alias Duration =
{ begin : DateTime
, end : DateTime
}
decodeDuration : Decoder Duration
decodeDuration =
Decode.map2 Duration
(Decode.field "begin" decodeDateTime)
(Decode.field "end" decodeDateTime)
decodeDateTime : Decoder DateTime
decodeDateTime =
Decode.string |> Decode.andThen decodeDateTime_
decodeDateTime_ : String -> Decoder DateTime
decodeDateTime_ s =
case DateTime.fromISO8601 s of
Err err ->
Decode.fail <| Debug.log "err" err
Ok date ->
Decode.succeed date
emptyItem : Item
emptyItem =
{ title = "This is title"
, duration = Nothing
}
mapItemForm : Model -> (Item -> Item) -> Model
mapItemForm model mapper =
case model of
ItemFormPage item ->
ItemFormPage <| mapper item
_ ->
model
-- Routing
type Route
= HelloPageRoute
| ItemFormRoute
-- Update
type Msg
= ChangeRoute Route
| TitleChanged String
| DurationChanged (Maybe Duration)
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ChangeRoute route ->
case route of
HelloPageRoute ->
HelloPage ! []
ItemFormRoute ->
ItemFormPage emptyItem ! []
TitleChanged title ->
mapItemForm model (\item -> { item | title = title }) ! []
DurationChanged duration ->
mapItemForm model (\item -> { item | duration = duration }) ! []
-- View
view : Model -> Html Msg
view model =
div [] (viewPage model)
viewPage : Model -> List (Html Msg)
viewPage model =
case model of
HelloPage ->
helloPage
ItemFormPage item ->
itemFormPage item
helloPage : List (Html Msg)
helloPage =
[ section [ class "content-header" ]
[ h3 [] [ text "Hello Page" ] ]
, section []
[ button
[ class "btn btn-primary"
, onClick <| ChangeRoute ItemFormRoute
]
[ text "Edit an item" ]
]
]
itemFormPage : Item -> List (Html Msg)
itemFormPage item =
[ section [ class "content-header" ]
[ h3 [] [ text "Item Page" ] ]
, section [] [ itemForm item ]
]
itemForm : Item -> Html Msg
itemForm item =
Html.form []
[ div [ class "form-group" ]
[ label [] [ text "Title" ]
, input
[ class "form-control"
, value item.title
, onInput TitleChanged
]
[]
]
, div [ class "form-group" ]
[ label [] [ text "Date range" ]
, input
[ class "form-control date-range"
, value <| formatMaybeDuration item.duration
, onDateRangePicker DurationChanged
]
[]
]
, button
[ type_ "button"
, class "btn btn-primary"
, onClick <| ChangeRoute HelloPageRoute
]
[ text "Go back" ]
, pre [] [ code [] [ text <| toString item ] ]
]
onDateRangePicker : (Maybe Duration -> Msg) -> Attribute Msg
onDateRangePicker tagger =
on "apply.daterangepicker" <|
Decode.map tagger <|
Decode.field "detail" <|
Decode.nullable decodeDuration
formatMaybeDuration : Maybe Duration -> String
formatMaybeDuration maybeDuration =
case maybeDuration of
Just d ->
(formatDateTime d.begin) ++ " - " ++ (formatDateTime d.end)
Nothing ->
""
formatDateTime : DateTime -> String
formatDateTime d =
int00 (DateTime.day d)
++ "."
++ int00 (DateTime.month d)
++ "."
++ toString (DateTime.year d)
++ " "
++ int00 (DateTime.hour d)
++ ":"
++ int00 (DateTime.minute d)
int00 : Int -> String
int00 i =
String.padLeft 2 '0' (toString i)
main : Program Never Model Msg
main =
Html.program
{ view = view
, update = update
, subscriptions = \_ -> Sub.none
, init = ( HelloPage, Cmd.none )
}
{
"version": "1.0.0",
"summary": "Tell the world about your project!",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"."
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "5.1.1 <= v < 5.1.1",
"elm-lang/html": "2.0.0 <= v < 2.0.0",
"elm-community/elm-time": "1.0.1 <= v < 1.0.1"
},
"elm-version": "0.18.0 <= v < 0.19.0"
}
<html>
<head>
<title></title>
<meta charset="utf8" />
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/bootstrap/3/css/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.css" />
</head>
<body>
<div id="demo-app"></div>
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="//cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.js"></script>
<script>
const main = document.getElementById("demo-app");
const app = Elm.Counter.embed(main);
const observer = new MutationObserver(mutations => {
mutations.forEach(m => {
$(m.addedNodes).find('.date-range').each(function () {
createDatePicker($(this));
});
});
});
observer.observe(main, {childList: true, subtree: true})
const createDatePicker = $elem => {
const format = 'DD.MM.YYYY HH:mm';
const [start,end] = ($elem.val() || '').split(' - ');
const startEnd = (start && end
? {
startDate: moment(start, format),
endDate: moment(end, format)
}
: {});
$elem.daterangepicker(Object.assign({}, startEnd, {
autoUpdateInput: false,
applyClass: 'btn-primary',
timePicker: true,
timePicker24Hour: true,
timePickerIncrement: 1,
locale: {
format,
cancelLabel: 'Clear'
}
}));
const publishUpdate = (elem, detail) => {
elem.dispatchEvent(new CustomEvent('apply.daterangepicker', { detail }));
};
$elem.on('cancel.daterangepicker', function() {
publishUpdate(this, null);
});
$elem.on('apply.daterangepicker hide.daterangepicker', function(e, picker) {
// https://github.com/elm-community/elm-time/issues/21
const iso = d => d.toISOString().replace('.000Z', 'Z');
publishUpdate(this, {
begin: iso(picker.startDate),
end: iso(picker.endDate)
});
});
};
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment