DataviewJS Snippet Showcase

Topic

Summary
  • How to find the bug from the DVJS10_bug_Tasks_groupBy_r?
  • How to group the data by r which is a link like [[Project A]] or a string like “Test”?

Test

Summary
  • dataview: v0.5.46

Input

Summary

dictionary files

  • Location: “100_Project/01_dataviewjs/01_by_example/Q13_Tasks_groupBy/Q13_test_data”

folder: 02

  • filename : dic_20220206
---
Date: 2022-02-06
---
# Daily notes
- [ ] Task 1 [r:: [[Project A]] ] [due:: 2022-07-18]
- [ ] Task 2 [r:: [[Project A]] ] [due:: 2022-07-18]
- [ ] Task 3 [r:: [[Project B]] ] [due:: 2022-07-18]
- [ ] Task 4 [r:: Test] [due:: 2022-07-18]
- [ ] Task 5 [r:: Test] [due:: 2022-07-18]
- [ ] Task 6 [r:: Test123] [due:: 2022-07-18]
- [ ] Task 7 [r:: Test123] [due:: 2022-07-18]
- [ ] Task 8 [r:: Test456] [due:: 2022-07-18]
- [ ] Task 9 [r:: Test456] [due:: 2022-07-18]

DQL10_use_fTasks_and_get_uncompleted_and_overdue_tasks_and_groupBy_r

Summary

Main DQL

Code Name Data type Group By Purposes Remark
DQL10
_use_fTasks
_and_get
_uncompleted_and_overdue_tasks
_and_groupBy_r
flattened file.tasks yes 1.To filter by due
2.To filter by uncompleted task
3.To define a field variable TODAY_MINUS_DUE by using FLATTEN
4.To filter by TODAY_MINUS_DUE
5.To display the result as a TaskList
1.The DQL10 is the same as the DVJS40 in the topic.

Code DQL10_use_fTasks_and_get_uncompleted_and_overdue_tasks_and_groupBy_r

Summary_code
title: DQL10_use_fTasks_and_get_uncompleted_and_overdue_tasks_and_groupBy_r =>1.To filter by `due` 2.To filter by uncompleted task 3.To define a field variable `TODAY_MINUS_DUE` by using FLATTEN 4.To filter by `TODAY_MINUS_DUE` 5.To display the result as a TaskList
collapse: close
icon: 
color: 
```dataview
Task
FROM "100_Project/01_dataviewjs/01_by_example/Q13_Tasks_groupBy/Q13_test_data"

WHERE due
WHERE !completed

FLATTEN date("today") - due AS TODAY_MINUS_DUE
WHERE TODAY_MINUS_DUE <= dur("36500 days") AND TODAY_MINUS_DUE >= dur("0 days")

GROUP BY r
```

Screenshots(DQL10)


DVJS10_bug_Tasks_groupBy_r

Summary

Main DVJS

Code Name Data type Purposes Remark
DVJS10
_bug
_Tasks
_groupBy_r
t.r:
1.a string
2.a link
1.(BUG) A task including a Wikilink is not presented in the note.
2.The codes are refactored.
1.easier to read
2.easier to modify
Summary_code

Code DVJS10_bug_Tasks_groupBy_r

title: DVJS10_bug_Tasks_groupBy_r =>1.(BUG) A task including a Wikilink is not presented in the note. 2.The codes are refactored.
collapse: close
icon: 
color: 
```dataviewjs
// M09. Define n:
// #####################################################################
// let n = dv.date("2022-07-18");
let n = luxon.DateTime.now(); 


// M11. Define filtered_tasks: gather all relevant tasks
// #####################################################################
let filtered_tasks = dv
    .pages(
        '"100_Project/01_dataviewjs/01_by_example/Q13_Tasks_groupBy/Q13_test_data"'
    )
    .file.tasks.filter(
        (t) =>
            t.due && 
            Math.floor(n.diff(t.due, "days").days) == 0 && 
            !t.completed
    );


// M13. GROUP BY task.r:
// #####################################################################
for (let related of filtered_tasks.groupBy((t) => t.r)) {
    dv.header(2, related.key);
    dv.taskList(
        filtered_tasks.filter((t) => t.r == related.key),
        false
    );
}

```


Screenshots(DVJS10)

let n = dv.date(“2022-07-18”);


DVJS20_bug_Tasks_groupBy_r

Summary

Main DVJS

Code Name Data type Purposes Remark
DVJS20
_bug
_Tasks
_groupBy_r
t.r:
1.a string
2.a link
1.The original bug is fixed.
2.A new bug occurs.
3.The codes are refactored.
1.easier to read
2.easier to modify
Summary_code

Code DVJS20_bug_Tasks_groupBy_r

title: DVJS20_bug_Tasks_groupBy_r =>1.The original bug is fixed. 2.A new bug occurs. 3.The codes are refactored.
collapse: close
icon: 
color: 
```dataviewjs
// M09. Define n:
// #####################################################################
// let n = dv.date("2022-07-18");
let n = luxon.DateTime.now();


// M11. Define filtered_tasks: gather all relevant tasks
// #####################################################################
let filtered_tasks = dv
    .pages(
        '"100_Project/01_dataviewjs/01_by_example/Q13_Tasks_groupBy/Q13_test_data"'
    )
    .file.tasks.filter(
        (t) =>
            t.due && 
            Math.floor(n.diff(t.due, "days").days) == 0 && 
            !t.completed
    );


// M13. GROUP BY task.r:
// #####################################################################
for (let related of filtered_tasks.groupBy((t) => t.r)) {
    dv.header(2, related.key);
    dv.taskList(
        // Edited by Justdoitcc 2022-07-18
        //filtered_tasks.filter((t) => t.r == related.key),
        filtered_tasks.filter((t) => dv.func.contains(t.r, related.key)),
        false
    );
}

```


Screenshots(DVJS20)

let n = dv.date(“2022-07-18”);


DVJS30_Tasks_groupBy_r_typeof

Summary

Main DVJS

Code Name Data type Purposes Remark
DVJS30
_Tasks
_groupBy_r
_typeof
t.r:
1.a string
2.a link
1.The new bug is fixed.
2.The codes are refactored.
1.easier to read
2.easier to modify
Summary_code

Code DVJS30_Tasks_groupBy_r_typeof

title: DVJS30_Tasks_groupBy_r_typeof =>1.The new bug is fixed. 2.The codes are refactored.
collapse: close
icon: 
color: 
```dataviewjs
// M09. Define n:
// #####################################################################
// let n = dv.date("2022-07-18");
let n = luxon.DateTime.now();


// M11. Define filtered_tasks: gather all relevant tasks
// #####################################################################
let filtered_tasks = dv
    .pages(
        '"100_Project/01_dataviewjs/01_by_example/Q13_Tasks_groupBy/Q13_test_data"'
    )
    .file.tasks.filter(
        (t) =>
            t.due && 
            Math.floor(n.diff(t.due, "days").days) == 0 && 
            !t.completed
    );


// M13. GROUP BY task.r:
// #####################################################################
for (let related of filtered_tasks.groupBy((t) => t.r)) {
    dv.header(2, related.key);
    dv.taskList(
        // Edited by Justdoitcc 2022-07-18 21:05
        //filtered_tasks.filter((t) => t.r == related.key),
        
        // Edited by Justdoitcc 2022-07-18 21:30
        //filtered_tasks.filter((t) => dv.func.contains(t.r, related.key)),
        filtered_tasks.filter((t) =>
            dv.func.choice(
                dv.func.typeof(t.r) === "link",
                dv.func.contains(t.r, related.key),
                t.r === related.key
            )
        ),
        false
    );
}

```


Screenshots(DVJS30)

let n = dv.date(“2022-07-18”);


DVJS40_Tasks_groupBy_r_overdue

Summary

Main DVJS

Code Name Data type Purposes Remark
DVJS40
_Tasks
_groupBy_r
_overdue
t.r:
1.a string
2.a link
1.To display tasks which are I_MAX_TODAY_MINUS_DUE days overdue and not yet completed
2.To groupBy task.r
3.The codes are refactored.
1.easier to read
2.easier to modify
Summary_code

Code DVJS40_Tasks_groupBy_r_overdue

title: DVJS40_Tasks_groupBy_r_overdue =>1.To display tasks which are `I_MAX_TODAY_MINUS_DUE` days overdue and not yet completed 2.To groupBy task.r 3.The codes are refactored.
collapse: close
icon: 
color: 
```dataviewjs
// M09. Define TODAY:
// #####################################################################
// const TODAY = dv.date("2022-07-18");
const TODAY = dv.date("today");


// M10. Define I_MAX_TODAY_MINUS_DUE:
// #####################################################################
const I_MAX_TODAY_MINUS_DUE = 36500; // TODAY - t.due <= 36500 days


// M11. Define filtered_tasks: gather all relevant tasks
// #####################################################################
let filtered_tasks = dv
    .pages(
        '"100_Project/01_dataviewjs/01_by_example/Q13_Tasks_groupBy/Q13_test_data"'
    )
    .file.tasks
    .where(
        (t) =>
            t.due &&
            !t.completed &&
            TODAY - t.due >= dv.duration("0 days") &&
            // dv.date("today") - t.due <= dv.duration("36500 days")
            TODAY - t.due <= dv.duration(I_MAX_TODAY_MINUS_DUE + " days")

    );


// M13. GROUP BY task.r:
// #####################################################################
for (let related of filtered_tasks.groupBy((t) => t.r)) {
    dv.header(2, related.key);
    dv.taskList(
        filtered_tasks
            .where((t) =>
                dv.func.choice(
                    dv.func.typeof(t.r) === "link",
                    dv.func.contains(t.r, related.key),
                    t.r === related.key
                )
            )
            .sort(r, "asc"),
        false
    );
}


```


Screenshots(DVJS40)

const TODAY = dv.date(“2022-07-18”);


2 Likes

Thanks, @justdoitcc. I’m going to try it out.

1 Like

Here’s a slight addition: colorful bars.

dataviewjs source block:

```dataviewjs

// First, get all notes:
const notes = dv.pages();

// Now get three JS arrays of the three data categories from those notes:
const fitnessDataArray = notes.Fitness.array();
const writingDataArray = notes.Writing.array();
const nutritionDataArray = notes.Nutrition.array();

// Now let's create the sums of each of these data categories:
const fitnessSum = fitnessDataArray.reduce((partialSum, a) => partialSum + a, 0);
const writingSum = writingDataArray.reduce((partialSum, a) => partialSum + a, 0);
const nutritionSum = nutritionDataArray.reduce((partialSum, a) => partialSum + a, 0);

// ... and put those in an array for later visualization:
const dataArray = [fitnessSum, writingSum, nutritionSum];

// Now let's setup the data for the chart:
const chartData = {
   labels: ['Fitness', 'Writing', 'Nutrition'],
   datasets: [
      {
         label: 'Data from notes',
         data: dataArray,
         backgroundColor: [
            'rgba(192, 0, 128, 0.3)',
            'rgba(128, 192, 32, 0.3)',
            'rgba(32, 0, 192, 0.3)',
         ],
         borderColor: [
            'rgba(192, 0, 128, 1.0)',
            'rgba(128, 192, 32, 1.0)',
            'rgba(32, 0, 192, 1.0)',
         ],
         borderWidth: 2
      }
   ]
}

// Let's configure the chart:
const config = {
   type: 'bar',
   data: chartData
}

// Lastly, let's render the chart:
window.renderChart(config, this.container)
```

Hope this helps, @snowbiker100

6 Likes

@justdoitcc - works as expected.

Another follow-up question. I’ve observed that the headings created using dv.header() function don’t fold. Is it possible to make them?

Dataview_v0.5.39 can convert dataview results to properly formatted markdown.
Maybe it will do that sooner or later.


In addition, I add the final version: DVJS40_Tasks_groupBy_r_overdue.
1.let i_max_today_minus_due = 0;
=>
1.To display tasks which are 0 days overdue and not yet completed
2.To groupBy task.r


2.let i_max_today_minus_due = 10;
=>
1.To display tasks which are 10 days overdue and not yet completed
2.To groupBy task.r

2 Likes

Turn your dataview table into a static standard table (can be used to publish!).

The trick is to use a templater template for your dataviewjs code.

Here is an example of a simple table that gets its pages from ‘a Folder, tagA and not tagB’, where a dataview field contains “This Word”. (For context, it is used to get a list of films that I have but haven’t seen yet that are on my wishlist for the next Criterion Blu-ray sale).

Put this code in a templater template (no backticks, just begin with <% and end with %> and modify it to suit your purposes.

<%*
const headers = ["File", "file.folder"];
const tableValues = DataviewAPI.pages('"Films" and -#saw and #wishlist')
.where (p => p.edition.includes("Criterion"))
.sort(p => p.file.name, 'asc')
.map(p =>[p.file.link, p.file.folder]);
const myTable = DataviewAPI.markdownTable(headers, tableValues);
-%>
<% myTable %>

Now call the template into a file. Done.

Results:
20220719_150144

Tip: I’m going to just keep re-using the same template name, thereby over-riding the code every time. So I’m going to keep the code wrapped in %% to hide it from preview mode just above the table it creates. That way I can re-use to ‘update’ the table.

Thanks to AnnaKornfeldSimpson who figured this out. She has written instructions with an example on Github’s Dataview Discussion here:

11 Likes

I didn’t see this already on the forums when I searched, so here’s an easy way to automatically populate an entry with data from Goodreads.

Add the ID of the book in your frontmatter:

---
goodreads: 57587638
---

Then add this script. Personally I put it in a separate .js file, and use dv.view() to insert it on the page.

```dataviewjs
const id = dv.current().goodreads
if (id) {
    const raw = await requestUrl({ url: "https://www.goodreads.com/en/book/show/" + parseInt(id, 10) })
    const html = raw.text
    const coverImage = html.match(/div class="editionCover".*?img src="([^"]+)"/s)
    if (coverImage) dv.paragraph(`![|150](${coverImage[1]})`)
    let rating = html.match(/itemprop="ratingValue">([^<]+)/s); rating = rating ? ` (${rating[1].trim()} stars)` : ''
    dv.paragraph(`[View on Goodreads](https://www.goodreads.com/en/book/show/${id})${rating}`)
}
```

And you’ll get a nice cover image and info pulled straight from Goodreads site:

Of course you can adjust this to pull out any of the info that you want - summary, genres, etc.

11 Likes

For the inline yaml data inside the file which includes the dataviesjs code,
now I’m usiing the top head tag like the following.

dv.pages("#tag_for_thisfile")

Is there any method to use something like ‘this.file.blahblah’?
Because I have many such files, it is very laborous to change every tag inside them.

As requested by @Ooker on Discord:
Here is a dataviewjs custom view that uses the plugin MetaEdit’s API to update an inline field in my note with the number of completed tasks in that note. I have auto-refresh on at an interval of about 30 seconds in my “Settings” → “Dataview” settings page, so within 30 seconds of checking off a task the count on the note will increase.

Note.md:

...
## Tasks
- [x] Task I finished, hurrah! Maybe there are more of these.
...
## Reflection
Tasks Done Today:: 1
...
```dataviewjs
await dv.view("scripts/dvjsViews/updateTodayFields", dv.current());
```
%% ABOVE THIS LINE IS THE DATAVIEWJS TO CALCULATE FIELDS %%

The comment is there because I use Live Preview, which hides the dataviewjs codeblock since it does not itself produce any output, and I do not want to accidentally overwrite it so I put in the big all-caps warning. :slight_smile:

scripts/dvjsViews/updateTodayFields.js:

await updateTodayFields(input, dv);

async function updateTodayFields(input, dv) {
	if (!input) return;
	const { getPropertyValue, update } = app.plugins.plugins.metaedit.api;

	const howMany = input.file.tasks.filter(t => t.completed).length;

	const currentlyRecorded = await getPropertyValue("Tasks Done Today", input.file.path);
	if (howMany !== currentlyRecorded) {
		await update("Tasks Done Today", howMany, input.file.path);
	}
}
4 Likes

I have tried tweaking the code but keep failing on how to make it work with my current YAML format of “birthday: DD-MM-YYYY”.

Would greatly appreciate any help i can get.

@metawops Thank you so much! This is a great start. I am working with it and this is a great help to me. :pray:

1 Like

Hi DataviewJs Team,
I have a quick question:
When I use the “query” I get the paragraph that I put the #highlight tag on.

#highlight

But when I use “dataview” How can I get the paragraph that I put the #highlight tag on? Of course, all I get is the file name NOT the paragraph text I put the tag on. Thank you for any help you can provide:

table   
from #highlight 

Just another user here, but as far as I know dataview (or dataviewjs) will not give you that because it does not index entire files, just metadata.
Exception: if your “paragraph” is actually a list item or a task, you might be able to get the text.
But otherwise, stick with the built-in Query blocks?

Thank you @scholarInTraining I very much appreciate your message. The problem with using the “Query block” is that it shows every time I have the “Query block”. So I end up with blank paragraphs for every day. :cry: How can I stop these blank listings?

1 Like

I see if I use (tag:#highlight) it works perfectly. Thank you for your reply @scholarInTraining

I didn’t know that there is already “dv.current()”.

By replacingdv.pages() with dv.current() ,
I can get the dataview data for the inline fields in the current file.

4 Likes

A very weird behavior appears when a task-text have some number in front of a due date.

  • 21 :spiral_calendar:2022-08-31
    goes to ‘overdue’.

On the other hand,

  • 22 :spiral_calendar:2022-08-31
    goes to ‘upcoming’.

From my test, only tasks including a number between 22 and 68 go to ‘upcoming’. (Today is 2022-08-10)

For example,

  • abc 22 :spiral_calendar:2022-08-31 → goes to upcoming.
  • abc 69 :spiral_calendar:2022-08-31 → goes to overdue.

Is there anyone who can give me some clue? Without any number in a task-text, everything is O.K.

Hi, do you have perhaps an updated version for [the new version](DataviewJS Snippet Showcase - #10 by Rishi! ?)

I tried it myself but was not able to get it to work.

Topic

Summary

1.How to display uncompleted sub-tasks which are unscheduled or upcoming?


Test

Summary
  • dataview: v0.5.41

Input

Summary

dictionary files

  • filename : dic_20100301
---
Date: 2010-03-01
---
#Project/P03

- [ ] pp : test
- [ ] pp :spiral_calendar:2022-08-13
- [ ] 21 :spiral_calendar:2022-08-14
- [ ] 22 :spiral_calendar:2022-08-15
- [ ] abc 22 :spiral_calendar:2022-08-16
- [x] abc 69 :spiral_calendar:2022-08-17
    - [ ] abc 69.1 :spiral_calendar:2022-08-17
- [x] abc 69 :spiral_calendar:2022-08-18



  • filename : dic_20100401
---
Date: 2010-04-01
---
#Project/P03

- [ ] KK : test
- [ ] KK :spiral_calendar:2023-08-13
- [ ] 21 :spiral_calendar:2023-08-14
- [ ] 22 :spiral_calendar:2023-08-15
- [ ] abc 22 :spiral_calendar:2023-08-16
- [x] abc 69 :spiral_calendar:2023-08-17
    - [ ] abc 69.1 :spiral_calendar:2023-08-17
- [x] abc 69 :spiral_calendar:2023-08-18




DVJS10_use_fTasks_to_display_unscheduled_or_upcoming_tasks

Summary

Main DVJS

Code Name Data type Group By Purposes Remark
DVJS10_use_fTasks_display
_unscheduled_or_upcoming_tasks
file.tasks no 1.To hide completed sub-tasks

2.To show uncompleted sub-tasks which are unscheduled or upcoming
1.b_unscheduled = true : when task.text contains no due date string like “yyyy-MM-dd” at the end of the line.

2.b_upcoming = true : when task.text contains a due date string like “yyyy-MM-dd” at the end of the line and today is less than it.

Notes

Summary_notes

code DVJS10_use_fTasks_to_display_unscheduled_or_upcoming_tasks

Summary_code
title: DVJS10_use_fTasks_to_display_unscheduled_or_upcoming_tasks => 1.To hide completed sub-tasks  2.To show uncompleted sub-tasks which are unscheduled or upcoming 3.b_unscheduled = true : when task.text contains no due date string like "yyyy-MM-dd" at the end of the line. 4.b_upcoming = true : when task.text contains a due date string like "yyyy-MM-dd" at the end of the line and today is less than it.
collapse: close
icon: 
color: 
```dataviewjs
// M11. define pages: gather all relevant pages
// #####################################################################
//let pages = dv.current();
let pages = dv
    .pages('"100_Project/01_dataviewjs/01_by_example/Q15_Tasks/Q15_test_data" and #Project')
    .where((page) => dv.func.contains(page.file.name, "dic_"));    


// M21. define tasks:
// #####################################################################
let tasks = pages.file.tasks
    .where((t) => !t.completed)
    .where((t) => show_unscheduled_or_upcoming(t));


// M51. output tasks:
// #####################################################################
dv.taskList(tasks);


// M90. define function: show unscheduled or upcoming tasks
// #####################################################################
// case_10: return true if b_unscheduled;
// case_20: return true if !b_unscheduled && dt_today < dt_due_date_in_text;
function show_unscheduled_or_upcoming(task) {
    // F13. define dt_today:
    // #####################################################################
    // let dt_today = dv.date("2022-08-18");//=>For debugging
    let dt_today = dv.date("today");

    // F21. define a_date_strings: get a_date_strings from the end of t.text
    // #####################################################################
    let a_date_strings = task.text.match(/\d{4}-\d{2}-\d{2}$/); //=>null or array

    // F25. define b_unscheduled:
    // false: when the end of task.text is /\d{4}-\d{2}-\d{2}$/
    // #####################################################################
    let b_unscheduled = true;
    if (a_date_strings) {
        b_unscheduled = false;
    }

    // F29. case_10: return true if b_unscheduled;
    // #####################################################################
    if (b_unscheduled) {
        return true;
    }

    // F31. define dt_due_date_in_text:
    // #####################################################################
    let dt_due_date_in_text;
    if (!b_unscheduled) {
        dt_due_date_in_text = dv.date(a_date_strings[0]);
    }

    // F41. define b_upcoming: 
    // case_20: true if !b_unscheduled && dt_today < dt_due_date_in_text;
    // #####################################################################
    let b_upcoming = false;
    if (!b_unscheduled && dt_today < dt_due_date_in_text) {
        b_upcoming = true;
    }

    // F80. return :
    // #####################################################################
    return b_upcoming;
}

```

Screenshots(DVJS10): (Today is 2022-08-18)


Unresolved links

The code was copied from Show unresolved links. All I did, was to improve the way the code ignore files on the search. Instead of type each file, all you have todo is to inform the folderPath using tags.

//how many links a non existing file should have at minimum
const count = 1;

//specify the full path here.
const filesPath = []
filesPath.push(
    ...dv.pagePaths("#dailynotes"),
    ...dv.pagePaths("#html"),
    ...dv.pagePaths("#helpers")
)

let ignoredExisting = []
for (let i = 0; i < filesPath.length; i++) {
    ignoredExisting+= '"' + filesPath[i] + '"' + ','
}

//keep these in lower case.
const ignoredNonExisiting = ["your non exisiting notes", "here is note that does not exist"];

let d = {};
function process(k, v) {
  Object.keys(v).forEach(function (x) {
    if(!ignoredNonExisiting.includes(x.toLowerCase())) {
        x = dv.fileLink(x);
        if (d[x]==undefined) { d[x] = []; }
        if(!ignoredExisting.includes(k)) {
            d[x].push(dv.fileLink(k));
        }
    }
  });
}

Object.entries(dv.app.metadataCache.unresolvedLinks)
    .filter(([k,v]) => Object.keys(v).length)
    .forEach(([k,v]) => process(k, v));
    
dv.table(["Non existing notes", "Linked from"],
         Object.entries(d)
         .filter(([k, v]) => v.length >= count)
	     .sort((a, b) => b[1].length - a[1].length)
         .map(([k,v]) => [k, v.join(" • ")]));
3 Likes