toaster.do/clojure_frontend/src/toaster/bulma.clj

303 lines
10 KiB
Clojure

;; Copyright (C) 2015-2018 Dyne.org foundation
;; Sourcecode designed, written and maintained by
;; Denis Roio <jaromil@dyne.org>
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Affero General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU Affero General Public License for more details.
;; You should have received a copy of the GNU Affero General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
(ns toaster.bulma
(:require [clojure.java.io :as io]
[clojure.data.csv :as csv]
[yaml.core :as yaml]
[hiccup.page :as page]
[hiccup.form :as hf]))
(declare render)
(declare render-head)
(declare navbar-guest)
(declare navbar-account)
(declare render-footer)
(declare render-yaml)
(declare render-edn)
(declare render-error)
(declare render-error-page)
(declare render-static)
;; TODO: navbars for bulma
(def navbar-brand [:div {:class "navbar"}])
(def navbar-guest [:div {:class "navbar"}])
(def navbar-account [:div {:class "navbar"}])
(defn button
([url text] (button url text [:p]))
([url text field] (button url text field "button"))
([url text field type]
(hf/form-to [:post url]
field ;; can be an hidden key/value field (project,
;; person, etc using hf/hidden-field)
[:p {:class "control"}
(hf/submit-button {:class (str "button " type)} text)])))
(defn button-cancel-submit [argmap]
[:div
{:class
(str "row col-md-6 btn-group btn-group-lg "
(:btn-group-class argmap))
:role "group"}
(button
(:cancel-url argmap) "Cancel"
(:cancel-params argmap)
"btn-primary btn-lg btn-danger col-md-3")
(button
(:submit-url argmap) "Submit"
(:submit-params argmap)
"btn-primary btn-lg btn-success col-md-3")])
(defn render
([body]
{:headers {"Content-Type"
"text/html; charset=utf-8"}
:body (page/html5
(render-head)
[:body ;; {:class "static"}
;; navbar-guest
body
(render-footer)])})
([account body]
{:headers {"Content-Type"
"text/html; charset=utf-8"}
:body (page/html5
(render-head)
[:body ;; (if (empty? account)
;; navbar-guest
;; navbar-account)
body
(render-footer)])}))
(defn render-success
"render a successful message without ending the page"
[succ]
[:div {:class "notification is-primary"} succ])
(defn render-error
"render an error message without ending the page"
[err]
[:div {:class "notification is-danger"} err])
(defn render-error-page
([] (render-error-page {} "Unknown"))
([err] (render-error-page {} err))
([session error]
(render
[:div {:class "container"}
(render-error error)])))
(defn render-head
([] (render-head
"toaster.do" ;; default title
"From Docker to VM or ARM SDcard in a few clicks, powered by Devuan and the DECODE project" "https://toaster.dyne.org")) ;; default desc
([title desc url]
[:head [:meta {:charset "utf-8"}]
[:meta {:http-equiv "X-UA-Compatible" :content "IE=edge,chrome=1"}]
[:meta
{:name "viewport"
:content "width=device-width, initial-scale=1"}]
[:title title]
[:link {:href "https://fonts.googleapis.com/css?family=Open+Sans:300,400,700"
:rel "stylesheet"}]
;; cascade style sheets
(page/include-css "/static/css/bulma.min.css")
(page/include-css "/static/css/json-html.css")
;; (page/include-css "/static/css/fa-regular.min.css")
;; (page/include-css "/static/css/fontawesome.min.css")
(page/include-css "https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css")
(page/include-css "/static/css/toaster.css")]))
(defn render-footer []
[:footer {:class "footer"}
[:div {:class "content has-text-centered"}
[:p {:class "has-text-grey"} "toaster.do transforms your Docker prototype into "
"an installable " [:a {:href "https://devuan.org"} "Devuan GNU+Linux"]
" image, choose any supported target architecture!"]
[:div {:class "columns is-variable is-8"}
[:div {:class "column is-one-quarter is-narrow-touch"}
[:a {:href "https://www.dyne.org"}
[:figure {:class "image"}
[:img {:src "/static/img/swbydyne.png"
:alt "Software by Dyne.org"
:title "Software by Dyne.org"}]]]]
[:div {:class "column auto"}]
[:div {:class "column is-one-quarter"}
[:figure {:class "image"}
[:img {:src "/static/img/AGPLv3.png" ;; :style "margin-top: 2.5em"
:alt "Affero GPLv3 License"
:title "Affero GPLv3 License"}]]]]]])
(defn render-static [body]
(page/html5 (render-head)
[:body {:class "fxc static"}
;; navbar-guest
[:div {:class "container"} body]
(render-footer)
]))
;; highlight functions do no conversion, take the format they highlight
;; render functions take edn and convert to the highlight format
;; download functions all take an edn and convert it in target format
;; edit functions all take an edn and present an editor in the target format
(defn render-yaml
"renders an edn into an highlighted yaml"
[data]
[:span
[:pre [:code {:class "yaml"}
(yaml/generate-string data)]]
[:script "hljs.initHighlightingOnLoad();"]])
(defn highlight-yaml
"renders a yaml text in highlighted html"
[data]
[:span
[:pre [:code {:class "yaml"}
data]]
[:script "hljs.initHighlightingOnLoad();"]])
(defn highlight-json
"renders a json text in highlighted html"
[data]
[:span
[:pre [:code {:class "json"}
data]]
[:script "hljs.initHighlightingOnLoad();"]])
(defn download-csv
"takes an edn, returns a csv plain/text for download"
[data]
{:headers {"Content-Type"
"text/plain; charset=utf-8"}
:body (with-out-str (csv/write-csv *out* data))})
(defn edit-edn
"renders an editor for the edn in yaml format"
[data]
[:div;; {:class "form-group"}
[:textarea {:class "form-control"
:rows "20" :data-editor "yaml"
:id "config" :name "editor"}
(yaml/generate-string data)]
[:script {:src "/static/js/ace.js"
:type "text/javascript" :charset "utf-8"}]
[:script {:type "text/javascript"}
(slurp (io/resource "public/static/js/ace-embed.js"))]
;; code to embed the ace editor on all elements in page
;; that contain the attribute "data-editor" set to the
;; mode language of choice
[:input {:class "btn btn-success btn-lg pull-top"
:type "submit" :value "submit"}]])
(def brand-img "/static/img/whale_toast.jpg")
(defn- hero-login-box [body]
[:section {:class "hero is-fullheight"}
[:div {:class "hero-body"}
[:div {:class "container has-text-centered"}
body
]]])
(def login-form
(hero-login-box
[:div {:class "column is-4 is-offset-4"}
[:h3 {:class "title has-text-grey"} "toaster.do"]
[:h4 {:class "subtitle has-text-grey"}
"from Docker to VM in a few clicks, powered by "
[:a {:href "https://decodeproject.eu"} "DECODEproject.EU"]]
[:p {:class "subtitle has-text-grey"}
"please login to operate"]
[:div {:class "box"}
[:figure {:class "avatar"}
[:img {:src brand-img }]]
[:form {:action "/login"
:method "post"}
[:div {:class "field"}
;; [:label {:class "label is-large"} "Email"]
[:div {:class "control has-icons-left"}
[:input {:type "email" :name "username"
:placeholder "Email"
:class "input is-large"}]
[:span {:class "icon is-small is-left"}
[:i {:class "fa fa-envelope fa-xs"}]]]]
[:div {:class "field"}
;; [:label {:class "label is-large"} "Password"]
[:div {:class "control has-icons-left"}
[:input {:type "password" :name "password"
:placeholder "Password"
:class "input is-large"}]
[:span {:class "icon is-small is-left"}
[:i {:class "fa fa-lock fa-xs"}]]]]
[:div {:class "field"}
[:p {:class "control"}
[:input {:type "submit" :value "Login"
:class "button is-block is-info is-large has-icons-left is-fullwidth"}]]]]]
[:p {:class "subtitle has-text-grey"}
"...or " [:a {:href "/signup"} "signup for a new account"]]]))
(def signup-form
(hero-login-box
[:div {:class "column is-4 is-offset-4"}
[:h3 {:class "title has-text-grey"} "toaster.do"]
[:h4 {:class "subtitle has-text-grey"}
"sign up for a new account"]
;; [:p {:class "subtitle has-text-grey"}]
[:div {:class "box"}
[:figure {:class "avatar"}
[:img {:src brand-img}]]
[:form {:action "/signup"
:method "post"}
[:div {:class "field"}
[:div {:class "control"}
[:input {:type "text" :name "name"
:placeholder "Name"
:class "input"}]]]
[:div {:class "field"}
[:div {:class "control"}
[:input {:type "email" :name "email"
:placeholder "Email"
:class "input"}]]]
[:div {:class "field"}
[:div {:class "control"}
[:input {:type "password" :name "password"
:placeholder "Password"
:class "input"}]]]
[:div {:class "field"}
[:div {:class "control"}
[:input {:type "password" :name "repeat-password"
:placeholder "Repeat password"
:class "input"}]]]
[:div {:class "field"}
[:div {:class "control"}
[:input {:type "submit" :value "Sign In"
:class "button is-block is-info is-large is-fullwidth"}]]]]]]))