~alcinnz/bureaucromancy

93bfa89a9d3a01b22e5ebac4171280bc72760042 — Adrian Cochrane 1 year, 1 month ago 9a65130
Add a timezone menu!
M bureaucromancy.cabal => bureaucromancy.cabal +2 -2
@@ 63,7 63,7 @@ library

    -- Modules exported by the library.
    exposed-modules:  Text.HTML.Form, Text.HTML.Form.Query,
        Text.HTML.Form.WebApp, Text.HTML.Form.WebApp.Ginger, Text.HTML.Form.WebApp.Ginger.Hourglass
        Text.HTML.Form.WebApp, Text.HTML.Form.WebApp.Ginger, Text.HTML.Form.WebApp.Ginger.Hourglass, Text.HTML.Form.WebApp.Ginger.TZ

    -- Modules included in this library but not exported.
    -- other-modules:


@@ 74,7 74,7 @@ library
    -- Other library packages from which modules are imported.
    build-depends:    base ^>=4.16.4.0, ginger, file-embed-lzma, file-embed, mtl,
            bytestring, text, xml-conduit, network-uri, regex-tdfa, containers,
            filepath, directory, hourglass >= 0.2.12 && < 0.3
            filepath, directory, hourglass >= 0.2.12 && < 0.3, tz >= 0.1 && < 0.2

    -- Directories containing source files.
    hs-source-dirs:   src

M src/Text/HTML/Form/WebApp.hs => src/Text/HTML/Form/WebApp.hs +9 -0
@@ 17,9 17,11 @@ import Text.HTML.Form.WebApp.Ginger (template, template', resolveSource, list')
import Text.HTML.Form.Query (renderQueryString, renderQuery')
import Text.HTML.Form.WebApp.Ginger.Hourglass (timeData, modifyTime', timeParseOrNow,
        gSeqTo, gPad2)
import Text.HTML.Form.WebApp.Ginger.TZ (tzdata)

import Text.Ginger.GVal as V (GVal(..), toGVal, orderedDict, (~>), fromFunction)
import Text.Ginger.Html (html)
import Data.Hourglass (Elapsed(..), Seconds(..), timeGetElapsed, localTimeToGlobal)

type Query = [(ByteString, Maybe ByteString)]
renderPage :: Form -> [Text] -> Query -> IO (Maybe (Either Query Text))


@@ 40,6 42,13 @@ renderInput form ix input@Input { inputType = "date", inputName = name } ["year"
            \prop -> case prop of
                "T" -> timeData t'
                _ -> toGVal ()
renderInput form ix input@Input { inputType = "date", inputName = name } ["zone", ""] qs = do
    t <- timeParseOrNow $ get name qs
    let Elapsed (Seconds t') = timeGetElapsed $ localTimeToGlobal t
    template' "cal/year-numpad.html" form ix input qs $ \prop -> case prop of
        "T" -> timeData t
        "zones" -> tzdata t'
        _ -> toGVal ()
renderInput form ix input@Input { multiple = True } [p] qs
    | '=':v' <- Txt.unpack p,
            (utf8 $ inputName input, Just $ utf8' v') `Prelude.elem` qs =

A src/Text/HTML/Form/WebApp/Ginger/TZ.hs => src/Text/HTML/Form/WebApp/Ginger/TZ.hs +20 -0
@@ 0,0 1,20 @@
{-# LANGUAGE OverloadedStrings #-}
module Text.HTML.Form.WebApp.Ginger.TZ(tzdata) where

import Text.Ginger.GVal as V (GVal, orderedDict, (~>), list)
import qualified Data.Map.Strict as M
import Data.Time.Zones.All (tzNameLabelMap, tzByLabel)
import Data.Time.Zones (diffForPOSIX)
import Data.Int (Int64)

tzdata :: Int64 -> GVal m
tzdata now = list [orderedDict [
        "label" ~> label,
        "value" ~> (diffForPOSIX tz' now `div` 60),
        "offset" ~> formatOffset (diffForPOSIX tz' now `div` 60)
    ] | (label, tz) <- M.toList tzNameLabelMap, let tz' = tzByLabel tz]
formatOffset :: (Show a, Integral a) => a -> [Char]
formatOffset offset = (show hours ++ ':': show minutes)
  where
    hours = offset `div` 60
    minutes = abs $ offset `rem` 60

A tpl/cal/timezone.html => tpl/cal/timezone.html +8 -0
@@ 0,0 1,8 @@
{% extends "/base.html" %}

{%- block main -%}<section>
  <h2><a href="..">{{ T.timezone }}</a></h2>
  <ul style="display: grid; gap: 5px; grid-template-columns: repeat(6, min-content); list-style-type: none">{% for tz in timezones %}
    <li><a href="../zone={{tz.value}}">{{ tz.label }}</a> ({{ tz.offset }})</li>
  {% endfor %}</ul>
</section>{% - endblock %-}

A tpl/cal/year-numpad.html => tpl/cal/year-numpad.html +28 -0
@@ 0,0 1,28 @@
{% extends "/base.html" %}

{%- block main -%}<section>
  <p>{{ T.year }}</p>
  <hr />
  <table>
    <tr>
      <td><a href=":7{{Q}}">7</a></td>
      <td><a href=":8{{Q}}">8</a></td>
      <td><a href=":9{{Q}}">9</a></td>
    </tr>
    <tr>
      <td><a href=":4{{Q}}">4</a></td>
      <td><a href=":5{{Q}}">5</a></td>
      <td><a href=":6{{Q}}">6</a></td>
    </tr>
    <tr>
      <td><a href=":1{{Q}}">1</a></td>
      <td><a href=":2{{Q}}">2</a></td>
      <td><a href=":3{{Q}}">3</a></td>
    </tr>
    <tr>
      <td><a href="-{{Q}}">DEL</a></td>
      <td><a href=":0{{Q}}">0</a></td>
      <td><a href="..{{Q}}">&check;</a></td>
    </tr>
  </table>
</section>{%- endblock -%}

A tpl/cal/year-numpad.html~ => tpl/cal/year-numpad.html~ +34 -0
@@ 0,0 1,34 @@
{% extends "base.html" %}

{%- block main -%}<section>
  <p><a href="+-{{input.step|default(1)}}{{Q}}">↓</a>
    {{ input.value }}
    <a href="+{{input.step|default(1)}}{{Q}}">↑</a></p>
  <hr />
  <table>
    <tr>
      <td><a href=":7{{Q}}">7</a></td>
      <td><a href=":8{{Q}}">8</a></td>
      <td><a href=":9{{Q}}">9</a></td>
      <td><a href=":-{{Q}}">-</a></td>
    </tr>
    <tr>
      <td><a href=":4{{Q}}">4</a></td>
      <td><a href=":5{{Q}}">5</a></td>
      <td><a href=":6{{Q}}">6</a></td>
      <td><a href=":%20{{Q}}">SPACE</a></td>
    </tr>
    <tr>
      <td><a href=":1{{Q}}">1</a></td>
      <td><a href=":2{{Q}}">2</a></td>
      <td><a href=":3{{Q}}">3</a></td>
      <td><a href="-{{Q}}">DEL</a></td>
    </tr>
    <tr>
      <td><a href=":.{{Q}}">.</a></td>
      <td><a href=":0{{Q}}">0</a></td>
      <td><a href=":,{{Q}}">,</a></td>
      <td><a href="={{Q}}">CLEAR</a></td>
    </tr>
  </table>
</section>{%- endblock -%}

M tpl/gregorian.html => tpl/gregorian.html +1 -1
@@ 33,7 33,7 @@
        <a href="meridiem{{Q}}" title="Toggle AM/PM">{{ T.meridiem }}</a>

        <a href="-zone{{Q}}" title="Previous timezone">↓</a>
        {{ T.zone }}
        <a href="zone/">{{ T.zone }}</a>
        <a href="+zone{{Q}}" title="Next zone">↑</a></p>
    <p><a href="now{{Q}}" title="Select current date & time">Now</a></a>