UW-Madison-DoIT/angularjs-portal — pull request #34 by apetro (2014-10-29 16:08:06+00:00)
Title: MUMUP-1267 : Dynamic Categories

Parses the Categories relevant to the user from the `portlets` data rather than relying upon hard-coded Categories array.

"Relevant" means
* browseable by the user (so that it's appropriate that the user see the Category), *and*
* contains at least one portlet browseable by the user (so it's useful that the user filter on the category).

Happily, that's exactly what portlet.categories is supposed to be. So, simply parses the relevant categories, client-side, out of the portlet data feed.

---

As an admin:

![categories_as_admin](https://cloud.githubusercontent.com/assets/952283/4829213/757742b0-5f85-11e4-82f6-e658f27d0701.png)

As a student:

![categories_as_student](https://cloud.githubusercontent.com/assets/952283/4829216/78ead218-5f85-11e4-8622-bc80ae750aff.png)

---

Tradeoffs made and Known issues:

* Instead of parsing categories out client-side, could instead have introduced a new REST service server-side and simply pulled the categories from that. Maybe should eventually refactor to that solution, would be more explicit and potentially yield re-usable REST service for other needs. Perhaps refactor to that if/when those needs arise or if/when this solution turns out to have client-side performance problems. (It doesn't seem to.) Googling around, the complaining about `$.inArray()` performance seems to just be about ancient browsers and not an issue in modern browsers.
* I'm not understanding when to use `store` vs when to use `$scope`. This changeset maintains status quo of storing categories into `$scope`.
* Parsing the categories in `getPortlets()` and including them in the response is cute. It has some nice characteristics in that here, categories are modeled as another view on that same data, and so the categories becomes available through the same means and in the same promise as portlets. It's arguably less complex than having two methods with two promises that will fire in an arbitrary order (and that depend on the same backing data, after all.) But it's also a little weird in that `getPortlets()` now returns portlets *and* categories and whenever you say *and* a thing is probably doing too much. **I suggest this is good enough for Beta1.** This code is definitely going to need future refactoring, since there's something weird going on with `getPortlets()` and `getPortlet()` and their relationship.
* **Doesn't fully cache the parsed categories.** Categories are not re-parsed on every request, but they are re-parsed sometimes, and performance would be faster if they were always cached. This is probably because the cache scope within `getPortlets()` is *on the `$url` invocation, not on the whole method.* I fought with caching the parsed categories within the Marketplace service, which is probably the right solution since that's a Singleton with the right area of responsibility, but I gave up after fighting with how to get the function-in-a-function to write the categories back into the right scope. Doubtless this would be trivial if I actually knew `JavaScript`. Nonetheless, **performance seems eminently good enough for Beta1.**