This is awesome but there is a small typo:
// .sort(v => v[1].id, 'asc'); // Sorted by the descriptive name
Should say
// .sort(v => v[1].name, 'asc'); // Sorted by the descriptive name
Cheers
I have gotten my Birthday list to work thanks to this post and have been using it quite happily for a while.
But I’ve come across something I can’t figure out. I want to ask and answer the question “How old will person be ON their birthday THIS year?”
So if I have the following file:
# Person Name
Start-Date:: 1980-12-05
Details:: turns `=date(date(today).year + "-" + this.Start-Date.month + "-" + this.Start-Date.day) - this.Start-Date` in `=date(today).year`
results in a Details line that reads:
Details:: turns in 2022
My date math is ignored.
I’ve tested without the Details:: callout - it’s definitely the two nested date() calls.
I can do this with DVJS, I’m just wondering if it’s something that can be done in straight inline DV. And if I’ve got an error or something in my code.
Topic
Summary
- How to calculate a person’s age?
Input
Summary
```md
# Person Name
Start-Date:: 1980-09-06
Details::
```
Notes
Summary
Q1: What is the data type of this.Start-Date.month
(or this.Start-Date.day
)?
Summary_Q1
A1:
Another Example: A1_11
```md
month_type = `=typeof(this.Start-Date.month)`
day_type = `=typeof(this.Start-Date.day)`
```
Screenshots: A1_11
month_type = number
day_type = number
Q2: How to transform this.Start-Date.month
into MM (or transform this.Start-Date.day
into dd)?
Summary_Q2
A2:
Another Example: A2_21
```md
month_MM = `=padleft(string(this.Start-Date.month),2,"0")`
day_dd = `=padleft(string(this.Start-Date.day),2,"0")`
```
Screenshots: A2_21
month_MM = 09
day_dd = 06
Q3: How to fix the bug in the Inline DQL?
Summary_Q3
Original Example: Q3 (To be modified)
```md
Details:: turns `=date(date(today).year + "-" + this.Start-Date.month + "-" + this.Start-Date.day) - this.Start-Date` in `=date(today).year`
```
A3:
Another Example: A3_31
```md
Details:: turns `=date(date("today").year + "-" + padleft(string(this.Start-Date.month),2,"0") + "-" + padleft(string(this.Start-Date.day),2,"0")) - this.Start-Date` in `=date("today").year`
```
Screenshots: A3_31
Details:: turns 42 years in 2022
Q4: How to simplify the Inline DQL(A3_31) when calculating date("2022-09-06")-date("1980-09-06")
with skipping the same month and day?
Summary_Q4
A4:
Another Example: A4_41
```md
Details:: turns `=date("today").year - this.Start-Date.year` years in `=date("today").year`
```
Screenshots: A4_41
Details:: turns 42 years in 2022
Q5: How to calculate a person’s age in months and years by using the dur
function?
THANKS!
I debated using the padleft to adjust it, but since my dates worked fine when I didn’t try specifying the year date(today) - this.Start-Date
I didn’t think that was an issue.
Of course, A4 is even better, and what I’ll be using.
Thanks again for the QA. My eyes were burning attempting it myself.
Hoping some of you DataviewJS veterans can help with this.
I currently have a DataviewJS + Buttons script that creates a button that changes the status variable in the yaml header. That all works great.
---
defer_date: 2022-11-22
status: on-going
---
```dataviewjs
const {update} = this.app.plugins.plugins["metaedit"].api
const {createButton} = app.plugins.plugins["buttons"]
dv.el("p", "Status: `$= dv.current().status`")
createButton({app, el: this.container, args: {name: "on going"}, clickOverride: {click: update, params: ['status', "on-going", dv.current().file.path]}})
createButton({app, el: this.container, args: {name: "completed"}, clickOverride: {click: update, params: ['status', "completed", dv.current().file.path]}})
Now, I’m trying to create a similar button for adding one day to the defer_date variable. (The idea is to let me push out the start date for certain projects)
However, when I click on the button, it turns the defer_date to just a number 1669122000000
and I don’t know how to change it back to a date.
Can someone help?
---
defer_date: 2022-11-22
---
```dataviewjs
let d = dv.current().defer_date;
const {update} = this.app.plugins.plugins["metaedit"].api
const {createButton} = app.plugins.plugins["buttons"]
dv.el("p", "Defer Date: `$= dv.current().defer_date`")
createButton({app, el: this.container, args: {name: "+1"}, clickOverride: {click: update, params: ['defer_date', d + 86400000, dv.current().file.path]}})
Topic
Summary
- How to get the day before the day “2022-11-18” in the format “yyyy-MM-dd”?
- How to get the day after the day “2022-11-18” in the format “yyyy-MM-dd”?
Test
Summary
- dataview: v0.5.46
- MetaEdit: v1.7.2 (For Q3 and A3_31)
- Buttons : v0.4.19 (For Q3 and A3_31)
Input
Summary
---
defer_date: 2022-11-18
status: on going
---
Notes
Summary
Q1: How to get the day before the day “2022-11-18” in the format “yyyy-MM-dd”?
Summary_Q1
A1:
Another Example: A1_11
```dataviewjs
let d2 = dv.date('2022-11-18').minus({ days: 1 }).toFormat("yyyy-MM-dd");
dv.span(d2);
```
Screenshots: A1_11
2022-11-17
Q2: How to get the day after the day “2022-11-18” in the format “yyyy-MM-dd”?
Summary_Q2
A2:
Another Example: A2_21
```dataviewjs
let d2 = dv.date('2022-11-18').plus({ days: 1 }).toFormat("yyyy-MM-dd");
dv.span(d2);
```
Screenshots: A2_21
2022-11-19
Q3: How to fix the bug in the DVJS?
Summary_Q3
Original Example: Q3 (To be modified)
```dataviewjs
// M11.define d:
// #####################################################################
let d = dv.current().defer_date;
// M21.define update: require the plugin MetaEdit
// #####################################################################
const { update } = this.app.plugins.plugins["metaedit"].api;
// M31.define createButton: require the plugin Buttons
// #####################################################################
const { createButton } = app.plugins.plugins["buttons"];
// M41.output defer_date:
// #####################################################################
dv.el("p", "Defer Date: `$= dv.current().defer_date`");
// M51.createButton "+1":
// #####################################################################
createButton({
app,
el: this.container,
args: { name: "+1" },
clickOverride: {
click: update,
params: ["defer_date", d + 86400000, dv.current().file.path],
},
});
```
Screenshots: Q3
Defer Date: 1668787200000
A3:
Another Example: A3_31
Bugs fixed:
- The Step M13 is added.
d + 86400000
is replaced withd2
in the Step M51.
```dataviewjs
// M11.define d:
// #####################################################################
let d = dv.current().defer_date;
// M13.define d2: the day after the day `d`
// #####################################################################
// let d2 = dv.date("2022-11-18").plus({ days: 1 }).toFormat("yyyy-MM-dd");
let d2 = d.plus({ days: 1 }).toFormat("yyyy-MM-dd");
// M21.define update: require the plugin MetaEdit
// #####################################################################
const { update } = this.app.plugins.plugins["metaedit"].api;
// M31.define createButton: require the plugin Buttons
// #####################################################################
const { createButton } = app.plugins.plugins["buttons"];
// M41.output defer_date:
// #####################################################################
dv.el("p", "Defer Date: `$= dv.current().defer_date`");
// M51.createButton "+1":
// #####################################################################
createButton({
app,
el: this.container,
args: { name: "+1" },
clickOverride: {
click: update,
params: ["defer_date", d2, dv.current().file.path],
},
});
```
Screenshots: A3_31
Defer Date: 11 19, 2022
Thank you! I was doing my brains in trying to get that to work.
Hello,
I’m looking to automatically generate the location: [lon, lat]
in my YAML frontmatter for Daily Notes. Ideally with a link to Google. How could I accomplish this?
Looks like:
.sort(v => v[1].id, ‘asc’); // Sorted by the command name
should be:
.sort(v => v[1].name, ‘asc’); // Sorted by the command name
“name” not “id”
Right?
Yeah, that seems correct. I’m thinking about redoing that party of script, to also enable easier sorting and detection of duplicates.
But good catch!
Great snip! Would it be possible to split the Plugin Name into its own column? I see the Plugin Name is in the Name column of your code, but I would like them separate for sorting and data-extraction purposes.
Hey everyone,
I’m trying to get a hierarchical folder and file view of my Template folder using this
let title = "Dateien";
let dir = 'Templates';
let processed = [];
function listRecursive(folder, depth) {
let files = [];
// All pages in the scope of the current path
let pages = dv.pages('"' + folder + '"')
// Collect files in the current folder here
let currentFiles = "";
pages.forEach(page => {
if (page.file.folder === folder) {
// Page is in current folder
currentFiles += page.file.link + " <br> ";
}
else {
// Page is in subfolder
let nestedFolder = page.file.folder;
// Make sure nested folder is direct child, not any other descendant from current folder
let isChild = folder.split('/').length + 1 == nestedFolder.split('/').length;
// Make sure we dont process sub-directories multiple times
if (!processed.includes(nestedFolder) && isChild) {
processed.push(nestedFolder);
// Result of recursive call is a list, by adding it to the current list we recursively build a tree
files.push(listRecursive(nestedFolder, depth +1));
}
}
});
if (currentFiles.endsWith(" | "))
currentFiles = currentFiles.slice(0, -3);
// Add files in current folder at the start
if (currentFiles !== "") files.unshift(currentFiles);
// Add current folder name at the start
let path = folder.split('/');
path = path [path.length - 1];
if (depth == 0) path = path;
files.unshift("<h3>" + path + "</h3>");
return files;
}
let files = listRecursive(dir, 0);
dv.header(2, title);
dv.list(files);
I’ve minimally adapted it from here
Even in the original thread the writer jonasfranz says that it could use with some punch up to make it prettier.
I’m trying to remove the random bullet points the script inserts and am trying to get it scan the whole subfolder and not just the level one subfolders. Here are two screenshots of the problem:
I hope someone can help me Oh and I’ve already got a css installed which shows less bullet points. So this is how it looks without that CSS if it helps:
As long as you’re using dv.pages
to get the page, why don’t you use that to also group and sort your entries?
You’re kind of going around yourself with the current code, and doing it recursively when you (can) get all information on that start query.
I’m in a rather busy week just now, so I can’t type out an alternative solution, but I do believe there is room for improvements.
I’ll try to patch something up or research something along those lines. I’m a non-coder with a limited amount of knowledge so thank you for your input =)
Found a solution using this snippet, for anyone who is also interested in listing all “Template” files, this script increments the headers per subfolder and puts the “Templates” folder on the top. This was writtten using ChatGPT, which also annotated the script. Anyway, hope it helps:
```dataviewjs
let pages = dv.pages('"Templates"');
// Create a new array to store the sorted groups
let sortedGroups = [];
// Set the initial header level to 3
let headerLevel = 3;
// Iterate through the groups, and push the "Templates" group first
for (let group of pages.groupBy(b => b.file.folder.replace(/^Templates\//, ""))) {
if (group.key === 'Templates') {
sortedGroups.unshift(group);
} else {
sortedGroups.push(group);
}
}
for (let group of sortedGroups) {
// Split the group key by '/' to check the number of subfolders
let subfolders = group.key.split('/');
// Increase the header level for each subfolder
headerLevel += subfolders.length - 1;
dv.header(headerLevel, group.key);
dv.list(group.rows.file.link);
// Reset the header level for the next group
headerLevel = 3;
}
Thank you so much for this.
I only wanted to see the list of hotkeys which I have modified. So I made a small change to get the desired output:
const getNestedObject = (nestedObj, pathArr) => {
return pathArr.reduce((obj, key) =>
(obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj);
}
function hilite(keys, how) {
if(how != "**") return "x"
// need to check if existing key combo is overridden by undefining it
if (keys && keys[1][0] !== undefined) {
return how + keys.flat(2).join('+').replace('Mod', 'Ctrl') + how;
} else {
return '–';
}
}
function getHotkey(arr, highlight=true) {
if(!highlight) return; // THIS IS THE CHANGE
let hi = highlight ? '**' : '';
let defkeys = arr.hotkeys ? [[getNestedObject(arr.hotkeys, [0, 'modifiers'])],
[getNestedObject(arr.hotkeys, [0, 'key'])]] : undefined;
let ck = app.hotkeyManager.customKeys[arr.id];
var hotkeys = ck ? [[getNestedObject(ck, [0, 'modifiers'])], [getNestedObject(ck, [0, 'key'])]] : undefined;
return hotkeys ? hilite(hotkeys, hi) : hilite(defkeys, '');
}
let cmds = dv.array(Object.entries(app.commands.commands))
.where(v => getHotkey(v[1]) != 'x')
.sort(v => v[1].id, 'asc')
.sort(v => getHotkey(v[1], false), 'asc');
dv.paragraph(cmds.length + " commands with assigned hotkeys; " +
"non-default hotkeys <strong>bolded</strong>.<br><br>");
dv.table(["Command ID", "Name in current locale", "Hotkeys"],
cmds.map(v => {
return [
v[1].id,
v[1].name,
getHotkey(v[1]),
]
})
);
Flattened List of tasks
Below code returns a flattened list of all tasks based on the filter criteria mentioned in the .where
clause.
The returned task list doesn’t have any hierarchy other than the file that they are from.
```dataviewjs
dv.taskList(dv.pages().file.tasks
.where(t => !t.completed)
.where(t => t.text.includes("2023-Jan-24"))
.map(t => {
t.children = [];
t.parent = 0;
return t
}))
```
Example Screenshot below:
What is the query you wrote into chatGPT?