UI Theming system

Hi,

I’ve been trying to think of a clean solution for laying various UIs
on top of CommCare while keeping the code relatively untouched. I came
up with the following idea:

  • In settings (rapidsms.ini), add a “template_theme” directive

  • render_to_response() will read this directive. If the directive is
    empty or has the value “default”, it will work as it does now - use
    the “<current_dir>/templates” path. If the directive has another
    value, it will use “<current_dir>/templates/” (or
    "<current_dir>/_templates", or whatever we decide makes most
    sense).

  • If there is no directory, render_to_response will revert to
    the default one.

This allows developers to create new themes without modifying the
existing code (no need for if statements in the views) and without
having to create a complete alternative template system. They only
need to change settings.template_theme and then add templates where
applicable.

Obviously, though, this only works for template-level theming.

What do you think?

  • Nir

this seems reasonable. Did we post/search stack overflow? I would imagine
many people have had to solve this.

Also, from a conceptual standpoint, what is a “theme?” If I want to have a
total new page with several components from other pages that doesn’t exist
in any current hq domain, is this sovled by creating a new theme?

thanks,

  • J
··· On Mon, Feb 15, 2010 at 4:59 PM, Nir Yariv wrote:

Hi,

I’ve been trying to think of a clean solution for laying various UIs
on top of CommCare while keeping the code relatively untouched. I came
up with the following idea:

  • In settings (rapidsms.ini), add a “template_theme” directive

  • render_to_response() will read this directive. If the directive is
    empty or has the value “default”, it will work as it does now - use
    the “<current_dir>/templates” path. If the directive has another
    value, it will use “<current_dir>/templates/” (or
    "<current_dir>/_templates", or whatever we decide makes most
    sense).

  • If there is no directory, render_to_response will revert to
    the default one.

This allows developers to create new themes without modifying the
existing code (no need for if statements in the views) and without
having to create a complete alternative template system. They only
need to change settings.template_theme and then add templates where
applicable.

Obviously, though, this only works for template-level theming.

What do you think?

  • Nir

A theme, in this system, is just the UI skin. A page with new
components would require a new view as well, so this won’t solve it.

If the change in the view is minor, it might make sense to add the new
data to the generic view and the themes will just use/ignore it as
they need. If the change is significant, though, it will require a
more sophisticated solution than described here.

  • Nir
··· On Mon, Feb 15, 2010 at 12:26 PM, Jonathan Jackson wrote: > this seems reasonable. Did we post/search stack overflow? I would imagine > many people have had to solve this. > Also, from a conceptual standpoint, what is a "theme?" If I want to have a > total new page with several components from other pages that doesn't exist > in any current hq domain, is this sovled by creating a new theme? > thanks, > - J > > On Mon, Feb 15, 2010 at 4:59 PM, Nir Yariv wrote: >> >> Hi, >> >> I've been trying to think of a clean solution for laying various UIs >> on top of CommCare while keeping the code relatively untouched. I came >> up with the following idea: >> >> * In settings (rapidsms.ini), add a "template_theme" directive >> >> * render_to_response() will read this directive. If the directive is >> empty or has the value "default", it will work as it does now - use >> the "/templates" path. If the directive has another >> value, it will use "/templates/" (or >> "/_templates", or whatever we decide makes most >> sense). >> >> * If there is no directory, render_to_response will revert to >> the default one. >> >> This allows developers to create new themes without modifying the >> existing code (no need for if statements in the views) and without >> having to create a complete alternative template system. They only >> need to change settings.template_theme and then add templates where >> applicable. >> >> Obviously, though, this only works for template-level theming. >> >> What do you think? >> >> - Nir > >

one thing that come to mind then, is whether the new GUI we are trying to
make is really a theme. I think the pages are structurally different. I’m
imaging that might be a more common difference between domains (structural
differences) vs. UI differences.

-J

··· On Mon, Feb 15, 2010 at 5:49 PM, Nir Yariv wrote:

A theme, in this system, is just the UI skin. A page with new
components would require a new view as well, so this won’t solve it.

If the change in the view is minor, it might make sense to add the new
data to the generic view and the themes will just use/ignore it as
they need. If the change is significant, though, it will require a
more sophisticated solution than described here.

  • Nir

On Mon, Feb 15, 2010 at 12:26 PM, Jonathan Jackson jjackson@dimagi.com wrote:

this seems reasonable. Did we post/search stack overflow? I would
imagine
many people have had to solve this.
Also, from a conceptual standpoint, what is a “theme?” If I want to have
a
total new page with several components from other pages that doesn’t
exist
in any current hq domain, is this sovled by creating a new theme?
thanks,

  • J

On Mon, Feb 15, 2010 at 4:59 PM, Nir Yariv niryariv@gmail.com wrote:

Hi,

I’ve been trying to think of a clean solution for laying various UIs
on top of CommCare while keeping the code relatively untouched. I came
up with the following idea:

  • In settings (rapidsms.ini), add a “template_theme” directive

  • render_to_response() will read this directive. If the directive is
    empty or has the value “default”, it will work as it does now - use
    the “<current_dir>/templates” path. If the directive has another
    value, it will use “<current_dir>/templates/” (or
    "<current_dir>/_templates", or whatever we decide makes most
    sense).

  • If there is no directory, render_to_response will revert to
    the default one.

This allows developers to create new themes without modifying the
existing code (no need for if statements in the views) and without
having to create a complete alternative template system. They only
need to change settings.template_theme and then add templates where
applicable.

Obviously, though, this only works for template-level theming.

What do you think?

  • Nir

one thing that come to mind then, is whether the new GUI we are trying to
make is really a theme. I think the pages are structurally different. I’m
imaging that might be a more common difference between domains (structural
differences) vs. UI differences.

I tend to agree with this assessment. Nir - could we do a similar scheme
that you are describing for both templates and views? So in the beginning
of the view you could check for a new view to send it to, and if one only
wanted to do template-level rendering you would check that at the end. It
may be confusing at first to support both, but I think some users will
eventually want both types of flexibility. Although… it’s possible the
template-level stuff might be okay to fully solve with .css. Not sure about
that or not.

-Cory

··· On Mon, Feb 15, 2010 at 1:01 PM, Jonathan Jackson wrote:

-J

On Mon, Feb 15, 2010 at 5:49 PM, Nir Yariv niryariv@gmail.com wrote:

A theme, in this system, is just the UI skin. A page with new
components would require a new view as well, so this won’t solve it.

If the change in the view is minor, it might make sense to add the new
data to the generic view and the themes will just use/ignore it as
they need. If the change is significant, though, it will require a
more sophisticated solution than described here.

  • Nir

On Mon, Feb 15, 2010 at 12:26 PM, Jonathan Jackson jjackson@dimagi.com wrote:

this seems reasonable. Did we post/search stack overflow? I would
imagine
many people have had to solve this.
Also, from a conceptual standpoint, what is a “theme?” If I want to have
a
total new page with several components from other pages that doesn’t
exist
in any current hq domain, is this sovled by creating a new theme?
thanks,

  • J

On Mon, Feb 15, 2010 at 4:59 PM, Nir Yariv niryariv@gmail.com wrote:

Hi,

I’ve been trying to think of a clean solution for laying various UIs
on top of CommCare while keeping the code relatively untouched. I came
up with the following idea:

  • In settings (rapidsms.ini), add a “template_theme” directive

  • render_to_response() will read this directive. If the directive is
    empty or has the value “default”, it will work as it does now - use
    the “<current_dir>/templates” path. If the directive has another
    value, it will use “<current_dir>/templates/” (or
    "<current_dir>/_templates", or whatever we decide makes most
    sense).

  • If there is no directory, render_to_response will revert to
    the default one.

This allows developers to create new themes without modifying the
existing code (no need for if statements in the views) and without
having to create a complete alternative template system. They only
need to change settings.template_theme and then add templates where
applicable.

Obviously, though, this only works for template-level theming.

What do you think?

  • Nir

Yeah, I was thinking along these lines too, following Jonathan’s comments.

I guess the major question on my side is whether HQ based custom
solutions are going to be a major feature - if so, it makes sense to
take the time to build an HQ extensions system: perhaps something like
a root level directory where all the custom code is stored, separate
from the main code base, and then modifying the existing
(Django/RapidSMS) request processing code to automatically import
custom views/models/urls/templates as needed.

··· On Mon, Feb 15, 2010 at 9:07 PM, Cory Zue wrote: > > On Mon, Feb 15, 2010 at 1:01 PM, Jonathan Jackson wrote: >> >> one thing that come to mind then, is whether the new GUI we are trying to >> make is really a theme. I think the pages are structurally different. I'm >> imaging that might be a more common difference between domains (structural >> differences) vs. UI differences. >> > > I tend to agree with this assessment. Nir - could we do a similar scheme > that you are describing for both templates _and_ views? So in the beginning > of the view you could check for a new view to send it to, and if one only > wanted to do template-level rendering you would check that at the end. It > may be confusing at first to support both, but I think some users will > eventually want both types of flexibility. Although... it's possible the > template-level stuff might be okay to fully solve with .css. Not sure about > that or not. > > -Cory > > >> >> -J >> >> On Mon, Feb 15, 2010 at 5:49 PM, Nir Yariv wrote: >>> >>> A theme, in this system, is just the UI skin. A page with new >>> components would require a new view as well, so this won't solve it. >>> >>> If the change in the view is minor, it might make sense to add the new >>> data to the generic view and the themes will just use/ignore it as >>> they need. If the change is significant, though, it will require a >>> more sophisticated solution than described here. >>> >>> - Nir >>> >>> On Mon, Feb 15, 2010 at 12:26 PM, Jonathan Jackson wrote: >>> > this seems reasonable. Did we post/search stack overflow? I would >>> > imagine >>> > many people have had to solve this. >>> > Also, from a conceptual standpoint, what is a "theme?" If I want to >>> > have a >>> > total new page with several components from other pages that doesn't >>> > exist >>> > in any current hq domain, is this sovled by creating a new theme? >>> > thanks, >>> > - J >>> > >>> > On Mon, Feb 15, 2010 at 4:59 PM, Nir Yariv wrote: >>> >> >>> >> Hi, >>> >> >>> >> I've been trying to think of a clean solution for laying various UIs >>> >> on top of CommCare while keeping the code relatively untouched. I came >>> >> up with the following idea: >>> >> >>> >> * In settings (rapidsms.ini), add a "template_theme" directive >>> >> >>> >> * render_to_response() will read this directive. If the directive is >>> >> empty or has the value "default", it will work as it does now - use >>> >> the "/templates" path. If the directive has another >>> >> value, it will use "/templates/" (or >>> >> "/_templates", or whatever we decide makes most >>> >> sense). >>> >> >>> >> * If there is no directory, render_to_response will revert to >>> >> the default one. >>> >> >>> >> This allows developers to create new themes without modifying the >>> >> existing code (no need for if statements in the views) and without >>> >> having to create a complete alternative template system. They only >>> >> need to change settings.template_theme and then add templates where >>> >> applicable. >>> >> >>> >> Obviously, though, this only works for template-level theming. >>> >> >>> >> What do you think? >>> >> >>> >> - Nir >>> > >>> > >> > >

Thanks Nir, is what you described basically the rapidsms app loader?

I don’t think we have a good handle on how much customization will be going
on for the future of HQ, so I don’t think it makes sense to build out now
until we have a better sense of the demand. We talked about trying to build
a plug-in architecture, but I think it feels like overkill for the short
term. I love the idea of building able to upload a module to a live server
that could hit APIs and add new web features, but I think we are pretty fair
off from needing that.

This particular use-case is hopefully not going to remain a custom solution.
If the views are found to be pretty useable, i think we would enable them
on every domain and let uses select “admin view” or “clinical view” as their
default landing page.

-J

I guess the major question on my side is whether HQ based custom
solutions are going to be a major feature - if so, it makes sense to
take the time to build an HQ extensions system: perhaps something like
a root level directory where all the custom code is stored, separate
from the main code base, and then modifying the existing
(Django/RapidSMS) request processing code to automatically import
custom views/models/urls/templates as needed.

Yeah, to expand on Jonathan’s point a little, the current rapidsms code lets
you specify apps in your config file and then automatically includes all of
those apps by looking anywhere on the python path for that app’s
models/views/templates/etc. Are you proposing something that’s different
from that? The major difference here is that some of the built in urls
(e.g. the landing page) need to be able to redirect to some potentially
unknown view.

··· On Mon, Feb 15, 2010 at 10:12 PM, Jonathan Jackson wrote:

I don’t think we have a good handle on how much customization will be going
on for the future of HQ, so I don’t think it makes sense to build out now
until we have a better sense of the demand. We talked about trying to build
a plug-in architecture, but I think it feels like overkill for the short
term. I love the idea of building able to upload a module to a live server
that could hit APIs and add new web features, but I think we are pretty fair
off from needing that.

This particular use-case is hopefully not going to remain a custom
solution. If the views are found to be pretty useable, i think we would
enable them on every domain and let uses select “admin view” or “clinical
view” as their default landing page.

Different domains or roles hijacking pages feels like a requirement that’s
likely to come up again and again, so I still think this is probably still a
good thing to build in support for, even if we are working towards standard,
role-based views. Really that can just be a special case of this
functionality that we can continue to extend with new roles or domains.

Yeah, to expand on Jonathan’s point a little, the current rapidsms code lets
you specify apps in your config file and then automatically includes all of
those apps by looking anywhere on the python path for that app’s
models/views/templates/etc. Are you proposing something that’s different
from that? The major difference here is that some of the built in urls
(e.g. the landing page) need to be able to redirect to some potentially
unknown view.

Does this mean that if I create a dir /extensions under the project
root and create /apps/newapp under that - and then add newapp to the
config - it will get included by RapidSMS?

If so, it sounds like a good start. I suppose then there’s the issue
of inheriting and extending existing view/model code…

nir, to answer your question, yes, adding a apps/newapp and adding that to
the ini that should do it.

jumping in late here…but i wonder if we need to revisit how the rapidsms
app structure can be extended into views using some sort of class based
model. I don’t think this solves our particular theming issue, but if it
means that we can control templates and view behavior from a central
location, maybe it’ll take us one step closer to that.

the stackoverflow discussions on theming tend to fall under the “just flip
your settings.py” (not helpful for our situation), vs using variables on
your templates names and such - which rapidsms’ base.html already does to
some effect.

so, we have one idiom for SMS app management, we probably could add some
view management as well.

a few projects auto add views to the urls.py using some wildcards and
registration system.

i just had another completely ridiculous thought with regard to all this as
well. it involves something along the lines of the android generic Content
system for making any piece of data accessible to other apps. kinda like
how the django contenttype system already works. but that’s completely
unrelated to what we got here.

Dan

··· On Mon, Feb 15, 2010 at 10:49 PM, Nir Yariv wrote:

Yeah, to expand on Jonathan’s point a little, the current rapidsms code
lets
you specify apps in your config file and then automatically includes all
of
those apps by looking anywhere on the python path for that app’s
models/views/templates/etc. Are you proposing something that’s different
from that? The major difference here is that some of the built in urls
(e.g. the landing page) need to be able to redirect to some potentially
unknown view.

Does this mean that if I create a dir /extensions under the project
root and create /apps/newapp under that - and then add newapp to the
config - it will get included by RapidSMS?

If so, it sounds like a good start. I suppose then there’s the issue
of inheriting and extending existing view/model code…


Daniel Myung
Senior Engineer, Dimagi, Inc
529 Main St, Suite 606 | Charlestown, MA 02129
office: (617) 580-3100 | mobile: (617) 863-0678| fax: (617) 580-3103
http://www.dimagi.com/

nir, to answer your question, yes, adding a apps/newapp and adding that to
the ini that should do it.

just to verify - this works when the path is
<project_root>/<the_new_extensions_dir>/apps/newapp ?

oh i see.

you’ll need to tweak the thing that runs manage.py to make sure that
new_extensions_dir/apps/ is in the PYTHONPATH

··· On Mon, Feb 15, 2010 at 11:04 PM, Nir Yariv wrote:

nir, to answer your question, yes, adding a apps/newapp and adding that
to
the ini that should do it.

just to verify - this works when the path is
<project_root>/<the_new_extensions_dir>/apps/newapp ?


Daniel Myung
Senior Engineer, Dimagi, Inc
529 Main St, Suite 606 | Charlestown, MA 02129
office: (617) 580-3100 | mobile: (617) 863-0678| fax: (617) 580-3103
http://www.dimagi.com/

The Django Pluggables framework might be an interesting thing to consider
for our needs here.