[silva.infrae.contact][Emiliano D'Alterio] First version of embe...
[email protected] Wed, 09 Oct 2013 10:23:30 +0200
| Newsgroups | gmane.comp.web.zope.silva.cvs |
|---|---|
| Message-ID | <[email protected]> |
author: Emiliano D'Alterio
date: Wed Oct 09 10:23:00 2013 +0200
revision: 0:93ba4ba697b2 in silva.infrae.contact
branch:
details: https://hg.infrae.com/silva.infrae.contact?cmd=changeset;node=93ba4ba697b2
modified: .hgignore README.txt docs/HISTORY.txt setup.py src/silva/__init__.py src/silva/infrae/__init__.py src/silva/infrae/contact/__init__.py src/silva/infrae/contact/configure.zcml src/silva/infrae/contact/contactform.py src/silva/infrae/contact/contactform_templates/contactformtemplate.cpt src/silva/infrae/contact/static/contactform.css src/silva/infrae/contact/static/contactform.js
added: .hgignore README.txt docs/HISTORY.txt setup.py src/silva/__init__.py src/silva/infrae/__init__.py src/silva/infrae/contact/__init__.py src/silva/infrae/contact/configure.zcml src/silva/infrae/contact/contactform.py src/silva/infrae/contact/contactform_templates/contactformtemplate.cpt src/silva/infrae/contact/static/contactform.css src/silva/infrae/contact/static/contactform.js
removed:
log: First version of embeddable "contact us" form for the Infrae site.
diffstat:
.hgignore | 7 +
README.txt | 18 +
setup.py | 44 +++
src/silva/__init__.py | 9 +
src/silva/infrae/__init__.py | 9 +
src/silva/infrae/contact/__init__.py | 9 +
src/silva/infrae/contact/configure.zcml | 13 +
src/silva/infrae/contact/contactform.py | 115 ++++++++++
src/silva/infrae/contact/contactform_templates/contactformtemplate.cpt | 58 +++++
src/silva/infrae/contact/static/contactform.css | 25 ++
src/silva/infrae/contact/static/contactform.js | 38 +++
11 files changed, 345 insertions(+), 0 deletions(-)
diffs (390 lines):
diff -r 000000000000 -r 93ba4ba697b2 .hgignore
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,7 @@
+.pyo
+.pyc
+.egg-info
+.cpt.py
+.DS_Store
+~
+#
diff -r 000000000000 -r 93ba4ba697b2 README.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/README.txt Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,18 @@
+====================
+silva.infrae.contact
+====================
+
+Introduction
+============
+
+``silva.infrae.contact`` contains the public
+"contact us" form for the Infrae site.
+You can embed this contact form in a template
+using: <tal:contactform tal:replace="structure provider:contactform" />
+
+Code repository
+===============
+
+This code can be found in Mercurial at:
+https://hg.infrae.com/silva.infrae.contact/.
+
diff -r 000000000000 -r 93ba4ba697b2 setup.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/setup.py Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2002-2010 Infrae. All rights reserved.
+# $Id$
+
+from setuptools import setup, find_packages
+import os
+
+version = '1.0'
+
+setup(name='silva.infrae.contact',
+ version=version,
+ description="Contact form for Infrae site",
+ long_description=open("README.txt").read() + "\n" + open(
+ os.path.join("docs", "HISTORY.txt")).read(),
+ classifiers=[
+ "Programming Language :: Python",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ ],
+ keywords='infrae contact form',
+ author='Infrae',
+ author_email='[email protected]',
+ url='http://infrae.com/products/silva',
+ license='BSD',
+ package_dir={'': 'src'},
+ packages=find_packages('src'),
+ namespace_packages=['silva'],
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ 'five.grok',
+ 'zope.interface',
+ 'zope.schema',
+ 'zope.publisher',
+ 'z3c.schema',
+ 'zeam.form.silva',
+ 'Products.Silva',
+ 'silva.translations',
+ 'silva.core.interfaces',
+ 'silva.core.conf',
+ 'silva.fanstatic',
+ 'megrok.pagetemplate',
+ 'js.jquery',
+ ],
+ )
diff -r 000000000000 -r 93ba4ba697b2 src/silva/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/silva/__init__.py Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2013 Infrae. All rights reserved.
+# See also LICENSE.txt
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
diff -r 000000000000 -r 93ba4ba697b2 src/silva/infrae/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/silva/infrae/__init__.py Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2013 Infrae. All rights reserved.
+# See also LICENSE.txt
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
diff -r 000000000000 -r 93ba4ba697b2 src/silva/infrae/contact/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/silva/infrae/contact/__init__.py Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2013 Infrae. All rights reserved.
+# See also LICENSE.txt
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
diff -r 000000000000 -r 93ba4ba697b2 src/silva/infrae/contact/configure.zcml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/silva/infrae/contact/configure.zcml Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,13 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:grok="http://namespaces.zope.org/grok"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ i18n_domain="silva">
+
+ <include package="five.grok" />
+
+ <!-- Grok package -->
+ <grok:grok package="." />
+
+</configure>
+
diff -r 000000000000 -r 93ba4ba697b2 src/silva/infrae/contact/contactform.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/silva/infrae/contact/contactform.py Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,115 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2013 Infrae. All rights reserved.
+# $Id$
+
+from five import grok
+from zope import interface, schema
+from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
+from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+from z3c.schema.email import RFC822MailAddress
+from zeam.form import silva as silvaforms
+from zeam.form.viewlet.interfaces import IInlineForm
+from Products.Silva.mail import sendmail
+from silva.translations import translate as _
+from silva.core.interfaces import IViewableObject
+from silva.core import conf as silvaconf
+from silva.fanstatic import need
+from megrok import pagetemplate as pt
+from js.jquery import jquery
+
+
+class IContactFormResources(IDefaultBrowserLayer):
+ """CSS and JS for the contact form.
+ """
+ silvaconf.resource('contactform.css')
+ silvaconf.resource('contactform.js')
+
+
+## Choices available for the subject in the contact form
+subjects = SimpleVocabulary([
+ SimpleTerm(value='Support Request', token='support',
+ title=u'Professional Support'),
+ SimpleTerm(value='Training Request', token='training',
+ title=u'Technical Training'),
+ SimpleTerm(value='Question', token='question',
+ title=u'Ask us a question'),
+ SimpleTerm(value='Feedback', token='feedback',
+ title=u'Give us your feedback'), ])
+
+
+class IContactFormFields(interface.Interface):
+ """Fields present in the contact form.
+ """
+ name = schema.TextLine(
+ title=u'Full Name', required=True)
+ company = schema.TextLine(
+ title=u'Company', required=False)
+ email = RFC822MailAddress(
+ title=u'Email', required=True)
+ phone = schema.TextLine(
+ title=u'Phone', required=False)
+ subject = schema.Choice(
+ title=u'Message subject', source=subjects, required=False)
+ message = schema.Text(
+ title=u'Message', required=True)
+
+
+EMAIL_TEMPLATE = u"""
+{subject} from {name}
+
+{message}
+
+From: {name}
+Company: {company}
+Email: {email}
+Telephone: {phone}
+"""
+
+
+class IPublicContactForm(IInlineForm):
+ """The public embeddable contact form.
+ """
+
+
+class ContactFormTemplate(pt.PageTemplate):
+ """Template for the public contact form.
+ """
+ pt.view(IPublicContactForm)
+
+
+class ContactForm(silvaforms.PublicContentProviderForm):
+ """The public 'contact us' form.
+ """
+ grok.name('contactform')
+ grok.context(IViewableObject)
+ grok.implements(IPublicContactForm)
+
+ label = u'Contact us'
+ fields = silvaforms.Fields(IContactFormFields)
+ fields['name'].htmlAttributes['placeholder'] = _(u'Your full name*')
+ fields['company'].htmlAttributes['placeholder'] = _(u'Your company name')
+ fields['email'].htmlAttributes['placeholder'] = _(u'Your email address*')
+ fields['phone'].htmlAttributes['placeholder'] = _(u'Your phone number')
+ fields['message'].htmlAttributes['placeholder'] = _(u'Your message to us*')
+
+ @silvaforms.action(u"Send", identifier='contact', accesskey='c')
+ def contact(self):
+ data, errors = self.extractData()
+ if errors:
+ self.status = u'There are errors, please check again.'
+ return silvaforms.FAILURE
+
+ msg = EMAIL_TEMPLATE.format(**data.getDictWithDefault())
+
+ sub = '%s from %s' % (data['subject'], data['name'])
+
+ sendmail(self.context, msg, mto='[email protected]',
+ mfrom='[email protected]', subject=sub)
+
+ self.status = _(u'Thank you for your message.')
+ return silvaforms.SUCCESS
+
+ def update(self):
+ need(jquery)
+ need(IContactFormResources)
+ return super(ContactForm, self).update()
diff -r 000000000000 -r 93ba4ba697b2 src/silva/infrae/contact/contactform_templates/contactformtemplate.cpt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/silva/infrae/contact/contactform_templates/contactformtemplate.cpt Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,58 @@
+<div id="contactus-wrapper">
+<form action="#" tal:attributes="action request.URL;
+ name form.prefix or None;
+ id form.prefix or None"
+ method="post"
+ enctype="multipart/form-data"
+ i18n:domain="zeam.form.base">
+
+ <h3 tal:condition="form.label"
+ tal:content="form.label">Label</h3>
+
+ <p tal:condition="form.description"
+ tal:content="form.description">Description</p>
+
+ <p class="form-status"
+ tal:condition="form.status"
+ tal:content="form.status">Status</p>
+
+ <div class="form-error"
+ tal:condition="form.errors">
+ <ul tal:condition="form.formErrors"
+ tal:repeat="error form.formErrors">
+ <li> <span tal:replace="error.title" /> </li>
+ </ul>
+ </div>
+
+ <div class="fields"
+ tal:condition="form.fieldWidgets">
+ <div class="field" tal:repeat="widget form.fieldWidgets">
+
+
+ <br />
+ <tal:description tal:condition="widget.description">
+ <span class="field-description"
+ tal:content="widget.description">
+ </span><br />
+ </tal:description>
+ <tal:error tal:define="error widget.error"
+ tal:condition="error">
+ <span class="field-error"
+ tal:content="error.title">
+ Error
+ </span>
+ <br />
+ </tal:error>
+ <tal:widget tal:content="structure widget.render()" />
+ </div>
+ </div>
+
+ <div class="actions"
+ tal:condition="form.actionWidgets">
+ <div class="action" tal:repeat="widget form.actionWidgets">
+ <tal:widget tal:content="structure widget.render()" />
+ </div>
+ </div>
+
+</form>
+</div>
\ No newline at end of file
diff -r 000000000000 -r 93ba4ba697b2 src/silva/infrae/contact/static/contactform.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/silva/infrae/contact/static/contactform.css Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,25 @@
+#contactus-wrapper {
+ color: #fff;
+ background: #222;
+ padding: 10px;
+ border: 2px solid #ddd;
+ margin: 10px 0;
+ float: left;
+ font-size: 1.2em;
+ -moz-box-shadow: 0 0 20px #999;
+ -webkit-box-shadow: 0 0 20px #999;
+ box-shadow: 0 0 20px #999;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+}
+
+#contactus-wrapper input,
+#contactus-wrapper textarea {
+ width: 98%;
+ margin: auto;
+}
+
+#contactus-wrapper h3 {
+ color: #fff;
+}
diff -r 000000000000 -r 93ba4ba697b2 src/silva/infrae/contact/static/contactform.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/silva/infrae/contact/static/contactform.js Wed Oct 09 10:23:00 2013 +0200
@@ -0,0 +1,38 @@
+// We have to "emulate" placeholder attribute behaviour
+// for browser that don't support it (e.g. internet explorer less than version 10)
+(function(){
+ $(document).ready(function(){
+
+ var placeholder_support = (function has_placeholder_support() {
+ var input = document.createElement('input');
+ return ('placeholder' in input);
+ })();
+
+ if(placeholder_support === false){
+ var placeholder = '';
+ var value = '';
+ $('#contactus-wrapper input, #contactus-wrapper textarea').each(function(){
+ placeholder = $(this).attr('placeholder');
+ $(this).css('color', '#888');
+ $(this).attr('value', placeholder);
+
+ $(this).on('keypress', function(){
+ placeholder = $(this).attr('placeholder');
+ value = $(this).attr('value');
+ if(value == placeholder){
+ $(this).attr('value', '');
+ $(this).css('color', '#222');
+ }
+ });
+ $(this).on('focusout', function(){
+ value = $(this).attr('value');
+ if(value === ''){
+ placeholder = $(this).attr('placeholder');
+ $(this).css('color', '#888');
+ $(this).attr('value', placeholder);
+ }
+ });
+ });
+ }
+ });
+})();