Filtering to find sub-tasks for specific blocks

What I’m trying to do

Find the sub-task blocks in a similar page:

2022-10-13.md
- [ ] some task
- [[anki inbox]]
  - [ ] task 1
  - [ ] task 2

I would like to query for open tasks under - [[anki inbox]] blocks across my vault

Things I have tried

```query
task-todo:"" block:"[[anki inbox]]"
```

```query
[[anki inbox]] task-todo:""
```

All of the above also end up finding - [ ] some task. I’ve also looked into dataview but even the js API in the DataView plugin seems to operate on the page level rather than the block level.

I am willing to switch to the following workflow:

2022-10-13.md
- [ ] some task
- [ ] task 1 #anki-inbox
- [ ] task 2 #anki-inbox

But I’d prefer to use hierarchy. Thought I’d reach out to the community before completely refactoring my approach.

Topic

Summary
  • How to get the mentioned texts which contains [[Note P]] from the file.lists for open tasks with the desired structure?

Test

Summary
  • dataview: v0.5.46

Input

Summary

dictionary files:

  • Location: “100_Project/01_dataviewjs/01_by_example/Q23_Mentions/Q23_test_data”

folder: 00

Summary_00
  • filename : My Test File
```md
The note is "My Test File".
```

  • filename : Note P
```md
The note is "Note P".
```

folder: 01 (Note_Structures)

Summary_01
  • filename : dic_19820101
---
Date: 1982-01-01
---
#Project/P01

## The Note Structures

### main tasks : CASE S1
- [[Note P]] main task GH
  - [ ] task g
  - [ ] task h
      - [ ] task h1
      - [ ] task h2

### main tasks : CASE S2
- [ ] [[Note P]] main task IJ
  - [ ] task i
  - [ ] task j
      - [ ] task j1
      - [ ] task j2

### some tasks : CASE S3
- some task MN
  - [ ] task m
  - [ ] task n
      - [ ] task n1
      - [ ] task n2 [[Note P]]

### some tasks : CASE S4
- [ ] some task RS
  - [ ] task r
  - [ ] task s
      - [ ] task s1
      - [ ] task s2 [[Note P]]

### other tasks: CASE S5
- other task UV
  - [ ] task u
  - [x] task v : Completed and not fullyCompleted
      - [ ] task v1
      - [ ] task v2

### other tasks: CASE S6
- [ ] other task XY
  - [ ] task x
  - [x] task y : Completed and not fullyCompleted
      - [ ] task y1
      - [ ] task y2




folder: 03_done_excluded_case

Summary_03
  • filename : dic_19820302
---
Date: 1982-03-02
---
#Project/P03

## input
### milestones
- 2004-03-01 add this feature_A #Test/d01 [[Note J]] , [[Note K]]
- 2004-03-02 add this feature_B #Test/d02 [[Note J]] 

### main tasks : CASE S1(done)
- [[Note P]] main task GH
  - [x] task g
  - [x] task h
      - [x] task h1
      - [x] task h2





  • filename : dic_19820307
---
Date: 1982-03-07
---
#Project/P03

## input

### main tasks : CASE S2(done)
- [x] [[Note P]] main task IJ
  - [x] task i
  - [x] task j
      - [x] task j1
      - [x] task j2




  • filename : dic_19820312
---
Date: 1982-03-12
---
#Project/P03

## input
### some tasks : CASE S3(done)
- some task MN
  - [x] task m
  - [x] task n
      - [x] task n1
      - [x] task n2 [[Note P]]




  • filename : dic_19820317
---
Date: 1982-03-17
---
#Project/P03

## input
### some tasks : CASE S4(done)
- [x] some task RS
  - [x] task r
  - [x] task s
      - [x] task s1
      - [x] task s2 [[Note P]]




  • filename : dic_19820322
---
Date: 1982-03-22
---
#Project/P03

## input
### other tasks : CASE S5(done)
- other task UV
  - [x] task u
  - [x] task v : Completed and not fullyCompleted
      - [x] task v1
      - [x] task v2




  • filename : dic_19820327
---
Date: 1982-03-27
---
#Project/P03

## input
### other tasks : CASE S6(done)
- [x] other task XY
  - [x] task x
  - [x] task y : Completed and not fullyCompleted
      - [x] task y1
      - [x] task y2




folder: 04_supported_case

Summary_04
  • filename : dic_19820402
---
Date: 1982-04-02
---
#Project/P04

## input
>CASE S1 =>
>case_FLST_LwithOL-T : A root list item contains an outlink like  [[[Note P]] and a sub task item which is not fullyCompleted.
>
>FLST    : Use file.lists
>L           : an element of file.lists
>OL        : L.outlinks
>FLST_L : A root list item L
>FLST_T : A root task item T
>-T          : A sub task item T

### main tasks : CASE S1
- [[Note P]] links to a project
    - [ ] do this task
    - [ ] and that task
    - [x] and that task01
    -  here’s a regular line
        - [ ] one last task
            - [ ] c3
                - [ ] c4
                    - [ ] c5
                        - [ ] c6
        - [x] one last task01 




  • filename : dic_19820407
---
Date: 1982-04-07
---
#Project/P04

## input
>CASE S2=>
>case_FLST_TwithOL-T : A root task item which is not fullyCompleted contains an outlink like  [[[Note P]] and a sub task item.
>
>FLST    : Use file.lists
>L           : an element of file.lists
>OL        : L.outlinks
>FLST_L : A root list item L
>FLST_T : A root task item T
>-T          : A sub task item T

### main tasks : CASE S2
- [ ] also remember to do this task for [[Note P]]
    - some more text with no task
    - [x] but a peer that is a task01
    - [ ] but a peer that is a task
        - [ ] and a child with another task
        - [x] and a child with another task01




  • filename : dic_19820412
---
Date: 1982-04-12
---
#Project/P04

## input
>CASE S3  =>
>case_FLST_LwithoutOL-T-TwithOL : A root list item doesn't contain an outlink and the last subtask item which is not fullyCompleted contains an outlink like  [[[Note P]].
>
>FLST    : Use file.lists
>L           : an element of file.lists
>OL        : L.outlinks
>FLST_L : A root list item L
>FLST_T : A root task item T
>-T          : A sub task item T

### some tasks : CASE S3
- last list of things to do remember to do this task
    - [ ] the only task I wouldn’t want to return because it doesn’t link to my test file
        - [ ] this is the actual last task [[Note P]]




  • filename : dic_19820417
---
Date: 1982-04-17
---
#Project/P04

## input
>CASE S4 =>
>case_FLST_TwithoutOL-T-TwithOL A root task item doesn't contain an outlink and the last subtask item which is not fullyCompleted contains an outlink like  [[[Note P]].
>
>FLST    : Use file.lists
>L           : an element of file.lists
>OL        : L.outlinks
>FLST_L : A root list item L
>FLST_T : A root task item T
>-T          : A sub task item T

### some tasks : CASE S4
- [ ] last list of things to do remember to do this task
    - [ ] the only task I wouldn’t want to return because it doesn’t link to my test file
      - [ ] this is the actual last task [[Note P]]




folder: 05_supported_not_fullyCompleted

Summary_05
  • filename : dic_19820522
---
Date: 1982-05-22
---
#Project/P05

## input
>CASE S5 =>
>case_FLST_LwithoutOL-TwithoutOL-TwithoutOL :  A root list item which contains an uncompleted subtask item doesn't contain an outlink and any sub task item doesn't contain an outlink.
>
>FLST    : Use file.lists
>L           : an element of file.lists
>OL        : L.outlinks
>FLST_L : A root list item L
>FLST_T : A root task item T
>-T          : A sub task item T

### other tasks:  CASE S5
- 1.==This should be shown== 
	- 1.1 This should be hidden
	- [x] 1.2 This should be hidden
	- [ ] 1.3 ==This should be shown==
		- 1.3.1 This should be hidden
		- [x] 1.3.2 Completed and not fullyCompleted ==This should be shown, as it contains uncompleted sub-tasks==
			- 1.3.2.1 This should be hidden
			- [ ] 1.3.2.2 ==This should be shown==
			- [x] 1.3.2.3 This should be hidden
		- [ ] 1.3.3 ==This should be shown==
		- 1.4 ==This should be shown, as it contains uncompleted sub-tasks==
			- 1.4.1 This should be hidden
			- [ ] 1.4.2 ==This should be shown==
			- [x] 1.4.3 This should be hidden




  • filename : dic_19820527
---
Date: 1982-05-27
---
#Project/P05

## input
>CASE S6 =>
>case_FLST_TwithoutOL-TwithoutOL-TwithoutOL :  A root task item which is not fullyCompleted doesn't contain an outlink and any sub task item doesn't contain an outlink.
>
>FLST    : Use file.lists
>L           : an element of file.lists
>OL        : L.outlinks
>FLST_L : A root list item L
>FLST_T : A root task item T
>-T          : A sub task item T

### other tasks:  CASE S6
- [ ] 1.==This should be shown== 
	- 1.1 This should be hidden
	- [x] 1.2 This should be hidden
	- [ ] 1.3 ==This should be shown==
		- 1.3.1 This should be hidden
		- [x] 1.3.2 Completed and not fullyCompleted ==This should be shown, as it contains uncompleted sub-tasks==
			- 1.3.2.1 This should be hidden
			- [ ] 1.3.2.2 ==This should be shown==
			- [x] 1.3.2.3 This should be hidden
		- [ ] 1.3.3 ==This should be shown==
		- 1.4 ==This should be shown, as it contains uncompleted sub-tasks==
			- 1.4.1 This should be hidden
			- [ ] 1.4.2 ==This should be shown==
			- [x] 1.4.3 This should be hidden




folder: 08_excluded_case

Summary_08
  • filename : dic_19820802
---
Date: 1982-08-02
---
#Project/P08

## input
### main tasks : CASE S1
- [[My Test File]] links to a project
    - [ ] do this task
    - [ ] and that task
    - [x] and that task01
    -  here’s a regular line
        - [ ] one last task
            - [ ] c3
                - [ ] c4
                    - [ ] c5
                        - [ ] c6
        - [x] one last task01




  • filename : dic_19820807
---
Date: 1982-08-07
---
#Project/P08

## input
### main tasks : CASE S2
- [ ] also remember to do this task for [[My Test File]]
    - some more text with no task
    - [x] but a peer that is a task01
    - [ ] but a peer that is a task
        - [ ] and a child with another task
        - [x] and a child with another task01




  • filename : dic_19820812
---
Date: 1982-08-12
---
#Project/P08

## input
### some tasks : CASE S3
- last list of things to do remember to do this task
    - [ ] the only task I wouldn’t want to return because it doesn’t link to my test file
      - [ ] this is the actual last task [[My Test File]]




  • filename : dic_19820817
---
Date: 1982-08-17
---
#Project/P08

## input
### some tasks : CASE S4
- [ ] last list of things to do remember to do this task
    - [ ] the only task I wouldn’t want to return because it doesn’t link to my test file
      - [ ] this is the actual last task [[My Test File]]




DVJS10_use_fLists_hide_fullyCompleted_subTasks_and_display_uncompleted_tasks: For CASE S1 to S6

Summary

Main DVJS

Code Name Data type Group By Purposes Remark
DVJS10
_use_fLists
_hide
_fullyCompleted_subTasks
_and
_display
_uncompleted_tasks
file.lists:
a list item or
a task item
with L.outlinks or not
yes 1.To hide fullyCompleted sub-tasks
2.To show uncompleted sub-tasks under list items and completed (sub)-tasks
3.To show items that contain a specific outlink
4.To display the result by using dv.taskList [with the original structure]
1.The DVJS10 is based on the DVJS10 in the following topic.
- Solutions: by Justdoitcc

2.Recursive Functions:
2.1 taskAny
2.2 hide_fullyCompleted_subTasks
2.3 designed by Developers:
2.3.1 jqhoogland@GiHub
2.3.2 wenlzhang@GiHub

Notes

Summary_notes

Q1: How to get the page information from the current note?

Original example
```dataviewjs
// M11. define pages: gather all relevant pages
// #####################################################################
// let pages = dv.current();
let pages = dv
    .pages('"100_Project/01_dataviewjs/01_by_example/Q23_Mentions/Q23_test_data" and #Project')
    .where((page) => dv.func.contains(page.file.name, "dic_"));
```

A1:

```dataviewjs
// M11. define pages: gather all relevant pages
// #####################################################################
let pages = dv.current();
// let pages = dv
//     .pages('"100_Project/01_dataviewjs/01_by_example/Q23_Mentions/Q23_test_data" and #Project')
//     .where((page) => dv.func.contains(page.file.name, "dic_"));
```

Q2: How to get the filename of the current note?

Original example
```dataviewjs
// M09. define PARTIAL_FILENAME_OF_LINK: 
// #####################################################################
// get the filename of the current note
// const PARTIAL_FILENAME_OF_LINK = dv.current().file.name;
const PARTIAL_FILENAME_OF_LINK = "Note P";
```

A2:

```dataviewjs
// M09. define PARTIAL_FILENAME_OF_LINK: 
// #####################################################################
// get the filename of the current note
const PARTIAL_FILENAME_OF_LINK = dv.current().file.name;
// const PARTIAL_FILENAME_OF_LINK = "Note P";
```

code DVJS10_use_fLists_hide_fullyCompleted_subTasks_and_display_uncompleted_tasks: For CASE S1 to S6

Summary_code
title: DVJS10_use_fLists_hide_fullyCompleted_subTasks_and_display_uncompleted_tasks => 1.To hide fullyCompleted sub-tasks 2.To show uncompleted sub-tasks under list items and completed (sub)-tasks 3.To show items that contain a specific outlink 4.To display the result by using `dv.taskList` [with the original structure]
collapse: close
icon: 
color: 
```dataviewjs
// M01. define b_SHOW_ANY_LIST_ITEMS: 
// false: To hide any list items (default)
// true : To show any list items 
// Q: What do list items mean?
// A1: list items with no children
// A2: list items with sublist items that have no children
// A3: list items with children that contain fullyCompleted tasks in any generation
// A4: list items with sublist items whose children contain fullyCompleted tasks in any generation
// #####################################################################
// let b_SHOW_ANY_LIST_ITEMS = false;


// M09. define PARTIAL_FILENAME_OF_LINK: 
// #####################################################################
// get the filename of the current note
// const PARTIAL_FILENAME_OF_LINK = dv.current().file.name;
const PARTIAL_FILENAME_OF_LINK = "Note P";


// M11. define pages: gather all relevant pages
// #####################################################################
// let pages = dv.current();
let pages = dv
    .pages('"100_Project/01_dataviewjs/01_by_example/Q23_Mentions/Q23_test_data" and #Project')
    .where((page) => dv.func.contains(page.file.name, "dic_")); 


// M21. define Recursive Function:To expand search to children
// #####################################################################
const taskAny = function taskAny(t, f) {
    if (f(t)) {
        return true;
    }
    for (let sub of t.children) {
        if (taskAny(sub, f)) {
            return true;
        }
    }
    return false;
};


// M25. define Recursive Function:To gather un-fullyCompleted children
// (1.To hide a fullyCompleted subtask item 2.Not to hide a root item)
// FLATTEN_CASE_10A:To gather an un-fullyCompleted task item that 
//                  doesn't contain an outlink
// 
// FLATTEN_CASE_10B:To gather an un-fullyCompleted task item that
//                  contains a specific outlink
//
//                  (CASE S3 or S4: For example
//                    1.To gather the last un-fullyCompleted subtask  
//                    item which contains an outlink like [[[Note P]]
//                    in the [[dic_19820412]] or [[dic_19820417]]
// 
//                    2.To exclude the last un-fullyCompleted subtask
//                    item which contains an outlink like [[[My Test File]]
//                    in the [[dic_19820812]] and [[dic_19820817]]
//                   )
// #####################################################################
// dv.span(hide_fullyCompleted_subTasks(root_tasks_or_lists.text));
const hide_fullyCompleted_subTasks = (t) => ({
    ...t,
    children: t.children
        .filter((st) =>
            taskAny(
                st,
                (st) =>
                    (st.task &&
                        !st.fullyCompleted &&
                        st.outlinks.length === 0) ||
                    (st.task &&
                        !st.fullyCompleted &&
                        dv.func.contains(
                            st.outlinks.map((hLink) =>
                                hLink.path.replace("^(.*/)(.+)(.md)$", "$2")
                            ),
                            PARTIAL_FILENAME_OF_LINK
                        ))
            )
        )
        .map(hide_fullyCompleted_subTasks),
});



// M31. define root_tasks_or_lists : gather a root item
// WHERE_CASE_11 :To gather a root list item or a root task item
// (comments)WHERE_CASE_12A:To gather a root task item which is not fullyCompleted
// (comments)WHERE_CASE_12B:To gather a root list item which contains a subtask
// (comments)               item that is not fullyCompleted
// (comments)               (CASE S1 or S3 or S5: To gather
// (comments)                [[dic_19820402]] or [[dic_19820412]] or [[dic_19820522]])
// WHERE_CASE_13A:To gather a root task item which is not fullyCompleted and
//                doesn't contain an outlink
//                (CASE S4 or S6:To gather [[dic_19820417]] or [[dic_19820527]])
// WHERE_CASE_13B:To gather a root task item which is not fullyCompleted and 
//                contains a specific outlink
//                (CASE S2:To gather [[dic_19820407]] and exclude [[dic_19820807]])
// WHERE_CASE_13C:To gather a root list item which contains an un-fullyCompleted
//                subtask item and doesn't contain a specific outlink
//                (CASE S3 or S5:To gather [[dic_19820412]] or [[dic_19820522]])
// WHERE_CASE_13D:To gather a root list item which contains an un-fullyCompleted
//                subtask item and contains a specific outlink
//                (CASE S1:To gather [[dic_19820402]] and exclude [[dic_19820802]])
// #####################################################################
let root_tasks_or_lists = pages.file.lists
    .where((L) => !L.parent)
    // .where(
    //     (L) =>
    //         (L.task && !L.fullyCompleted) ||
    //         (!L.task &&
    //             L.children.length > 0 &&
    //             L.children.filter((c) => c.task && !c.fullyCompleted))                
    // );
    .where(
        (L) =>
            (L.task && !L.fullyCompleted && L.outlinks.length === 0) ||
            (L.task &&
                !L.fullyCompleted &&
                dv.func.contains(
                    L.outlinks.map((hLink) =>
                        hLink.path.replace("^(.*/)(.+)(.md)$", "$2")
                    ),
                    PARTIAL_FILENAME_OF_LINK
                )) ||
            (!L.task &&
                L.children.length > 0 &&
                L.children.filter((c) => c.task && !c.fullyCompleted) &&
                L.outlinks.length === 0) ||
            (!L.task &&
                L.children.length > 0 &&
                L.children.filter((c) => c.task && !c.fullyCompleted) &&
                dv.func.contains(
                    L.outlinks.map((hLink) =>
                        hLink.path.replace("^(.*/)(.+)(.md)$", "$2")
                    ),
                    PARTIAL_FILENAME_OF_LINK
                ))
    );

    

// M33. Hide completed Subtasks:
// #####################################################################
root_tasks_or_lists.values = root_tasks_or_lists.values.map(
    hide_fullyCompleted_subTasks
);


// M81. deal with root_tasks_or_lists: 
// To groupBy t.path
// To sort in ascending order
// #####################################################################
// t.path   : "100_Project/02_dataview/Q12_Tasks/Q12_test_data02/08/dic_20110801.md"
// group.key: "100_Project/02_dataview/Q12_Tasks/Q12_test_data02/08/dic_20110801.md"
root_tasks_or_lists = root_tasks_or_lists
    .groupBy((t) => t.path)
    .sort((group) => group.key, "asc");


// M83. output root_tasks_or_lists:
// #####################################################################
for (let group of root_tasks_or_lists) {

    
    // M83.FR13 define s_display_name:
    // #####################################################################     
    let s_file_name = dv.page(group.key).file.name;
    let s_display_name = s_file_name + ": ";
    
    
    // M83.FR15 define s_link:  \[[alphabet#a|pqr]\]  //=>pqr
    // ##################################################################### 
    // let s_link =  "[[" + group.key + "#" + Heading + "|" + s_display_name + "]]";//=>pqr
    let s_link =  "[[" + group.key + "|" + s_display_name + "]]";
    
    
    // M83.FR21 output s_link: \[[08/dic_20110801.md|dic_20110301: 7 uncompleted]\]
    // ##################################################################### 
    dv.header(3, s_link);
    
    
    // M83.FR31 output group.rows:
    // ##################################################################### 
    dv.taskList(group.rows, false);
}


```

Screenshots(DVJS10_A)

const PARTIAL_FILENAME_OF_LINK = “Note P”;
Summary_A
Part1/5 : “Note P”

Part2/5 : “Note P” (The screenshot should be hidden.)

Part3/5 : “Note P”

Part4/5 : “Note P”

Part5/5 : “Note P”


Screenshots(DVJS10_B)

const PARTIAL_FILENAME_OF_LINK = “Note Q”;
Summary_B
Part1/5 : “Note Q”

Part2/5 : “Note Q” (The screenshot should be hidden.)

Part3/5 : “Note Q”

Part4/5 : “Note Q”

Part5/5 : “Note Q”


Reference

Summary

1 Like

Wow @justdoitcc, this is a Herculean effort. Thank you for sharing. Looking through the git history, there have been tremendous improvements in the readability of the dataview docs since I posted this. (–or I just missed it : P )

Anyways, I’m sharing the below Javascript snippet for those who come across this to help with the above issue. Some portions are directly inspired from your work as well, @justdoitcc, so thank you!

Note: throw backticks and the dataviewjs label on the below code

/* Intelligently collect tasks using dataview

This dataview collects all tasks from pages specified by a query. It renders
all tasks that have any un-completed subtasks.

Author: Adithya Balaji (https://www.adithyabalaji.com/about)

*/

// The base tag to search for
const LINK_TAG = '[[anki inbox]]';
// The base filter query to use to collect pages. Use an empty string to collect
// all pages. See the linked docs to learn what are valid querys
// https://blacksmithgu.github.io/obsidian-dataview/api/code-reference/#dvpagessource
const PAGE_FILTER_QUERY = LINK_TAG;
const GROUP_HEADER_LEVEL = 3

/**
 * [cleanTasks Remove non tasks (bare list items) and completed tasks]
 */
function cleanTasks(taskRoot) {
    // all cases where we want to filter out the task immediately
    if (!taskRoot.task || taskRoot.fullyCompleted) {
        return false
    // the case where it's a task that may contain children, 
    } else if (taskRoot.children) {
        taskRoot.children = taskRoot.children.filter(cleanTasks);
        return !!taskRoot.children;
    // the case where it's a singular task remaining
    } else {
        return taskRoot.completed
    }
}

// Filter the initial search space of pages to only pages that even include the `LINK_TAG`
let pages = dv.pages(PAGE_FILTER_QUERY);
// Collect the list of root tasks that contain the specified link tag
let rootLists = pages.file.lists.where(listItem => listItem.text.includes(LINK_TAG));
let rootTasks = (
    rootLists
    // Collect and flatten the list of tasks underneath root list items
    .flatMap(listItem => listItem.children)
    // Only collect tasks that are not fully completed and are actually tasks (includes sub tasks)
    .filter(cleanTasks)
    // Group the list of tasks by the page that they originate from
    .groupBy((taskItem) => taskItem.path)
    // Sort the page headers in ascending order (A-Z)
    .sort((group) => group.key, "asc")
);


for (let group of rootTasks) {
    // Create a header backlink with a display alias for the group of tasks
    let fileName = dv.page(group.key).file.name;
    let displayName = fileName + ": ";
    let displayLink =  "[[" + group.key + "|" + displayName + "]]";
    
    dv.header(GROUP_HEADER_LEVEL, displayLink);
    dv.taskList(group.rows, false);
}
1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.