There has been a lot of discussion about managing pages in logseq, specifically about ways on how to represent a hierarchy. My goal in this post is to showcase my method of showing (and querying for) hierarchy, in case someone else finds it useful. Btw, this is not an original idea, it is largely inspired by the index method by alex0.
Assumptions, disclaimers, and notes
-
I don’t use the graph view. But if you do, you should know that after doing the index hack, all the pages (children and grandchildren) would directly connect to the top level page, so it doesn’t show any hierarchy.
-
I have minimal programming experience. After looking at the logseq advanced query documentation, looking at a lot of code, and a bit of testing, I only guessed at what the attributes actually meant (please tell me where to find the list of all logseq block/page attributes and their descriptions ). Because of this, the queries might not have the best syntax/method. Also, please forgive (and correct) my misuse of terminologies, if ever.
-
This is my first time posting in any forum, so please educate me on some manners/conventions/practices that you think I might need to know.
-
I use inline code not only for codes, but for whenever I want to emphasize that I have a strict definition for a certain word or phrase.
Charactaristics of the heirarchy that I am aiming for:
- If ever I decide that the hierarchy should be modified, it should be easy for me to do, like how easy for me it is to indent/de-indent blocks in a logseq page.
- I want to write things while keeping its context in mind. That’s why I want a visible hierarchy on the page I am writing on, like an index.
- I use hierarchies mainly for project pages, so I want a query to show all tasks relating to a page and its subpages.
How it works
The index block
If you haven’t read the index method, it’s simply an indented list of pages with a tag, in my case an #.index
tag, at the top level of the block. This complies with the 1st characteristic I was aiming for, since it is quite literally a block in logseq.
Show index in subpages using an advanced query
Now to comply with the 2nd characteristic, I need to be able to display the index in the subpages. I do this using the following advanced query:
#+BEGIN_QUERY
{
:title [:b "index"]
:query [
:find (pull ?iblock [*])
:in $ ?pname %
:where
[?current-page :page/name ?pname]
[?itag :page/name ".index"]
[?iblock :block/refs ?itag]
(get-children ?iblock ?pblock)
[?pblock :block/refs ?current-page]
]
:inputs [:current-page
[
[(get-children ?parent ?child) [?child :block/parent ?parent]]
[(get-children ?parent ?child) [?t :block/parent ?parent]
(get-children ?t ?child)]
]
]
:breadcrumb-show? false
:table-view? false
:group-by-page? false
}
#+END_QUERY
What the query looks like on a page:
I have a template that contains this query, so I can quickly query the index on any page whenever I need to. The queried index block is also editable inside any subpage (careful though because you might edit the code instead).
Query to search for tasks relating to a page and its subpages
For the 3rd characteristic, I might need to explain what I mean when I say “tasks relating to
the page
” For me, this means all task blocks which either tags the page
, or is in the page
. I also have some commented code which can give me tasks relating to
any page that has the property tags:: the page
.
The following query gives me tasks relating to the current page and tasks with importance relating to all the current page’s subpages. If you want to include all tasks (not just with importance) in all subpages, replace (getabctask ?b ?subpages))
to (getanytask ?b ?subpages))
. It works on any page (top level or bottom??? level), as long as it is in an index block
. (Sorry for the long code, please tell me if there are custom rules or functions in logseq)
#+BEGIN_QUERY
{
:title [:b "Tasks"]
:query [
:find (pull ?b [*])
:in $ ?pname %
:where
[?current-page :page/name ?pname]
[?itag :page/name ".index"]
(or-join [?pblock ?current-page ?itag]
(and [?pblock :block/refs ?current-page]
[?pblock :block/refs ?itag])
(and [?iblock :block/refs ?itag]
(get-children ?iblock ?pblock)
[?pblock :block/refs ?current-page])
)
(or-join [?pblock ?b]
(and (get-children ?pblock ?childblocks)
[?childblocks :block/refs ?subpages]
(getabctask ?b ?subpages)) ;;get tasks with priority relating to subpages
(and (?pblock :block/refs ?page)
(getanytask ?b ?page)) ;;get all tasks relating to current page
)
]
:inputs [:current-page
[
[(get-children ?parent ?child) [?child :block/parent ?parent]]
[(get-children ?parent ?child) [?t :block/parent ?parent]
(get-children ?t ?child)]
;;[(getanytask ?task ?page) ;;recursive search. I only have it here in case I want to use it
;;[?pagetaggedwith ?page/tags ?page]
;;(getanytask ?task ?pagetaggedwith)
;;]
[(getanytask ?task ?page)
(or [?task :block/refs ?page]
(get-children ?page ?task))
[?task :block/marker ?marker]
[(contains? #{"TODO" "DOING" "NOW" "WAITING" "LATER"} ?marker)]]
[(getabctask ?task ?page)
(getanytask ?task ?page)
[?task :block/priority ?priority]
[(contains? #{"A" "B" "C"} ?priority)]]
]
]
:result-transform (fn [result] ;;sort by priority
(sort-by (fn [h]
(get h :block/priority "Z")) result))
:breadcrumb-show? false
:group-by-page? false
}
#+END_QUERY
I also have a template for this, so I can quickly put it in any page. This is what the query looks like on a page.
Advantagous side effects
Pages as tasks
Since the index block
is just a logseq block, you can put more than just page links. Which means I can make any block in the index block
into a task. I have a query in my logseq journal that gets all DOING
blocks, and tagging a project as DOING
helps me remind myself what I am working on.
If you have a master projects page, you can easily query for blocks tagged with #.index
and is in a DOING
state to show all projects that you are currently doing.
That wraps up my post. I hope I was not being redundant. I also hope that this can help or inspire someone in their own workflows, particularly those who are not familiar with advanced queries.