[Checkins]
SVN: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/
addressbook working and added sqlmessage
Darryl Cousins
darryl at darrylcousins.net.nz
Fri Jul 13 03:36:44 EDT 2007
Log message for revision 77800:
addressbook working and added sqlmessage
Changed:
U Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.py
U Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.txt
U Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/browser/index.pt
U Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/configure.zcml
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/README.txt
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/__init__.py
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/add.pt
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/db/
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/db/msg/
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/db/msg/MSG.grl
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/db/msg/msg.gfd
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/display.pt
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/edit.pt
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/overview.pt
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/rdb.zcml
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.css
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.py
A Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.txt
U Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py
-=-
Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.py 2007-07-13 07:36:39 UTC (rev 77799)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.py 2007-07-13 07:36:43 UTC (rev 77800)
@@ -8,7 +8,7 @@
from z3c.form.interfaces import IFormLayer, INPUT_MODE
from z3c.formdemo.addressbook import interfaces, browser, dateselect
-SESSION_KEY = 'mars.formdemo.addressbook'
+SESSION_KEY = 'z3c.formdemo.addressbook'
import grok
@@ -19,10 +19,12 @@
mars.layer.layer(IDemoBrowserLayer)
+
class DateSelectWidget(mars.adapter.AdapterFactory):
- mars.adapter.factory(dateselect.DateSelectFieldWidget)
+ mars.adapter.factory(dateselect.DateSelectDataConverter)
class ContactLabel(mars.adapter.AdapterFactory):
+ grok.name('title')
mars.adapter.factory(button.StaticButtonActionAttribute(
u'Add Contact',
button=form.AddForm.buttons['add'],
@@ -84,7 +86,7 @@
grok.template('addressbook.pt')
class ContactAddTemplate(mars.template.TemplateFactory):
- grok.context(browser.ContactEditForm)
+ grok.context(browser.ContactAddForm)
grok.template('contact.pt')
class ContactTemplate(mars.template.TemplateFactory):
Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.txt 2007-07-13 07:36:39 UTC (rev 77799)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.txt 2007-07-13 07:36:43 UTC (rev 77800)
@@ -21,4 +21,182 @@
on the "Address Book" link:
>>> user.open(skinURL + '/addressbook')
- >>> print user.contents
+
+There is only one screen for this demo. In it you see the table of all
+contacts on the left side and on the right side is the contact
+form. Initially, this is an add form.
+
+ >>> testing.printElement(user, "//h1")
+ <h1><span>Address Book Demo</span></h1>
+
+So let's start by filling out the add form. The first portion contains basic
+personal information:
+
+ >>> user.getControl('First Name').value = 'Stephan'
+ >>> user.getControl('Last Name').value = 'Richter'
+
+ >>> user.getControl(name='contact.add.widgets.birthday.day:list')\
+ ... .getControl('25').click()
+ >>> user.getControl(name='contact.add.widgets.birthday.year:list')\
+ ... .getControl('1980').click()
+
+In the second portion we can add any number of addresses. Let's just add a
+home address:
+
+ >>> user.getControl('Add', index=0).click()
+
+ >>> user.getControl('Street').value = '110 Main Street'
+ >>> user.getControl('City').value = 'Maynard'
+ >>> user.getControl('State').value = 'MA'
+ >>> user.getControl('ZIP').value = '01754'
+
+You cannot add the same address twice:
+
+ >>> user.getControl('Add', index=0).click()
+ >>> testing.printElement(user, "//div[@class='summary']")
+ <div class="summary">Address already provided for contact.</div>
+
+When accidently adding another address, ...
+
+ >>> user.getControl(name='contact.add.addresses.widgets.addressName:list')\
+ ... .getControl('Work').click()
+ >>> user.getControl('Add', index=0).click()
+
+you can delete it any time:
+
+ >>> user.getControl('Delete', index=1).click()
+
+Let's now add the home phone number, because it is a required field:
+
+ >>> user.getControl(name='contact.add.phones.homePhone.widgets.countryCode')\
+ ... .value = '+1'
+ >>> user.getControl(name='contact.add.phones.homePhone.widgets.areaCode')\
+ ... .value = '555'
+ >>> user.getControl(name='contact.add.phones.homePhone.widgets.number')\
+ ... .value = '127-1284'
+
+Finally, the user is requested to enter the E-mail addresses of the contact;
+we have two in this case:
+
+ >>> user.getControl(name='contact.add.emails.widgets.fullAddress')\
+ ... .value = 'srichter at gmail.com'
+ >>> user.getControl('Add', index=1).click()
+
+ >>> user.getControl(name='contact.add.emails.widgets.fullAddress')\
+ ... .value = 'srichter at tufts.edu'
+ >>> user.getControl('Add', index=1).click()
+
+Once all the information has been provided, we can add the contact:
+
+ >>> user.getControl('Add Contact').click()
+
+The new contact appears now in the contact list:
+
+ >>> testing.printElement(user, "//table/tbody/tr[1]")
+ <tr class="odd"><td class="sorted-on">
+ <a href="...?selectContact=contact-0">Richter</a>
+ </td>
+ <td class="">
+ <a href="...?selectContact=contact-0">Stephan</a>
+ </td>
+ </tr>
+
+By clicking on the name, the edit form for Stephan is shown:
+
+ >>> user.getLink('Richter').click()
+
+Note that the row is highlighted now:
+
+ >>> testing.printElement(user, "//table/tbody/tr[1]")
+ <tr class="selected"><td class="sorted-on">
+ <a href="...?selectContact=contact-0">Richter</a>
+ </td>
+ <td class="">
+ <a href="...?selectContact=contact-0">Stephan</a>
+ </td>
+ </tr>
+
+After adding a work phone number and deleting one of the two E-mail addresses,
+
+ >>> user.getControl(name='contact.edit.phones.workPhone.widgets.countryCode')\
+ ... .value = '+1'
+ >>> user.getControl(name='contact.edit.phones.workPhone.widgets.areaCode')\
+ ... .value = '555'
+ >>> user.getControl(name='contact.edit.phones.workPhone.widgets.number')\
+ ... .value = '346-3573'
+
+ >>> user.getControl('Delete', index=1).click()
+
+we now save the contact changes:
+
+ >>> user.getControl('Apply').click()
+
+This submission saves all the data but stays in the edit form of the
+contact. Only by pressing the "Done" button, the add form will return.
+
+ >>> user.getControl('Done').click()
+ >>> user.getControl('Add Contact')
+ <SubmitControl name='contact.add.buttons.add' type='submit'>
+
+You will also notice that the contact is not highlighted in the table
+anymore. Let's nwo add a second contact:
+
+ >>> user.getControl('First Name').value = 'Roger'
+ >>> user.getControl('Last Name').value = 'Ineichen'
+
+ >>> user.getControl(name='contact.add.phones.homePhone.widgets.countryCode')\
+ ... .value = '+41'
+ >>> user.getControl(name='contact.add.phones.homePhone.widgets.areaCode')\
+ ... .value = '43'
+ >>> user.getControl(name='contact.add.phones.homePhone.widgets.number')\
+ ... .value = '12 23 23'
+
+ >>> user.getControl('Add Contact').click()
+
+You can now sort the contacts by last and first name now, of course. Clicking
+on the "Last Name" table header cell, will leave the order, since the ordering
+must be initialized. The second time the order is reversed:
+
+ >>> user.getLink('Last Name').click()
+ >>> user.getLink('Last Name').click()
+
+ >>> testing.printElement(user, "//table/tbody/tr/td[1]/a/text()",
+ ... multiple=True, serialize=False)
+ Richter
+ Ineichen
+
+Selecting another header will sort on it. Let's choose the first name;
+clicking on it once sorts it in ascending order:
+
+ >>> user.getLink('First Name').click()
+ >>> testing.printElement(user, "//table/tbody/tr/td[2]/a/text()",
+ ... multiple=True, serialize=False)
+ Roger
+ Stephan
+
+Clicking it again, reverses the order:
+
+ >>> user.getLink('First Name').click()
+ >>> testing.printElement(user, "//table/tbody/tr/td[2]/a/text()",
+ ... multiple=True, serialize=False)
+ Stephan
+ Roger
+
+To delete a contact, you must first select it:
+
+ >>> user.getLink('Roger').click()
+
+At the bototm of the contact form is a delete button that will delete the
+entire contact:
+
+ >>> user.getControl('Delete').click()
+
+The user is now gone from the table and we are returned to the add form:
+
+ >>> user.getLink('Roger')
+ Traceback (most recent call last):
+ ...
+ LinkNotFoundError
+
+ >>> user.getControl('Add Contact')
+ <SubmitControl name='contact.add.buttons.add' type='submit'>
Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/browser/index.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/browser/index.pt 2007-07-13 07:36:39 UTC (rev 77799)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/browser/index.pt 2007-07-13 07:36:43 UTC (rev 77800)
@@ -30,7 +30,13 @@
<a href="../wizard">Wizard</a>
</div>
<div>
+ <a href="../addressbook">Address Book</a>
+ </div>
+ <div>
<a href="../spreadsheet">Spreadsheet</a>
</div>
+ <div>
+ <a href="/showallsql">SQL Hello World</a>
+ </div>
</div>
Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/configure.zcml
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/configure.zcml 2007-07-13 07:36:39 UTC (rev 77799)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/configure.zcml 2007-07-13 07:36:43 UTC (rev 77800)
@@ -15,5 +15,7 @@
</resourceLibrary>
</configure>
+ <include package=".sqlmessage" file="rdb.zcml" />
+
</configure>
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/README.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/README.txt (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/README.txt 2007-07-13 07:36:43 UTC (rev 77800)
@@ -0,0 +1,9 @@
+============================
+SQL Hello World Message Demo
+============================
+
+The purpose of the SQL Hello World Message demo is to demonstrate how
+non-object data can be manipulated and displayed using the form framework.
+
+The original doctest is at ./sqlmessage.txt.
+
Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/README.txt
___________________________________________________________________
Name: svn:keywords
+ Date Author
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/__init__.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/__init__.py (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/__init__.py 2007-07-13 07:36:43 UTC (rev 77800)
@@ -0,0 +1 @@
+#
Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/add.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/add.pt (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/add.pt 2007-07-13 07:36:43 UTC (rev 77800)
@@ -0,0 +1,5 @@
+<h1>Hello World Message Add Form</h1>
+
+<div id="body">
+ <div metal:use-macro="macro:form" />
+</div>
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/db/msg/MSG.grl
===================================================================
(Binary files differ)
Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/db/msg/MSG.grl
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/db/msg/msg.gfd
===================================================================
(Binary files differ)
Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/db/msg/msg.gfd
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/display.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/display.pt (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/display.pt 2007-07-13 07:36:43 UTC (rev 77800)
@@ -0,0 +1,14 @@
+<h1>
+ A <span tal:replace="structure view/widgets/what/render" /> Hello World
+ from <span tal:replace="structure view/widgets/who/render" />
+ on <span tal:replace="structure view/widgets/when/render" />!
+</h1>
+
+<div id="body">
+ <div class="actions">
+ <a href="./edit.html"
+ tal:attributes="href string:editsql?id=${request/id}">
+ [Edit Message]</a>
+ <a href="showallsql">[Show All Messages]</a>
+ </div>
+</div>
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/edit.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/edit.pt (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/edit.pt 2007-07-13 07:36:43 UTC (rev 77800)
@@ -0,0 +1,10 @@
+<h1>Hello World Message Edit Form</h1>
+
+<div id="body">
+ <div metal:use-macro="macro:form">
+ <metal:block fill-slot="above-buttons">
+ <input type="hidden" name="id" value=""
+ tal:attributes="value request/form/id" />
+ </metal:block>
+ </div>
+</div>
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/overview.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/overview.pt (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/overview.pt 2007-07-13 07:36:43 UTC (rev 77800)
@@ -0,0 +1,21 @@
+<h1>SQL Hello World Message Demo</h1>
+
+<div id="body">
+ <div class="status"
+ tal:define="status view/status"
+ tal:condition="status">
+ <div class="summary"
+ tal:content="status">
+ status summary
+ </div>
+ </div>
+
+ <div tal:replace="structure view/table" />
+
+ <div class="actions">
+ <a href="addsql">[Add message]</a>
+ <a href="showallsql?initialize=1">
+ [Initialize the database]
+ </a>
+ </div>
+</div>
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/rdb.zcml
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/rdb.zcml (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/rdb.zcml 2007-07-13 07:36:43 UTC (rev 77800)
@@ -0,0 +1,14 @@
+<configure
+ xmlns:rdb="http://namespaces.zope.org/rdb"
+ i18n_domain="mars.formdemo">
+
+ <!-- RDB setup -->
+
+ <rdb:gadflyRoot path="./db" />
+
+ <rdb:provideConnection
+ name="msg"
+ component="zope.rdb.gadflyda.GadflyAdapter"
+ dsn="dbi://msg" />
+
+</configure>
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.css
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.css (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.css 2007-07-13 07:36:43 UTC (rev 77800)
@@ -0,0 +1,85 @@
+body {
+ background: #EBE6D3;
+}
+
+a:visited {
+ color: #D91813;
+}
+
+a:hover {
+ color: #D91813;
+}
+
+h1 {
+ background: #574E3F;
+ color: #D5CDC6;
+ font-weight: bold;
+ padding: 5px;
+ border-bottom: 3px solid #900002;
+}
+
+input[type=text] {
+ padding: 2px;
+}
+
+input[type=submit] {
+ border: 1px solid black;
+ background: #900002;
+ color: white;
+ font-weight: bold;
+ padding: 2px;
+ -moz-border-radius: 5px;
+}
+
+div#content {
+ margin: 0;
+ padding: 0;
+}
+
+div#body {
+ margin: 20px;
+}
+
+div.status {
+ background-color: #F5F2EB;
+ border: 1px solid #CAC8C2;
+ color: #D91813;
+ font-style: italic;
+ margin: 10px 0px;
+ padding: 7px;
+ -moz-border-radius: 5px;
+}
+
+div.actions, div.buttons {
+ background-color: #F5F2EB;
+ border: 1px solid #CAC8C2;
+ margin-top: 10px;
+ padding: 7px;
+ -moz-border-radius: 5px;
+}
+
+table.message-list th {
+ background: #A79E8D;
+ padding: 3px;
+}
+
+table.message-list td {
+ color: #574E3F;
+ padding: 2px 0px;
+}
+
+table.message-list tr.even {
+ background-color: #F5F2EB;
+}
+
+table.message-list td a {
+ color: #574E3F;
+}
+
+table.message-list td a:hover {
+ color: #574E3F;
+}
+
+table.message-list td a:visited {
+ color: #574E3F;
+}
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.py (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.py 2007-07-13 07:36:43 UTC (rev 77800)
@@ -0,0 +1,207 @@
+import datetime
+
+import zope.interface
+import zope.rdb
+from zope.traversing.browser import absoluteURL
+from zope.viewlet.viewlet import CSSViewlet
+
+from zc.table import column
+from zc.table.interfaces import ISortableColumn
+
+from z3c.form import widget, field, form, button
+from z3c.form.interfaces import IAddForm
+from z3c.formui import layout
+from z3c.formdemo.sqlmessage import sql
+from z3c.formdemo.browser import formatter
+from z3c.formdemo.sqlmessage.interfaces import IHelloWorld
+from z3c.formdemo.sqlmessage.browser import (ISQLMessagePage,
+ SQLColumn,
+ DateSQLColumn,
+ DeleteSQLColumn)
+
+import grok
+
+import mars.adapter
+import mars.resource
+import mars.viewlet
+import mars.view
+import mars.layer
+
+from mars.formdemo.layer import IDemoBrowserLayer
+from mars.formdemo.skin import skin
+
+mars.layer.layer(IDemoBrowserLayer)
+
+SESSION_KEY = 'mars.formdemo.sqlmessage'
+
+
+class DefaultDate(mars.adapter.AdapterFactory):
+ grok.name('default')
+ mars.adapter.factory(widget.ComputedWidgetAttribute(
+ lambda adapter: datetime.date.today(),
+ field=IHelloWorld['when'], view=IAddForm))
+
+## CSS requirement
+class MessageStyle(mars.resource.ResourceFactory):
+ """File resource"""
+ grok.name('sqlmessage.css')
+ mars.resource.file('sqlmessage.css')
+
+MessageCSS = CSSViewlet('sqlmessage.css')
+class MessageCSSViewlet(mars.viewlet.SimpleViewlet, MessageCSS):
+ """css viewlet"""
+ weight = 1000
+ grok.name('sqlmessage.css')
+ grok.context(zope.interface.Interface)
+ mars.viewlet.view(ISQLMessagePage)
+ mars.viewlet.manager(skin.CSSManager)
+
+class AddForm(mars.view.FormView, layout.AddFormLayoutSupport, form.AddForm):
+ grok.context(zope.interface.Interface)
+ grok.name('addsql')
+ zope.interface.implements(ISQLMessagePage)
+
+ fields = field.Fields(IHelloWorld)
+
+ def create(self, data):
+ return data
+
+ def add(self, data):
+ data['id'] = sql.getNextId()
+ data['when'] = data['when'].toordinal()
+ sql.addMessage(data)
+ return data
+
+ def nextURL(self):
+ url = absoluteURL(self.context, self.request)
+ return url + '/showallsql'
+
+class EditForm(mars.view.FormView, layout.FormLayoutSupport, form.EditForm):
+ grok.context(zope.interface.Interface)
+ grok.name('editsql')
+ zope.interface.implements(ISQLMessagePage)
+
+ form.extends(form.EditForm)
+ fields = field.Fields(IHelloWorld)
+
+ def getContent(self):
+ msg = sql.getMessage(self.request.form['id'])
+ content = dict(
+ [(name, getattr(msg, name.upper()))
+ for name in self.fields.keys()] )
+ content['when'] = datetime.date.fromordinal(content['when'])
+ return content
+
+ def applyChanges(self, data):
+ changed = False
+ for name, value in self.getContent().items():
+ if data[name] != value:
+ changed = True
+ data['when'] = data['when'].toordinal()
+ if changed:
+ id = self.request.form['id']
+ sql.updateMessage(id, data)
+ return changed
+
+ @button.buttonAndHandler(u'Apply and View', name='applyView')
+ def handleApplyView(self, action):
+ self.handleApply(self, action)
+ if not self.widgets.errors:
+ url = absoluteURL(self.context, self.request)
+ url += '/showsql?id=' + self.request['id']
+ self.request.response.redirect(url)
+
+class DisplayForm(mars.view.FormView, layout.FormLayoutSupport, form.DisplayForm):
+ grok.context(zope.interface.Interface)
+ grok.name('showsql')
+ zope.interface.implements(ISQLMessagePage)
+
+ fields = field.Fields(IHelloWorld)
+
+ def getContent(self):
+ msg = sql.getMessage(self.request.form['id'])
+ content = dict(
+ [(name, getattr(msg, name.upper()))
+ for name in self.fields.keys()] )
+ content['when'] = datetime.date.fromordinal(content['when'])
+ return content
+
+class SQLColumn(column.GetterColumn):
+ zope.interface.implements(ISortableColumn)
+
+ def getter(self, item, formatter):
+ return getattr(item, self.name.upper())
+
+ def cell_formatter(self, value, item, formatter):
+ return '<a href="showsql?id=%s">%s</a>' %(
+ item.ID, unicode(value))
+
+class DateSQLColumn(SQLColumn):
+
+ def getter(self, item, formatter):
+ value = super(DateSQLColumn, self).getter(item, formatter)
+ return datetime.date.fromordinal(value)
+
+class DeleteSQLColumn(column.Column):
+
+ def renderCell(self, item, formatter):
+ link = '<a href="showallsql?delete=%i">[Delete]</a>'
+ return link % item.ID
+
+class Overview(mars.view.PageletView):
+ grok.context(zope.interface.Interface)
+ grok.name('showallsql')
+ zope.interface.implements(ISQLMessagePage)
+
+ status = None
+
+ columns = (
+ SQLColumn(u'Id', name='id'),
+ SQLColumn(u'Who', name='who'),
+ DateSQLColumn(u'When', name='when'),
+ SQLColumn(u'What', name='what'),
+ DeleteSQLColumn(u'', name='delete')
+ )
+
+ def update(self):
+ if 'initialize' in self.request.form:
+ try:
+ sql.initialize()
+ except zope.rdb.DatabaseException, exc:
+ self.status = "Database Message: " + exc.message
+ elif 'delete' in self.request.form:
+ try:
+ sql.deleteMessage(self.request.form['delete'])
+ except zope.rdb.DatabaseException, exc:
+ self.status = "Database Message: " + exc.message
+
+ try:
+ messages = sql.queryAllMessages()
+ except zope.rdb.DatabaseException, exc:
+ # No message table exists yet.
+ messages = ()
+
+ self.table = formatter.ListFormatter(
+ self.context, self.request, messages,
+ prefix = SESSION_KEY + '.', columns=self.columns,
+ sort_on=[('id', False)])
+ self.table.sortKey = 'z3c.formdemo.sqlmessage.sort-on'
+ self.table.cssClasses['table'] = 'message-list'
+ self.table.widths = (50, 200, 100, 150, 100)
+
+class AddFormTemplate(mars.template.TemplateFactory):
+ grok.context(AddForm)
+ grok.template('add.pt')
+
+class EditFormTemplate(mars.template.TemplateFactory):
+ grok.context(EditForm)
+ grok.template('edit.pt')
+
+class DisplayFormTemplate(mars.template.TemplateFactory):
+ grok.context(DisplayForm)
+ grok.template('display.pt')
+
+class OverviewTemplate(mars.template.TemplateFactory):
+ grok.context(Overview)
+ grok.template('overview.pt')
+
Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.txt (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.txt 2007-07-13 07:36:43 UTC (rev 77800)
@@ -0,0 +1,195 @@
+============================
+SQL Hello World Message Demo
+============================
+
+The purpose of the SQL Hello World Message demo is to demonstrate how
+non-bject data can be manipulated and displayed using the form framework.
+
+To start, we need to open a browser and go to the demo applications overview
+screen:
+
+ >>> from z3c.formdemo import testing
+ >>> from z3c.etestbrowser.testing import ExtendedTestBrowser
+ >>> user = ExtendedTestBrowser()
+ >>> user.addHeader('Accept-Language', 'en')
+ >>> user.handleErrors = False
+ >>> skinURL = 'http://localhost:8080/++skin++marsformdemo'
+
+Since all demos are purely public, there is no need to log in. Let's now click
+on the "SQLMessage" link:
+
+ >>> user.open('http://localhost:8080/showallsql')
+
+
+The initial page of the demo is the list of all messages. This screen exists,
+because the ZMI management screens are not helpful for unmapped relational data.
+
+ >>> testing.printElement(user, "//h1")
+ <h1>SQL Hello World Message Demo</h1>
+
+Let's make sure the database is truly empty:
+
+ >>> testing.printElement(user, "//table/tbody", multiple=True)
+
+We can now initialize the database using one of the action links below the
+table:
+
+ >>> user.getLink('[Initialize the database]').click()
+ >>> testing.printElement(user, "//div[@class='summary']", multiple=True)
+
+The page returns with no notable messages. Clicking the link again results in
+an error, because the database is already initialized:
+
+ >>> user.getLink('[Initialize the database]').click()
+ >>> testing.printElement(user, "//div[@class='summary']")
+ <div class="summary">Database Message: cannot create MSG, exists</div>
+
+Let's now add a new message:
+
+ >>> user.getLink('[Add message]').click()
+
+You are now represented with the message add form.
+
+ >>> user.url
+ 'http://localhost:8080/addsql'
+
+If we submit the form by clicking on add, ...
+
+ >>> user.getControl('Add').click()
+
+... the same page returns telling us we have some errors:
+
+ >>> testing.printElement(user, "//div[@class='summary']")
+ <div class="summary">There were some errors.</div>
+
+This is because we forgot to enter the "Who" field, which is required:
+
+ >>> testing.printElement(user, "//ul[@class='errors']/li")
+ <li>
+ Who: <div class="error">Required input is missing.</div>
+ </li>
+
+Let's now fill out all the required fields and try to add the message again:
+
+ >>> user.getControl('Who').value = u'Stephan'
+ >>> user.getControl('When').value = u'7/1/07'
+ >>> user.getControl('Add').click()
+
+Once submitted, the message is now added to the database and we are returned
+back to the overview:
+
+ >>> testing.printElement(user, "//table/tbody/tr[1]")
+ <tr class="odd"><td class="sorted-on">
+ <a href="showsql?id=0">0</a>
+ </td>
+ <td class="">
+ <a href="showsql?id=0">Stephan</a>
+ </td>
+ <td class="">
+ <a href="showsql?id=0">2007-07-01</a>
+ </td>
+ <td class="">
+ <a href="showsql?id=0">cool</a>
+ </td>
+ <td class="">
+ <a href="showallsql?delete=0">[Delete]</a>
+ </td>
+ </tr>
+
+Clicking on any data item, brings us to the message display screen:
+
+ >>> user.getLink('Stephan').click()
+ >>> testing.printElement(user, "//h1")
+ <h1>
+ A cool Hello World from Stephan on 7/1/07 !
+ </h1>
+
+The message's edit form can be accessed by clicking on the "Edit Message"
+link:
+
+ >>> user.getLink('Edit Message').click()
+
+When immediately pressing "Apply", a message appears telling us that no data
+has been changed:
+
+ >>> user.getControl('Apply', index=0).click()
+ >>> testing.printElement(user, "//div[@class='summary']")
+ <div class="summary">No changes were applied.</div>
+
+Let's now change the name and submit the form:
+
+ >>> user.getControl('Who').value = u'Roger'
+ >>> user.getControl('Apply', index=0).click()
+
+The page now informs us that the data has been updated:
+
+ >>> testing.printElement(user, "//div[@class='summary']")
+ <div class="summary">Data successfully updated.</div>
+
+When pressing the "Apply and View" button, the changed data is stored and the
+user is also forwarded to the view page again:
+
+ >>> user.getControl('What').getControl('best').click()
+ >>> user.getControl('Apply and View').click()
+
+Of course, the view shows the latest data:
+
+ >>> testing.printElement(user, "//h1")
+ <h1>
+ A best Hello World from Roger on 7/1/07 !
+ </h1>
+
+From the display screen you can also return to the overview:
+
+ >>> user.getLink('[Show All Messages]').click()
+ >>> user.url
+ 'http://localhost:8080/showallsql'
+
+Let's now add a new message:
+
+ >>> user.getLink('[Add message]').click()
+
+ >>> user.getControl('Who').value = u'Stephan'
+ >>> user.getControl('When').value = u'7/2/07'
+ >>> user.getControl('Add').click()
+
+As you probably already guessed, the table headers can be used to sort
+items. Clicking on the "Id" table header cell, will leave the order,
+since the ordering must be initialized. The second time the order is reversed:
+
+ >>> user.getLink('Id').click()
+ >>> user.getLink('Id').click()
+
+ >>> testing.printElement(user, "//table/tbody/tr/td[1]/a/text()",
+ ... multiple=True, serialize=False)
+ 1
+ 0
+
+Selecting another header will sort on it. Let's choose the "Who" column;
+clicking on it once sorts it in ascending order:
+
+ >>> user.getLink('Who').click()
+ >>> testing.printElement(user, "//table/tbody/tr/td[2]/a/text()",
+ ... multiple=True, serialize=False)
+ Roger
+ Stephan
+
+Clicking it again, reverses the order:
+
+ >>> user.getLink('Who').click()
+ >>> testing.printElement(user, "//table/tbody/tr/td[2]/a/text()",
+ ... multiple=True, serialize=False)
+ Stephan
+ Roger
+
+To delete a contact, you Simply click on the "Delete" link of the
+corresponding row:
+
+ >>> user.getLink('[Delete]', index=1).click()
+
+The message is now gone from the table:
+
+ >>> user.getLink('Roger')
+ Traceback (most recent call last):
+ ...
+ LinkNotFoundError
Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/sqlmessage/sqlmessage.txt
___________________________________________________________________
Name: svn:keywords
+ Date Author
Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py 2007-07-13 07:36:39 UTC (rev 77799)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py 2007-07-13 07:36:43 UTC (rev 77800)
@@ -15,7 +15,8 @@
('widgets', 'widgets.txt'),
('spreadsheet', 'spreadsheet.txt'),
('wizard', 'wizard.txt'),
- # ('addressbook', 'addressbook.txt'),
+ ('addressbook', 'addressbook.txt'),
+ ('sqlmessage', 'sqlmessage.txt'),
):
suite = functional.FunctionalDocFileSuite(
os.path.join(*docpath),
More information about the Checkins
mailing list