Merge pull request #132 from logseq/feature/templates

Add templates support
pull/645/head
Tienson Qin 2020-09-23 21:02:05 +08:00 committed by GitHub
commit aec13e0a87
10 changed files with 164 additions and 8 deletions

View File

@ -115,6 +115,8 @@
[:editor/search-block :reference]]]
["Block Embed" (embed-block)]
["Link" link-steps]
["Template" [[:editor/input "/" nil]
[:editor/search-template]]]
;; same as link
["Image Link" link-steps]
(when (state/logged?)
@ -379,6 +381,9 @@
(defmethod handle-step :editor/search-block [[_ type]]
(state/set-editor-show-block-search true))
(defmethod handle-step :editor/search-template [[_]]
(state/set-editor-show-template-search true))
(defmethod handle-step :editor/show-input [[_ option]]
(state/set-editor-show-input option))

View File

@ -72,6 +72,39 @@
"rgb(38, 76, 155)"
"rgb(121, 62, 62)"])
(rum/defcs block-template <
(rum/local false ::edit?)
(rum/local "" ::input)
[state block-id]
(let [edit? (get state ::edit?)
input (get state ::input)]
(if @edit?
(do
(state/clear-edit!)
[:div.px-4.py-2 {:on-click (fn [e] (util/stop e))}
[:p "What's the template's name?"]
[:input#new-template.form-input.block.w-full.sm:text-sm.sm:leading-5.my-2.text-gray-700
{:auto-focus true
:on-change (fn [e]
(reset! input (util/evalue e)))}]
(ui/button "Submit"
:on-click (fn []
(let [title (string/trim @input)]
(when (not (string/blank? title))
(if (db/template-exists? title)
(notification/show!
[:p "Template already exists!"]
:error)
(do
(editor-handler/set-block-property! block-id "template" title)
(state/hide-custom-context-menu!)))))))])
(ui/menu-link
{:key "Make template"
:on-click (fn [e]
(util/stop e)
(reset! edit? true))}
"Make template"))))
(rum/defc block-context-menu-content
[target block-id]
(rum/with-context [[t] i18n/*tongue-context*]
@ -148,6 +181,8 @@
(editor-handler/copy-block-ref! block-id))}
"Copy block ref")
(block-template block-id)
;; (ui/menu-link
;; {:key "Make template"
;; :on-click (fn [_e]

View File

@ -33,6 +33,7 @@
[cljs-time.coerce :as tc]
[cljs-drag-n-drop.core :as dnd]
[frontend.search :as search]
[frontend.text :as text]
["/frontend/utils" :as utils]))
(rum/defc commands < rum/reactive
@ -41,6 +42,7 @@
@*slash-caret-pos
(not (state/sub :editor/show-page-search?))
(not (state/sub :editor/show-block-search?))
(not (state/sub :editor/show-template-search?))
(not (state/sub :editor/show-input))
(not (state/sub :editor/show-date-picker?)))
(let [matched (util/react *matched-commands)]
@ -51,7 +53,7 @@
(let [command-steps (get (into {} matched) chosen)
restore-slash? (and
(not (contains? (set (map first command-steps)) :editor/input))
(not (contains? #{"Date Picker"} chosen)))]
(not (contains? #{"Date Picker" "Template"} chosen)))]
(editor-handler/insert-command! id command-steps
format
{:restore? restore-slash?})))
@ -158,6 +160,59 @@
(subs content 0 64))
:class "black"}))))))
(rum/defc template-search < rum/reactive
{:will-unmount (fn [state] (reset! editor-handler/*selected-text nil) state)}
[id format]
(when (state/sub :editor/show-template-search?)
(let [pos (:editor/last-saved-cursor @state/state)
input (gdom/getElement id)]
(when input
(let [current-pos (:pos (util/get-caret-pos input))
edit-content (state/sub [:editor/content id])
edit-block (state/sub :editor/block)
q (or
(when (>= (count edit-content) current-pos)
(subs edit-content pos current-pos))
"")
matched-templates (editor-handler/get-matched-templates q)
chosen-handler (fn [[template db-id] _click?]
(if-let [block (db/entity db-id)]
(let [properties' (dissoc (:block/properties block) "custom_id" "template")
new-level (:block/level edit-block)
template-parent-level (:block/level block)
pattern (config/get-block-pattern format)
content
(db/get-block-full-content
(state/get-current-repo)
(:block/uuid block)
(fn [{:block/keys [level content]}]
(let [new-level (+ new-level (- level template-parent-level))]
(string/replace-first content
(apply str (repeat level pattern))
(apply str (repeat new-level pattern))))))
content (-> (text/remove-properties! content)
(text/rejoin-properties properties'))
content (if (string/includes? (string/trim edit-content) "\n")
content
(text/remove-level-spaces content format))]
(state/set-editor-show-template-search false)
(editor-handler/insert-command! id
content
format
{})))
(when-let [input (gdom/getElement id)]
(.focus input)))
non-exist-handler (fn [_state]
(state/set-editor-show-template-search false))]
(ui/auto-complete
matched-templates
{:on-chosen chosen-handler
:on-enter non-exist-handler
:empty-div [:div.text-gray-500.pl-4.pr-4 "Search for a template"]
:item-render (fn [[template _block-db-id]]
template)
:class "black"}))))))
(rum/defc date-picker < rum/reactive
[id format]
(when (state/sub :editor/show-date-picker?)
@ -683,6 +738,11 @@
true
*slash-caret-pos)
(transition-cp
(template-search id format)
true
*slash-caret-pos)
(transition-cp
(date-picker id format)
false

View File

@ -938,7 +938,7 @@
(let [cursor-range (util/caret-range (gdom/getElement block-id))
properties-hidden? (text/properties-hidden? properties)
content (text/remove-level-spaces content format)
content (if properties-hidden? (text/remove-properties! block content) content)]
content (if properties-hidden? (text/remove-properties! content) content)]
(state/set-editing!
edit-input-id
content

View File

@ -111,4 +111,4 @@
[]
(let [journals-length (state/sub :journals-length)
latest-journals (db/get-latest-journals (state/get-current-repo) journals-length)]
(journals latest-journals)))
(journals latest-journals)))

View File

@ -1995,7 +1995,7 @@
other-children)]
(recur others children))))))))
;; recursively with children content
;; recursively with children content for tree
(defn get-block-content-rec
([block]
(get-block-content-rec block (fn [block] (:block/content block))))
@ -2010,6 +2010,16 @@
block)]
(apply util/join-newline @contents))))
;; with children content
(defn get-block-full-content
([repo block-id]
(get-block-full-content repo block-id (fn [block] (:block/content block))))
([repo block-id transform-fn]
(let [blocks (get-block-and-children repo block-id false)]
(->> blocks
(map transform-fn)
(apply util/join-newline)))))
(defn get-block-end-pos-rec
[repo block]
(let [children (:block/children block)]
@ -2244,6 +2254,30 @@
(reset! blocks-count-cache n)
n))))
(defn get-all-templates
[]
(let [pred (fn [db properties]
(some? (get properties "template")))]
(->> (d/q
'[:find ?b ?p
:in $ ?pred
:where
[?b :block/properties ?p]
[(?pred $ ?p)]]
(get-conn)
pred)
(map (fn [[e m]]
[(get m "template") e]))
(into {}))))
(defn template-exists?
[title]
(when title
(let [templates (keys (get-all-templates))]
(when (seq templates)
(let [templates (map string/lower-case templates)]
(contains? (set templates) (string/lower-case title)))))))
(defn rebuild-page-blocks-children
"For performance reason, we can update the :block/children value after every operation,
but it's hard to make sure that it's correct, also it needs more time to implement it.

View File

@ -354,7 +354,7 @@
content (string/trim (text/remove-level-spaces content format))
properties (or custom-properties properties)
content (if (and (seq properties) (text/properties-hidden? properties))
(text/remove-properties! block content)
(text/remove-properties! content)
content)
content-length (count content)
text-range (if (or (= :max pos) (<= content-length pos))
@ -676,6 +676,7 @@
(state/set-editor-show-date-picker false)
(state/set-editor-show-page-search false)
(state/set-editor-show-block-search false)
(state/set-editor-show-template-search false)
(commands/restore-state true))
(defn get-state
@ -1325,6 +1326,10 @@
(:block/uuid h)))
(search/search q 21))))
(defn get-matched-templates
[q]
(search/template-search q))
(defn get-matched-commands
[input]
(try
@ -1367,6 +1372,7 @@
(state/get-editor-show-input)
(state/get-editor-show-page-search)
(state/get-editor-show-block-search)
(state/get-editor-show-template-search)
(state/get-editor-show-date-picker)))
(defn get-previous-input-char

View File

@ -92,7 +92,7 @@
(map (fn [{:block/keys [content format properties] :as block}]
(assoc block :block/content
(->> (text/remove-level-spaces content format)
(text/remove-properties! block)))) blocks)))))))
(text/remove-properties!)))) blocks)))))))
(defn page-search
([q]
@ -103,3 +103,13 @@
(let [pages (db/get-pages (state/get-current-repo))]
(when (seq pages)
(fuzzy-search pages q :limit limit)))))))
(defn template-search
([q]
(template-search q 10))
([q limit]
(let [q (clean-str q)]
(let [templates (db/get-all-templates)]
(when (seq templates)
(let [result (fuzzy-search (keys templates) q :limit limit)]
(vec (select-keys templates result))))))))

View File

@ -335,6 +335,12 @@
(defn get-editor-show-block-search
[]
(get @state :editor/show-block-search?))
(defn set-editor-show-template-search
[value]
(set-state! :editor/show-template-search? value))
(defn get-editor-show-template-search
[]
(get @state :editor/show-template-search?))
(defn set-editor-show-date-picker
[value]
(set-state! :editor/show-date-picker? value))

View File

@ -36,7 +36,7 @@
(every? hidden-properties ks))))
(defn remove-properties!
[block content]
[content]
(let [lines (string/split-lines content)
[title-lines properties-and-body] (split-with (fn [l] (not (string/starts-with? (string/upper-case (string/triml l)) ":PROPERTIES:"))) lines)
body (drop-while (fn [l]
@ -82,5 +82,5 @@
(= (:block/properties (db/entity [:block/uuid (:block/uuid block)]))
properties))
content
(-> (remove-properties! block content)
(-> (remove-properties! content)
(rejoin-properties properties))))