Populate milestone due dates from projects into portfolio list view

Is there any way I can display my milestone due dates in list view in my portfolio, which isn’t shown as the milestone progress bar?

I would love to have a field called “Milestone 1 Due Date” and have the portfolio grab the info from my project and autofill the field in the portfolio.

1 Like

@Samuel_Michaels2,

Does the Milestone progress column not work for you?

If you’re asking for a Milestone due date column, that would need a variable number of those for each project since it’s arbitrary how many milestones each project has.

Thanks,

Larry

This unfortunately does not provide a good overview at all.

Imagine my scenario: I have close to 200 projects in my portfolio and they all have the same 5 milestones. What I want is a date column in my list view with a field that automatically updates if the value in the milestone field is changed.

Cos let’s be serious here, how am I supposed to see at a glance which milestones are up next?

Yes I know I can build a dashboard to show me but that is again not an “at one glance” overview

What I want is this:

But with the dates being grabbed automatically by Asana from the milestones in the projects.

This is a very basic function IMO.

Note: Not a solution but marked as such to elevate a key reply

@Samuel_Michaels2,

I’ve moved your post to where you can click the title to scroll to the top and vote by clicking the Vote button.

There’s an existing workaround, though, that can create exactly what you’re asking for as shown in your screenshot. See this post and also the entire topic it’s in:

A note re the Milestone progress portfolio column:

They are displayed in order left to right by Due date. Also, any overdue milestones are shown as red diamonds.

Thanks,

Larry

The easiest solution would be to use Custom Scripts. I did it for a client, you setup a couple of date fields, and a rule that says “milestone date changed > run code” and this code will update the date field. I can share the code if needed

I’d say the solution from @Tetsuo_Kawakami I mentioned is easier. It doesn’t require either custom code or a rule.

I would definitely be interested in the code :slight_smile:

In the below code, I recognise milestones based on their name, and map those names to a different date field. We also find the “parent” project by filter on a prefix.


async function run() {
  const triggeringTask = await tasksApiInstance.getTask(task_gid);

  const parentProject = triggeringTask.data.memberships.find(m => m.project?.name.startsWith('PREFIX_TO_CHANGE_')).project
  let targetFieldGid
  switch(triggeringTask.data.name) {
    case "Milestone name #1 to change":
      targetFieldGid='1210250119968006'
      break;
    case "Name #2":
      targetFieldGid='1210250128776650'
      break;
    case "Name #3":
      targetFieldGid='1210250118406783'
      break;
  }

  log('Found parent project=',parentProject.name,parentProject.gid)
  log('Triggering task',triggeringTask.data.name.name,triggeringTask.data.name.gid,triggeringTask.data.due_on)
  log("Target field gid",targetFieldGid)
  if(targetFieldGid) {
    if (triggeringTask.data.due_on) {
      log("Updating project")
      projectsApiInstance.updateProject({
        data:{
          custom_fields: {
            [targetFieldGid]: {date:triggeringTask.data.due_on}
          }
        }
      }, parentProject.gid).then(result => {
        log("Project updated")
      })
    } else {
      log("No date on the triggering task")
    }
  } else {
    log("The task doesn't have a known name")
  }

}

run();

I haven’t noticed “run script” action until now.
I like this method so much!
I think this spreads capability.I’m going to learn it!

Total game changer, was quietly released.

1 Like

I have tried script action below. I’m sorry that descriptions are Japanese💦.
This makes a parent task return incomplete when at least a subtask is incomplete.
That can be also done with using AI studio or complicated rule settings.
I think that is not worth using AI studio because it’s too simple requirement.
Now I believe script action is the best way to achieve it.

async function run() {
  // サブタスクを取得
  const subtasks = await tasksApiInstance.getSubtasksForTask(task_gid);
  // サブタスクの完了状態を確認
  let allSubtasksCompleted = true;
  for (const subtask of subtasks.data) {
    // サブタスクの詳細情報を取得
    const subtaskDetails = await tasksApiInstance.getTask(subtask.gid);
    // 未完了のサブタスクがあるかチェック
    log(subtaskDetails.data.completed)
    if (!subtaskDetails.data.completed) {
      allSubtasksCompleted = false;
      break;
    }
  }
  
  // 未完了のサブタスクがある場合、親タスクを未完了に設定
  if (!allSubtasksCompleted) {
    let body = {
      "data":{
        "completed": false
      }
    }
    await tasksApiInstance.updateTask(body, task_gid);
  }
}

// To function properly, the script must end with returning a Promise via run().
run();