git.fiddlerwoaroof.com
src/index.cljs.hl
efaf2944
 (page "index.html"
   (:require [datascript.core :as d]
             [clojure.string :as cstr]))
 
 (def db (let [schema {:aka {:db/cardinality :db.cardinality/many}}
               conn (d/create-conn schema)]
           (d/transact! conn [ {:db/id -1
                                :name "Maksim"
                                :age 45
                                :aka ["." "Max Otto von Stierlitz", "Jack Ryan"]} ])
           (d/transact! conn [ {:db/id -1
                                :name "Foom"
                                :age 45
                                :aka ["."]} ])
           conn))
 
 (def search-query
   '[:find  ?n (distinct ?k)
     :in $ ?startsWith %
     :where
     (dothings ?startsWith ?e)
     [?e :name ?n]
     [?e :aka ?k]])
 
 (def search-rules
   '[[(dothings ?startsWith ?e)
      [?e :name ?n]
      [(?startsWith ?n)]]
     [(dothings ?startsWith ?e)
      [?e :aka ?n]
      [(?startsWith ?n)]]])
 
 (defn do-query [prefix]
   (d/q search-query
        @db
        (fn [e] (cstr/starts-with? (cstr/lower-case e)
                                   (cstr/lower-case prefix)))
        search-rules))
 
 (def initial-state
   {})
 
 (defn init-search-panel [state]
   (let [initial-search ""
         initial-results (do-query initial-search)]
     (assoc state :search-panel {:current-search initial-search
                                 :search-results initial-results})))
 
 (defn init-add-contact [state]
   (assoc state :add-contact {}))
 
 (defc state
   ((comp init-search-panel
          init-add-contact)
    initial-state))
 
 (defc= search-panel
   (get state :search-panel)
   #(dosync
     (swap! state assoc :search-panel %)))
 
 (defc= search
   (get search-panel :current-search)
   #(dosync
     (reset! search-panel {:current-search %
                           :search-results (do-query %)})))
 
 (d/listen! db :datascript->hoplon #(swap! search-panel assoc :search-results
                                           (do-query (:current-search @search-panel))))
 
 (defc= search-results (get search-panel :search-results))
 
 (defc= add-contact-data
   (:add-contact state)
   #(swap! state assoc :add-contact %))
 
 (defc= new-contact-name
   (:name add-contact-data)
   #(swap! add-contact-data assoc :name %))
 
 (defc= new-contact-age
   (:age add-contact-data)
   #(swap! add-contact-data assoc :age %))
 
 (defc= new-contact-aka
   (:aka add-contact-data)
   #(swap! add-contact-data assoc :aka ["." %]))
 
 (defn starts-with? [s ss]
   (cstr/starts-with? s ss))
 
 (def event-value
   #(.-value (.-target %)))
 
 (html
  (head (link :href "app.css" :rel "stylesheet" :type "text/css"))
  (body (h1 "My Contacts")
        (section :id "add-contact"
                 (form (input :type "text"
                              :placeholder "name"
                              :value new-contact-name
                              :keyup #(reset! new-contact-name (event-value %)))
                       (input :type "text"
                              :placeholder "age"
                              :value new-contact-age
                              :keyup #(reset! new-contact-age (event-value %)))
                       (input :type "text"
                              :placeholder "aka"
                              :value (cell= (and new-contact-aka (second new-contact-aka)))
                              :keyup #(reset! new-contact-aka (event-value %)))
                       (button :click #(do (.preventDefault %)
                                           (d/transact! db
                                                        [{:db/id -1
                                                          :name @new-contact-name
                                                          :age @new-contact-age
                                                          :aka @new-contact-aka}]))
                               "Add Contact")))
        (section :id "do-search"
                 (div search)
                 (input :type "text" :value search :keyup #(reset! search (event-value %))
                        :placeholder "query ยป")
 
                 (div :id "results"
                      (for-tpl [[name aka] search-results]
                        (div (h2 name)
                             (ul
                              (for-tpl [alias (cell= (rest aka))]
                                (li alias)))))))
        ))