Ab sofort ist der Login auf der Weboberfläche von git.fh-muenster.de bevorzugt über FH Muenster SSO möglich.

Commit 83ac20cf authored by Joachim Schunk's avatar Joachim Schunk

Merge branch 'bulma-css' into 28-create-new-multistep-calculation-exercise-type

parents 79ae7277 7f09dfe7
Pipeline #45183 passed with stages
in 1 minute and 40 seconds
(ns lernmeister.components.bulma.card)
(defn card-panel [& content]
[:div.card
[:div.card-content
(apply vector
:div.content
content)]])
(defn card [{:keys [title footer-items class]} content]
[:div.card {:class class}
(when title
[:header.card-header
[:p.card-header-title
title]])
[:div.card-content content]
(when (pos? (count footer-items))
[:footer.card-footer
(for [fi footer-items]
^{:key (hash fi)} [:span.card-footer-item fi])])])
(ns lernmeister.components.bulma.common)
(ns lernmeister.components.bulma.common
(:require [clojure.string :refer [join]]))
(defn icon [ligature & {:keys [class]}]
(defn icon [{:keys [class size position id] :as options}]
;;;TODO check if this makes sense. Use ligature as key to force 'font awesome' to re-render
(let [id (gensym "icon")]
(fn [ligature & {:keys [class]}]
^{:key (str id "-" ligature)}
[:span.icon {:class class}
[:i.fas {:class (str ligature)}]])))
(let [component-id (gensym "icon")]
(fn [{:keys [class i-class size position style id]
:or {style :fas} :as options}]
^{:key (str component-id)}
[:span.icon {:class (join " "
[class
(case position
:left "is-left"
:right "is-right"
"")
(case size
:small "is-small"
"")])}
[:i {:class
(if (string? options) ;;; fallback for old icon component
(str "fas " options)
(join " " [i-class
(case style
:solid "fas"
:regular "far"
:light "fal"
:brand "fab"
"")
(name style)
(when id
(name id))]))}]])))
(ns lernmeister.components.bulma.datetime)
(defn parseDate [date]
(if (not-empty date)
(let [parts (split (js->clj date) ".")
parsed-date (js/Date. (js/Number. (get parts 2))
(- (js/Number. (get parts 1)) 1)
(js/Number. (get parts 0)))]
parsed-date)
(new js/Date)))
(def weekdays ["Sonntag"
"Montag"
"Dienstag"
"Mittwoch"
"Donnerstag"
"Freitag"
"Samstag"])
(def calendar-settings
{:i18n {:months ["Januar"
"Februar"
"März"
"April"
"Mai"
"Juni"
"Juli"
"August"
"September"
"Oktober"
"November"
"Dezember"]
:monthsShort ["Jan"
"Feb"
"Mär"
"Apr"
"Mai"
"Jun"
"Jul"
"Aug"
"Sep"
"Okt"
"Nov"
"Dez"]
:weekdays weekdays
:weekdaysShort ["So"
"Mo"
"Di"
"Mi"
"Do"
"Fr"
"Sa"]
:weekdaysAbbrev ["S"
"M"
"D"
"M"
"D"
"F"
"S"]}
:firstDay 1
:format "dd.mm.yyyy"
:parse parseDate
:showDaysInNextAndPreviousMonths true})
(defn format-date [date]
(let [month (+ (.getMonth date) 1)
day (.getDate date)]
(str (.getFullYear date)
"-"
(when-not (>= month 10)
0)
(+ (.getMonth date) 1)
"-"
(when-not (>= day 10)
0)
day)))
(defn datepicker [{:keys [field-class icon input-class input-size
label-icon value placeholder on-change
label disabled tooltip autocomplete]}]
(fn [{:keys [field-class icon input-class input-size
label-icon value placeholder on-change
label disabled tooltip autocomplete]}]
[:div.field
[:label.label
label]
[:div.control
[:input {:type :date
:disabled disabled
:value (when value
(format-date value))
:on-change #(on-change
(-> %
.-target
.-valueAsDate))}]]]))
#_(defn datepicker
[{:keys [field-class icon input-class input-size
label-icon value placeholder on-change
label disabled tooltip autocomplete]}]
(let [id (gensym "datepicker")
instance (reagent/atom nil)]
(reagent/create-class
{:component-did-mount
(fn []
(let [elems (js/document.querySelectorAll (str "#" id))]
(reset! instance
(.attach js/bulmaCalendar (str "[id=" id "]")
(clj->js {:displayMode "dialog"})))
(when-let [calendar (first @instance)]
(.value calendar value)
(.on calendar "select"
(fn [event]
(on-change (oget event "data.date.start")))))))
:component-did-update (fn [this _]
#_(let [[{:keys [value]}] (rest (reagent/argv this))]
(when-let [calendar (first @instance)]
(.value calendar value))))
:reagent-render
(fn [{:keys [field-class icon input-class input-size
label-icon value placeholder on-change
label disabled tooltip autocomplete]}]
[:div.field
;;;TODO https://reactjs.org/docs/integrating-with-other-libraries.html
(when label
[:label.label {:for id} label])
[:div.control.has-icons-left
[:span.icon.is-left [:i.fas.fa-calendar]]
[:input.input {:type "date"
:id id
:disabled disabled
:class input-class
:data-date value
:placeholder (or placeholder "")
:default-value (when value
(str (.getFullYear value)
"-"
(+ (.getMonth value) 1)
"-"
(.getDate value)))
;;:on-change #(on-change (js/Date. (-> % .-target .-value)))
}]]])})))
(defn timepicker [{:keys [field-class icon input-class input-size
label-icon value placeholder on-change
label disabled tooltip autocomplete]}]
(fn [{:keys [field-class icon input-class input-size
label-icon value placeholder on-change
label disabled tooltip autocomplete]}]
[:div.field
[:label.label
label]
[:div.control
[:input {:type :time
:value value
:on-change #(on-change
(-> %
.-target
.-value))}]]]))
#_(defn timepicker
[{:keys [field-class icon input-class input-size
value on-change placeholder label
disabled tooltip autocomplete]}]
(let [id (gensym "timepicker")
instances (reagent/atom nil)]
(reagent/create-class
{:component-did-mount
(fn []
(let [elems (js/document.querySelectorAll (str "#" id))]
(reset! instances
(first (js/M.Timepicker.init
elems
(clj->js {:twelveHour false
:autoClose true
:onCloseEnd #(when-let [time (.-time @instances)]
(on-change time))}))))))
:reagent-render
(fn [{:keys [field-class icon input-class input-size
placeholder value on-change label
disabled tooltip autocomplete]}]
[:div.input-field
(when icon
[:i.material-icons.prefix
icon])
[:input {:type "text"
:id id
:class input-class
:disabled disabled
:placeholder (or placeholder "")
:read-only true
:value (or value "")}]
(when label
[:label.active {:for id} label])])})))
(ns lernmeister.components.bulma.form.button)
(defn button [{:keys [static?]} & content]
[:a.button {}
content])
(ns lernmeister.components.bulma.form.control
(:require [lernmeister.components.bulma.common :refer [icon]]
[clojure.string :refer [join]]))
(defn control-icons [icons]
(if (string? icons)
[icon {:i-class icons
:position :left}]
[:<>
(for [i icons]
^{:key (hash i)}
[icon i])]))
(defn get-control-icon-classes [icons]
(str
(if (string? icons)
"has-icons-left")
(when (vector? icons)
(join " " [(when (some #(= (:position %) :left) icons)
"has-icons-left")
(when (some #(= (:position %) :right) icons)
"has-icons-right")]))))
(defn control [{:keys [expanded? icons]} content]
[:div.control {:class
(str
(get-control-icon-classes icons)
(when expanded?
" is-expanded"))}
content
[control-icons icons]
]
)
(ns lernmeister.components.bulma.form.field)
(defn field
([content]
[field {} content])
([{:keys [field-class label grouped? addons? expanded? narrow? help]} & content]
[:div.field {:class (str field-class
(when grouped?
" is-grouped")
(when addons?
" has-addons")
(when expanded?
" is-expanded")
(when narrow?
" is-narrow"))}
(when label
[:label.label
label])
(into [:<>] content)
(when help
[:p.help help])]))
(defn horizontal-field [{:keys [field-class label normal?]} & content]
[:div.field.is-horizontal {:class field-class}
(when label
[:div.field-label {:class (when normal?
"is-normal")}
[:label.label
label]])
[:div.field-body
(into [:<>] content)]])
(ns lernmeister.components.bulma.form.textarea
(:require [reagent.core :as reagent]
[lernmeister.components.bulma.form.control :refer [control]]))
(defn textarea
[{:keys [field-class input-class input-size label-icon
placeholder value on-change label icons expanded?
disabled tooltip autocomplete]}]
(let [id (gensym "textarea")]
(reagent/create-class
{:reagent-render
(fn [{:keys [field-class input-class input-size label-icon
placeholder value on-change label icons expanded?
disabled tooltip autocomplete]}]
[:<> ;;:div.field {:class field-class}
[control {:icons icons
:expanded? expanded?}
[:textarea.textarea
{:on-change #(on-change (-> %
.-target
.-value))}
value]
#_[:input.input (merge {:id id
:type "text"
:class input-class
:value value
:placeholder (or placeholder "")
:size input-size
:disabled disabled
:on-change #(on-change (-> %
.-target
.-value))}
(when tooltip
{:data-position (:position tooltip)
:data-tooltip (:label tooltip)}))]
#_(when label-icon
[icon label-icon
:class "is-left"])]])})))
(ns lernmeister.components.bulma.modal
(:require [lernmeister.components.jshelper :refer [execute-and-reset]]))
(defn modal-panel [{:keys [title state footer subject on-close-fn]} & content]
(let [close-fn (fn []
(execute-and-reset on-close-fn subject)
(reset! state false))]
[:div.modal {:class (str (when @state
"is-active"))}
[:div.modal-background {:on-click close-fn}]
[:div.modal-card
[:header.modal-card-head
[:span.modal-card-title (or title "")]
[:button.delete {:on-click close-fn}]]
(into [:div.modal-card-body]
content)
(when footer
[:footer.modal-card-foot
footer])]]))
(defn open-modal [selector-tag]
#_(.open (js/M.Modal.getInstance (js/document.querySelector selector-tag))))
(defn close-modal [selector-tag]
#_(.close (js/M.Modal.getInstance (js/document.querySelector selector-tag))))
(defn modal-exists? [selector-tag]
#_(try
(js/M.Modal.getInstance (js/document.querySelector selector-tag))
(catch js/Error. e
nil)))
(defn init-modal [selector-tag]
#_(if-let [instance (modal-exists? selector-tag)]
instance
(js/M.Modal.init (js/document.querySelector selector-tag))))
(ns lernmeister.components.bulma.navbar
(:require [reagent.core :as reagent]
[lernmeister.components.bulma.common :refer [icon]]))
(defn navbar
[{:keys [links active-link brand brand-align
links-position
side-nav
side-nav-id
color
font-color
fixed
side-nav-trigger-position :left
side-nav-trigger-position]
:or {brand false
brand-align "right"
side-nav false
color "purple"
font-color "black"}}]
(let [navbar-id (gensym "navbar")]
(reagent/create-class
{:reagent-render
(fn [{:keys [links active-link brand brand-align
links-position
side-nav
side-nav-id
color
font-color
fixed
side-nav-trigger-position]
:or {brand false
side-nav false
side-nav-trigger-position :left
color "purple"
font-color "black"}}]
[:nav.navbar {:class (when fixed "navbar-fixed")}
(when brand
[:div.navbar-brand {:class (str "brand-logo " (when brand-align
(name brand-align)))}
[:a.navbar-item brand]])
[:div.navbar-menu
[:div.navbar-start
(when (and side-nav (= (keyword side-nav-trigger-position) :left))
[:a.navbar-burger {:href "#"
:data-target side-nav-id}
[:i.material-icons "menu"]])
(for [nl links]
[:a.navbar-item {:key (hash nl)
:href (:route nl)
:style {:color font-color}}
(when (:icon nl)
[icon (:icon nl) :class "left"]) (:label nl)])]
[:div.navbar-end
(when (and side-nav (= (keyword side-nav-trigger-position) :right))
[:a.sidenav-trigger.right {:href "#"
:data-target side-nav-id}
[:i.material-icons "menu"]])]]])})))
(defn side-nav [& {:keys [links active-link
side-nav-id
edge]
:or {side-nav-id (gensym "side-nav")
edge "left"}}]
(let [instance (reagent/atom nil)
id side-nav-id]
(reagent/create-class
{:component-did-mount #(let [elem (js/document.querySelector (str "#" id))]
#_(reset! instance
(js/M.Sidenav.init elem (clj->js {:closeOnClick true
:draggable true
:edge edge}))))
:reagent-render
(fn [& {:keys [links active-link
side-nav-id
edge]
:or {side-nav-id (gensym "side-nav")
edge "left"}}]
[:p ""]
#_[:ul.sidenav {:id id}
(for [nl links]
[:li {:class (when (= (:panel nl) active-link) ["active"])
:key (str id "_" (:label nl))}
[:a {:href (:route nl)
:on-click #(.close @instance)}
(when (:icon nl)
[icon (:icon nl) :class "left"]) (:label nl)]])])})))
(ns lernmeister.components.bulma.select
(:require [reagent.core :as reagent]
[lernmeister.components.bulma.form.control :refer [control]]))
(defn select
[{:keys [value on-change options label multiple icons
expanded? fullwidth?
choose-option-label]}]
(let [id (gensym "select")
instance (reagent/atom nil)
change-fn (reagent/atom on-change)]
(reagent/create-class
{:display-name "input-select-component"
:reagent-render
(fn [{:keys [value on-change options label disabled multiple
choose-option-label icons expanded? fullwidth?]}]
[:<>
[control {:icons icons
:expanded? expanded?}
[:div.select
{:class (str
(when multiple
" is-multiple")
(when fullwidth?
" is-fullwidth"))
}
[:select
{:id id
:disabled disabled
:multiple multiple
:value (if multiple
(or value [])
(or value ""))
:on-change (fn [event]
(js/console.log multiple)
(let [value (-> event
.-target
.-value)]
(when on-change
(on-change
(if multiple
(set (map (fn [o]
(keyword (.-value o)))
(-> event
.-target
.-selectedOptions
array-seq)))
(keyword value))))))}
[:option {:value ""
:disabled true}
(or choose-option-label "Bitte wählen")]
(when options
(doall
(for [o options]
(let [key (or (:key o) (first o))
title (or (:title o) (:label o) (second o))]
[:option {:value (name key)
:key (str id "-" key)}
title]))))]]]])})))
(defn select*
[{:keys [cursor options label multiple
choose-option-label on-change]}]
(let [id (gensym "select")
instance (reagent/atom nil)
get-element #(js/document.querySelector (str "#" id))]
(reagent/create-class
{:display-name "select*-component"
:reagent-render
(fn [{:keys [cursor options label multiple
choose-option-label on-change]}]
[select
{:value @cursor
:options options
:label label
:multiple multiple
:choose-option-label choose-option-label
:on-change (fn [value]
(reset! cursor value)
(when on-change
(on-change cursor)))}])})))
(ns lernmeister.components.bulma.tag
(:require [reagent.core :as reagent]))