Weekly/Daily Notes Uncompleted/Completed Dataview Table

I ran across this post Dataview query for all tasks in folder with custom status where holroy provided an amazing solution. However, I’ve been attempting to simplify to just show “Count,” and the progress bars.

What I’m trying to do

I initially was looking for something where I could view weekly notes and daily notes’ uncompleted tasks from the past week filtering using my metadata of “week” and “year.”

But realized that the previous mentioned forum post was looking all a folder, and for me is not returning all uncompleted tasks (so it seems). It would be more practical for me to have this by file not folder. Also, that I needed to just simplify this for my needs. A uncompleted tasks bar and a completed tasks bar, maybe somehow to include the count within the bar(s) would awesome! Unfortunately, that’s where my capabilities fall very short.

Things I have tried

I’ve attempted to do the below but without success.

Here’s my current code, when I try to reposition the uncompleted bar below the completed bar using
it errors.

TABLE without id file.link + "<br>" + "<progress value='" + (CompleteCount * 100)    / Count + "' max='100' />" as "Completed Progress", Count, UncompleteCount as UnC, CompleteCount as C, 
  "<progress value='" + (UncompleteCount * 100 ) / Count + "' max='100' />" as "Uncompleted Progress"
FROM "Work"
FLATTEN file.lists as item
WHERE item.task and contains(list(" ", "/", "-", "x"), item.status)
WHERE year = "2024"
GROUP BY file.folder
FLATTEN length(rows.item.text) as Count
FLATTEN length(filter(rows.item.status, (s) => s = " ")) as Open
FLATTEN length(filter(rows.item.status, (s) => s = "/")) as InProgress
FLATTEN length(filter(rows.item.status, (s) => s = "x")) as Complete
FLATTEN length(filter(rows.item.status, (s) => s = "-")) as Canceled
FLATTEN Open + InProgress + Canceled as UncompleteCount
FLATTEN Complete as CompleteCount

here is the solution :slightly_smiling_face:

```dataviewjs
const currentYear = new Date().getFullYear();
const pages = dv.pages('"Work"')
    .filter(p => p.year == currentYear && p.file.lists.some(item => item.task && [" ", "/", "-", "x"].includes(item.status)));

dv.table(
    ["File Name", "Summary"],
    pages.map((p, index) => {
        const tasks = p.file.lists.filter(item => item.task);
        const count = tasks.length;
        const complete = tasks.filter(item => item.status == "x").length;
        const uncomplete = count - complete;
        const fileNameContent = `[[${p.file.name}]]<br>` + 
                                `C <progress value='${(complete * 100) / count}' max='100'></progress> ${complete}<br>` + 
                                `Unc <progress value='${(uncomplete * 100) / count}' max='100'></progress> ${uncomplete}`;
        return [
            fileNameContent + (index < pages.length - 1 ? "<br>-" : ""),
            p.summary || "No summary has been written"
        ];
    })
);

Make sure the javascript queries enabled in the dataview settings

The final result :

1 Like

You’re a wizard sir! I need some time to unpack how you did this. I’m not too handy with JS. However, this initial solution is great! and runs faster than just dataview alone. However, I just need to filter it to weekly notes for the current week in the format of “[W]WW” and current fiscal year (fy) as that looks like FY24".

Thank you again for the big hand-up on this!

1 Like

I’ve got two questions, is there a way to make the first column width a min-width? Also, is there a way to target a specific folder with files where “Year” and “Week” equal specific values, e.g., “2024” and “W35”?

Oh and one other thing, is there a way to simply sort the returned files ascending order?

I found Sorting Dataview JS - #4 by justdoitcc, but this is using “where” and “sort” based on the file name and cday values which. I need to pull files from “where” equals “Work/Weekly Notes” and metadata value “week” equals a specific text value “W35.” to help narrow this, it including the text value for “fy” like “FY25” would be great! I’m testing it now, but I can’t seem to wrap my head around js…

1 Like

This query sorts the notes in ascending order as you requested and takes the notes from the “Work/Weekly Notes” folder and displays the notes where the week is equal to the current week as well as the current year.

```dataviewjs
const currentYear = new Date().getFullYear();
const currentDate = new Date();
const startWeekday = 6; // 0 = Sunday, 1 = Monday, ..., 6 = Saturday (adjust this value as needed)

const firstDayOfYear = new Date(currentYear, 0, 1);
const daysSinceFirstDay = Math.floor((currentDate - firstDayOfYear) / (24 * 60 * 60 * 1000));
const adjustedDays = daysSinceFirstDay + (firstDayOfYear.getDay() <= startWeekday ? startWeekday - firstDayOfYear.getDay() : 7 - (firstDayOfYear.getDay() - startWeekday));
const currentWeek = Math.ceil(adjustedDays / 7);
const formattedWeek = `W${String(currentWeek).padStart(2, '0')}`;

const pages = dv.pages('"Work/Weekly Notes"')
    .filter(p => p.year == currentYear && p.week == formattedWeek && p.file.lists.some(item => item.task && [" ", "/", "-", "x"].includes(item.status)))
    .sort(p => p.file.name, 'asc');

dv.table(
    ["File Name", "Summary"],
    pages.map((p, index) => {
        const tasks = p.file.lists.filter(item => item.task);
        const count = tasks.length;
        const complete = tasks.filter(item => item.status == "x").length;
        const uncomplete = count - complete;
        const fileNameContent = `[[${p.file.name}]]<br>` + 
                                `C <progress value='${(complete * 100) / count}' max='100'></progress> ${complete}<br>` + 
                                `Unc <progress value='${(uncomplete * 100) / count}' max='100'></progress> ${uncomplete}`;
        return [
            fileNameContent + (index < pages.length - 1 ? "<br>-" : ""),
            p.summary || "No summary has been written"
        ];
    })
);
1 Like

Again, you’re a wizard. However, this would pose some issues as I’m going through my notes where this is applied, it would always show the current situation. Is the below possible, it isn’t working for me, but obviously I don’t know the correct syntax.

const currentYear = metaData.year "2024";
const formattedWeek = metaData.week "W34";
1 Like

I want it to be dynamic so that you don’t have to go through the trouble of modifying the code over and over again, can you explain these issues so that I can solve them for you? If the issue is with the current week, you can change the day of the week through the code, and in any case if you want to do it manually, here is the code:

```dataviewjs
const currentYear = "2024"
const currentWeek = "W34";

const pages = dv.pages('"Work/Weekly Notes"')
    .filter(p => p.year == currentYear && p.week == currentWeek && p.file.lists.some(item => item.task && [" ", "/", "-", "x"].includes(item.status)))
    .sort(p => p.file.name, 'asc');

dv.table(
    ["File Name", "Summary"],
    pages.map((p, index) => {
        const tasks = p.file.lists.filter(item => item.task);
        const count = tasks.length;
        const complete = tasks.filter(item => item.status == "x").length;
        const uncomplete = count - complete;
        const fileNameContent = `[[${p.file.name}]]<br>` + 
                                `C <progress value='${(complete * 100) / count}' max='100'></progress> ${complete}<br>` + 
                                `Unc <progress value='${(uncomplete * 100) / count}' max='100'></progress> ${uncomplete}`;
        return [
            fileNameContent + (index < pages.length - 1 ? "<br>-" : ""),
            p.summary || "No summary has been written"
        ];
    })
);

Here is another query in which you can modify the width of the first column by changing
inline-block; width: 250px; to the value you want but I prefer leave it as it is

The query that has dynamic week and year:

```dataviewjs
const currentYear = new Date().getFullYear();
const currentDate = new Date();
const startWeekday = 6; // 0 = Sunday, 1 = Monday, ..., 6 = Saturday (adjust this value as needed)

const firstDayOfYear = new Date(currentYear, 0, 1);
const daysSinceFirstDay = Math.floor((currentDate - firstDayOfYear) / (24 * 60 * 60 * 1000));
const adjustedDays = daysSinceFirstDay + (firstDayOfYear.getDay() <= startWeekday ? startWeekday - firstDayOfYear.getDay() : 7 - (firstDayOfYear.getDay() - startWeekday));
const currentWeek = Math.ceil(adjustedDays / 7);
const formattedWeek = `W${String(currentWeek).padStart(2, '0')}`;

const pages = dv.pages('"Work/Weekly Notes"')
    .filter(p => p.year == currentYear && p.week == formattedWeek && p.file.lists.some(item => item.task && [" ", "/", "-", "x"].includes(item.status)))
    .sort(p => p.file.name, 'asc');

dv.table(
    ["File Name", "Summary"],
    pages.map((p, index) => {
        const tasks = p.file.lists.filter(item => item.task);
        const count = tasks.length;
        const complete = tasks.filter(item => item.status == "x").length;
        const uncomplete = count - complete;
        const fileNameLink = `[[${p.file.name}]]`;
        const fileNameContent = `C <progress value='${(complete * 100) / count}' max='100'></progress> ${complete}<br>` + 
                                `Unc <progress value='${(uncomplete * 100) / count}' max='100'></progress> ${uncomplete}`;
        return [
            `<span>${fileNameLink}</span><br><div style="display: inline-block; width: 250px; overflow: hidden; text-overflow: ellipsis;">${fileNameContent}</div>`,
            p.summary || "No summary has been written"
        ];
    })
);

The query that has a manual week and year:

```dataviewjs
const currentYear = "2024"
const currentWeek = "W34"

const pages = dv.pages('"Work/Weekly Notes"')
    .filter(p => p.year == currentYear && p.week == currentWeek && p.file.lists.some(item => item.task && [" ", "/", "-", "x"].includes(item.status)))
    .sort(p => p.file.name, 'asc');

dv.table(
    ["File Name", "Summary"],
    pages.map((p, index) => {
        const tasks = p.file.lists.filter(item => item.task);
        const count = tasks.length;
        const complete = tasks.filter(item => item.status == "x").length;
        const uncomplete = count - complete;
        const fileNameLink = `[[${p.file.name}]]`;
        const fileNameContent = `C <progress value='${(complete * 100) / count}' max='100'></progress> ${complete}<br>` + 
                                `Unc <progress value='${(uncomplete * 100) / count}' max='100'></progress> ${uncomplete}`;
        return [
            `<span>${fileNameLink}</span><br><div style="display: inline-block; width: 250px; overflow: hidden; text-overflow: ellipsis;">${fileNameContent}</div>`,
            p.summary || "No summary has been written"
        ];
    })
);
1 Like

I believe for most people, the dynamic solution will be best :+1:. However, I’ll use this in my weekly notes and monthly notes as a sort of high-level view of my completed actions. I haven’t become advanced enough to warrant a “homepage” although I have one, but it was becoming overwhelming and I needed to simplify. I already use multiple other project management and communications apps. Obsidian is one where I just feel is my personal and private space, unlike OneNote, MS Teams, MS Project, Miro, and the countless shared PowerPoints, Word Docs, and Excel workbooks, my Obsidian is a more secure space for me.

The reason why I prefer a solution that makes me have to select the ‘year’ and ‘week’ is to force me to be more deliberate in my action to review uncompleted tasks. Unlike my notebook, which I use daily for random notes and scratch bad, Obsidian allows for a lot of automation. Although I try to automate nearly anything I can at work, with note taking (or rather note making) I prefer to keep most of it manual. It forces me to keep my focus and be deliberate with what I’m recording and why.

The script I’ll use in my monthly notes:

const currentYear = "2024";
const currentMonth = "8";

const pages = dv.pages('"Work/Weekly Notes"')
    .filter(p => p.year == currentYear && p.month == currentMonth && p.file.lists.some(item => item.task && [" ", "/", "-", "x"].includes(item.status)))
    .sort(p => p.file.name, 'asc');

dv.table(
    ["Weekly Notes", "Summary"],
    pages.map((p, index) => {
        const tasks = p.file.lists.filter(item => item.task);
        const count = tasks.length;
        const complete = tasks.filter(item => item.status == "x").length;
        const uncomplete = count - complete;
        const fileNameLink = `[[${p.file.name}]]`;
        const fileNameContent = `Cpl. <progress value='${(complete * 100) / count}' max='100'></progress> ${complete}<br>` + 
                                `Unc. <progress value='${(uncomplete * 100) / count}' max='100'></progress> ${uncomplete}`;
        return [
            `<span>${fileNameLink}</span><br><div style="display: inline-block; width: 250px; overflow: hidden; text-overflow: ellipsis;">${fileNameContent}</div>`,
            p.summary || "No summary has been written"
        ];
    })
);

The script that I’ll use in my weekly notes:

const currentYear = "2024"
const currentWeek = "W31"

const pages = dv.pages('"Work/Daily Notes"')
    .filter(p => p.year == currentYear && p.week == currentWeek && p.file.lists.some(item => item.task && [" ", "/", "-", "x"].includes(item.status)))
    .sort(p => p.file.name, 'asc');

dv.table(
    ["Daily Notes", "Summary"],
    pages.map((p, index) => {
        const tasks = p.file.lists.filter(item => item.task);
        const count = tasks.length;
        const complete = tasks.filter(item => item.status == "x").length;
        const uncomplete = count - complete;
        const fileNameLink = `[[${p.file.name}]]`;
        const fileNameContent = `Cpl. <progress value='${(complete * 100) / count}' max='100'></progress> ${complete}<br>` + 
                                `Unc. <progress value='${(uncomplete * 100) / count}' max='100'></progress> ${uncomplete}`;
        return [
            `<span>${fileNameLink}</span><br><div style="display: inline-block; width: 250px; overflow: hidden; text-overflow: ellipsis;">${fileNameContent}</div>`,
            p.summary || "No summary has been written"
        ];
    })
);

@Rios – Thank you again Rios for the awesome insights and work. I appreciate it, and I really hope this helps others! Also, thanks to @holroy for the initial posting and support.

In the future, I’ll try to figure out how to add a count of meetings, and list of objectives worked on for a month or week to include in the Weekly Notes scripting.

1 Like

@Rios – Not sure if I’ve missed something but I’m trying to make the “Summary” font-size smaller. It renders the summary but not at the specified font-size.

const currentFy = "FY25";
const currentWeek = "W36";

const pages = dv.pages('"Work/Daily Notes"')
    .filter(p => p.fy == currentFy && p.week == currentWeek && p.file.lists.some(item => item.task && [" ", "/", "-", "x"].includes(item.status)))
    .sort(p => p.file.name, 'asc');

dv.table(
    ["Daily Notes", "Summary"],
    pages.map((p, index) => {
        const tasks = p.file.lists.filter(item => item.task);
        const count = tasks.length;
        const complete = tasks.filter(item => item.status == "x").length;
        const uncomplete = count - complete;
        const fileNameLink = `[[${p.file.name}]]`;
        const fileNameContent = `Cpl. <progress value='${(complete * 100) / count}' max='100'></progress> ${complete}<br>` + 
                                `Unc. <progress value='${(uncomplete * 100) / count}' max='100'></progress> ${uncomplete}`;
        return [
            `<span>${fileNameLink}</span><br><div style="display: inline-block; width: 250px; overflow: hidden; text-overflow: ellipsis;">${fileNameContent}</div>`,
            `<p class="summary" style="font-size: 10px;">${p.summary || "No summary has been written"}</p>`
        ];
    })
);

I’m also trying to add a border bottom of light grey to make rows more clear

1 Like

figured out that I needed to set a span in the p for the summary… I forgot

1 Like

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