'Display a history as a nested structure showing the jobs and workflow
invocations that created each dataset (if any).'

@web.expose
def display_structured(self, trans, id=None):

    if (id is None):
        id = trans.history.id
    else:
        id = self.decode_id(id)
    trans.sa_session.expunge(trans.history)
    history = trans.sa_session.query(model.History).options(eagerload_all('active_datasets.creating_job_associations.job.workflow_invocation_step.workflow_invocation.workflow'), eagerload_all('active_datasets.children')).get(id)
    assert history
    assert ((history.user and (history.user.id == trans.user.id)) or (history.id == trans.history.id) or trans.user_is_admin())
    items = []
    jobs = odict()
    for hda in history.active_datasets:
        if (hda.visible is False):
            continue
        original_hda = hda
        if (not original_hda.creating_job_associations):
            items.append((hda, None))
        for assoc in original_hda.creating_job_associations:
            job = assoc.job
            if (job in jobs):
                jobs[job].append((hda, None))
            else:
                jobs[job] = [(hda, None)]
    wf_invocations = odict()
    for (job, hdas) in jobs.iteritems():
        if job.workflow_invocation_step:
            wf_invocation = job.workflow_invocation_step.workflow_invocation
            if (wf_invocation in wf_invocations):
                wf_invocations[wf_invocation].append((job, hdas))
            else:
                wf_invocations[wf_invocation] = [(job, hdas)]
        else:
            items.append((job, hdas))
    items.extend(wf_invocations.items())
    items.sort(key=(lambda x: x[0].create_time), reverse=True)
    return trans.fill_template('history/display_structured.mako', items=items, history=history)
