Let’s make it more user friendly
4. Let’s make it more user friendly#
4.1. Step 1: let’s improve site’s usability for our visitors#
The first thing I’ve noticed is that people to whom I send links to photos with some login/password authentication get lost, because they don’t grasp they have to login by clicking on the ‘authenticate’ link. That’s much probably because they only get a 404 when trying to access an unauthorized folder, and the site doesn’t make clear that 1. you’re not authenticated, 2. you could get more content by authenticating yourself.
So, to improve this situation, I decided that I should:
make a login box appears for anonymous, so they see at a first glance a place to put the login / password information I provided
customize the 404 page, proposing to login to anonymous.
Here is the code, samples from my cube’s
from cubicweb import _ from cubicweb.web import component from cubicweb.web.views import error from cubicweb.predicates import anonymous_user class FourOhFour(error.FourOhFour): __select__ = error.FourOhFour.__select__ & anonymous_user() def call(self): self.w(u"<h1>%s</h1>" % self._cw._('this resource does not exist')) self.w(u"<p>%s</p>" % self._cw._('have you tried to login?')) class LoginBox(component.CtxComponent): """display a box containing links to all startup views""" __regid__ = 'sytweb.loginbox' __select__ = component.CtxComponent.__select__ & anonymous_user() title = _('Authenticate yourself') order = 70 def render_body(self, w): cw = self._cw form = cw.vreg['forms'].select('logform', cw) form.render(w=w, table_class='', display_progress_div=False)
The first class provides a new specific implementation of the default page you get on 404 error, to display an adapted message to anonymous user.
Thanks to the selection mecanism, it will be selected for anoymous user, since the additional anonymous_user() selector gives it a higher score than the default, and not for authenticated since this selector will return 0 in such case (hence the object won’t be selectable)
The second class defines a simple box, that will be displayed by default with
boxes in the left column, thanks to default
selector. The HTML is written to match default CubicWeb boxes style. The code
fetch the actual login form and render it.
4.2. Step 2: providing a custom index page#
Another thing we can easily do to improve the site is… A nicer index page (e.g. the first page you get when accessing the web site)! The default one is quite intimidating (that should change in a near future). I will provide a much simpler index page that simply list available folders (e.g. photo albums in that site).
Here is the code, samples from my cube’s
from cubicweb.web.views import startup class IndexView(startup.IndexView): def call(self, **kwargs): self.w(u'<div>\n') if self._cw.cnx.session.anonymous_session: self.w(u'<h4>%s</h4>\n' % self._cw._('Public Albums')) else: self.w(u'<h4>%s</h4>\n' % self._cw._('Albums for %s') % self._cw.user.login) self._cw.vreg['views'].select('tree', self._cw).render(w=self.w) self.w(u'</div>\n') def registration_callback(vreg): vreg.register_all(globals().values(), __name__, (IndexView,)) vreg.register_and_replace(IndexView, startup.IndexView)
As you can see, we override the default index view found in cubicweb.web.views.startup, getting back nothing but its identifier and selector since we override the top level view’s call method.
in that case, we want our index view to replace the existing one. To do so we’ve to implements the registration_callback function, in which we tell to register everything in the module but our IndexView, then we register it instead of the former index view.
Also, we added a title that tries to make it more evident that the visitor is authenticated, or not. Hopefully people will get it now!
4.4. Step 4: preparing the release and migrating the instance#
Now that greatly enhanced our cube, it’s time to release it to upgrade production site. I’ll probably detail that process later, but I currently simply transfer the new code to the server running the web site.
However, I’ve still today some step to respect to get things done properly…
First, as I’ve added some translatable string, I’ve to run:
$ cubicweb-ctl i18ncube sytweb
To update the cube’s gettext catalogs (the ‘.po’ files under the cube’s i18n directory). Once the above command is executed, I’ll then update translations.
To see if everything is ok on my test instance, I do:
$ cubicweb-ctl i18ninstance sytweb_instance $ cubicweb-ctl start -D sytweb_instance
The first command compile i18n catalogs (e.g. generates ‘.mo’ files) for my test instance. The second command start it in debug mode, so I can open my browser and navigate through the web site to see if everything is ok…
In the ‘cubicweb-ctl i18ncube’ command, sytweb refers to the cube, while in the two other, it refers to the instance (if you can’t see the difference, reread CubicWeb’s concept chapter!).
Once I’ve checked it’s ok, I simply have to bump the version number in the
__pkginfo__ module to trigger a migration once I’ll have updated the code on
the production site. I can check then check the migration is also going fine, by
first restoring a dump from the production site, then upgrading my test instance.
To generate a dump from the production site:
$ cubicweb-ctl db-dump sytweb_instance # if it's postgresql pg_dump -Fc --username=syt --no-owner --file /home/syt/etc/cubicweb.d/sytweb/backup/tmpYIN0YI/system sytweb # if it's sqlite gzip -c /home/psycojoker/etc/cubicweb.d/sytweb_instance/sytweb_instance.sqlite -> backup file /home/syt/etc/cubicweb.d/sytweb/backup/sytweb-2010-07-13_10-22-40.tar.gz
I can now get back the dump file (
sytweb-2010-07-13_10-22-40.tar.gz) to my test
machine (using scp for instance) to restore it and start migration:
$ cubicweb-ctl db-restore sytweb_instance /path/path/to/sytweb-2010-07-13_10-22-40.tar.gz $ cubicweb-ctl upgrade sytweb_instance
You might have to answer some questions, as we’ve seen in a previous part.
Now that everything is tested, I can transfer the new code to the production server, pip install CubicWeb and its dependencies, and eventually upgrade the production instance.