Browse Source

Add month journal

Tienson Qin 5 years ago
parent
commit
a3023564e3

+ 1 - 0
web/package.json

@@ -19,6 +19,7 @@
     "purgecss": "^2.1.0",
     "react": "^16.12.0",
     "react-dom": "^16.12.0",
+    "react-textarea-autosize": "^7.1.2",
     "react-transition-group": "^4.3.0",
     "showdown": "^1.9.1",
     "tailwindcss": "^1.2.0"

+ 1 - 1
web/public/static/css/style.css

@@ -255,5 +255,5 @@ textarea {
 }
 
 #content p, #content div {
-    word-break: break-all;
+    word-break: break-word;
 }

File diff suppressed because it is too large
+ 0 - 0
web/public/static/js/manifest.edn


+ 7 - 1
web/src/frontend/components/file.cljs

@@ -31,8 +31,14 @@
        [:div#content
         [:a {:href (str "/file/" encoded-path "/edit")}
          "edit"]
-        (if content
+        (cond
+          (string/blank? content)
+          [:span]
+
+          content
           (util/raw-html (format/to-html content suffix))
+
+          :else
           "Loading ...")]
        [:div "File " suffix " is not supported."]))))
 

+ 34 - 19
web/src/frontend/components/journal.cljs

@@ -5,44 +5,59 @@
             [clojure.string :as string]
             [frontend.ui :as ui]
             [frontend.format :as format]
-            [frontend.mixins :as mixins]))
+            [frontend.mixins :as mixins]
+            [frontend.db :as db]))
 
 (defonce content-atom (atom ""))
 (defonce edit?-atom (atom false))
 
 (defn today
   []
-  (.toLocaleDateString (js/Date.) "default" (clj->js {:month "long"
-                                                      :year "numeric"
-                                                      :day "numeric"
-                                                      :weekday "long"})))
+  (.toLocaleDateString (js/Date.) "default"
+                       (clj->js {:month "long"
+                                 :year "numeric"
+                                 :day "numeric"
+                                 :weekday "long"})))
 
 
 (rum/defc editor-box <
   (mixins/event-mixin
    (fn [state]
-     (mixins/close-when-esc-or-outside state
-                                       true
-                                       :on-close (fn []
-                                                   (reset! edit?-atom false)))))
+     (mixins/close-when-esc-or-outside
+      state
+      edit?-atom
+      :on-close (fn []
+                  (reset! edit?-atom false)
+                  (handler/alter-file (util/current-journal-path) "Auto save" @content-atom false)))))
   [content-atom]
-  [:textarea
-   {:rows 10
-    :on-change #(reset! content-atom (.. % -target -value))
-    :value @content-atom
+  (ui/textarea-autosize
+   {:on-change (fn [e]
+                 (reset! content-atom (util/evalue e)))
+    :default-value @content-atom
     :auto-focus true
     :style {:border "none"
             :border-radius 0
-            :background "transparent"}}])
+            :background "transparent"
+            :margin-top 12.5}}))
 
 (rum/defcs journal < rum/reactive
+  {:will-mount (fn [state]
+                 (reset! content-atom (db/get-current-journal))
+                 state)}
   [state]
   (let [content (rum/react content-atom)
-        edit? (rum/react edit?-atom)]
+        edit? (rum/react edit?-atom)
+        show-textarea? (or edit? (string/blank? content))]
+    (when (and show-textarea? (not edit?))
+      (reset! edit?-atom true))
     [:div#content
-     [:h1.text-gray-600 (today)]
-     (if (or edit? (string/blank? content))
+     [:h1 {:style {:color "#202b33"
+                   :font-weight 450}}
+      (today)]
+     (if show-textarea?
        (editor-box content-atom)
-       [:div {:on-click (fn []
-                          (reset! edit?-atom true))}
+       [:div.flex-1 {:on-click (fn []
+                                 (reset! edit?-atom true))
+                     :style {:padding 8
+                             :min-height 200}}
         (util/raw-html (format/to-html content "org"))])]))

+ 17 - 10
web/src/frontend/db.cljs

@@ -4,7 +4,8 @@
             [medley.core :as medley]
             [datascript.transit :as dt]
             [frontend.format.org-mode :as org]
-            [frontend.format.org.block :as block]))
+            [frontend.format.org.block :as block]
+            [clojure.string :as string]))
 
 ;; TODO: don't persistent :github/token
 
@@ -302,15 +303,17 @@
 
 (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)))
+  (if (string/blank? 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]
@@ -393,6 +396,10 @@
   [id-or-lookup-ref]
   (d/entity (d/db conn) id-or-lookup-ref))
 
+(defn get-current-journal
+  []
+  (get-file (util/current-journal-path)))
+
 (comment
   (d/transact! conn [{:db/id -1
                       :repo/url "https://github.com/tiensonqin/notes"

+ 17 - 1
web/src/frontend/fs.cljs

@@ -1,4 +1,6 @@
-(ns frontend.fs)
+(ns frontend.fs
+  (:require [frontend.util :as util]
+            [promesa.core :as p]))
 
 (defn mkdir
   [dir]
@@ -16,3 +18,17 @@
 (defn write-file
   [dir path content]
   (js/pfs.writeFile (str dir "/" path) content))
+
+(defn stat
+  [dir path]
+  (js/pfs.stat (str dir "/" path)))
+
+(defn create-if-not-exists
+  ([dir path]
+   (create-if-not-exists dir path ""))
+  ([dir path initial-content]
+   (util/p-handle
+    (stat dir path)
+    (fn [_stat] true)
+    (fn [_error]
+      (write-file dir path initial-content)))))

+ 37 - 9
web/src/frontend/handler.cljs

@@ -94,7 +94,7 @@
   (when-let [token (db/get-github-token)]
     (pull repo-url token)
     (js/setInterval #(pull repo-url token)
-                    (* 10 1000))))
+                    (* 60 1000))))
 
 (defn git-add-commit
   [repo-url file message content]
@@ -207,14 +207,17 @@
                  3000))
 
 (defn alter-file
-  [path commit-message content]
-  (let [token (db/get-github-token)
-        repo-url (db/get-current-repo)]
-    (util/p-handle
-     (fs/write-file (git/get-repo-dir repo-url) path content)
-     (fn [_]
-       (rfe/push-state :file {:path (b64/encodeString path)})
-       (git-add-commit repo-url path commit-message content)))))
+  ([path commit-message content]
+   (alter-file path commit-message content true))
+  ([path commit-message content redirect?]
+   (let [token (db/get-github-token)
+         repo-url (db/get-current-repo)]
+     (util/p-handle
+      (fs/write-file (git/get-repo-dir repo-url) path content)
+      (fn [_]
+        (when redirect?
+          (rfe/push-state :file {:path (b64/encodeString path)}))
+        (git-add-commit repo-url path commit-message content))))))
 
 (defn clear-storage
   [repo-url]
@@ -315,10 +318,34 @@
                (fn [error]
                  (prn "Get token failed, error: " error)))))
 
+;; journals
+(defn create-month-journal-if-not-exists
+  [repo-url]
+  (let [repo-dir (git/get-repo-dir repo-url)
+        path (util/current-journal-path)
+        {:keys [year month day weekday]} (util/get-date)
+        file-path (str "/" path)
+        ;; org-journal format, something like `* Tuesday, 06/04/13`
+        default-content (util/format "* %s, %d/%d/%d\n" weekday month day year)]
+    (->
+     (util/p-handle
+      (fs/mkdir (str repo-dir "/journals"))
+      (fn [result]
+        (fs/create-if-not-exists repo-dir file-path default-content))
+      (fn [error]
+        ;; exists
+        (fs/create-if-not-exists repo-dir file-path default-content)))
+     (util/p-handle
+      (fn [result]
+        (git-add-commit repo-url path "create a month journal" default-content))
+      (fn [error]
+        (prn error))))))
+
 (defn clone-and-pull
   [repo]
   (p/then (clone repo)
           (fn []
+            (create-month-journal-if-not-exists repo)
             (periodically-pull repo))))
 
 (defn set-route-match!
@@ -370,4 +397,5 @@
     (db/set-current-repo! first-repo))
   (let [repos (db/get-repos)]
     (doseq [repo repos]
+      (create-month-journal-if-not-exists repo)
       (periodically-pull-and-push repo))))

+ 8 - 4
web/src/frontend/mixins.cljs

@@ -49,20 +49,24 @@
 ;;      (dissoc state name))})
 
 (defn close-when-esc-or-outside
-  [state open? & {:keys [on-close]}]
-  (let [node (rum/dom-node state)]
-    (when open?
+  [state open? & {:keys [on-close node]}]
+  (let [node (or node (rum/dom-node state))]
+    (when @open?
       (listen state js/window "click"
               (fn [e]
                 ;; If the click target is outside of current node
                 (when-not (dom/contains node (.. e -target))
+                  (prn "hide b")
                   (on-close e))))
 
       (listen state js/window "keydown"
               (fn [e]
+                (prn "key code: " (.-keyCode e))
                 (case (.-keyCode e)
                   ;; Esc
-                  27 (on-close e)
+                  27 (do
+                       (prn "hide a")
+                       (on-close e))
                   nil))))))
 
 (defn event-mixin

+ 5 - 1
web/src/frontend/ui.cljs

@@ -2,13 +2,17 @@
   (:require [rum.core :as rum]
             [frontend.rum :as r]
             ["react-transition-group" :refer [TransitionGroup CSSTransition]]
+            ["react-textarea-autosize" :as Textarea]
             [frontend.util :as util]
             [frontend.mixins :as mixins]
-            [frontend.state :as state]))
+            [frontend.state :as state]
+            [goog.object :as gobj]))
 
 (defonce transition-group (r/adapt-class TransitionGroup))
 (defonce css-transition (r/adapt-class CSSTransition))
 
+(defonce textarea-autosize (r/adapt-class (gobj/get Textarea "default")))
+
 (rum/defc dropdown-content-wrapper [state content]
   [:div.origin-top-right.absolute.right-0.mt-2.w-48.rounded-md.shadow-lg
    {:class (case state

+ 13 - 0
web/src/frontend/util.cljs

@@ -112,3 +112,16 @@
                  (on-failed %)))
        (.then bean/->clj)
        (.then #(on-ok %)))))
+
+(defn get-date
+  []
+  (let [date (js/Date.)]
+    {:year (.getFullYear date)
+     :month (inc (.getMonth date))
+     :day (.getDate date)
+     :weekday (.toLocaleString date "en-us" (clj->js {:weekday "long"}))}))
+
+(defn current-journal-path
+  []
+  (let [{:keys [year month]} (get-date)]
+    (str "journals/" year "_" month ".org")))

+ 21 - 1
web/yarn.lock

@@ -2,6 +2,13 @@
 # yarn lockfile v1
 
 
+"@babel/runtime@^7.1.2":
+  version "7.9.2"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06"
+  integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==
+  dependencies:
+    regenerator-runtime "^0.13.4"
+
 "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3":
   version "7.7.6"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f"
@@ -1211,7 +1218,7 @@ process@^0.11.10:
   resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
   integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
 
-prop-types@^15.6.2:
+prop-types@^15.6.0, prop-types@^15.6.2:
   version "15.7.2"
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
   integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -1300,6 +1307,14 @@ react-is@^16.8.1:
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c"
   integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==
 
+react-textarea-autosize@^7.1.2:
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-7.1.2.tgz#70fdb333ef86bcca72717e25e623e90c336e2cda"
+  integrity sha512-uH3ORCsCa3C6LHxExExhF4jHoXYCQwE5oECmrRsunlspaDAbS4mGKNlWZqjLfInWtFQcf0o1n1jC/NGXFdUBCg==
+  dependencies:
+    "@babel/runtime" "^7.1.2"
+    prop-types "^15.6.0"
+
 react-transition-group@^4.3.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.3.0.tgz#fea832e386cf8796c58b61874a3319704f5ce683"
@@ -1359,6 +1374,11 @@ regenerator-runtime@^0.13.2:
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5"
   integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==
 
+regenerator-runtime@^0.13.4:
+  version "0.13.5"
+  resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
+  integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==
+
 require-directory@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"

Some files were not shown because too many files changed in this diff