Hi,
I’ve been quietly absorbing much of the information shared here, and I must say a huge thank you to everyone who’s answered other folks’ questions. I never had to ask any myself! This is my first exposure to Clojure, and it’s been a ride.
I’ve made a few other things, but I wanted to share this quite self-contained example as to what I’ve found you can accomplish in Logseq. I’m amazed every day!
Plugins are great, but I use my phone to take notes quite often, so I’ve been seeing what kinds of plugin-like functionality you can do with Advanced Queries (and their :view
s)
After seeing this post and realizing I could combine macros with Advanced Queries, I’ve found a whole world of possibilities. (Big thanks to all those on that thread).
Ok, let’s get to it…
With the following in place, you can write,
{{insert-template Name of Template}}
and get a button that says:
Insert: Name of Template
that does what you’d expect: clicking it appends a block below it with the template populated. (Adding , erase
to the end of the macro makes it delete the button too.)
Inside logseq/config.edn
add to the :macros
section:
:macros
{;; Usage: {{insert-template <template-name>,<erase-on-click>}}
;; where
;; <template-name> is the name of the template to insert when clicked.
;; <erase-on-click> is the word "erase" if the button is to be removed on click.
;; Examples:
;; {{insert-template A Template}}
;; {{insert-template My Other Template, erase}}
:insert-template "\n#+BEGIN_QUERY
{:inputs [:current-block]
:query [:find ?block-uuid
:in $ ?block
:where [?block :block/uuid ?block-uuid]]
:result-transform (fn [[block-uuid]]
[block-uuid \"$1\" (= \"$2\" \"erase\")])
:view :insert-template-view}
#+END_QUERY"
;;
}
and the :query/views
section:
:query/views
{;;
;; Displays the result data as nicely formatted text
:pprint
(fn [r] [:pre.code (pprint r)])
;;
;; Creates a button from a block UUID, template name and erase flag
;; On click, appends the specified template after the given block,
;; optionally removing the original block (if the erase flag is set)
:insert-template-view
(fn [[block-uuid template-name erase-on-click?]]
[:button
{:style {:border "1px solid silver" :border-radius "6px" :padding "2px 8px"}
:on-click
(fn [_]
(if (call-api "exist_template" template-name)
(do (call-api "insert_template" block-uuid template-name)
(if erase-on-click?
(call-api "remove_block" block-uuid)))
(call-api "show_msg"
(str "Template not found:\n" template-name) :error)))}
"Insert: " template-name])
;;
}
And that’s it… almost.
The key to getting macros to work with queries is to include a newline at the top. Unfortunately, this also leaves some blank space at the top, and macros in general take up a whole block of space.
To fix this, we can turn to custom CSS. Here’s the contents of mine that fix these issues:
/* Queries inside macros only work if preceded by a blank line. This results
* in a <br> tag being added and the query appearing lower than the bullet.
* Remove the <br> here: */
div.macro>div:first-child>br:first-child {
display: none;
}
/* Make certain macros appear inline rather than as separate HTML block elements */
div.macro[data-macro-name="insert-template"] {
display: inline-block;
}
/* The insert template query has a custom view, hide the usual query view controls */
div.macro[data-macro-name="insert-template"] .custom-query .th {
display: none;
}
I’m happy to answer any questions on how this works. I’m keen to give back to this community given how much I’ve learnt from you
For now, enjoy.
Thanks,
Ian