obsidian-dataview
obsidian-dataview copied to clipboard
dv table displaying due dates doesn't pick up due dates in tasks
What happened?
I have dataview due dates (formatted as (due:: 2022-07-11)
) everywhere: frontmatter, tasks, within notes.
I discovered today that all due dates within tasks don't appear in my dataview tables that display due dates.
My guess is that it has something to do with inline fields being tied to a note title and tasks being tied to, well, a task I guess.
If this is the way it goes, is there a way to get a list or table of all due dates regardless of where they appear (frontmatter, note, task)?
Example file: due date does not appear in my table
- [ ] this is (due:: 2022-07-11)
- [ ] more tasks
due date does appear
this is (due:: 2022-07-11)
- [ ] more tasks
DQL
table (due.month + "-" + due.day) as "due date"
WHERE (striptime(due) - striptime(date(now)) <= dur(30 days)) and (striptime(due) - striptime(date(now)) >= dur(1 days))
sort due
JS
No response
Dataview Version
0.5.36
Obsidian Version
0.14.15
OS
Windows
Your idea is correct. When doing tables for tasks, due
will be available under file.tasks
. You can inspect the metadata in the console to verify.
Is there anyway to modify my DQL to include both tasks and anything else?
The idea is to get notification of upcoming due dates - I think most users will not care if they put the due date in a task or in a note; but they will care when they miss a due date because it was a task rather than a note (or vice versa)!
I think I found it. I can add
or contains(striptime(file.tasks.due), striptime(date(today)))
and it seems to work!
Very cool! Don't think you need striptime
BTW.
I'll try without the striptime as you suggest.
I spoke too soon when I said the entire thing worked. It works fine when using contains(striptime(file.tasks.due), striptime(date(tomorrow))
where one could just include the date as today, or tomorrow. But it doesn't work when trying to get upcoming due dates.
This works for due dates not in tasks:
table WHERE due - date(now) <= dur(30 days) and due - date(now) >= dur(1 days)
but it doesn't work for file.tasks (so I can't add an OR condition because it doesn't work on its own)
table Where file.tasks.due - date(now) <= dur(30 days) and file.tasks.due - date(now) >= dur(1 days)
Let me test some stuff out and get back to you. It's been a while since I've done stuff like this.
You want to list all pages which have due
field somewhere, including in the tasks? Maybe something like
TABLE WHERE
(due - date(now) <= due(30 days) and due - date(now) >= dur(1 days))
OR any(map(file.tasks, (t) => t.due - date(now) <= due(30 days) and t.due - date(now) >= dur(1 days)))
It's kind of hard to sort on the task field though... a few more DQL functions for array operations would probably make this easier.
Thank you for the suggestion. I'll keep noodling to try to make it work. Unfortunately, as is, I get the following error:
Dataview: Error:
I should say I hope you don't think I'm being a pain for something that only I can use. I really do think people use due dates all the time and they really can't be bothered to have to remember how they input the due date (i.e., task or within the note, or frontmatter), I think it's a fairly important issue because when inserting due dates in one form or another we tend to think they will appear when necessary, and one doesn't want to forget a Doctor's appointment, for example, because it was entered as a task rather than within a note.
Just saying that this particular issue is not a small one. But, maybe I'm wrong. Maybe people are fastidious about how they enter due dates (tasks only, notes only, etc) and I'm the outlier, entering stuff willy-nilly!
There's a typo in the blacksmithgu query ( 🙂 ) easy to identify: dur()
function instead of due()
:
TABLE
WHERE
(due - date(now) <= dur(30 days) and due - date(now) >= dur(1 days))
OR any(map(file.tasks, (t) => t.due - date(now) <= dur(30 days) and t.due - date(now) >= dur(1 days)))
@mnvwvnm Ah good catch! Thanks.
Alas... it doesnt pick up tasks with due dates.
It's no biggie. I'll just create a query for tasks right under my query for notes.
(need @blacksmithgu confirmation)
I think the code fails because the map()
part related with file.tasks
can't deal with the "null - date" in tasks with no due date.
Maybe with a filter to consider only the tasks with due date:
TABLE
WHERE
(due - date(now) <= dur(30 days) and due - date(now) >= dur(1 days)) OR
any(map(filter(file.tasks, (t) => t.due), (k) => k.due - date(now) <= dur(30 days) AND k.due - date(now) >= dur(1 days)))
Good thinking. Alas, it still doesn't pick up the tasks with due dates in them.
But you want to see where they're (the notes) or you want to see the tasks (the task text)?
I would prefer displaying the tasks (the picture is two separate queries), but the filenames would work as well... but the code you suggested doesn't display either; it just displays the due dates in notes. I did manage to create a query that included the tasks filenames at one point in my testing, but I think it errorred out when there were no tasks that fit the bill, as per your 'filter' suggestion. I'll go through my tests to see if I can find it.
Ok, adding this to my regular "due tomorrow" query for notes includes tasks (their filenames):
or contains(striptime(file.tasks.due), date(tomorrow))
But that uses "contains". For an "upcoming" query, I can't use "contains" and that's what got me into trouble.
My suggestion: create two queries. For example:
## Projects: next 30 days
```dataview
TABLE due
FROM "your-folder-path"
WHERE (due - date(now) <= dur(30 days) and due - date(now) >= dur(1 days))
```
## Tasks: next 30 days
```dataview
TABLE T.text AS Tasks, T.due AS "Due date"
FROM "your-folder-path"
FLATTEN file.tasks as T
WHERE (T.due - date(now) <= dur(30 days) AND T.due - date(now) >= dur(1 days))
```
Yeah, that's what I doing now. My only issue, really, is that there may be others who think (like I did) that looking for a due date means looking for ALL due dates. Users might not know they need separate queries for the different formats, and may miss important due dates because of it. I suppose one could just stick to one format, but dataview is so damned convenient allowing us to stick in due dates all over the place no matter where we are in our vault ;-)
Hey @filmgal , do you think it would help if we add a hint to the documentation that task-leveled metadata are not propagated to page level?
Hey @filmgal , do you think it would help if we add a hint to the documentation that task-leveled metadata are not propagated to page level?
@s-blu, yeah. Although more people might understand what that means if you were to spell it out: due dates within tasks and due dates everywhere else each require their own query; i.e., no single query will give you due dates in both places. (or something like that)
Hey, thanks for you feedback!
To be precise you can query that in one query:
TABLE duedat, map(file.tasks, (x) => x.duedat)
WHERE duedat OR any(map(file.tasks, (x) => x.duedat))
But that is, of course, not very intuitive. There's a good reason that task meta data does not get written to the page though: Tasks inherit everything from their page, so when task fields would be saved on the page, too, it would mean every task gets every field value of all the other tasks in the file, too - making it impossible to search for only these tasks that are i.e. due < date(today)
.
I'll add this to the documentation board and look for a good place to add a appropiate hint to this, as soon as the new documentation is live.
By the way: You could do something like this if you want to use either the duedate (duedat
here) on the page, if available, or the earliest duedate found on a TASK.
```dataview
TABLE due
FLATTEN default(duedat, min(map(file.tasks, (x) => x.duedat))) AS due
WHERE due AND due < date(today)
```
Is this completed with the addition of the documentation on https://github.com/blacksmithgu/obsidian-dataview/commit/b26465af61100b98c77ac0fa469738ab133574fe where it states that nowadays all page fields are inherited into the task?