I had a dream about making uPortal skins more dynamic last night [1],
prompted by this feature branch and pull request.
https://github.com/jameswennmacher/uPortal/tree/UP-3940
https://github.com/Jasig/uPortal/pull/239
I'm eager to have a conversation about the big picture.
So. Here's what I hope is the best next nudge I can give this:
# A couple of motivating user stories: [2]
## 0. Many more skins
As a portal service owner I would like to be able to offer and manage
hundreds of (slightly different) skins rather than just one or a few.
The bigger picture context here is supporting massively more
multi-tenant uPortal. That entails, among I imagine many other
considerations, supporting potentially hundreds of skins rather than the
one or a handful that are currently typical in uPortal adoptions.
## 1. Editing a skin live via admin UI in portal
As a user with privileges over some skins, I would like to be able to
edit those skins live in the portal via a friendly UI rather than having
to edit raw source code (text editors?! Ew!) and run it through a build
process (Ant that invokes Maven that invokes a Ruby gem? Ew!). I would
like immediate visual feedback about what my changed skin feels like.
## 2. Skin edited in live portal takes effect immediately
As a portal service owner I would like the live edits to skins to take
effect immediately-ish. That doesn't necessarily mean having to tickle
active end-user uPortal sessions with changed skins, but it does mean I
don't want to have to restart the servlet container to pick up a skin tweak.
# Some background:
uPortal has Skins. Users can pick among them in the Customize Drawer in
Universality and I imagine they'll be able to do so in Respondr once the
Customize Drawer shapes up. [3] There's currently no concept, that I
know of offhand, of mapping which skins ought to be available to which
users. A user's preference for which skin is modeled as a stylesheet
parameter ("Skin name") [4] and they can select among all the skins
registered in the skinList.xml manifest applicable to the theme they are
using.
Skins live in /webapp/media/skins in the source tree, namespaced by the
theme they skin. There's a skinList.xml for each theme that registers
which skins apply to that theme with a wee bit of metadata. Skin
directories themselves can contain JavaScript, CSS, things that get
compiled into CSS namely SCSS and LESS, images used in the skin, and a
preview image of the skin useful for the end user UI for selecting among
skins.
At build time the skin source is transformed (LESS is compiled to CSS)
and the resulting browser-ready user-facing files are included in the
resulting uPortal.war in the /media/skins/ directory of the webapp,
served directly to the browser by Tomcat,
# Alternative implementation sketch
I think these user stories amount to "I want uPortal skins to be dynamic
data rather than static, compiled artifacts. I want them to be more like
entities, more like layout content, amenable to live editing because
they're part of the uPortal object model and are persisted and
communicated amongst nodes via the database, and less like Java classes
that are compiled from source, deployed, shared among uPortal nodes
through the happenstance of carefully deploying the same compiled static
artifacts to all the nodes, and expect that the Tomcat server will
restart to make changes take effect."
Which seems a fine enough set of wants. Dynamic, richer Java model, and
administration via portlets can enable some wonderful things.
So I suggest inventing a richer model for skins in the Java layer,
modeling what is (Skins with name and description, preview image, with
LESS source, and JavaScript and image sources, and compiled results from
some of that) and eventually what could be (perhaps some skins could be
built from still simpler primitives such as the
select-three-colors-to-tweak-the-skin demonstrated in the pull request
above).
Almost certainly invent a fronting SkinService too to incorporate a more
sophisticated model of how to figure out what skin goes with what user
in what context, who has permissions to do what to what skins, etc.
Skin selection stops being an incidental stylesheet parameter and starts
being something richer and separate. Maybe skins end up being
permissible entities. There's a fair amount of routine richness to bake
into the API in making this more dynamic-and-serviced-in-the-portal-UI
and less implied-process-through-edit-at-source-code-time.
The existing functionality would be a BoringFilesystemBackedSkinDao
implementation. Its behavior would be to read the compiled skin from
the filesystem. It would politely decline to support write operations,
perhaps, because folks interested in write operations would
implement a new JpaSkinDao implementation that, rather than getting the
skin from the file system, would get the skin from the uPortal database,
share it among nodes via the database.
Put not just metadata about the skins but the actual skin content, the
actual CSS content (and, eventually, images?) into the uPortal database.
Build out a skin administration portlet for administering, editing
these. I think it would always ought to support getting down to brass
tacks and uploading externally developed skins, I imagine, but of course
this also creates the opportunity to build out templating for easily
creating variations on existing skins setting a few colors, swapping
images for logos, etc. Skin creation / edit wizards and workflows.
Invent a SkinDeliveryController that serves up skin content to browsers,
and have browsers get the CSS, JavaScript, even images from that
controller rather than from paths that Tomcat serves directly from the
media directory. It would be backed by the SkinService and somewhere in
here there would be aggressive caching, of course.
All of which is a fair amount of work, but we'd come out the other end
with something pretty spiffy in modeling skins as data rather than as
compiled artifacts on the filesystem, and it feels a cleaner approach
than adding functionality that triggers writes down to the filesystem to
update skins in ways not reflected in the source code from which they
were compiled.
I mean, we have this problem now, live action in the portal changing
things that are in source control, but we have it scoped to entity
files, and so I expect that importing entity files is importing into the
database and live edits to entities need to be reflected in those source
entity files if I want them retained on a fresh import. I don't expect
the portal to be generating skins down to the filesystem on the fly?
Andrew
[1]: To be honest, I didn't actually have a dream. I am an intermittent
insomniac and it was more a matter of laying awake staring at the
ceiling thinking about making uPortal skins more dynamic. But
summarizing this as a dream is oh so much more romantic.
[2]: Just that, a couple of stories that seem central to what's being
pursued here, *not* a comprehensive set of requirements. Much
imagination (dreaming?) required.
[3]: Looks like continued progress in making the customize drawer shape
up, incidentally: https://github.com/Jasig/uPortal/pull/245 .
https://github.com/Jasig/uPortal/pull/242 .
[4]: User preference of which skin to use is stored in
UP_SS_USER_PREF_PARAM. It's declared as a parameter on the theme
stylesheet descriptor.
https://github.com/Jasig/uPortal/blob/master/uportal-war/src/main/data/required_entities/stylesheet-descriptor/Respondr.stylesheet-descriptor.xml
--
You are currently subscribed to [email protected] as:
[email protected]
To unsubscribe, change settings or access archives, see
http://www.ja-sig.org/wiki/display/JSG/uportal-dev