Skip to content

Commit

Permalink
Download and copy-to-clipboard buttons (#29)
Browse files Browse the repository at this point in the history
* added a prototype download button

* rudimentary download button is working

* added prototype copy-to-clipboard button

* changed link button to use button element for uniformity

* improving CSS docs; added css class names for download/clip buttons

* adding disabled button logic; added more CSS docs

* minor css fix and doc update

* pulling in recent version of metajelo-web

* fixed institution name, commented out test buttons
  • Loading branch information
bbarker authored Mar 4, 2020
1 parent 7a2a701 commit c484563
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 30 deletions.
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"cSpell.words": [
"metajelo",
"unminified"
]
}
70 changes: 58 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,67 @@
Web tools to display
[metajelo](https://github.com/labordynamicsinstitute/metajelo) packages.

# Styling with CSS
# Retrieving and Integrating Metajelo-UI

By default, CSS files are retrieved from a [separate repository](https://github.com/labordynamicsinstitute/metajelo-ui-css-classes) using `scripts/getcss`; the file `css/style.css` contains some default styles used in our examples.
Feel free to include it, or modify it (renaming the file is also possible):
## Get the latest build

```html
<link rel="stylesheet" href="css/style.css">
```

Rather than [buidling](#Building) metajelo-ui to get the JavaScript code, you can retrieve the latest build that is
Rather than [building](#Building) metajelo-ui to get the JavaScript code,
you can retrieve the latest build that is
[running on github-pages](https://labordynamicsinstitute.github.io/metajelo-ui):

```
wget -r -np -k https://labordynamicsinstitute.github.io/metajelo-ui/
```

You can then modify the retrieved `index.html` to use the custom CSS;
## Get a versioned build

(TODO)

## Modifying existing CSS

Once you've retrieved a build, as discussed above, or built metajelo-ui,
you may wish to modify the styles. You can modify the retrieved
`index.html` to use the custom CSS;
it will by default be using a minified CSS file which might have a name
like `prod.80f5279b.css`.
like `prod.80f5279b.css`, which is auto-generated as part of the build. You
can change this to point to your css file. This is much faster than pulling
in CSS as part of the build of metajelo-ui.

See the [metajelo-ui-css-classes](https://github.com/labordynamicsinstitute/metajelo-ui-css-classes#building)
repository for information on how to modify and build the default CSS. Once
built and stored in a repository, you can modify
[scripts/getcss](https://github.com/labordynamicsinstitute/metajelo-ui/blob/master/scripts/getcss)
to point to the repository containing the modified CSS. Alternatively, one
could use use a more customized script to retrieve the CSS from
whatever location is desired.

For example, instead of using `getcss`, let's say we have a build of metajelo-ui
stored in `metajelo-ui-css-testing`. Then wee can do the following:

```
cd metajelo-ui-css-testing
mkdir css
ln -s /PATH/TO/metajelo-ui-css-classes/uicss css
```

Now edit `index.html` and replace `prod.XXXXX.css` with `css/style-dev.css`
so that you now have a line that looks like:

```html
<link rel="stylesheet" href="css/style-dev.css">
```

You should now be able to browse to `index.html` and test CSS changes immediately
after rebuilding the locally referenced clone of `metajelo-ui-css-classes`.

You may also find a CSS-reload addon helpful so that you can fill
in test data only once while rebuilding and reloading just the CSS.
An example is [CSS Reload](https://addons.mozilla.org/en-US/firefox/addon/css-reload-we/) for Firefox.

# Building

If you have the relevant build tools intalled (npm, spago, pulp, etc.), you can
build using `npm run build && npm run prod`. For a more convient approach, see
If you have the relevant build tools installed (`npm`, `spago`, `pulp`, etc.), you can
build using `npm run build && npm run prod`. For a more convenient approach, see
the section on Docker below, and for complete build commands used in CI, see
`scripts/dist_build_commands.sh`.

Expand All @@ -39,6 +76,15 @@ the command in the container with the CWD mounted and then exit. Alternatively
if you want to issue multiple commands in the container quickly, you can
run `./psc.sh bash`.

## Styling with CSS as part of a build

By default, CSS files are retrieved from a [separate repository](https://github.com/labordynamicsinstitute/metajelo-ui-css-classes) using `scripts/getcss`; the file `css/style.css` contains some default styles used in our examples.
Feel free to include it, or modify it (renaming the file is also possible):

```html
<link rel="stylesheet" href="css/style.css">
```

## Debugging

For an unminified build that is easier to debug from the browser, use
Expand Down
14 changes: 10 additions & 4 deletions packages.dhall
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@ let additions =
, metajelo =
mkPackage
[ "generics-rep"
, "naturals"
, "email-validate"
, "naturals"
, "nonbili-dom"
, "stringutils"
, "url-validator"
, "web-dom"
Expand All @@ -202,7 +203,7 @@ let additions =
, "xpath-like"
]
"https://github.com/labordynamicsinstitute/purescript-metajelo.git"
"49a28c5c511bdd260b627151c7b898720313cc66"
"f494f0a3571f2594de829dddb8ebe1abe563c8cf"
, metajelo-web =
mkPackage
[ "prelude"
Expand All @@ -215,17 +216,22 @@ let additions =
, "url-validator"
]
"https://github.com/labordynamicsinstitute/metajelo-web.git"
"bcfddbcf3184d530eb163451f8006b90e2b02631"
"c90b1c096ba0bbb4699db363b31325a80589a38c"
, metajelo-ui-css-classes =
mkPackage
[ "prelude", "concur-core", "concur-react" ]
"https://github.com/labordynamicsinstitute/metajelo-ui-css-classes.git"
"v0.1.3"
"0746a0dae2ab7cdaded4c9c9fc3f24c3038e506a"
, naturals =
mkPackage
[ "enums", "maybe", "prelude" ]
"https://github.com/LiamGoodacre/purescript-naturals.git"
"v3.0.0"
, nonbili-dom =
mkPackage
[ "effect", "web-dom", "web-html" ]
"https://github.com/nonbili/purescript-nonbili-dom.git"
"v0.3.0"
, option =
mkPackage
[ "argonaut-codecs"
Expand Down
101 changes: 89 additions & 12 deletions src/Metajelo/UI.purs
Original file line number Diff line number Diff line change
@@ -1,47 +1,118 @@
module Metajelo.UI where

import Prelude (Unit, bind, discard, join, map, pure, ($), (<$>), (>>=), (<>))
import Prelude (Unit, bind, discard, join, map, pure, unit, ($), (<$>), (>>=), (<>))

import Concur.Core (Widget)
import Concur.Core.FRP (Signal, display, dyn, loopS)
import Concur.Core.FRP (Signal, display, dyn, loopS, step)
import Concur.React (HTML)
import Concur.React.DOM as D
import Concur.React.Props as P
import Concur.React.Run (runWidgetInDom)
import Control.Monad.State
import Control.Plus (empty)
import Data.Array.NonEmpty (NonEmptyArray)
import Data.Either (Either(..), hush)
import Data.Foldable (fold, foldMap)
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Maybe (Maybe(..), fromMaybe, maybe)
import Data.String.Common (null)
import Data.String.NonEmpty (fromString,toString)
import Data.Symbol (class IsSymbol, SProxy(..))
import Data.Traversable (sequence)
import Data.Tuple (Tuple(..), fst, snd)
import Effect (Effect)
import Effect.Class (liftEffect)
import Effect.Class.Console (log)
import Global (encodeURIComponent)
import Metajelo.Forms as MF
import Metajelo.FormUtil (CtrlSignal, arrayView, checkBoxS, dateTimeSig, formatXsdDate,
initDate, labelSig, labelSig', menuSignal, nonEmptyArrayView, textInput,
urlInput, consoleShow)
import Metajelo.Types as M
import Metajelo.View as MV
-- import Metajelo.CSS.UI.ClassNames as MCN
import Metajelo.XPaths.Write as MXW
import Metajelo.CSS.UI.ClassProps as MC
-- import Metajelo.CSS.UI.Util (cList)
import Metajelo.CSS.Web.ClassProps as MWC -- TODO: change occurrences to something UI-specific!
import Nonbili.DOM (copyToClipboard)
import Option as Opt
import Prim.Row as Prim.Row
import Text.URL.Validate (URL)

-- import Data.Newtype (unwrap)
-- import Data.Semigroup.First (First(..))
import Web.HTML (window) as DOM
import Web.DOM.Document (createElement) as DOM
import Web.DOM.Element (setAttribute) as DOM
import Web.HTML.HTMLDocument (toDocument) as HTML
import Web.HTML.HTMLElement (HTMLElement)
import Web.HTML.HTMLElement (click) as DOM
import Web.HTML.HTMLElement (fromElement) as HTML
import Web.HTML.Window (document) as DOM

runFormSPA :: String -> Effect Unit
runFormSPA divId = runWidgetInDom divId page

page :: a. Widget HTML a
page = do
-- _ <- dyn $ formatSigArray (Tuple 0 [])
D.div [MC.page] $ pure $ dyn $ accumulateMetajeloRecord
--D.text "Hi"
D.div' [
{- let mjStr = "\xD800" in D.div [MC.previewButtons] [
downloadButton mjStr
, copyButton mjStr
]
-- ^^ Example string to fail: "\xD800"
, -} D.div [MC.page] $ pure $ dyn $ accumulateMetajeloRecord
]

utf8DataAttr :: String
utf8DataAttr = "data:text/plain;charset=utf-8"

downloadButton :: forall a. String -> Widget HTML a
downloadButton mjStr = D.div_ [] $ do
let encodedMjStrMay = encodeURIComponent(mjStr)
dlClicker <- liftEffect $
mkDLAnchorAndClicker $ fromMaybe "" encodedMjStrMay
maybe errorBox (downloadBtn dlClicker) encodedMjStrMay
where
downloadBtn :: Effect Unit -> String -> Widget HTML a
downloadBtn clicker cstr = do
dyn $ go cstr
where
go str = step str $ do
_ <- D.button_ [MC.downloadBtn, P.onClick, P.disabled $ null str] $
D.text "Download"
_ <- liftEffect clicker
pure $ go str
errorBox = D.div_ [MWC.errorDisplayBox] $
D.span [MWC.errorDisplay] [D.text errorMsg]
errorMsg = "Couldn't encode XML, please copy to clipboard instead."


mkDLAnchorAndClicker :: String -> Effect (Effect Unit)
mkDLAnchorAndClicker encTxt = do
win <- DOM.window
hdoc <- DOM.document win
let doc = HTML.toDocument hdoc
aEle <- DOM.createElement "a" doc
DOM.setAttribute "download" "metajelo.xml" aEle
DOM.setAttribute "href" (utf8DataAttr <> "," <> encTxt) aEle
pure $ clickAMay $ HTML.fromElement aEle
where
clickAMay :: Maybe HTMLElement -> Effect Unit
clickAMay hEleMay = case hEleMay of
Just hEle -> do
log "got a click"
DOM.click hEle
Nothing -> log $
"Couldn't create HTMLElement to click with encoded string"
<> encTxt



copyButton :: forall a. String -> Widget HTML a
copyButton cstr = dyn $ go cstr
where
go str = step str $ do
_ <- D.button_ [MC.clipBtn, P.onClick, P.disabled $ null str] $
D.text "Copy to Clipboard"
_ <- liftEffect $ copyToClipboard str
pure $ go str

-- | ViewModel for MetajeloRecord
type MetajeloRecordExtra r = (
Expand Down Expand Up @@ -146,9 +217,15 @@ accumulateMetajeloRecord = loopS Opt.empty \recOpt -> D.div_ [MC.record] do
where
recWidg :: forall a. Maybe M.MetajeloRecord -> Widget HTML a
recWidg recMay = D.div [MC.recPreview] [
D.br'
do
mjStr <- liftEffect mjStrEff
-- TODO: make greay of mjStr is empty:
D.div [MC.previewButtons] [downloadButton mjStr, copyButton mjStr]
, D.br'
, fold $ MV.mkRecordWidget <$> recMay
]
where
mjStrEff = maybe (pure "") MXW.recordToString recMay

-- FIXME: check how the header is grouped into these?
accumulateSuppProd :: CtrlSignal HTML (MayOpt SupplementaryProductRowOpts)
Expand Down Expand Up @@ -211,7 +288,7 @@ accumulateLocation locOptMay = D.div_ [MC.location] do
identOpt <- D.span_ [MC.institutionId] $ accumulateIdent $
getOpt (SProxy :: _ "institutionID_opt") locOpt
let identMay = Opt.getAll identOpt
instNameMay <- textInput $
instNameMay <- D.span_ [MC.institutionName] $ textInput $
Opt.get (SProxy :: _ "institutionName") locOpt
instTypeMay <- D.span_ [MC.institutionType] $ menuSignal $
Opt.get (SProxy :: _ "institutionType") locOpt
Expand Down
2 changes: 0 additions & 2 deletions static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tests for purescript-web-xpath</title>
<link rel="stylesheet" href="index.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/combine/npm/[email protected]/build/base-min.css,npm/[email protected]/build/grids-responsive-min.css">
<!-- add other Pure modules above, e.g.: npm/[email protected]/build/forms-min.css -->
<script type="application/javascript" src="index.js" charset="utf-8"></script>
</head>
<body>
Expand Down

0 comments on commit c484563

Please sign in to comment.