diff --git a/resources/app/stylesheets/app.less b/resources/app/stylesheets/app.less index 5c49978..7f1ca3a 100644 --- a/resources/app/stylesheets/app.less +++ b/resources/app/stylesheets/app.less @@ -51,6 +51,10 @@ h2 { main { grid-area: main; + + .schema-title__name { + font-weight: normal; + } } aside { diff --git a/src/wanijo/attribute/domain.clj b/src/wanijo/attribute/domain.clj index af06d62..1692217 100644 --- a/src/wanijo/attribute/domain.clj +++ b/src/wanijo/attribute/domain.clj @@ -2,6 +2,14 @@ (:require [clojure.spec.alpha :as spec] [wanijo.framework.neo4j :as neo4j])) +(spec/def ::name + (spec/and string? not-empty)) + +(spec/def ::type + (spec/and + string? + #(some #{"date" "file" "string" "text"} %))) + (neo4j/defquery findy-by-schema "MATCH (a:attribute)-->(s:schema) diff --git a/src/wanijo/attribute/routes.clj b/src/wanijo/attribute/routes.clj new file mode 100644 index 0000000..e233417 --- /dev/null +++ b/src/wanijo/attribute/routes.clj @@ -0,0 +1,12 @@ +(ns wanijo.attribute.routes + (:require [compojure.core :refer [defroutes GET POST]] + [ring.util.response :as resp] + [wanijo.framework.form :as form] + [wanijo.framework.routing :refer [register]])) + +(defn new! [req]) + +(register :attribute-new "/attribute/new") + +(defroutes routes + (POST "/attribute/new" [] new!)) diff --git a/src/wanijo/framework/form.clj b/src/wanijo/framework/form.clj index 667bda8..6744f62 100644 --- a/src/wanijo/framework/form.clj +++ b/src/wanijo/framework/form.clj @@ -3,41 +3,82 @@ [hiccup.form :as hform] [wanijo.framework.view :as view])) +(spec/def ::label string?) +(spec/def ::required boolean?) +(spec/def ::spec keyword?) +(spec/def ::options + (spec/coll-of (spec/tuple string? string?))) +(spec/def ::field + (spec/keys :req-un [::label + ::required + ::spec] + :opt-un [::options])) +(spec/def ::fields + (spec/and map? + (fn [map] + (every? #(spec/valid? ::field (val %)) map)) + (fn [map] + (every? #(keyword? (key %)) map)))) +(spec/def ::form + (spec/keys :req-un [::fields])) + (defn spec-to-errmsg [label spec-key field-value] (view/flash-error - (map - (fn [prob] - [:p - "Field " - [:span.flash__field label] - " must comply to " - [:span.flash__pred (:pred prob)]]) - (:clojure.spec.alpha/problems - (spec/explain-data spec-key field-value))))) + (map + (fn [prob] + [:p + "Field " + [:span.flash__field label] + " must comply to " + [:span.flash__pred (:pred prob)]]) + (:clojure.spec.alpha/problems + (spec/explain-data spec-key field-value))))) (defn field-valid? [value spec-key req] (or (empty? (:form-params req)) (spec/valid? spec-key value))) (defn field [form-def field req] + {:pre [(spec/valid? ::form form-def)]} (let [field-value (get-in req [:params field]) field-def (get-in form-def [:fields field]) {:keys [label required] spec-key :spec} field-def] (list + (when-not (field-valid? field-value spec-key req) + (spec-to-errmsg label spec-key field-value)) + (hform/label field label) + (hform/text-field {:required (when required "required")} + field + field-value)))) + +(defn drop-down + ([form-def field req] + {:pre [(spec/valid? ::form form-def)]} + (drop-down form-def + field + req + (get-in form-def [:fields field :options]))) + ([form-def field req options] + {:pre [(spec/valid? ::form form-def)]} + (let [field-value (get-in req [:params field]) + field-def (get-in form-def [:fields field]) + {:keys [label required] spec-key :spec} field-def] + (list (when-not (field-valid? field-value spec-key req) (spec-to-errmsg label spec-key field-value)) (hform/label field label) - (hform/text-field {:required (when required "required")} - field - field-value)))) + (hform/drop-down field + options + field-value))))) (defn valid? [form-def req] + {:pre [(spec/valid? ::form form-def)]} (reduce-kv - (fn [result field value] - (if-let [field-spec (get-in form-def [:fields field :spec])] - (if (spec/valid? field-spec value) - true - (reduced false)) - result)) - true - (:params req))) + (fn [result field value] + (if-let [field-spec (get-in form-def [:fields field :spec])] + (if (spec/valid? field-spec value) + true + (reduced false)) + result)) + true + (:params req))) diff --git a/src/wanijo/framework/time.clj b/src/wanijo/framework/time.clj index b9f0fa8..7b42617 100644 --- a/src/wanijo/framework/time.clj +++ b/src/wanijo/framework/time.clj @@ -1,2 +1,10 @@ (ns wanijo.framework.time - (:require [clj-time.core :as t])) + (:require [clj-time.format :as format])) + +(defn prettify-dt [date-str] + (->> + date-str + (format/parse + (format/formatters :basic-date-time)) + (format/unparse + (format/formatter "yyyy-MM-dd HH:mm:ss")))) diff --git a/src/wanijo/schema/routes.clj b/src/wanijo/schema/routes.clj index 786170f..ff4a36f 100644 --- a/src/wanijo/schema/routes.clj +++ b/src/wanijo/schema/routes.clj @@ -17,11 +17,11 @@ (resp/redirect "/schema")) (view-schema/overview! req))) -(defn show-schema! [uuid session] +(defn show-schema! [uuid req] (view-schema/show-schema! (domain/find-by-uuid! uuid) (attr-domain/find-by-schema! uuid) - session)) + req)) (defn delete-schema! [uuid session] (if (domain/can-user-modify? uuid (:uuid session)) @@ -37,6 +37,6 @@ (defroutes routes (GET "/schema" [] view-schema/overview!) - (GET "/schema/:uuid" [uuid :as req] (show-schema! uuid (:session req))) + (GET "/schema/:uuid" [uuid :as req] (show-schema! uuid req)) (POST "/schema/new" [] new!) (DELETE "/schema/:uuid" [uuid :as req] (delete-schema! uuid (:session req)))) diff --git a/src/wanijo/schema/view.clj b/src/wanijo/schema/view.clj index 38f0a76..10fcd63 100644 --- a/src/wanijo/schema/view.clj +++ b/src/wanijo/schema/view.clj @@ -4,13 +4,27 @@ [wanijo.framework.view :as view] [wanijo.framework.form :as form] [wanijo.framework.routing :refer [path]] - [wanijo.schema.domain :as domain])) + [wanijo.framework.time :refer [prettify-dt]] + [wanijo.schema.domain :as domain] + [wanijo.attribute.domain :as attr-domain])) (def new-form {:fields {:schema-name {:label "Nimi" :required true :spec ::domain/name}}}) +(def new-attr-form + {:fields {:name {:label "Nimi" + :required true + :spec ::attr-domain/name} + :type {:label "Tomo" + :required true + :spec ::attr-domain/type + :options [["Lon e lipu" "string"] + ["Ali lon e lipu" "text"] + ["Kama" "date"] + ["Sitelen" "file"]]}}}) + (defn overview! [req] (let [session (:session req) uuid (:uuid session) @@ -30,7 +44,8 @@ [:td [:a {:href (path :schema-show schema)} (:name schema)]] - [:td (:created_at schema)]])]] + [:td + (prettify-dt (:created_at schema))]])]] [:h1 "Pali sin e jaki ijo"] (hform/form-to [:post (path :schema-new)] @@ -38,17 +53,26 @@ (hform/submit-button "Pali") (anti-forgery-field))]))) -(defn show-schema! [schema attrs session] +(defn show-schema! [schema attrs req] (view/layout! - :session session + :session (:session req) :content - [[:h1 "Jaki ijo " (:name schema)] + [[:h1 "Jaki ijo " + [:span.schema-title__name (:name schema)]] (hform/form-to [:post "/schema/edit"]) [:h2 "Lili wan e jaki ijo"] [:ul (for [attr attrs] [:li (:name attr)])] + [:h3 "Pali lili wan"] + (hform/form-to + [:post (path :attribute-new)] + (anti-forgery-field) + (hform/hidden-field "schema" (:uuid schema)) + (form/field new-attr-form :name req) + (form/drop-down new-attr-form :type req) + (hform/submit-button "Pali")) [:h2 "Mute pali"] (hform/form-to {:class "inline"}