TracksApp / tracks

Tracks is a GTD™ web application, built with Ruby on Rails
https://www.getontracks.org/
GNU General Public License v2.0
1.17k stars 537 forks source link

Propagated due date #2411

Open Werkov opened 4 years ago

Werkov commented 4 years ago

Consider the following scenario:

There will be visible only action B in the next actions (A won't have satisfied deps), however, there'll be no information that action B needs to be completed until date D too.

Suggestion -- introduce a propagated due date. It's a minimum effective due date of actions that an action is prerequisite for. The effective due date is either due date explicitly set by a user or propagated due date of an action.

This way it's possible to create chained actions and set/modify explicit due date only on the last one. If there are no other constraints, this date would propagate through the chain to the actionable action.

ZeiP commented 4 years ago

You're right. Something like this seems like a very good idea. There was a duplicate issue #2474, there are also some comments on the feature in that issue.

I've got my hands full of maintaining the current code base (fixing bugs and hopefully trying to clean up a bit at some point) but I warmly welcome any contributions towards fixing this. Let me know if you can contribute and need any help.

GregSutcliffe commented 4 years ago

Moving the key comment here :)

I think this is a UI-level thing - it can probably be calculated in the controller when rendering. After all, we already know how to figure out and render the dependant tasks, we just need to calculate some additional metadata while we do it. I can't promise when, but I can probably try to fix it in the next few weeks.

ZeiP commented 4 years ago

Yep. One lane to investigate would be to override the due date field in the model with a method that contains this logic.

GregSutcliffe commented 4 years ago

I'm wary of that because you'd also have to undo that when dependant actions are unchained. Consider:

If we override A to be "2 days from now" and then later we decide that B doesn't really depend on A, then we'd need to restore "4 days from now", which means saving it to another attribute or something. Seems cleaner to leave the objects alone and do it in the view/controller?

ZeiP commented 4 years ago

Ah yes. I didn't mean changing the data. My idea is basically similar than for example the starred attribute of todos. They are actually tags, but are calculated on-the-go:

  def starred?
    return has_tag?(STARRED_TAG_NAME)
  end

  def toggle_star!
    self.starred= !starred?
  end

  def starred=(starred)
    if starred
      _add_tags STARRED_TAG_NAME unless starred?
    else
      _remove_tags STARRED_TAG_NAME
    end
    starred
  end

So basically I'm proposing overriding the getter of the due field in the model with a method that returns either the smallest due date of any dependent actions or the due date of the todo itself. Or actually it might be better to add the calculated due date with a different name to also allow showing the real due date of the todo item itself when necessary.

GregSutcliffe commented 4 years ago

Yeah, here we go, I think I can add something here: https://github.com/TracksApp/tracks/blob/master/app/helpers/todos_helper.rb#L270

Looping over todo.uncompleted_predecessors should do it, I think.

GregSutcliffe commented 4 years ago

Heh, crossed threads :)

So I think my proposal of changing the helper is not so different from your getter, either should work. I'm still not convinced we need to store it on the object - if we need to render the "real" due date, it's still available in todo.due

EDIT: oh, of course, todo.due won't be available if we change the getter. Definitely leaning towards changing the helper...

ZeiP commented 4 years ago

Yeah, I didn't mean that we should store the date, we should calculate it on-the go. So basically add something like this:

def real_due
  first_due = self.due
  # Loop over todo.pending_successors and save the due date to first_due variable if it's smaller than the previous value
  return due

So the idea is that the data is calculated in the model file, but of course not saved to database. This way it can be easily called where ever the ”real” due date is needed in the UI.

GregSutcliffe commented 4 years ago

That makes some sense. In any case, we've got a least 3 approaches now, so I'll poke at it later on (probably next week, tbh) and see what feels good :)