NOJIRA Fix syntax issues for IE
SSP-1983 Render Action Plan Task link as HTML
SSP-1994 Fix dept/div code transposition
SSP-1994 Guard against bad codes when printing templates
SSP-1999 Remove event listener on SemesterPanelContainerViewController#destroy()

Previously was being added instead of removed.
SSP-1997 Add guard for MAP TOs without a modification timestamp
SSP-2001 Destroy SemesterPanels when rendering different Plan/Template

Previously they were just being removed from the view, not destroyed.
SSP-2005 Fix course un-plan button

Appears to have been a regression from recent perf enhancements which
changed the type of SemesterPanel from Ext.Panel to Ext.grid.Panel,
which then invalidated assumptions about the view hierarchy in that
component.
SSP-2005 Re-enable planned course double click handler

Looks like this was a regression from recent perf changes that
migrated code from SemesterGridViewController to
SemesterPanelViewController. The itemdblclick event handler
registration just went missing.
SSP-2011 Remove dead code
SSP-2009 Fix on/off-plan display corruption issues

Reported issue involved loading a MAP template, navigating to a
different tool, coming back to MAP, and the display of the
student's on/off plan status would be corrupt, e.g. just the
"question mark" icon.

The most proximate cause of the display being unexpected in general
was that neither dismissing the MAP tool nor loading it back up
reset the current MAP plan singleton. And because the component
that looks up and displays the student's on/off-plan status
initializes before the component that loads the "current" plan
upon navigating to the MAP tool, the former thought it was
dealing with a template, not a plan, so it gave up on calculating
the status. But when it did so it only partially hid the view
components that represent that status.

The actual patch ended up being rather large for several reasons,
esp because the current plan needed to be reset in several locations
and to avoid regressing to a state where we were loading the plan
status several times on every plan render. The patch also ended up
simplifying the plan lookup plumbing code in MapPlanToolViewController
to eliminate all the nested functions for tracking multiple service
calls. It just wasn't necessary in this case and was making debugging
more difficult than it needed to be. Also tried to be more consistent
w/r/t when that component marks its view as loading and finished
loading.
SSP-2007 Fix elective and color store load timing for MAP

The originally reported issue was that elective colors wouldn't
render correctly for the very first MAP rendered in a given
client-side application instance.

This was caused by a timing problem. SemesterPanel's need
the elective and color stores to be fully loaded to support
its renderer functions. Initialization of these stores was
happening somewhat by accident, though, by virtue of their
injection into SemesterPanelViewController, which, because of
the way the stores were coded, just happened to result in a
load() when injected for the first time. But that load() is,
of course, asynchronous. So SemesterPanels would start to render
before the store/s had completed loading.

The workaround in this patch is to make sure those stores
are initialized before creating/rendering any SemesterPanels.
This is complicated by the fact that that loading is async and
most of the MAP rendering code assumes a more or less synchronous
process.

Once that was working, the "load on instantiation" code had to
be removed from the relevant store implementations, else we'd
be loading these stores several times over per MAP render. This
broke the elective admin UI, which assumed the colors store
would be fully loaded just by virtue of referencing it.

The workaround for the admin problem was to add a config option
to our AdminTreeMenu (interfaceOptions.storeDependencies), with
which we can specify the set of stores that should be initialized
along with the "main" admin item store.

I'm concerned the admin piece might still have some timing issues
because the "main" admin item store is bound to the view before
being loaded. So if it ends up loading before its dependencies
load, the view might still end up corrupted. But so far I've not
actually seen this happen locally.
SSP-2007 Delay "main" admin UI store load until dependencies loaded

In the original SSP-2007 patch it was possible to render the admin
UI before all the dependent stores loaded, e.g. before the color
store had loaded in the elective admin UI. This actually mostly worked
OK, at least in that particular situation. The color column could
potentially just take a while to render.

I elected to reorder things a bit, though, to not trigger the
"main" store load until all the dependencies had loaded b/c we
don't really have a good way of indicating onscreen that a column is
still waiting for data. And I have no idea what chaos would ensue
if you tried to edit an incompletely rendered column.
SSP-2008 Reflect term validations against all planned courses

Previously, duplicate planned courses would not reflect term
validation violations.

This was happening b/c planned courses were placed into a map
keyed by course code but with only one course per code. After
calculating violations for all the courses in a term, the
invalid courses in the course-code map were marked as such. But
because the course-code map could only have one course per code,
plans with multiple instances of the same course-code pair (even
across terms) would end up with at most one flagged course per code,
effectively chosen at random.
SSP-2015 Clear dirty flag when resetting current Plan state

Not sure why, but in some cases the dirty flag was being set on the
singleton "current plan" - seemingly just when navigating from a user
with a plan to a user without a plan after having visited the MAP tool
for the former. My theory is that the navigation to the plan-less user
would either skip the dirty check for some reason or set the dirty
flag itself. And because the target user didn't herself have a plan,
some or all of the plan response mapping code would be skipped
altogether and the flag wouldn't be unset. So the next time you
navigated away from the planless user it would look like the singleton
plan was dirty.

Worrisome that I can't find the root cause, but clearing the dirty
flag every time the singleton plan model is reset seems to fix the
symptoms.
SSP-2017 Exit person sync gracefully on empty person result set

This behavior should have been present regardless, but the root cause
of the empty result sets in the originally reported issue was the
presence of a soft-deleted person record. PersonDao.getAll() does not
take the requested object status filter into account when producing
its count for the unpaginated result set, but it does when actually
running invidual paginated queries. So when a soft-deleted person
exists, the total count did not match the count that could actually
be returned. Thus the sync job would request an additional page
which would always be empty.

The PersonDao.getAll() behavior has been around since April 2012, so
I did not make any changes to it for this ticket. That will need to
be dealt with separately.
SSP-2022 Only set MAP menu bar spinner if data definitely being loaded
SSP-2022 Clear spinner after accepting 'no selected template' alert
SSP-2025 Make sure plan is dirtied when dropping a valid course
SSP-2004 Fix MAP event handler registrations

MapViewController seems to have been clobbering existing application
event handlers before adding its own. It was doing this at least in
part because the SSP ApplicationEventsController API only allowed one
listener per event. This mostly worked except for the case of the
'toolsNav' event for which we do have other important event listeners,
notably the listener that expands and contracts the search/caseload
panel. So you'd get the expected expand/contract behavior until you
navigated to the MAP tool, then MAP's 'toolsNav' handler would replace
the 'standard' one, and the expand/contract behavior wouldn't work
until circumstances conspired to re-register the "standard" handler,
which usually only happened when reloading the browser. Other events
just happened to not exhibit this behavior because there weren't other
listeners.

The workaround for 'toolsNav' was to remove the handler clobbering code
and drop down below ApplicationEventsController to the standard Ext.js
Application API to register the MapViewController handler while
preserving the registration of the handler already added by
SearchViewController (which actually implements the expand/collapse
behavior).

This patch is conservative in that it doesn't try to fix the
registration of events that aren't currently broken (basically
all events except 'toolsNav'), but because event registration is a
first-one-wins situation, expect unreliable behavior in the future
should we introduce any other components that rely on the same
application events:

  toolsNav
  personNav
  personButtonAdd
  personToolbarEdit
  personButtonEdit
  personButtonDeleted
  retrieveCaseload
  personStatusChange

I think the solution for this problem is at least two-fold...

  1) Change the ApplicationEventsController API to stop
     silently dropping event handler registrations. Nobody
     will ever expect that behavior. A "replace" operation
     is fine, but not a "set unless already set".

  2) Refactor the event model into before*, on*, and after*
     events for each change to be broadcast. 'before*' events
     are intended to offer the option of canceling the other two.

Number 2 will go a long way toward eliminating the need for an
event handler registration function with "set unless already set"
semantics. I.e. the only reason you'd want that would be to make sure
a privileged listener gets veto power, but you can get the same thing
with events that better reflect change lifecyles without creating the
fragility we're seeing in this current issue.

This patch also moves all handler de-registration to destroy() and
properly scopes the de-registrations to make sure we're only cleaning
up handlers we registered and to make sure we actually do clean up
those registrations. This is intended primarily to address the
'toolsNav' event handler clobbering problem. It might also have an
incrementally beneficial impact on memory management since MAP
components can now be GC'd immediately upon navigating away from MAP.
But I don't think the original factoring was actually causing the
memory leaks reported in the field because navigating back to MAP
would again clobber any event listeners previously registered.

It's worth noting that the code doing the clobbering doesn't behave
as expected given the Ext.js docs
(http://docs.sencha.com/extjs/4.1.0/#!/api/Ext.app.Application-method-removeListener):

  me.appEventsController.removeEvent({eventName: 'toolsNav', scope: me.application});

Which is handled by:

  removeEvent: function( args ){
    if ( this.getApplication().hasListener( args.eventName ))
    {
      this.getApplication().removeListener( args.eventName, args.callBackFunc, args.scope);
    }
  }

The Ext.js docs (and code, as I read it) strongly suggest that the
absence of a args.callBackFunc here would result in a no-op. But that
seems pretty clearly to not be the case.

On the non-conservative side, this patch also simplifies
MapViewController event handler callback scopes to be less indirect.
In no case do we need the callback scope to be the application so it is
now always the current component (MapViewController).