Result transform conditional

Hi all,

So I have this problem, and I’m not sure how to solve.
Within my journal query, I have the following result -transform:

 :result-transform (fn [r] (map (fn [m] (assoc m :block/collapsed? true)) r))

What this does is that it collapses every block that results from the query. This way, I end up with a neat list - which is itself uncollapsed by default - containing all the tasks I want, where the tasks themselves are collapsed.

However, the side-effect of this approach is that every task has the ‘bullet glow’ of a ‘collapsed task’. Which renders the indicator of which bullet is collapsed (and thus has non-displayed indents) and which does not useless.

So I’m wondering, whether it’s possible to add some kind of check, to make the bullets (tasks) that have no children set as “collapsed? false” and have the bullets (tasks) that do have children as “collapsed? true”. That way, I can see by indicators which bullets (tasks) have additional information attached to them and which don’t.

The difficulty is that Logseq only stores relationships to a blocks parents. And therefore, it’s not obvious to me how to check whether there are children to a block.

I’m optimistic that this is possible. But I just don’t know where to start this challenging puzzle.

Does anyone have some pointers or tips?

Edit: for clarification:

What I have: (all tasks show a glowing bullet)
image

What the structure is: (only the second task has children)
image

What I want: (a list with tasks and functioning indicators of which tasks have children)
image

1 Like

That would be so epic!
But yes the problem arises that a block doesn’t know whether it has children :expressionless:

We could try and count the children blocks in the where and give that number to the result and then add an assoc with if statement in the result-transform… but… :woman_shrugging:t4: idk if that will even work.

For counting see this post for some ideas:

If statements are possible in the result-transform, but I don’t have an example of the top of my head.

Starting from here:

…this works to me:

:query [:find ?has-child (pull ?b [*])
:where

[...other patterns...]

  (or
    (and
      (not
        (not
          [?child :block/uuid ?id]
          [?child :block/parent ?b]
        )
      )
      [(not false) ?has-child]
    )
    (and
      (not
        [?child :block/uuid ?id]
        [?child :block/parent ?b]
      )
      [(not true) ?has-child]
    )
  )
]
:result-transform (fn [r]
  (map
    (fn [[collapsed, b]]
      (assoc b :block/collapsed? collapsed)
    )
    (partition 2 r)
  )
)

And since @Siferiax looks for epicness, here is a variation of :result-transform:

:result-transform (fn [r]
  (for [[collapsed, b] (partition 2 r)]
    (assoc b :block/collapsed? collapsed)
  )
)
1 Like

Why the double not statement? Seems a bit overkill :joy:
Otherwise, lovely solution :grin: figured it was something like this.

Can you make it work without the double not?

Yes, using an or-join. We don’t care about the child block, just whether it exists or not.

#+BEGIN_QUERY
{:title "Block has child"
 :query [:find ?has-child (pull ?b [*])
  :where
   [?b :block/marker "TODO"]
   (or-join [?b ?has-child]
     (and
       [?child :block/uuid ?id]
       [?child :block/parent ?b]
       [(not false) ?has-child]
     )
     (and
       (not
         [?child :block/uuid ?id]
         [?child :block/parent ?b]
       )
       [(not true) ?has-child]
     )
   )
 ]
 :result-transform (fn [r]
   (for [[collapsed, b] (partition 2 r)]
     (assoc b :block/collapsed? collapsed)
   )
 )
}
#+END_QUERY

1 Like