mirror of https://github.com/logseq/logseq
commit
aec13e0a87
|
@ -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))
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))))))))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))))
|
||||
|
|
Loading…
Reference in New Issue