remove posh

pull/645/head
Tienson Qin 2020-04-03 23:06:42 +08:00
parent 096e6fae24
commit 6c7fc9c64c
14 changed files with 286 additions and 283 deletions

View File

@ -4,9 +4,7 @@
cider/cider-nrepl {:mvn/version "0.23.0-SNAPSHOT"}
binaryage/devtools {:mvn/version "0.9.10"}
sablono {:mvn/version "0.8.1"}
rum {:local/root "/home/tienson/codes/source/clj/rum"}
posh {:local/root "/home/tienson/codes/projects/posh"}
rum {:mvn/version "0.11.4"}
datascript-transit {:mvn/version "0.3.0"}
funcool/promesa {:mvn/version "4.0.2"}
medley {:mvn/version "1.2.0"}

File diff suppressed because one or more lines are too long

View File

@ -50,68 +50,68 @@
[:span
name]])])
(rum/defq agenda <
{:q (fn [state] (db/sub-agenda))}
[state tasks]
(sidebar/sidebar
[:div#agenda
[:h2.mb-3 "Agenda"]
(if (seq tasks)
[:div.ml-1
(let [parent-tasks (block/group-by-parent (block/sort-tasks tasks))]
(for [[parent tasks] parent-tasks]
(let [parent (cond
(string? parent)
parent
(rum/defc agenda
[]
(let [tasks (db/get-agenda)]
(sidebar/sidebar
[:div#agenda
[:h2.mb-3 "Agenda"]
(if (seq tasks)
[:div.ml-1
(let [parent-tasks (block/group-by-parent (block/sort-tasks tasks))]
(for [[parent tasks] parent-tasks]
(let [parent (cond
(string? parent)
parent
(and (map? parent)
(:label parent))
(title-cp (:label parent))
(and (map? parent)
(:label parent))
(title-cp (:label parent))
:else
"uncategorized")]
[:div.mt-10
[:h4.mb-3.text-gray-500 parent]
(for [{:heading/keys [uuid marker title priority level tags children timestamps meta repo file] :as task} tasks]
[:div.mb-2
{:key (str "task-" uuid)
:style {:padding-left 8
:padding-right 8}}
[:div.column
[:div.row {:style {:align-items "center"}}
(case marker
(list "DOING" "IN-PROGRESS" "TODO")
(ui/checkbox {:on-change (fn [_]
;; FIXME: Log timestamp
(handler/check repo file marker (:pos meta)))})
:else
"uncategorized")]
[:div.mt-10
[:h4.mb-3.text-gray-500 parent]
(for [{:heading/keys [uuid marker title priority level tags children timestamps meta repo file] :as task} tasks]
[:div.mb-2
{:key (str "task-" uuid)
:style {:padding-left 8
:padding-right 8}}
[:div.column
[:div.row {:style {:align-items "center"}}
(case marker
(list "DOING" "IN-PROGRESS" "TODO")
(ui/checkbox {:on-change (fn [_]
;; FIXME: Log timestamp
(handler/check task))})
"WAIT"
[:span {:style {:font-weight "bold"}}
"WAIT"]
"WAIT"
[:span {:style {:font-weight "bold"}}
"WAIT"]
"DONE"
(ui/checkbox {:checked true
:on-change (fn [_]
;; FIXME: Log timestamp
(handler/uncheck repo file (:pos meta))
)})
"DONE"
(ui/checkbox {:checked true
:on-change (fn [_]
;; FIXME: Log timestamp
(handler/uncheck task)
)})
nil)
[:div.row.ml-2
(if priority
[:span.priority.mr-1
(str "#[" priority "]")])
(title-cp title)
(marker-cp marker)
(when (seq tags)
(tags-cp tags))]]
(when (seq timestamps)
(timestamps-cp timestamps))
nil)
[:div.row.ml-2
(if priority
[:span.priority.mr-1
(str "#[" priority "]")])
(title-cp title)
(marker-cp marker)
(when (seq tags)
(tags-cp tags))]]
(when (seq timestamps)
(timestamps-cp timestamps))
;; FIXME: parse error
;; (when (seq children)
;; (children-cp children))
;; FIXME: parse error
;; (when (seq children)
;; (children-cp children))
]]
)])))]
"Empty")]))
]]
)])))]
"Empty")])))

View File

@ -16,17 +16,15 @@
decoded-path (b64/decodeString encoded-path)]
[encoded-path decoded-path]))
(rum/defq file <
{:q (fn [state]
(db/sub-file (last (get-path state))))
:did-mount (fn [state]
(rum/defcs file <
{:did-mount (fn [state]
(doseq [block (-> (js/document.querySelectorAll "pre code")
(array-seq))]
(js/hljs.highlightBlock block))
state)}
[state content]
(let [[encoded-path path] (get-path state)
content (ffirst content)
(let [content (db/get-file (last (get-path state)))
[encoded-path path] (get-path state)
suffix (last (string/split path #"\."))]
(sidebar/sidebar
(if (and suffix (contains? #{"md" "markdown" "org"} suffix))
@ -42,21 +40,23 @@
[s]
(count (re-seq #"\n" (or s ""))))
(rum/defq edit <
(rum/defcs edit <
(rum/local nil ::content)
(rum/local "" ::commit-message)
{:q (fn [state]
(db/sub-file (last (get-path state))))}
[state initial-content]
(let [content (get state ::content)
{:will-mount (fn [state]
(assoc state ::initial-content (db/get-file (last (get-path state)))))}
[state]
(let [initial-content (get state ::initial-content)
initial-rows (+ 3 (count-newlines initial-content))
content (get state ::content)
commit-message (get state ::commit-message)
rows (if (nil? @content) initial-rows (+ 3 (count-newlines @content)))
[_encoded-path path] (get-path state)]
(sidebar/sidebar
[:div#content
[:h3.mb-2 (str "Update " path)]
[:textarea
{:rows (+ 3 (count-newlines @content))
:style {:min-height 300}
{:rows rows
:default-value initial-content
:on-change #(reset! content (.. % -target -value))
:auto-focus true}]

View File

@ -70,13 +70,12 @@
[:p.text-sm.text-gray-500.leading-tight
"Author of Refactoring UI"]]]]]]])
(rum/defq home < (rum/local false ::loading?)
(rum/defc home <
{:will-mount (fn [state]
(when-not (db/get-github-token)
(handler/get-github-access-token))
state)
:q (fn [_state] (db/sub-github-token))}
[state {:keys [:github/token]}]
(if token
state)}
[state]
(if (db/get-github-token)
(sidebar/sidebar (sidebar/main-content))
(front-page)))

View File

@ -8,15 +8,14 @@
(defn repos
[repos]
(when (seq repos)
(let [repos (->> repos (map first) distinct)]
[:div#repos
[:ul
(for [url repos]
[:li {:key url}
[:button {:on-click (fn []
;; (handler/set-current-repo url)
)}
(string/replace url "https://github.com/" "")]])]])))
[:div#repos
[:ul
(for [url repos]
[:li {:key url}
[:button {:on-click (fn []
;; (handler/set-current-repo url)
)}
(string/replace url "https://github.com/" "")]])]]))
(rum/defcs add-repo < (rum/local "https://github.com/" ::repo-url)
[state]

View File

@ -26,19 +26,18 @@
:stroke-linecap "round"}]]
title])))
(rum/defq files-list <
{:q (fn [] (db/sub-files))}
[state files file-active?]
[:div.cursor-pointer.my-1.flex.flex-col.ml-2
(if (seq files)
(let [files (->> files (map first))]
(rum/defc files-list
[file-active?]
(let [files (db/get-files)]
[:div.cursor-pointer.my-1.flex.flex-col.ml-2
(if (seq files)
(for [file files]
(let [encoded-path (b64/encodeString file)]
[:a {:key file
:class (util/hiccup->class "mt-1.group.flex.items-center.px-2.py-1.text-base.leading-6.font-medium.rounded-md.text-gray-500.hover:text-white.hover:bg-gray-700.focus:outline-none.focus:text-white.focus:bg-gray-700.transition.ease-in-out.duration-150")
:style {:color (if (file-active? encoded-path) "#FFF")}
:href (str "/file/" encoded-path)}
file]))))])
file])))]))
(rum/defc sidebar-nav < rum/reactive
[]
@ -55,14 +54,14 @@
(active? :agenda))
(files-list file-active?)]))
(rum/defq main-content <
{:q (fn [_state] (db/sub-repos))}
[state repos]
[:div.max-w-7xl.mx-auto.px-4.sm:px-6.md:px-8
(if (seq repos)
[:div
(repo/repos repos)]
(repo/add-repo))])
(rum/defc main-content
[]
(let [repos (db/get-repos)]
[:div.max-w-7xl.mx-auto.px-4.sm:px-6.md:px-8
(if (seq repos)
[:div
(repo/repos repos)]
(repo/add-repo))]))
(rum/defcs sidebar < (mixins/modal)
[state main-content]

View File

@ -2,8 +2,9 @@
(:require [datascript.core :as d]
[frontend.util :as util]
[medley.core :as medley]
[posh.rum :as posh]
[datascript.transit :as dt]))
[datascript.transit :as dt]
[frontend.format.org-mode :as org]
[frontend.format.org.block :as block]))
;; TODO: don't persistent :github/token
@ -46,9 +47,7 @@
})
(defonce conn
(let [conn (d/create-conn schema)]
(posh/posh! conn)
conn))
(d/create-conn schema))
;; transit serialization
@ -65,15 +64,6 @@
(defn reset-conn! [db]
(reset! conn db))
(d/listen! conn :persistence
(fn [tx-report] ;; FIXME do not notify with nil as db-report
;; FIXME do not notify if tx-data is empty
(when-let [db (:db-after tx-report)]
(prn "DB changed")
(js/setTimeout (fn []
(posh/posh! conn)
(persist db)) 0))))
;; (new TextEncoder().encode('foo')).length
(defn db-size
[]
@ -175,6 +165,23 @@
headings (mapv (fn [eid] [:db.fn/retractEntity eid]) headings)]
(d/transact! conn headings)))
(defn get-file-headings
[repo-url path]
(-> (d/q '[:find ?heading
:in $ ?repo-url ?path
:where
[?repo :repo/url ?repo-url]
[?file :file/path ?path]
[?heading :heading/file ?file]
[?heading :heading/repo ?repo]]
@conn repo-url path)
seq-flatten))
(defn delete-file-headings!
[repo-url path]
(let [headings (get-file-headings repo-url path)]
(mapv (fn [eid] [:db.fn/retractEntity eid]) headings)))
;; transactions
(defn reset-headings!
[repo-url headings]
@ -204,27 +211,9 @@
[(?pred $ ?tags)]]
@conn pred)))
(comment
(frontend.handler/initial-db!)
)
(defn pull
[selector eid]
(posh/pull conn selector eid))
(defn pull-many
([eids]
(pull-many '[*] eids))
([selector eids]
(posh/pull-many conn selector eids)))
(defn q
[query & inputs]
(apply posh/q query inputs))
(defn transact!
[tx-data]
(posh/transact! conn tx-data))
(d/transact! conn tx-data))
(defn set-key-value
[key value]
@ -241,10 +230,6 @@
(some-> (d/entity (d/db conn) key)
key))
(defn sub-github-token
[]
(pull '[*] [:db/ident :github/token]))
(defn get-github-token
[]
(get-key-value :github/token))
@ -253,20 +238,10 @@
[repo]
(set-key-value :repo/current [:repo/url repo]))
(defn sub-current-repo
[]
(pull '[*] [:db/ident :repo/current]))
(defn get-current-repo
[]
(:repo/url (get-key-value :repo/current)))
(defn sub-repos
[]
(q '[:find ?url
:where [_ :repo/url ?url]]
conn))
(defn get-repos
[]
(->> (d/q '[:find ?url
@ -275,14 +250,16 @@
(map first)
distinct))
(defn sub-files
(defn get-files
[]
(q '[:find ?path
:where
[_ :repo/current ?repo]
[?file :file/repo ?repo]
[?file :file/path ?path]]
conn))
(->> (d/q '[:find ?path
:where
[_ :repo/current ?repo]
[?file :file/repo ?repo]
[?file :file/path ?path]]
@conn)
(map first)
distinct))
(defn set-repo-cloning
[repo-url value]
@ -323,31 +300,17 @@
:file/path file
:file/content content}]))
(defn get-file-content
[repo-url path]
(->> (d/q '[:find ?content
:in $ ?repo-url ?path
:where
[?repo :repo/url ?repo-url]
[?file :file/repo ?repo]
[?file :file/path ?path]
[?file :file/content ?content]
]
@conn repo-url path)
(map first)
first))
(defn sub-file
[path]
(q '[:find ?content
:in $ ?path
:where
[_ :repo/current ?repo]
[?file :file/repo ?repo]
[?file :file/path ?path]
[?file :file/content ?content]]
conn
path))
(defn extract-headings
[repo-url file content]
(let [headings (-> content
(org/parse-json)
(util/json->clj))
headings (block/extract-headings headings)]
(map (fn [heading]
(assoc heading
:heading/repo [:repo/url repo-url]
:heading/file [:file/path file]))
headings)))
(defn get-all-files-content
[repo-url]
@ -360,26 +323,54 @@
[?file :file/path ?path]]
@conn repo-url))
(defn extract-all-headings
[repo-url]
(let [contents (get-all-files-content repo-url)]
(vec
(mapcat
(fn [[file content] contents]
(extract-headings repo-url file content))
contents))))
(defn reset-file!
[repo-url file content]
(let [file-content [{:file/repo [:repo/url repo-url]
:file/path file
:file/content content}]
delete-headings (delete-file-headings! repo-url file)
headings (extract-headings repo-url file content)
headings (safe-headings headings)]
(d/transact! conn (concat file-content delete-headings headings))))
(defn get-file-content
[repo-url path]
(->> (d/q '[:find ?content
:in $ ?repo-url ?path
:where
[?repo :repo/url ?repo-url]
[?file :file/repo ?repo]
[?file :file/path ?path]
[?file :file/content ?content]]
@conn repo-url path)
(map first)
first))
(defn get-file
[path]
(->
(d/q '[:find ?content
:in $ ?path
:where
[_ :repo/current ?repo]
[?file :file/repo ?repo]
[?file :file/path ?path]
[?file :file/content ?content]]
@conn
path)
ffirst))
;; marker should be one of: TODO, DOING, IN-PROGRESS
;; time duration
(defn sub-agenda
([]
(sub-agenda :week))
([time]
(let [duration (case time
:today []
:week []
:month [])
tasks-ids (-> @(q '[:find ?h
:where
(or [?h :heading/marker "TODO"]
[?h :heading/marker "DOING"]
[?h :heading/marker "IN-PROGRESS"]
[?h :heading/marker "DONE"])]
conn)
seq-flatten)]
(pull-many tasks-ids))))
(defn get-agenda
([]
(get-agenda :week))
@ -388,13 +379,15 @@
:today []
:week []
:month [])]
(d/q '[:find (pull ?h [*])
:where
(or [?h :heading/marker "TODO"]
[?h :heading/marker "DOING"]
[?h :heading/marker "IN-PROGRESS"]
[?h :heading/marker "DONE"])]
@conn))))
(->
(d/q '[:find (pull ?h [*])
:where
(or [?h :heading/marker "TODO"]
[?h :heading/marker "DOING"]
[?h :heading/marker "IN-PROGRESS"]
[?h :heading/marker "DONE"])]
@conn)
seq-flatten))))
(defn entity
[id-or-lookup-ref]

View File

@ -95,11 +95,19 @@
m2 (get markers (:heading/marker t2) 0)
p1 (get priorities (:heading/priority t1) 0)
p2 (get priorities (:heading/priority t2) 0)]
(if (= m1 m2)
(cond
(and (= m1 m2)
(= p1 p2))
(compare (:heading/title t1) (:heading/title t2))
(= m1 m2)
(> p1 p2)
:else
(> m1 m2))))
headings)))
(defn group-by-parent
[headings]
(group-by :heading/parent-title headings))
(->> (group-by :heading/parent-title headings)
(into (sorted-map-by (fn [x y]
(compare (str x) (str y)))))))

View File

@ -62,6 +62,7 @@
{:dir (get-repo-dir repo-url)
:filepath file})))
;; TODO: cache email and name
(defn commit
[repo-url message]
(js/git.commit (clj->js

View File

@ -6,8 +6,6 @@
[frontend.db :as db]
[frontend.storage :as storage]
[frontend.util :as util]
[frontend.format.org-mode :as org]
[frontend.format.org.block :as block]
[frontend.config :as config]
[clojure.walk :as walk]
[clojure.string :as string]
@ -15,7 +13,9 @@
[cljs-bean.core :as bean]
[reitit.frontend.easy :as rfe]
[goog.crypt.base64 :as b64]
[goog.object :as gobj])
[goog.object :as gobj]
[rum.core :as rum]
[datascript.core :as d])
(:import [goog.events EventHandler]))
;; We only support Github token now
@ -69,21 +69,24 @@
;; TODO: callback hell
(defn pull
[repo-url token]
(util/p-handle (git/pull repo-url token)
(fn [result]
(get-latest-commit
(fn [commit]
(when (or (nil? @latest-commit)
(and @latest-commit
commit
(not= (gobj/get commit "oid")
(gobj/get @latest-commit "oid"))))
(prn "New commit oid: " (gobj/get commit "oid"))
(-> (load-files repo-url)
(p/then
(fn []
(load-repo-to-db! repo-url)))))
(reset! latest-commit commit))))))
(prn "pushing? " (:pushing? @state/state))
(when-not (:pushing? @state/state)
(util/p-handle
(git/pull repo-url token)
(fn [result]
(get-latest-commit
(fn [commit]
(when (or (nil? @latest-commit)
(and @latest-commit
commit
(not= (gobj/get commit "oid")
(gobj/get @latest-commit "oid"))))
(prn "New commit oid: " (gobj/get commit "oid"))
(-> (load-files repo-url)
(p/then
(fn []
(load-repo-to-db! repo-url)))))
(reset! latest-commit commit)))))))
(defn periodically-pull
[repo-url]
@ -92,23 +95,10 @@
(js/setInterval #(pull repo-url token)
(* 10 1000))))
(defn add-transaction
[tx]
(swap! state/state update :tasks-transactions conj tx))
(defn clear-transactions!
[]
(swap! state/state assoc :tasks-transactions nil))
(defn- transactions->commit-msg
[transactions]
(let [transactions (reverse transactions)]
(str
"Gitnotes auto save tasks.\n\n"
(string/join "\n" transactions))))
;; TODO: update latest commit
(defn push
[repo-url file message]
(swap! state/state assoc :pushing? true)
(let [token (db/get-github-token)]
(git/add-commit-push
repo-url
@ -116,9 +106,11 @@
message
token
(fn []
(prn "Push successfully!"))
(prn "Push successfully!")
(swap! state/state assoc :pushing? false))
(fn []
(prn "Failed to push.")))))
(prn "Failed to push.")
(swap! state/state assoc :pushing? false)))))
(defn clone
[repo]
@ -196,14 +188,16 @@
(util/p-handle
(fs/write-file (git/get-repo-dir repo-url) path content)
(fn [_]
(rfe/push-state :file {:path (b64/encodeString path)})
(db/reset-file! repo-url path content)
(git/add-commit-push repo-url
path
commit-message
token
(fn []
(db/set-file-content! repo-url path content)
(rfe/push-state :file {:path (b64/encodeString path)})
(show-notification! "File updated!"))
;; (show-notification! "File updated!")
)
(fn [error]
(prn "Failed to update file, error: " error)))))))
@ -213,8 +207,10 @@
(clone repo-url))
(defn check
[repo file marker pos]
(let [repo (db/entity (:db/id repo))
[heading]
(let [{:heading/keys [repo file marker meta uuid]} heading
pos (:pos meta)
repo (db/entity (:db/id repo))
file (db/entity (:db/id file))
repo-url (:repo/url repo)
file (:file/path file)
@ -223,15 +219,18 @@
(let [content' (str (subs content 0 pos)
(-> (subs content pos)
(string/replace-first marker "DONE")))]
(db/set-file-content! repo-url file content')
(util/p-handle
(fs/write-file (git/get-repo-dir repo-url) file content')
(fn [_]
(prn "check successfully, " file)
(db/reset-file! repo-url file content')
(push repo-url file (util/format "`%s` marked as DONE." marker))))))))
(defn uncheck
[repo file pos]
(let [repo (db/entity (:db/id repo))
[heading]
(let [{:heading/keys [repo file marker meta]} heading
pos (:pos meta)
repo (db/entity (:db/id repo))
file (db/entity (:db/id file))
repo-url (:repo/url repo)
file (:file/path file)
@ -240,24 +239,13 @@
(let [content' (str (subs content 0 pos)
(-> (subs content pos)
(string/replace-first "DONE" "TODO")))]
(db/set-file-content! repo-url file content')
(util/p-handle
(fs/write-file (git/get-repo-dir repo-url) file content')
(fn [_]
(prn "uncheck successfully, " file)
(db/reset-file! repo-url file content')
(push repo-url file "DONE rollbacks to TODO.")))))))
(defn extract-headings
[repo-url file content]
(let [headings (-> content
(org/parse-json)
(util/json->clj))
headings (block/extract-headings headings)]
(map (fn [heading]
(assoc heading
:heading/repo [:repo/url repo-url]
:heading/file [:file/path file]))
headings)))
(defn load-all-contents!
[repo-url ok-handler]
(let [files (db/get-repo-files repo-url)]
@ -269,22 +257,13 @@
(fn [_]
(ok-handler))))))
(defn extract-all-headings
[repo-url]
(let [contents (db/get-all-files-content repo-url)]
(vec
(mapcat
(fn [[file content] contents]
(extract-headings repo-url file content))
contents))))
(defonce headings-atom (atom nil))
(defn load-repo-to-db!
[repo-url]
(load-all-contents! repo-url
(fn []
(let [headings (extract-all-headings repo-url)]
(let [headings (db/extract-all-headings repo-url)]
(reset! headings-atom headings)
(db/reset-headings! repo-url headings)))))
@ -326,9 +305,34 @@
[route]
(swap! state/state assoc :route-match route))
(defn set-ref-component!
[k ref]
(swap! state/state assoc :ref-components k ref))
(defn set-root-component!
[comp]
(swap! state/state assoc :root-component comp))
(defn re-render!
[]
(when-let [comp (get @state/state :root-component)]
(rum/request-render comp)))
(defn db-listen-to-tx!
[]
(d/listen! db/conn :persistence
(fn [tx-report] ;; FIXME do not notify with nil as db-report
;; FIXME do not notify if tx-data is empty
(when-let [db (:db-after tx-report)]
(prn "DB changed, re-rendered!")
(re-render!)
(js/setTimeout (fn []
(db/persist db)) 0)))))
(defn start!
[]
(db/restore!)
(db-listen-to-tx!)
(when-let [first-repo (first (db/get-repos))]
(db/set-current-repo! first-repo))
(let [repos (db/get-repos)]

View File

@ -1,11 +1,16 @@
(ns frontend.page
(:require [rum.core :as rum]
[frontend.state :as state]))
[frontend.state :as state]
[frontend.handler :as handler]))
(rum/defc current-page < rum/reactive
{:did-mount (fn [state]
(handler/set-root-component! (:rum/react-component state))
state)}
[]
(let [state (rum/react state/state)
route-match (:route-match state)]
(if route-match
(when-let [view (:view (:data route-match))]
(view route-match)))))
(view route-match))
[:div "404 Page"])))

View File

@ -1,4 +0,0 @@
(ns frontend.posh
(:require [posh.core :as posh]))
;; experiment

View File

@ -5,4 +5,5 @@
{:route-match nil
:notification/show? false
:notification/text nil
:tasks-transactions nil}))
:root-component nil
:pushing? false}))