Inputs

ContributorTag: INPUT[text:ContributorTag] GoalTags: INPUT[inlineListSuggester(optionQuery("Efforts/Goal Board/GoalTags")):GoalTags] Start Date: INPUT[datePicker:startDate] End Date: INPUT[datePicker:endDate]

BUTTON[new-goal-tag] BUTTON[refresh-tables]

[[GoalTag Buttons]]

Tasks Completed
const contributorTag = dv.current().ContributorTag;
 
const goalTagsList = dv.current().GoalTags
  .map(gt => {
    const fileName = gt.path.split('/').pop().replace('.md', '');
    return '#' + fileName.replace(/\s+/g, '-');
  });
 
const startDate = dv.date(dv.current().startDate);
const endDate = dv.date(dv.current().endDate);
 
dv.taskList(dv.pages().file.tasks
  .where(t => t.text.includes(contributorTag))
  .where(t => t.completed && t.completion >= startDate && t.completion <= endDate)
  .where(t => goalTagsList.some(goalTag => t.text.includes(goalTag)))
  ,false)
Tasks In Progress
const contributorTag = dv.current().ContributorTag;
const goalTagsList = dv.current().GoalTags
  .map(gt => {
    const fileName = gt.path.split('/').pop().replace('.md', '');
    return '#' + fileName.replace(/\s+/g, '-');
  });
const endDate = dv.date(dv.current().endDate);
 
dv.taskList(dv.pages().file.tasks
  .where(t => t.text.includes(contributorTag))
  .where(t => !t.completed)
  .where(t => !t.text.includes("#Blocked"))
  .where(t => goalTagsList.some(goalTag => t.text.includes(goalTag)))
  ,false)
Tasks Blocked
const contributorTag = dv.current().ContributorTag;
const goalTagsList = dv.current().GoalTags
  .map(gt => {
    const fileName = gt.path.split('/').pop().replace('.md', '');
    return '#' + fileName.replace(/\s+/g, '-');
  });
const endDate = dv.date(dv.current().endDate);
 
dv.taskList(dv.pages().file.tasks
  .where(t => t.text.includes(contributorTag))
  .where(t => !t.completed)
  .where(t => t.text.includes("#Blocked"))
  .where(t => goalTagsList.some(goalTag => t.text.includes(goalTag)))
  ,false)

INPUT[textArea(placeholder('Please explain the blocked tasks, if any')):blockedReasons]

Steps to Finalize Task Sheet

  1. Bry Please explain the blocked tasks, if any
  2. Bry Generate the Task Sheet Report
  3. Bry Review and Sign this Task Sheet Report

Task Sheet Report

const contributorTag = dv.current().ContributorTag;
const goalTagsList = dv.current().GoalTags
  .map(gt => {
    const fileName = gt.path.split('/').pop().replace('.md', '');
    return '#' + fileName.replace(/\s+/g, '-');
  });
const startDate = dv.date(dv.current().startDate);
const endDate = dv.date(dv.current().endDate);
 
function extractMinutes(text, tag) {
  const regex = new RegExp(`${tag}\\/(?:timed|spent)\\/(\\d+)minutes`);
  const match = text.match(regex);
  return match ? parseInt(match[1]) : 0;
}
 
let tableData = goalTagsList.map(goalTag => {
  const tasks = dv.pages().file.tasks
    .where(t => t.text.includes(contributorTag))
    .where(t => t.completed && t.completion >= startDate && t.completion <= endDate)
    .where(t => t.text.includes(goalTag));
  
  let tasksCompleted = 0;
  let minutesWorked = 0;
  
  tasks.forEach(task => {
    tasksCompleted++;
    minutesWorked += extractMinutes(task.text, contributorTag);
  });
  
  return {
    goalTag: goalTag,
    tasksCompleted: tasksCompleted,
    minutesWorked: minutesWorked
  };
});
 
dv.table(["Goal Tags", "Tasks Completed", "Minutes Worked"], 
  tableData.map(row => [
    row.goalTag,
    row.tasksCompleted,
    row.minutesWorked
  ])
);