I didn’t have a lot of time this weekend. So I decided to implement the simplest part of upcoming OpenWrt GUI (webui) — hosts editor. It is a perfect candidate to write something in 15 minutes or less — it has almost no "business" logic in it: read/edit/verify/write cycle. The hardest part was to learn how to upload dynamically generated files without writing them to disk first.
It turned out to be very simple. Right now it is implemented using Dojo
’s versatile dojo.io.bind()
facility and some external code.
Update: this document is officially obsolete — alpha is released
!
Finally I released a preview: /webui-0.1-pre-alpha.ipk!
I included two information applets and a simple network configuration applet. I think it would be enough for a proof of concept. I borrowed heavily from nbd’s webif
. So if it works for you, it is due to his OpenWrt expertise. If it doesn’t, it is my fault.
Both webif and webui can be installed side by side:
Finally I found time to finish it up. It is pre-alpha quality now, but shows the direction.
The only problem is a packaging. I didn’t mean OpenWrt
’s IPKG. I am talking about creating a custom build of Dojo
to reduce the foot print. Dojo has a special provision for that but so far I was not able to do it getting some strange errors. I hope I’ll get some help from developers.
Today I have good news and bad news.
The good news is tonight I was able to work on AJAX OpenWrt GUI a little bit more. It is coming together. I coded my first applet. It shows current stats, nothing fancy.
The bad news is I bricked my router apparently by running nvram show repeatedly. I suspect that nvram is corrupted beyond salvation. I have to reset it somehow. I tried simple recipies listed in OpenWrt Wiki
but no luck so far. I’ll try to revive it on weekend. I have a feeling that my future lies with JTAG. Until the router is up I cannot debug OpenWrt GUI.
I was able to spend several hours this week to work on upcoming OpenWrt
GUI. I use Dojo
as a foundation. At this point I coded a skeleton, which works as a proof of concept. As soon as I finish putting in AJAX guts, I’ll switch to meaty functionality. Add some nice skin to it and we have our homunculus
up and running.
Huh? AJAX? No, it’s not Ajax the detergent
. No, I didn’t mean Ajax the pro soccer club
. "Now I clearly remember that AJAX is a Trojan, and I don’t like Trojans and viruses" — clever, but no. Go see the movie
about Greek heroes and the Wooden Horse. And let’s skip "Trojan" discussion altogether — I’m trying to be PG-13 rated.
Once again, let’s grab new version of TinyMCE
.
For a long time I wanted to have two TinyMCE toolbars for Django Admin:
- One-line toolbar with the most essential tools, which gives a lot of space for inline editing of text.
- Full-featured toolbar with all tools for full-screen mode.
It finally happened. Spocke (the main developer of TinyMCE) helped me to figure out how to do it. I updated my article in Django Wiki
with new config file, and removed my notes about space problem (new config file solves it) and flickering (new TinyMCE 2.0 RC2 works perfectly).
In my previous post
I complained about annoying flickering. Well, I’ve upgraded to TinyMCE 2.0 RC2
and it doesn’t flicker anymore! Run, don’t walk, and upgrade immediatelly!
Finally I bit the bullet and decided to implement OpenWrt
web-based user interface using Felix Fietkau
’s code. Well, MIPS processors used by OpenWrt units
are not race horses and GUI is slow to my taste. Yes, I know that stock firmware is not faster. "Slow" is absolute category for me.
How do we combat latencies and slow network speed? Exactly. We can apply the same for OpenWrt, where "slow network speed" is replaced with "slow processor on local network". So I decided to do The Right Thing(tm) and implement it using AJAX approach. I will use Dojo
.
After some requests I decided to publish my code for categories. It’s very simple. It was inspired by following articles: A "category" Data Model
(note: this article uses old-style model format, it doesn’t work anymore) and Relating an object to itself, many-to-one
.
from django.core import meta
class Category(meta.Model):
"""
Category defines following fields:
name - simple name of category, e.g., 'C++'
full_name - full name of category, which includes names of all parents,
e.g. 'Development::C++'
parent - reference to parent category or null
description - HTML description of category, or null
Notes:
1) full_name is not editable. It is calculated automatically
by calculate_full_name() method during save phase (hook _pre_save).
2) Separator specified by get_separator() method. It can be
overridden in subclasses.
"""
name = meta.CharField(maxlength=50)
full_name = meta.CharField(maxlength=250, unique=True,
editable=False)
parent = meta.ForeignKey('self', blank=True, null=True,
related_name='child')
description = meta.TextField(blank=True, null=True,
help_text="Use raw HTML.")
class META:
verbose_name_plural = 'Categories'
module_name = verbose_name_plural.lower()
admin = meta.Admin(
list_display = ('full_name',),
search_fields = ['full_name',],
js = (
'/tiny_mce/tiny_mce.js',
'/appmedia/admin/js/textareas.js',
),
)
ordering = ('full_name',)
def __repr__(self):
return self.full_name
def _pre_save(self):
self.full_name = self.calculate_full_name()
def get_separator(self):
return '::'
# note: used in templates
def get_all_children(self):
"get list of all children of the category"
output = []
children = self.get_child_list()
for c in children:
output.append(c)
output.extend(c.get_all_children())
return output
# note: the last object of the list is the category itself
# note: used in templates
def get_all_parents(self):
"get list of all parents of the category from top level parent down"
id_list = []
object = self
while True:
id_list.append(object)
if not object.parent_id:
break
object = object.get_parent()
id_list.reverse()
return id_list
# note: used in templates
def calculate_full_name(self):
"calculate full name from parent list"
return self.get_separator().join([x.name for x in self.get_all_parents()])
# note: used in templates
def get_path(self):
"get relative path of the category"
return 'categories/%d/' % self.id
As you can see it is very simple. This model defines full_name field, which is auto-populated. I was toying with an idea to keep parent_name and produce full_name by concatenating parent_name with name. But after some trials I decided against it: it introduced a lot of complexities and runtime overhead by saving a few bytes in database. In my opinion it doesn’t worth it. This model defines some convenience methods as well. They are meant to be used in templates.
TinyMCE 2.0RC1 is out. Take it
while it’s hot! I’ve upgraded my admin pages and it looks better than previous one (duh!).
Nevertheless I see annoying flickering in FireFox. But it flickers less now.
I decided to try how well Opera
works with my site. It mostly works. You can go and see stuff but all Dojo-related code doesn’t work. Interesting that Google Maps works properly.
When I switched to admin mode to edit this article, it turned out that TinyMCE
doesn’t work either.
But good news is Dojo and TinyMCE failed gracefully.
The best thing about Dojo 0.1: it’s quite easy to create portable widgets. Such widgets work similar to Microsoft IE’s behaviors but they are even more self-contained. Dojo widgets can work with fragments of HTML and CSS, which will be inserted during the object creation. The event system is very elaborate. Of course Dojo is more than a simple widget factory. For example I didn’t try the I/O facility yet.
New design is here. Well, some elements of it. I had bigger ideas, but CSS didn’t work reliably, and JavaScript option was in debugging mode. So I decided to update this site now and add other planned stuff later.
One reason I postponed JavaScript thingy is I want to try Dojo
. It looks like a good foundation for widgets. I am going to create a couple of them at least. If it works okay, I’ll be using it in other projects as well. Stay tuned.
Update (3/13/2011): this article is obsolete now and preserved here mostly for its historic value. Nowadays I use Dojo’s dijit.Editor as a WYSIWYG HTML editor — it is more functional and much simpler to setup and extend. Read all gory details in Using Dojo Rich Editor with Django’s Admin
.
I decided to add a WYSIWYG editor to my admin portion of the site. Apparently you can find some nice open source WYSIWYG editors nowadays. Probably FCKeditor, Xinha and TinyMCE are the most prominent ones. Some people already tried different editors with Django, e.g., Xinha — http://www.socialistsoftware.com/?p=10
, TinyMCE — http://www.socialistsoftware.com/?p=8
. Now it’s my turn.