Time for action customizing entity lists

Of course, if we offer the user the opportunity to customize the display of individual entities, it makes sense to offer the same functionality for lists of entities. If you run crm4.py and click on the Contacts menu item, you will see a list as follows:

Time for action customizing entity lists

You will notice that in the column containing the telephone numbers, those beginning with a plus sign are shown in a bold font. This will give a visible hint that this is probably a foreign number that needs some special code on your telephone switch.

What just happened?

The customization itself is a small piece of JavaScript that is inserted at the end of the page that shows the list of contacts:

Chapter10/customizationexample3.html

<script>
var re = new RegExp("^\s*\+");
$("td:nth-child(4)").each(function(i){
	if($(this).text().match(re)){
		$(this).css({'font-weight':'bold'})
	};
});
</script>

It uses jQuery to iterate over all<td> elements, which is the fourth child of their parent (a<tr> element, code highlighted). If the text contained in that element matches something that begins with optional whitespace and a plus sign (the regular expression itself is defined in the first line of the script), we set the font-weight CSS attribute of that element to bold.

Just as with the customization of Display, we need to add some way to store the customizations. The alterations to the custom class in the entity module are straightforward and copy the pattern set for Display (the complete code is available in rbacentity.py):

Chapter10/rbacentity.py

def __init__(self):
		...
		class BrowseCustomization(CustomEntity):
			entity = Attribute(notnull= True, displayname = "Entity")
			description = Attribute(displayname = "Description")
			customhtml = Attribute(displayname = "Custom HTML", 
				htmlescape=True, displayclass="mb-textarea")
		self.BrowseCustomization = BrowseCustomization
		...
def getBrowseCustomization(self):
		return self.BrowseCustomization
def getBrowseCustomHTML(self,entity):
		return "".join(dc.customhtml 
		for dc in self.BrowseCustomization.list( 
					pattern=[('entity',entity)]))

The definition of the Browse class in browse.py needs to be extended as well to retrieve and deliver the customizations (shown are the relevant lines from browse.py):

Chapter10/browse.py

yield self.entity._custom().getBrowseCustomHTML('*')
yield self.entity._custom().getBrowseCustomHTML(self.entity.__name__)

And the final step is to provide the user with a link to edit the customizations. This is done in the main application (available as crm4.py) by adding these lines, again following the pattern set for the display customizations (the lines relevant for the browse customizations are highlighted):

Chapter10/crm4.py

displaycustom = User._custom().getDisplayCustomization()
browsecustom = User._custom().getBrowseCustomization()
class DisplayCustomizationBrowser(Browse):
	edit = Display(displaycustom, edit=True, logon=logon)
	add = Display(displaycustom, add=True, logon=logon)
class BrowseCustomizationBrowser(Browse):
	edit = Display(browsecustom, edit=True, logon=logon)
	add = Display(browsecustom, add=True, logon=logon)
with open('basepage.html') as f:
	basepage=f.read(-1)
class Root():
	logon = logon
	user = UserBrowser(User)
	account = AccountBrowser(Account, 
				columns=Account.columns+[User,Address,Contact])
	contact = ContactBrowser(Contact, 
				columns=Contact.columns+[Address,Account])
	address = AddressBrowser(Address)
	displaycustomization = DisplayCustomizationBrowser( 
				displaycustom,columns=['entity','description'])
	browsecustomization = BrowseCustomizationBrowser( 
				browsecustom,columns=['entity','description'])
	@cherrypy.expose
	def index(self):
		return Root.logon.index(returnpage='../entities')
	@cherrypy.expose
	def entities(self):
		username = self.logon.checkauth()
	if username is None : raise HTTPRedirect('.')
	user=User.list(pattern=[('name',username)])
	if len(user) < 1 : User(name=username)
	return basepage%'''<div class="navigation">
	<a href="user">Users</a>
	<a href="displaycustomization">Customize Item</a>
	<a href="http://browsecustomization">Customize List</a>
	<a href="http://account">Accounts</a>
	<a href="contact">Contacts</a>
	<a href="http://address">Addresses</a>
	</div><div class="content">
	</div>
	<script src="/browse.js" type="text/javascript"></script>
	'''

We are, of course, not restricted to actions on the client-side only. As we may utilize all the AJAX capabilities of jQuery, we can do quite elaborate things.

Our entity browser already has the functionality to mark a row as selected if we click it a single time. However, we did not implement any useful action to go with this selection.

When we first implemented the Display class, we added a delete() method and exposed it to the CherryPy engine. We do not make use of this method in any way. Now that we can customize the entity browser, we can correct this and implement some functionality to add a button that when clicked will delete all selected entries. Mind you, it probably makes more sense to provide such basic functionality in a real application from the start, but it does show what is possible.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.79.241