DataviewJS help—having trouble matching key values that are also links

Hi all, hoping you can help me get over the finish line.

What I’m trying to do

I’m trying to write a query that sorts the files in #project by most recently edited, but I want that to include the mtime of any page that has that project as a parent. So I want projects ordered by what I most recently worked on, including subpages.

I’m mostly there—the problem is that I don’t know how to match with values that are also links.

So for frontmatter that looks like this:

And for the body, that looks like this:

And for the body, that looks like this:

Things I have tried

let update = dv.pages()
		.where(p => 
		p.parent === project.file.name || 
		p.file.name === project.file.name || 
                dv.array(p.parent)[0] === project.file.name)

Any ideas? Full codeblock below.

let projects = dv.pages("#project and -#project/todos and -#archival")
	.where(p => !p.file.folder.includes("Dailies") & !p.file.folder.includes("Inbox"));
	
let stack = [];
	
	
for (let project of projects) {

		let update = dv.pages()
		.where(p => 
		p.parent === project.file.name || 
		p.file.name === project.file.name || dv.array(p.parent)[0] === project.file.name)
		.sort(p => p.file.mtime, 'desc')[0]
		.file.mtime; 
			
			let pair = [project.file.link, update];
		
		
		stack.push(pair);	// so now I've added the file and the corresponding mtime to the stack.
		
	} // leaving this loop, stack is a 2D array of ordered pairs. Each pair has a file link, and an mtime that corresponds to a subproject. Now I want to sort by that mtime.

		

	dv.table(["Project","Modified"],
	dv.array(stack)
		.sort(p => p[1], 'desc').slice(0,10)
		);
		

I understood most of what you posted (thank you for the pictures and details!) but unfortunately I do not quite understand what your goal is for the part you are stuck on. Can you write out in words for the specific example pictures you showed us what you want to filter for? Is it that you want to find every file with the parent field [[test Project]]? Or …?

Also I would definitely try it first on the non-YAML version of parent since YAML does weird things with links.

Topic

Summary

1.How to get the unique links from each page.parent?
2.How to create a_pages_from_links?


Input

Summary

dictionary files

sons

  • location: “100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_sons”
A04
  • filename : dic_20130401
---
date created: 2013-04-01T19:30:50.000Z
date updated: 2013-04-11 19:30:50
aliases: []
parent: "[[ProjectI]]"
tags:
    - project/p1
---

  • filename : dic_20130406
---
date created: 2013-04-06T19:30:50.000Z
date updated: 2013-04-16 19:30:50
aliases: []
parent: ["[[ProjectN]]", "[[ProjectK]]"]
tags:
    - project/p6
---

F02
  • filename : dic_20130201
---
date created: 2013-02-01T19:30:50.000Z
date updated: 2013-02-11 19:30:50
aliases: []

tags:
    - project/p1
---

parent:: [[ProjectD]]

  • filename : dic_20130206
---
date created: 2013-02-06T19:30:50.000Z
date updated: 2013-02-06 19:30:50
aliases: []

tags:
    - project/p6
---

parent:: [[ProjectR]], [[ProjectD]]

R03_excluding
  • filename : dic_20130301
---
date created: 2013-03-01T19:30:50.000Z
date updated: 2013-03-11 19:30:50
aliases: []
tags:
    - JOTnote/j1
---

parent:: [[ProjectN_J1]]

  • filename : dic_20130306
---
date created: 2013-03-06T19:30:50.000Z
date updated: 2013-03-16 19:30:50
aliases: []
tags:
    - JOTnote/j6
---

parent:: [[ProjectN_J6]]

Y05_excluding
  • filename : dic_20130501
---
date created: 2013-05-01T19:30:50.000Z
date updated: 2013-05-11 19:30:50
aliases: []
tags:
    - JOTnote/j1
---

parent:: [[ProjectK_J1]]

  • filename : dic_20130506
---
date created: 2013-05-06T19:30:50.000Z
date updated: 2013-05-16 19:30:50
aliases: []
tags:
    - JOTnote/j6
---

parent:: [[ProjectK_J6]]

Z06
  • filename : dic_20130601
---
date created: 2013-06-01T19:30:50.000Z
date updated: 2013-06-11 19:30:50
aliases: []
parent: "[[ProjectK]]"
tags:
    - project/p1
---

parents

  • location: “100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_parents”
P01
  • filename : ProjectD
  • ctime: 2013-02-01T19:30:50
  • mtime: ctime + dv.func.duration(10 days)
---
date: 2013-02-01
name: ProjectD
---
#project/p01

P02
  • filename : ProjectR
  • ctime: 2013-02-06T19:30:50
  • mtime: ctime + dv.func.duration(10 days)
---
date: 2013-02-06
name: ProjectR
---
#project/p02

P03
  • filename : ProjectI
  • ctime: 2013-04-01T19:30:50
  • mtime: ctime + dv.func.duration(10 days)
---
date: 2013-04-01
name: ProjectI
---
#project/p03

P04
  • filename : ProjectN
  • ctime: 2013-04-06T19:30:50
  • mtime: ctime + dv.func.duration(10 days)
---
date: 2013-04-06
name: ProjectN
---
#project/p04

P05
  • filename : ProjectK
  • ctime: 2013-06-01T19:30:50
  • mtime: ctime + dv.func.duration(10 days)
---
date: 2013-06-01
name: ProjectK
---
#project/p05

P06
  • filename : ProjectS
  • ctime: 2013-07-01T19:30:50
  • mtime: ctime + dv.func.duration(10 days)
---
date: 2013-07-01
name: ProjectS
---
#project/p06


DVJS10_output_a_parents_and_a_sons:

Summary

Main DVJS

Code Name data type Purposes Remark
DVJS10_output_a_parents_and_a_sons non-lists or lists 1.get a_parents: Project[DRINKS]

2.get a_sons

3.output a_parents

4.output a_sons
(unique son_of_project.parent = links of Project[DRINK])

Code DVJS10_output_a_parents_and_a_sons

Summary_code
title: DVJS10_output_a_parents_and_a_sons =>1.get a_parents: Project[DRINKS] 2.get a_sons 3.output a_parents 4.output a_sons (unique son_of_project.parent = links of Project[DRINK])
collapse: close
icon: 
color: 
```dataviewjs
// M21. define a_parents: Project[DRINKS]
// #####################################################################
let a_parents = dv
    .pages(
        '"100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_parents"'
    )
    .where((page) => dv.func.contains(page.file.name, "Project") )
    .where(
        (page) =>
            dv.func.contains(page.file.tags, "#project") &&
            !dv.func.contains(page.file.tags, "#project/todos") &&
            !dv.func.contains(page.file.tags, "#archival")
    )
    .where(
        (p) =>
            !p.file.folder.includes("Dailies") &&
            !p.file.folder.includes("Inbox")
    );



// M31. define a_sons: 
// dic_20130201, [[dic_20130201]].parent = [[ProjectD]]
// #####################################################################
let a_sons = dv
    .pages(
        '"100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_sons"'
    )
    .where(
        (page) =>
            dv.func.contains(page.file.name, "dic")
    )
    .where(
        (page) =>
            dv.func.contains(page.file.tags, "#project") &&
            !dv.func.contains(page.file.tags, "#project/todos") &&
            !dv.func.contains(page.file.tags, "#archival")
    );
    
// M81. Output a_parents:
// #####################################################################
dv.header(5, "M81.Print a table of the `a_parents`");
dv.table(
    ["N", "Project", "file.tags"],
    a_parents.map((project, index) => [
        index + 1,
        project.file.name,
        project.file.tags,    
    ])
);



// M91. Output a_sons: unique son_of_project.parent = Project[DRINK]
// #####################################################################
dv.header(5, "M91.Print a table of the `a_sons`");
dv.table(
    ["N", "son_of_project", "tags", "parent", "file.tags"],
    a_sons.map((son_of_project, index) => [
        index + 1,
        son_of_project.file.name,
        son_of_project.tags,    
        son_of_project.parent,
        
        son_of_project.file.tags,
    ])
);

```

Screenshots(DVJS10)


DVJS20_output_filelink_and_mtime_of_a_unique_son_of_links :

Summary

Main DVJS

Code Name data type Purposes Remark
DVJS20_output_filelink_and_mtime
_of_a_unique_son_of_links
non-lists or lists 1.get a_unique_son_of_links

2.create a_pages_from_links

3.output each page.file.link and page.file.mtime
The code is refactered.

Code DVJS20_output_filelink_and_mtime_of_a_unique_son_of_links

Summary_code
title: DVJS20_output_filelink_and_mtime_of_a_unique_son_of_links =>1.get a_unique_son_of_links 2.create a_pages_from_links 3.output each page.file.link and page.file.mtime
collapse: close
icon: 
color: 
```dataviewjs
// M11. define i_max_amount_of_md_files: 
// #####################################################################
let i_max_amount_of_md_files = 20;


// M31. define a_sons: 
// #####################################################################
let a_sons = dv
    .pages(
        '"100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_sons"'
    )
    .where(
        (page) =>
            dv.func.contains(page.file.name, "dic")
    )
    .where(
        (page) =>
            dv.func.contains(page.file.tags, "#project") &&
            !dv.func.contains(page.file.tags, "#project/todos") &&
            !dv.func.contains(page.file.tags, "#archival")
    );

// M41. get a_unique_son_of_links: js array
// #####################################################################
let a_unique_son_of_links = a_sons
    .map((e) => e.parent)
    .array()  //=>Data Arrays to js array
    .flat()   //=>flatten
    .filter((e) => !(this[e] = e in this)); //=>get unique e



//dv.list(a_unique_son_of_links);
//=>
// [[ProjectD]]
// [[ProjectR]]
// [[ProjectI]]
// [[ProjectN]]
// [[ProjectK]]


// M43. create a_pages_from_links from a_unique_son_of_links:
// dic_20130201, [[dic_20130201]].parent = [[ProjectD]]
// #####################################################################
// CASE 1: When the file does not exist : 
// [[wikiLinkNotExist]]=>Hash(Link).path:wikiLinkNotExist
// CASE 2: When the file exists: 
// [[wikiLinkExist]]=>Hash(Link).path:100_Project/wikiLinkExist.md
let a_pages_from_links = a_unique_son_of_links.map(
    (hLink) =>
        dv.func.endswith(hLink.path, ".md") && dv.page(hLink.path)
);


// M45.a_pages_from_links : 1.js array to Data Arrays 2.sort 3.limit
// #####################################################################
a_pages_from_links = dv
    .array(a_pages_from_links)
    .sort((page) => page.file.mtime, "asc")
    .limit(i_max_amount_of_md_files);


// M71. Output a_pages_from_links: page.file.link and page.file.mtime
// #####################################################################
dv.header(5, "M71.Print a table of the `a_pages_from_links`");
dv.table(
    ["N", "File", "Mtime"],
    a_pages_from_links        
        .map((page, index) => [
            index + 1,
            page.file.link,
            page.file.mtime.toFormat("yyyy-MM-dd HH:mm:ss"),
        ])

);


```

Screenshots(DVJS20)


Reference

Summary

Hey thanks! Happy to clarify.

Yes, you’ve identified my goal correctly: to find every page that has [[Test Project]] as its parent. (‘Test Project’ is a stand-in for any given project; that’s why my queries )

Ultimately, I use a for-loop to find the children of every project; in that sense, [[Test Project]] is just one project in projects.

So, in the pictures, I’ve got a non-YAML inline link, and a YAML link. The code I’ve written doesn’t recognize either of those, but it does pick up inlined and YAML ‘parent’ fields that aren’t links.

Got it. Dataview has some sense of data types, so when parent is a link you’ll want to either “index through it” to get to the name of the parent file with p.parent.file.name or compare it to something else that is a link p.parent === project.file.link. See if one of these works?
Also check out justdoitcc 's answer above - I always learn things from those!

So, checking against project.file.link didn’t help, but I think I solved this portion of my problem. I’ll admit to finding justdoitcc’s answer a little difficult to crawl through, but there was definitely some helpful stuff in there. Unfortunately, there’s a new problem that I’ve tried to document as thoroughly as I could.

In some files, p.parentis undefined or null. That was fine in my queries that were just p.parent === ... but created problems for querying p.parent.path or dv.file(p.parent.path).file.name because you can’t read the .path property of an undefined.

So I added some checks for undefined, and it worked in a test context, but unexpectedly broke my original code.

The plan was to add something like this:

.where(p => typeof(p.parent) !== 'undefined' && p.parent !== null)

so that my query could safely include this:

.where(...
(typeof(p.parent.path) !== 'undefined' && typeof(dv.page(p.parent.path)) !== 'undefined' &&
dv.page(p.parent.path).file.name == project.file.name))

and that was going to work.

But for some reason, when I added the filter for undefined and null, it broke my original code. I’ve managed to figure out what it doesn’t like, but I can’t tell what the problem is.

Somehow, just the addition of the extra filter made something else undefined, in a way that makes me feel crazy.

Here’s the original code:


let projects = dv.pages("#project and -#project/todos and -#archival")
	.where(p => !p.file.folder.includes("Dailies") & !p.file.folder.includes("Inbox"));
	
let stack = [];
	
	
for (let project of projects) {

		let update = dv.array(dv.pages()
		.where(p => 
		p.parent === project.file.name || 
		p.file.name === project.file.name || dv.array(p.parent).includes(project.file.name)
		)
		.sort(p => p.file.mtime, 'desc')[0].file.mtime)
		; 
			
			let pair = [project.file.link, update];
		
		
		stack.push(pair);	// so now I've added the file and the corresponding mtime to the stack.
		
	} 

	dv.table(["Project","Modified"],
	dv.array(stack)
		.sort(p => p[1], 'desc').slice(0,10)
		);

and here it is with the problems that were created:


let projects = dv.pages("#project and -#project/todos and -#archival")
	.where(p => !p.file.folder.includes("Dailies") & !p.file.folder.includes("Inbox"));
	
let stack = [];
	
	
for (let project of projects) {

		let update = dv.array(dv.pages()
		// here's the new where clause
//########################
		.where(p => typeof(p.parent) !== 'undefined' && p.parent !== null)
//########################
		.where(p => 
		p.parent === project.file.name || 
		p.file.name === project.file.name || dv.array(p.parent).includes(project.file.name)
		)
		.sort(p => p.file.mtime, 'desc')[0]
		// I've discovered that the following .file is what it doesn't like! It says that it's reading an undefined. But how did things become undefined by my adding a filter to exclude those things?
	//###########
		.file.mtime)
		//##############
		; 
			
			let pair = [project.file.link, update];
		
		
		stack.push(pair);	// so now I've added the file and the corresponding mtime to the stack.
		
	} 

	dv.table(["Project","Modified"],
	dv.array(stack)
		.sort(p => p[1], 'desc').slice(0,10)
		);
1 Like

Topic

Summary

1.How to check if the result of an expression is defined?


Input

Summary

The same : Solutions_01



DVJS10_fix_tommygents_original_code:

Summary

Main DVJS

Code Name data type Purposes Remark
DVJS10_fix_tommygents_original_code page.parent: a link or a list of links 1.get a_parents: Project[DRINKS]

2.get pages_from_sons_or_parents : the files which paths are those of sons or parents

3.get update: the newest Project mtime from pages_from_sons_or_parents

4.push [file.link, update] into stack

5.output stack
1.The code will not be broken by the undefined filter.

2.The time complexity of the code is O(n²).

Notes

dv.array

  • The dv.array() transforms JS arrays into Data Arrays.
  • The dv.array() in the dv.array(dv.pages()) is not necessary because dv.pages() returns Data Arrays.

Step M41

  • Step M41_DEB20 presents the purpose of Step M41.
  • Step M41_UP30 checks the existence of pages_from_sons_or_parents. As a result, the code will not crash when it does not exist.
Time complexity
  • Suppose that a_parents.length is 10000 and a_sons is 12000.
  • Step M41 runs 10000*(10000+12000) times for you in order to get the result.
  • The time complexity of the code is O(n²).
  • Can it be refactored as the code where the time complexity is O(n)?

Code DVJS10_fix_tommygents_original_code

Summary_code
title: DVJS10_fix_tommygents_original_code =>1.get a_parents: Project[DRINKS] 2.get pages_from_sons_or_parents : the files which paths are those of sons or parents 3.get update: the newest Project mtime from pages_from_sons_or_parents 4.push [file.link, update] into stack 5.output stack
collapse: close
icon: 
color: 
```dataviewjs
// M21. define a_parents: Project[DRINKS]
// #####################################################################
let a_parents = dv
    .pages(
        '"100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_parents"'
    )
    .where((page) => dv.func.contains(page.file.name, "Project") )
    .where(
        (page) =>
            dv.func.contains(page.file.tags, "#project") &&
            !dv.func.contains(page.file.tags, "#project/todos") &&
            !dv.func.contains(page.file.tags, "#archival")
    )
    .where(
        (page) =>
            !page.file.folder.includes("Dailies") &&
            !page.file.folder.includes("Inbox")
    );


// M33. define pages_from_sons_or_parents: 
// the files which paths are those of sons or parents
// #####################################################################
let pages_from_sons_or_parents = dv.pages(
    '"100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_sons" OR "100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_parents"'
);


// M40. define stack: AoA = array of arrays
// #####################################################################
let stack = [];
 

// M41. get stack: an element of AoA = [file.link, update]
// #####################################################################
for (let project of a_parents) {
    // M41_PG10 filter by pages_from_sons_or_parents: 
    // ####################################################################
    pages_from_sons_or_parents = pages_from_sons_or_parents
        .where(
            (page) =>
                // M41_WH10.Edited by Justdoitc 2022-08-02 11:00
                // M41_WH10 is replaced with M41_WH30
                // ##############################################
                //p.parent === project.file.name ||
                // ##############################################

                page.file.name === project.file.name ||
                // M41_WH30.Edited by Justdoitc 2022-08-02 11:30
                // ##############################################
                // dv.array(p.parent).includes(project.file.name)
                // If p.parent is defined a "link", check if its file.name includes project.file.name
                (page.parent &&
                    dv.func.contains(
                        dv
                            .array(page.parent)
                            .filter((hLink) =>
                                dv.func.endswith(hLink.path, ".md")
                            )
                            .map((hLink) => dv.page(hLink.path).file.name),
                        project.file.name
                    ))
            // ##############################################
        );


    // M41_DEB20 debug print pages_from_sons_or_parents:  when project.file.name is "ProjectD"
    // ####################################################################
    if (project.file.name === "ProjectD") {
        dv.header(5, "M41_DEB20. The `ProjectD` and each of its `mtime`s");
        dv.table(
            ["N", "project", "mtime", "tags", "parent"],
            pages_from_sons_or_parents
                .map((page, index) => [
                    index + 1,
                    page.file.name,
                    page.file.mtime,
                    page.tags,
                    page.parent,
                ])
        );
    }


    // M41_UP30 define update and pair=>the pair array is pushed into the bottom of the stack array(AoA) :
    // check if pages_from_sons_or_parents is an empty array
    // update : the newest Project mtime from pages_from_sons_or_parents
    // ####################################################################
    let update = "";
    let pair = [];
    pages_from_sons_or_parents = pages_from_sons_or_parents.sort(
        (page) => page.file.mtime,
        "desc"
    );
    if (pages_from_sons_or_parents.length !== 0) {
        update = pages_from_sons_or_parents[0].file.mtime;
        pair = [project.file.link, update.toFormat("yyyy-MM-dd HH:mm:ss")];
        stack.push(pair);
    } else {
        // debug output : when update is an empty array
        dv.span(project.file.name);
        dv.span(" : ");
        dv.span("update is an empty array");
        dv.span(", ");
    }
} 


// M51. Output stack:
// #####################################################################
dv.header(5, "M51. print a table of the `stack`");
dv.table(
    ["Project", "Modified"],
    dv
        .array(stack)
        .sort((pair) => pair[1], "desc")
        .slice(0,10)

);


```

Screenshots(DVJS10)


1 Like

Hey, this worked!

I have no idea why sort(...)[0].file.mtime worked in my original code but was broken by the undefined filter, but sort(...).file.mtime.first() did not create the same TypeError.

Thanks for your help and nor notes, I agree with @scholarInTraining that there’s a lot to learn from here.

2 Likes

Topic

Summary

1.How to debug the original code?


Input

Summary

The same : Solutions_01


DVJS20_debug_tommygents_original_code_with_null_filter:

Summary

Main DVJS

Code Name data type Purposes Remark
DVJS20_debug_tommygents_original
_code_with_null_filter
page.parent: a link or a list of links 1.get a_parents: Project[DRINKS]

2.get pages_from_sons_or_parents : the files which paths are those of sons or parents

3.get update: the newest Project mtime from pages_from_sons_or_parents

4.push [file.link, update] into stack

5.output stack
1.The code will not be broken by the undefined filter.

2.The time complexity of the code is O(n²).

3.The code is copied from DVJS10_fix_tommygents_original_code.

4.The two where expressions such as M41_WH10 and M41_WH30 are copied from tommygents_original_code.

5.M41_WH10: Sons pass the filter and no parents pass the filter.

6.M41_WH30: No sons pass the filter.

7.The final pages_from_sons_or_parents is an empty array.

Notes

Summary_Notes

Step M41

  • Step M41_DEB20 presents the purpose of Step M41.
  • Step M41_UP30 checks the existence of pages_from_sons_or_parents. As a result, the code will not crash when it does not exist.

sort an array and get the first() of the result

//A: 
let update = pages.sort(page => page.file.mtime, 'desc')[0].file.mtime;

//B: 
let update = pages.sort(page => page.file.mtime, 'desc').first().file.mtime;  
//C:
let update = pages.sort(page => page.file.mtime, 'desc').file.mtime.first();
  • Program execution efficiency: A = B > C

Step M41_WH10

  • page is one of sons or parents.
  • page.parent of sons is a link or a list of links.
  • page.parent of parents is undefined.
pages_from_sons_or_parents = pages_from_sons_or_parents
        // M41_WH10.sons pass the filter and no parents pass the filter
        // ##################################################################
        .where((page) => typeof page.parent !== "undefined" && page.parent !== null)

  • Therefore, sons pass the filter and no parents pass the filter.

Step M41_WH30

  • page is one of sons.
  • page.parent of sons is a link or a list of links.
pages_from_sons_or_parents = pages_from_sons_or_parents
        // M41_WH30.(false || false || false) =>return false =>No sons pass the filter.
        // ##################################################################
        .where(
            (page) =>
                //=>false ([[link]] !== "string")
                page.parent === project.file.name ||
                //=>false (page is one of sons) PS.no parents pass the undefined/null filter
                page.file.name === project.file.name ||
                //=>false (a list of links contains "string"=>return false)
                dv.array(page.parent).includes(project.file.name)
        )

  • Therefore, no sons pass the filter.

Step M41_WH10 + M41_WH30

  • No parents pass the filter M41_WH10 and no sons pass the filter M41_WH30. As a result, the final pages_from_sons_or_parents is an empty array.

Code DVJS20_debug_tommygents_original_code_with_null_filter

Summary_code
title: DVJS20_debug_tommygents_original_code_with_null_filter =>1.get a_parents: Project[DRINKS] 2.get pages_from_sons_or_parents : the files which paths are those of sons or parents 3.get update: the newest Project mtime from pages_from_sons_or_parents 4.push [file.link, update] into stack 5.output stack R01.<u>M41_WH10: Sons pass the filter and no parents pass the filter.</u> R02.<u>M41_WH30: No sons pass the filter.</u> R03.<u>The final pages_from_sons_or_parents is an empty array.</u>
collapse: close
icon: 
color: 
```dataviewjs
// M21. define a_parents: Project[DRINKS]
// #####################################################################
let a_parents = dv
    .pages(
        '"100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_parents"'
    )
    .where((page) => dv.func.contains(page.file.name, "Project") )
    .where(
        (page) =>
            dv.func.contains(page.file.tags, "#project") &&
            !dv.func.contains(page.file.tags, "#project/todos") &&
            !dv.func.contains(page.file.tags, "#archival")
    )
    .where(
        (page) =>
            !page.file.folder.includes("Dailies") &&
            !page.file.folder.includes("Inbox")
    );


// M33. define pages_from_sons_or_parents: 
// the files which paths are those of sons or parents
// #####################################################################
let pages_from_sons_or_parents = dv.pages(
    '"100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_sons" OR "100_Project/01_dataviewjs/01_by_example/Q14_links/Q14_test_data_parents"'
);


// M40. define stack: AoA = array of arrays
// #####################################################################
let stack = [];


// M41. get stack: an element of AoA = [file.link, update]
// #####################################################################
for (let project of a_parents) {
    // M41_PG10 filter by pages_from_sons_or_parents:
    // ####################################################################
    pages_from_sons_or_parents = pages_from_sons_or_parents
        // M41_WH10.sons pass the filter and no parents pass the filter
        // ##################################################################
        .where(
            (page) => typeof page.parent !== "undefined" && page.parent !== null
        )
        // M41_WH30.(false || false || false) =>return false =>No sons pass the filter.
        // ##################################################################
        .where(
            (page) =>
                //=>false ([[link]] !== "string")
                page.parent === project.file.name ||
                //=>false (page is one of sons) PS.no parents pass the undefined/null filter
                page.file.name === project.file.name ||
                //=>false (a list of links contains "string"=>return false)
                dv.array(page.parent).includes(project.file.name)
        );

    // M41_DEB20 debug print pages_from_sons_or_parents:  when project.file.name is "ProjectD"
    // ####################################################################
    if (project.file.name === "ProjectD") {
        dv.header(5, "M41_DEB20. The `ProjectD` and each of its `mtime`s");
        dv.table(
            ["N", "project", "mtime", "tags", "parent"],
            pages_from_sons_or_parents.map((page, index) => [
                index + 1,
                page.file.name,
                page.file.mtime,
                page.tags,
                page.parent,
            ])
        );
    }

    // M41_UP30 define update and pair=>the pair array is pushed into the bottom of the stack array(AoA) :
    // check if pages_from_sons_or_parents is an empty array
    // update : the newest Project mtime from pages_from_sons_or_parents
    // ####################################################################
    let update = "";
    let pair = [];
    pages_from_sons_or_parents = pages_from_sons_or_parents.sort(
        (page) => page.file.mtime,
        "desc"
    );
    if (pages_from_sons_or_parents.length !== 0) {
        update = pages_from_sons_or_parents[0].file.mtime;
        pair = [project.file.link, update.toFormat("yyyy-MM-dd HH:mm:ss")];
        stack.push(pair);
    } else {
        // debug output : when update is an empty array
        dv.span(project.file.name);
        dv.span(" : ");
        dv.span("update is an empty array");
        dv.span(", ");
    }
}

// M51. Output stack:
// #####################################################################
dv.header(5, "M51. print a table of the `stack`");
dv.table(
    ["Project", "Modified"],
    dv
        .array(stack)
        .sort((pair) => pair[1], "desc")
        .slice(0,10)

);


```

Screenshots(DVJS20)


1 Like