Include some file metadata to be displayed in the Dataview file link

What I’m trying to do

I have a simple dataview task query:

task
from #flagged/in-progress
group by file.link

Which works fine, enough:

What I would like is to have some extra information in the file links that group the results.

E.g., the page may (or may not) have the following metadata fields: project-id, project-area, project-status etc.
And instead of just “@shannon-1949-mathematical-theory”, I would like the underlying generated markdown to look something like:

### (project-area:: foo) (project-id:: bar) @shannon-1949-mathematical-theory

- [  ] blah blah blah blah #flagged/inprogress 

It would be nice to sort on the composite key of project-area/id as well.

The GROUP BY expressions allow you to do just that, add an expression, so you should be able to do something like:

```dataview
TASK
FROM #flagged/in-progress
GROUP BY project-area + " " + project-id + " " + file.link
```

Or if it’s not a given that the field you want to include is always set, you could try some variant like: choice(project-area, project-area + " ", ""). Where if it’s set it include the value and a space, and if not set, it’ll just do an empty string.

If you want to sort on the same expression, you could either just add SORT key at the end, or use FLATTEN to store the result for later retrieval in other parts of the query, like in the following:

```dataview
TASK
FROM #flagged/in-progress
FLATTEN project-area + " " + project-id + " " + file.link as myThingy
GROUP BY myThingy
SORT myThingy
```

This latter version could potentially also allow for the myThingy to be used in WHERE clauses and so on.

1 Like

Ah! That solves it :slight_smile:

Thank you!

I suppose I use dv.query() and pass in the query string if I want to do this in dataviewjs? I see dv.taskList() takes true/false to determine whether it should group by file, but not a way to support custom keys/fields as the DQL GROUP BY.

Ok, fiddling this with a bit more, this is an alternate approach: basically, hacking in the group key. Not sure if there are any differences in practice.

Also, thought I would share a dataviewjs implementation of your solution. I wanted to bring in page level tags to decorate the group headings. Plan to add things like priority etc.

function getPageTags(taskPage, tagPatterns) {
    let pageTags = taskPage.tags
    if (pageTags) {
        const filteredTags = pageTags.filter(t => {
            return tagPatterns.some(pattern => pattern.test(t));
        });
        if (filteredTags) {
            return filteredTags.map(i => "#" + i).join(" ")
        }
    }
    return null
}

async function runQuery() {
    let options = input ?? {}
    let queryFrom = ""
    if (options.from) {
        queryFrom = `FROM ${options.from}`
    }
    const query = `
      TASK
      ${queryFrom}
      FLATTEN
        file.path
      AS GroupExpression
      GROUP BY GroupExpression
      SORT GroupExpression
     `
    let result = await dv.query(query)
    let items = result.value.values
    let _mklink = function (path, title) {
        return "[" + title + "](" + path + ")"
    }
    const tagPatterns = [/project.*/, /area.*/]
    const pageFields = ["planning-area", "project-id"]
    items = items.map(function(item) {
        // const separator = " ▶ "
        let newGroupExpression = []
        let path = item.key
        let basePath = path.split(/[\\/]/).pop()
        let taskPage = dv.page(path)
        let pageTags = getPageTags(taskPage, tagPatterns)
        if (pageTags) {
            newGroupExpression.push(pageTags)
        }
        for (pageField of pageFields) {
            if (taskPage[pageField]) {
                newGroupExpression.push(taskPage[pageField])
            }
        }
        pageLink = "[" + (taskPage["title"] ?? basePath) + "](" + path + ")"
        // dv.span(Object.keys(pageLink))
        newGroupExpression.push(pageLink)
        item.key = newGroupExpression.join(" ⏺ ")
        return item
    })
    dv.taskList(items)
}

One weirdness I noticed is that with the above approach, dataview picks up tags when given in the yaml but not in the body. So, for e.g., the logic I use above will pick up “foo” (as a tag, without the “#”) but not “#bar”.

---
tags:
 - foo
---

#bar

If you extend your tag example with the following:

Just `tags`: `$= dv.current().tags `

Using `file.tags`: `$= dv.current().file.tags `

You’ll hopefully see that the latter does include both, but the former only lists the frontmatter variant. Whether this is intentionally, or to be considered a bug it for someone else to comment upon. I’ve not seen it referenced elsewhere that there should this distinction, so I’m likely to call this a bug, and something which ought to be mentioned on the github page of Dataview.

1 Like

Thank you.

Your sharing of your knowledge in these forums is fantastic.

I’ve set up my tasks to telescoping callouts based on this


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