Show task only if previous ones were completed - Tasks plugin

Things I have tried

I tried adding the task in reversed nested list. 3rd task would be the first in the list, the 2nd would be nested one level down, and the 1st task would be nested two levels down.
I hoped I could query only the bottom-most incompleted task and ignore the above ones.

image

What I’m trying to do

I tried to do sequential tasks. If you have two tasks:

  1. Empty the trash bin
  2. Take out the trash

You don’t necessarily need to see task 2 if you haven’t yet completed task 1.

I think you’ll be more successful using a combination of not showing completed tasks, and then limit to only showing 1 task.

Not sure how to translate that into multiple tasklist (from different notes/projects), whether you then could group on a single note and select only the first.

Can’t test right now, but I think either limit or group by should be able to help you accomplish your goal.

Doesn’t limit work globally for the entire query? As you rightly pointed out here:

Not sure how to translate that into multiple tasklist (from different notes/projects)

Having a global query that takes tasks from several notes makes limit not a viable choice, I think.

limit <value> does indeed limit the overall result set, but could be applied both before and after the group by clause. Sadly, it didn’t produce the wanted result. Since we’re dealing with tasks, I’m not quite sure how to only fetch the first task from each file, maybe @mnvwvnm could do that, but I’m not enough of a wizard to do that for a straight DQL query.

However, I do know a little javascript, and since I lead you onto this path, I would like to present some alternatives using DataviewJS, which is getting to be my new favorite toy.

## Postprocessing magic

```dataviewjs

let firstTasks = []
const tasks = dv.pages('"ForumStuff/f48291"')
                .file.tasks
                .where(t => !t.completed)

let prevPath = ""
for (let task of tasks) {
  // console.log(task)
  if (task.path != prevPath) {
    firstTasks.push(task)
    prevPath = task.path
  }
}

dv.el("h3", "With no project references")
dv.taskList(firstTasks, false)

dv.el("h3", "With project references")
dv.taskList(firstTasks)
```

## Even more magic

```dataviewjs

let firstTasks = []
const tasks = dv.pages('"ForumStuff/f48291"')
                .file.tasks
                .where(t => !t.completed)

let prevPath = ""
for (let task of tasks) {
  // console.log(task)
  if (task.path != prevPath) {
    task.text = task.link + ": " + task.text
    // task.text = task.link.fileName() + ": " + task.text
    firstTasks.push(task)
    prevPath = task.path
  }
}

dv.el("h3", "Inline project reference")
dv.taskList(firstTasks, false)
```

These two (and a half) scripts, produces three variants of the output which all lists just the first uncompleted tasks from my two example projects, aptly named FirstProject and Second Project.

The output produced are:
image

My two example files are simply (with “First” changed to “Second” in the other file):

- [x] First project, first task completed
- [ ] first project, second task not completed
- [ ] first project, third task not completed
- [x] first project, fourth completed task?!

Some explanations are in order

There are just slight variations between the scripts, and they both use the same principle:

  1. Collate all tasks that are not completed, and store these in tasks
  2. Loop through all tasks, and store away the first task in each file
  3. Present the tasks using dv.taskList()

The differences are how we present the result. The first variant presents just the task (due to the false at the end of the dv.taskList()). Do note that as usual the task text links to the original note/project, but it can be kind of hard to identify the project.

So the second variant includes the note header, which I personally don’t like that much since it introduces another element into the list, and especially when we only present one task, I think it becomes a little cluttered.

Therefor I made the third variant, where I actually change the task text, and include the link to the original note. If you look carefully in the code, you’ll also see commented line with just the fileName, if you don’t like the visual link. This I think looks the best, as it indicates which project the task originates from.

So, hopefully this helps, and if lucky a simpler pure query will present itself in the near future. But until then, this could be an option to get the first uncompleted task from your projects.

@holroy, since you tagged me :slight_smile: , I need to clarify: I still don’t understand the wanted goal (but that is my fault), but related with the ability of apply a limit before and after the group command, indeed I don’t know a solution to do that in regular DQL.

I need to review the dictionary definition of “little”.

Finally, I think I don’t understand 50% of your js code (mainly I don’t understand the way you get the first task) , but I leave a question: in the third variation don’t you need to use task.visual = ... instead of task.text = ... to retain the interaction with the original task?

@mnvwvnm, The goal, as I see it is to get various tasklists from different notes (aka projects), and then only list the first uncompleted task from each tasklist. Hence my idea of grouping by file.name or file.link.

The way I get the first task is that I rely on knowing which file the previous task I checked was from, this is stored in the prevPath variable, and it starts out with nothing so I get a “file change” right at the start. Then for every task I check after that, I ignore all tasks which comes from the same file as the prevPath variable.

And then each time I actually get a task, I change the prevPath to the newest task stored away in the firstTasks lists. This depends on the task list being sorted according to the originating files, but that seems to be the case, so this works rather nicely.

It sure seems fine to adjust the task.text, and not only the task.visual, and still preserve the task. I’ve done this in a few occasions. The only thing which might be confused/buggy, is that when clicking on the task text it sometimes doesn’t find the correct task, and just ends up in the neighborhood of it.

Bug in my code: I first used this trick when decorating tasks (aka already completed tasks), so I then didn’t discover that the actual linking of tasks where the text changes doesn’t hit the target always. In other words, tasks with extra text seems not being able to be completed from the dataquery anymore.

2 Likes

tl;dr My code works as expected if you change the task.text = ... line, into task.visual = ...

It bugged me that this didn’t behave as expected, and it actually seems to be two issues occuring at the same time here:

  1. I should definitively use and changed task.visual, and not task.text. This was pure incompetence on my behalf. So the latter variants needs to do task.visual = ... . This will allow for task linking and completion to work as expected, and a better visual view (according to my preferences)
  2. It seems like there is a feature/glitch when clicking on a task, and the resulting note has a blank first line, which my test cases had. Not sure what other, if any, can result in the same glitch. But with my test data, when I clicked on a task it highlighted the next task/line, so it seemed a little off.
1 Like

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