2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/examples/Common/Candidate/Resources/candidate_display_template.xhtml Tue Nov 15 00:25:51 2005 +0000
2.3 @@ -0,0 +1,59 @@
2.4 +<?xml version="1.0" encoding="iso-8859-1"?>
2.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
2.6 + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2.7 +<html xmlns="http://www.w3.org/1999/xhtml"
2.8 + xmlns:template="http://www.boddie.org.uk/ns/xmltools/template">
2.9 +<head>
2.10 + <title>Candidate</title>
2.11 +</head>
2.12 +<body template:element="candidate">
2.13 +
2.14 +<h1>Candidate Details</h1>
2.15 +
2.16 +<table border="0" cellspacing="0" cellpadding="5" width="80%" align="left">
2.17 + <tbody>
2.18 + <tr template:element="identity">
2.19 + <th width="30%">Name</th>
2.20 + <td width="70%">
2.21 + <span template:if="not(@anonymous = 'true')" template:attribute-area="name,replace">...</span>
2.22 + <span template:if="@anonymous = 'true'"><strong>Candidate name withheld</strong></span>
2.23 + </td>
2.24 + </tr>
2.25 + <tr>
2.26 + <th width="30%">Work status</th>
2.27 + <td width="70%">
2.28 + <span template:element="status" template:value="@value">...</span>
2.29 + </td>
2.30 + </tr>
2.31 + <tr>
2.32 + <th width="30%">Skills</th>
2.33 + <td width="70%">
2.34 + <span template:element="skills,skill" template:attribute="value">
2.35 + <span template:effect="replace" template:value="$this-value">...</span><br/>
2.36 + </span>
2.37 + </td>
2.38 + </tr>
2.39 + <tr>
2.40 + <th width="30%">Qualifications</th>
2.41 + <td width="70%" xml:space="preserve">
2.42 + <span template:element="qualifications,qualification">
2.43 + <span template:attribute-area="title,replace">...</span>
2.44 + <span template:attribute-area="grade,replace">...</span>
2.45 + <span template:attribute-area="institution,replace">...</span>
2.46 + </span>
2.47 + </td>
2.48 + </tr>
2.49 + <tr template:element="experience,employment">
2.50 + <th width="30%">
2.51 + From <span template:attribute-area="from,replace">...</span>
2.52 + to <span template:attribute-area="to,replace">...</span>
2.53 + </th>
2.54 + <td width="70%">
2.55 + <span template:attribute-area="employer,replace">...</span>
2.56 + </td>
2.57 + </tr>
2.58 + </tbody>
2.59 +</table>
2.60 +
2.61 +</body>
2.62 +</html>
3.1 --- a/examples/Common/Candidate/Resources/candidate_template.xhtml Tue Nov 15 00:24:15 2005 +0000
3.2 +++ b/examples/Common/Candidate/Resources/candidate_template.xhtml Tue Nov 15 00:25:51 2005 +0000
3.3 @@ -11,22 +11,22 @@
3.4
3.5 <h1>Candidate Details</h1>
3.6
3.7 -<table border="0" cellspacing="0" cellpadding="5">
3.8 +<table border="0" cellspacing="0" cellpadding="5" width="80%" align="left">
3.9 <tbody>
3.10 <tr>
3.11 <th colspan="2">General</th>
3.12 </tr>
3.13 <tr template:element="identity">
3.14 - <th>Name</th>
3.15 - <td>
3.16 + <th width="30%">Name</th>
3.17 + <td width="70%">
3.18 <input template:attribute-field="name" name="..." type="text" /><br />
3.19 Anonymous
3.20 <input template:attribute-button="anonymous,true,checked" name="..." value="..." type="checkbox" />
3.21 </td>
3.22 </tr>
3.23 <tr>
3.24 - <th>Work status</th>
3.25 - <td>
3.26 + <th width="30%">Work status</th>
3.27 + <td width="70%">
3.28 <select template:multiple-choice-field="status,value" name="...">
3.29 <option template:multiple-choice-value="status-enum,value,selected"/>
3.30 </select>
3.31 @@ -36,15 +36,15 @@
3.32 <th colspan="2">Skills</th>
3.33 </tr>
3.34 <tr template:element="skills,skill">
3.35 - <th>Skill</th>
3.36 - <td>
3.37 + <th width="30%">Skill</th>
3.38 + <td width="70%">
3.39 <input template:attribute-field="value" type="text" name="..." />
3.40 <input template:selector-field="remove" type="submit" name="..." value="Remove" />
3.41 </td>
3.42 </tr>
3.43 <tr>
3.44 - <th></th>
3.45 - <td>
3.46 + <th width="30%"></th>
3.47 + <td width="70%">
3.48 <input template:selector-field="add-skill,skill" type="submit" name="..." value="Add" />
3.49 </td>
3.50 </tr>
3.51 @@ -54,29 +54,29 @@
3.52 </tbody>
3.53 <tbody template:element="qualifications,qualification">
3.54 <tr>
3.55 - <th>Course/Diploma/Title</th>
3.56 - <td>
3.57 + <th width="30%">Course/Diploma/Title</th>
3.58 + <td width="70%">
3.59 <input template:attribute-field="title" type="text" name="..." />
3.60 <input template:selector-field="remove" type="submit" name="..." value="Remove" />
3.61 </td>
3.62 </tr>
3.63 <tr>
3.64 - <th>Grade/Level/Class</th>
3.65 - <td>
3.66 + <th width="30%">Grade/Level/Class</th>
3.67 + <td width="70%">
3.68 <input template:attribute-field="grade" type="text" name="..." />
3.69 </td>
3.70 </tr>
3.71 <tr>
3.72 - <th>Institution</th>
3.73 - <td>
3.74 + <th width="30%">Institution</th>
3.75 + <td width="70%">
3.76 <input template:attribute-field="institution" type="text" name="..." />
3.77 </td>
3.78 </tr>
3.79 </tbody>
3.80 <tbody>
3.81 <tr>
3.82 - <th></th>
3.83 - <td>
3.84 + <th width="30%"></th>
3.85 + <td width="70%">
3.86 <input template:selector-field="add-qualification,qualification" type="submit" name="..." value="Add" />
3.87 </td>
3.88 </tr>
3.89 @@ -88,27 +88,34 @@
3.90 </tbody>
3.91 <tbody template:element="experience,employment">
3.92 <tr>
3.93 - <th>Employment</th>
3.94 - <td>
3.95 + <th width="30%">Employment</th>
3.96 + <td width="70%">
3.97 From <input template:attribute-field="from" type="text" name="..." />
3.98 to <input template:attribute-field="to" type="text" name="..." />
3.99 <input template:selector-field="remove" type="submit" name="..." value="Remove" />
3.100 </td>
3.101 </tr>
3.102 <tr>
3.103 - <th>Employer</th>
3.104 - <td>
3.105 + <th width="30%">Employer</th>
3.106 + <td width="70%">
3.107 <input template:attribute-field="employer" type="text" name="..." />
3.108 </td>
3.109 </tr>
3.110 </tbody>
3.111 <tbody>
3.112 <tr>
3.113 - <th></th>
3.114 - <td>
3.115 + <th width="30%"></th>
3.116 + <td width="70%">
3.117 <input template:selector-field="add-employment,employment" type="submit" name="..." value="Add" />
3.118 </td>
3.119 </tr>
3.120 + <tr>
3.121 + <th width="30%"></th>
3.122 + <td width="70%">
3.123 + <input type="submit" name="show" value="Show..." />
3.124 + <input type="submit" name="admin" value="Admin..." />
3.125 + </td>
3.126 + </tr>
3.127 </tbody>
3.128 </table>
3.129
4.1 --- a/examples/Common/Candidate/__init__.py Tue Nov 15 00:24:15 2005 +0000
4.2 +++ b/examples/Common/Candidate/__init__.py Tue Nov 15 00:25:51 2005 +0000
4.3 @@ -6,6 +6,7 @@
4.4 import XSLForms.Resources.WebResources
4.5 import XSLForms.Utils
4.6 import os
4.7 +import libxml2dom
4.8
4.9 # Site map imports.
4.10
4.11 @@ -14,6 +15,158 @@
4.12
4.13 # Resource classes.
4.14
4.15 +class AdminResource(XSLForms.Resources.WebResources.XSLFormsResource):
4.16 +
4.17 + "A resource providing administration facilities for job candidate profiles."
4.18 +
4.19 + resource_dir = os.path.join(os.path.split(__file__)[0], "Resources")
4.20 + encoding = "utf-8"
4.21 + template_resources = {
4.22 + "admin" : ("admin_template.xhtml", "admin_output.xsl")
4.23 + }
4.24 + init_resources = {
4.25 + "admin" : ("admin_template.xhtml", "admin_input.xsl")
4.26 + }
4.27 +
4.28 + def respond_to_form(self, trans, form):
4.29 +
4.30 + """
4.31 + Respond to a request having the given transaction 'trans' and the given
4.32 + 'form' information.
4.33 + """
4.34 +
4.35 + parameters = form.get_parameters()
4.36 + documents = form.get_documents()
4.37 +
4.38 + # Get the "show" and "edit" resource paths.
4.39 + # NOTE: These should be obtained from the site map.
4.40 +
4.41 + parts = trans.get_processed_virtual_path_info(self.path_encoding).split("/")
4.42 + show_path = "/".join(parts[:-1] + ["show"])
4.43 + edit_path = "/".join(parts[:-1] + ["edit"])
4.44 +
4.45 + # Ensure the presence of a document.
4.46 +
4.47 + form_is_new = 0
4.48 + if documents.has_key("admin"):
4.49 + admin = documents["admin"]
4.50 + else:
4.51 + admin = form.new_instance("admin")
4.52 + form_is_new = 1
4.53 +
4.54 + # Redirect if one of the CVs is to be shown or edited.
4.55 +
4.56 + selectors = form.get_selectors()
4.57 + if selectors.has_key("show"):
4.58 + name = selectors["show"][0].getAttribute("name")
4.59 + self._redirect(trans, show_path + "?name=%s" % name.encode(self.path_encoding))
4.60 + elif selectors.has_key("edit"):
4.61 + name = selectors["edit"][0].getAttribute("name")
4.62 + self._redirect(trans, edit_path + "?name=%s" % name.encode(self.path_encoding))
4.63 +
4.64 + # Add and remove elements according to the selectors found.
4.65 +
4.66 + XSLForms.Utils.remove_elements(selectors.get("remove"))
4.67 + XSLForms.Utils.add_elements(selectors.get("new"), "cv", "cvs")
4.68 +
4.69 + # Transform, adding enumerations/ranges.
4.70 +
4.71 + init_xsl = self.prepare_initialiser("admin")
4.72 + admin = self.get_result([init_xsl], admin)
4.73 +
4.74 + # Synchronise the session with the CVs found.
4.75 +
4.76 + cvs = admin.xpath("/admin/cvs")[0]
4.77 + session = trans.get_session()
4.78 + for key in session.keys():
4.79 + if key.startswith("candidate-"):
4.80 + name = key[len("candidate-"):]
4.81 + # NOTE: Apostrophes not quoted.
4.82 + if not cvs.xpath("cv[@name = '%s']" % name):
4.83 + if form_is_new:
4.84 + cv = admin.createElement("cv")
4.85 + cv.setAttribute("name", name)
4.86 + cvs.appendChild(cv)
4.87 + else:
4.88 + del session[key]
4.89 +
4.90 + # Start the response.
4.91 +
4.92 + trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding))
4.93 +
4.94 + # Ensure that an output stylesheet exists.
4.95 +
4.96 + trans_xsl = self.prepare_output("admin")
4.97 + stylesheet_parameters = {}
4.98 +
4.99 + # Complete the response.
4.100 +
4.101 + self.send_output(trans, [trans_xsl], admin, stylesheet_parameters)
4.102 +
4.103 + def _redirect(self, trans, path):
4.104 + trans.set_response_code(302)
4.105 + trans.set_header_value("Location", path)
4.106 + raise WebStack.Generic.EndOfResponse
4.107 +
4.108 +class DisplayResource(XSLForms.Resources.WebResources.XSLFormsResource):
4.109 +
4.110 + "A resource providing editing facilities for a job candidate profile."
4.111 +
4.112 + resource_dir = os.path.join(os.path.split(__file__)[0], "Resources")
4.113 + encoding = "utf-8"
4.114 + template_resources = {
4.115 + "candidate_display" : ("candidate_display_template.xhtml", "candidate_display_output.xsl")
4.116 + }
4.117 + init_resources = {
4.118 + "candidate" : ("candidate_template.xhtml", "candidate_input.xsl")
4.119 + }
4.120 + document_resources = {
4.121 + "status" : "candidate_status.xml"
4.122 + }
4.123 +
4.124 + def respond_to_form(self, trans, form):
4.125 +
4.126 + """
4.127 + Respond to a request having the given transaction 'trans' and the given
4.128 + 'form' information.
4.129 + """
4.130 +
4.131 + parameters = form.get_parameters()
4.132 + documents = form.get_documents()
4.133 + fields = trans.get_fields_from_path()
4.134 + name = fields.get("name", [u"None"])[0]
4.135 +
4.136 + # Ensure the presence of a document.
4.137 +
4.138 + if documents.has_key("candidate"):
4.139 + candidate = documents["candidate"]
4.140 + else:
4.141 + session = trans.get_session(create=0)
4.142 + if session is None or not session.has_key("candidate-%s" % name.encode("utf-8")):
4.143 + candidate = form.new_instance("candidate")
4.144 + else:
4.145 + candidate = libxml2dom.parseString(session["candidate-%s" % name.encode("utf-8")])
4.146 +
4.147 + # Transform, adding enumerations/ranges.
4.148 +
4.149 + init_xsl = self.prepare_initialiser("candidate")
4.150 + status_xml = self.prepare_document("status")
4.151 + candidate = self.get_result([init_xsl], candidate, references={"status" : status_xml})
4.152 +
4.153 + # Start the response.
4.154 +
4.155 + trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding))
4.156 +
4.157 + # Ensure that an output stylesheet exists.
4.158 + # Handle the "show" operation.
4.159 +
4.160 + trans_xsl = self.prepare_output("candidate_display")
4.161 + stylesheet_parameters = {}
4.162 +
4.163 + # Complete the response.
4.164 +
4.165 + self.send_output(trans, [trans_xsl], candidate, stylesheet_parameters)
4.166 +
4.167 class CandidateResource(XSLForms.Resources.WebResources.XSLFormsResource):
4.168
4.169 "A resource providing editing facilities for a job candidate profile."
4.170 @@ -29,8 +182,6 @@
4.171 document_resources = {
4.172 "status" : "candidate_status.xml"
4.173 }
4.174 - in_page_resources = {
4.175 - }
4.176
4.177 def respond_to_form(self, trans, form):
4.178
4.179 @@ -39,16 +190,28 @@
4.180 'form' information.
4.181 """
4.182
4.183 - in_page_resource = self.get_in_page_resource(trans)
4.184 parameters = form.get_parameters()
4.185 documents = form.get_documents()
4.186 + fields = trans.get_fields_from_path()
4.187 + name = fields.get("name", [u"None"])[0]
4.188 +
4.189 + # Get the "show" resource path.
4.190 + # NOTE: This should be obtained from the site map.
4.191 +
4.192 + parts = trans.get_processed_virtual_path_info(self.path_encoding).split("/")
4.193 + show_path = "/".join(parts[:-1] + ["show"])
4.194 + admin_path = "/".join(parts[:-1] + [""])
4.195
4.196 # Ensure the presence of a document.
4.197
4.198 if documents.has_key("candidate"):
4.199 candidate = documents["candidate"]
4.200 else:
4.201 - candidate = form.new_instance("candidate")
4.202 + session = trans.get_session(create=0)
4.203 + if session is None or not session.has_key("candidate-%s" % name.encode("utf-8")):
4.204 + candidate = form.new_instance("candidate")
4.205 + else:
4.206 + candidate = libxml2dom.parseString(session["candidate-%s" % name.encode("utf-8")])
4.207
4.208 # Add and remove elements according to the selectors found.
4.209
4.210 @@ -64,23 +227,44 @@
4.211 status_xml = self.prepare_document("status")
4.212 candidate = self.get_result([init_xsl], candidate, references={"status" : status_xml})
4.213
4.214 + # Redirect if the CV is to be shown.
4.215 +
4.216 + if parameters.has_key("show"):
4.217 +
4.218 + # Save the candidate information.
4.219 +
4.220 + session = trans.get_session()
4.221 + session["candidate-%s" % name.encode("utf-8")] = candidate.toString()
4.222 + self._redirect(trans, show_path + "?name=%s" % name.encode(self.path_encoding))
4.223 +
4.224 + # Redirect if the administration interface is to be used.
4.225 +
4.226 + elif parameters.has_key("admin"):
4.227 +
4.228 + # Save the candidate information.
4.229 +
4.230 + session = trans.get_session()
4.231 + session["candidate-%s" % name.encode("utf-8")] = candidate.toString()
4.232 + self._redirect(trans, admin_path)
4.233 +
4.234 # Start the response.
4.235
4.236 trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding))
4.237
4.238 # Ensure that an output stylesheet exists.
4.239
4.240 - if in_page_resource in self.in_page_resources.keys():
4.241 - trans_xsl = self.prepare_fragment("candidate", in_page_resource)
4.242 - stylesheet_parameters = self.prepare_parameters(parameters)
4.243 - else:
4.244 - trans_xsl = self.prepare_output("candidate")
4.245 - stylesheet_parameters = {}
4.246 + trans_xsl = self.prepare_output("candidate")
4.247 + stylesheet_parameters = {}
4.248
4.249 # Complete the response.
4.250
4.251 self.send_output(trans, [trans_xsl], candidate, stylesheet_parameters)
4.252
4.253 + def _redirect(self, trans, path):
4.254 + trans.set_response_code(302)
4.255 + trans.set_header_value("Location", path)
4.256 + raise WebStack.Generic.EndOfResponse
4.257 +
4.258 # Site map initialisation.
4.259
4.260 def get_site():
4.261 @@ -90,15 +274,16 @@
4.262 # Get the main resource and the directory used by the application.
4.263
4.264 candidate_resource = CandidateResource()
4.265 + display_resource = DisplayResource()
4.266 + admin_resource = AdminResource()
4.267 directory = candidate_resource.resource_dir
4.268
4.269 # Make a simple Web site.
4.270
4.271 resource = MapResource({
4.272 - # Static resources:
4.273 - #"scripts" : DirectoryResource(os.path.join(directory, "scripts"), {"js" : "text/javascript"}),
4.274 - # Main page and in-page resources:
4.275 - None : candidate_resource
4.276 + "edit" : candidate_resource,
4.277 + "show" : display_resource,
4.278 + "" : admin_resource
4.279 })
4.280
4.281 return resource