Support printing user's itinerary

- Define print.css with media=print type (note: could've been handled with
  @media queries)
- Define printPage port to interop with window.print() JS function
- Support UI.wrapNoPrint to wrap components with a the no-print CSS
This commit is contained in:
William Carroll 2020-08-02 14:23:38 +01:00
parent 699892883c
commit 803db7a5b2
5 changed files with 55 additions and 24 deletions

View file

@ -4,7 +4,8 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="google-signin-client_id" content="580018768696-4beppspj6cu7rhjnfgok8lbmh9a4n3ok.apps.googleusercontent.com"> <meta name="google-signin-client_id" content="580018768696-4beppspj6cu7rhjnfgok8lbmh9a4n3ok.apps.googleusercontent.com">
<title>Elm SPA</title> <title>Elm SPA</title>
<link rel="stylesheet" href="./output.css" /> <link rel="stylesheet" type="text/css" href="./output.css" />
<link rel="stylesheet" type="text/css" href="./print.css" media="print" />
<script src="https://apis.google.com/js/platform.js" async defer></script> <script src="https://apis.google.com/js/platform.js" async defer></script>
<script src="./Main.min.js"></script> <script src="./Main.min.js"></script>
</head> </head>
@ -27,7 +28,11 @@
}); });
} }
Elm.Main.init({node: document.getElementById("mount")}); var app = Elm.Main.init({node: document.getElementById("mount")});
app.ports.printPage.subscribe(function() {
window.print();
});
</script> </script>
</body> </body>
</html> </html>

3
client/print.css Normal file
View file

@ -0,0 +1,3 @@
.no-print {
display: none;
}

View file

@ -1,4 +1,4 @@
module State exposing (..) port module State exposing (..)
import Array exposing (Array) import Array exposing (Array)
import Browser import Browser
@ -39,6 +39,7 @@ type Msg
| UpdateTripComment String | UpdateTripComment String
| ClearErrors | ClearErrors
| ToggleLoginForm | ToggleLoginForm
| PrintPage
-- SPA -- SPA
| LinkClicked Browser.UrlRequest | LinkClicked Browser.UrlRequest
| UrlChanged Url.Url | UrlChanged Url.Url
@ -476,11 +477,14 @@ userHome flags url key =
) )
port printPage : () -> Cmd msg
{-| The initial state for the application. {-| The initial state for the application.
-} -}
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url key = init flags url key =
prod flags url key userHome flags url key
{-| Now that we have state, we need a function to change the state. {-| Now that we have state, we need a function to change the state.
@ -591,6 +595,9 @@ update msg model =
, Cmd.none , Cmd.none
) )
PrintPage ->
( model, printPage () )
LinkClicked urlRequest -> LinkClicked urlRequest ->
case urlRequest of case urlRequest of
Browser.Internal url -> Browser.Internal url ->

View file

@ -310,3 +310,8 @@ datePicker { mDate, prompt, prefix, picker, onUpdate } =
in in
div [ [ "w-1/2", "py-4", "mx-auto" ] |> Tailwind.use |> class ] div [ [ "w-1/2", "py-4", "mx-auto" ] |> Tailwind.use |> class ]
[ DatePicker.view mDate settings picker |> Html.map onUpdate ] [ DatePicker.view mDate settings picker |> Html.map onUpdate ]
wrapNoPrint : Html State.Msg -> Html State.Msg
wrapNoPrint component =
div [ [ "no-print" ] |> Tailwind.use |> class ] [ component ]

View file

@ -78,19 +78,20 @@ renderTrip trip =
|> Tailwind.use |> Tailwind.use
|> class |> class
] ]
[ p [] [ UI.paragraph
[ text (Date.toIsoString trip.startDate
(Date.toIsoString trip.startDate ++ " - "
++ " - " ++ Date.toIsoString trip.endDate
++ Date.toIsoString trip.endDate ++ " -> "
++ " -> " ++ trip.destination
++ trip.destination )
) , UI.paragraph ("\"" ++ trip.comment ++ "\"")
] , UI.wrapNoPrint
, UI.textButton (UI.textButton
{ label = "Delete" { label = "Delete"
, handleClick = State.AttemptDeleteTrip trip.destination trip.startDate , handleClick = State.AttemptDeleteTrip trip.destination trip.startDate
} }
)
] ]
@ -109,7 +110,15 @@ trips model =
UI.paragraph ("Error: " ++ Utils.explainHttpError e) UI.paragraph ("Error: " ++ Utils.explainHttpError e)
RemoteData.Success xs -> RemoteData.Success xs ->
ul [] (xs |> List.map renderTrip) div [ [ "mb-10" ] |> Tailwind.use |> class ]
[ ul [ [ "my-4" ] |> Tailwind.use |> class ] (xs |> List.map renderTrip)
, UI.wrapNoPrint
(UI.simpleButton
{ label = "Print iternary"
, handleClick = State.PrintPage
}
)
]
] ]
@ -126,13 +135,15 @@ render model =
|> Tailwind.use |> Tailwind.use
) )
] ]
[ UI.header 2 ("Welcome, " ++ session.username ++ "!") [ UI.wrapNoPrint (UI.header 2 ("Welcome, " ++ session.username ++ "!"))
, createTrip model , UI.wrapNoPrint (createTrip model)
, trips model , trips model
, UI.textButton , UI.wrapNoPrint
{ label = "Logout" (UI.textButton
, handleClick = State.AttemptLogout { label = "Logout"
} , handleClick = State.AttemptLogout
}
)
, Common.allErrors model , Common.allErrors model
] ]
) )