Permalink
Browse files

saving the support request on the site

close #62
  • Loading branch information...
1 parent 41a7a2b commit d98277b3be67db84a47ff7d396d6716b89995694 @sassur sassur committed Mar 26, 2012
@@ -6,4 +6,5 @@
def includeme(config):
""" Include Site adapter and register views."""
config.scan('voteit.site')
+ config.include('voteit.site.models.support_storage')
config.add_translation_dirs('voteit.site:locale/')
No changes.
@@ -0,0 +1,27 @@
+from zope.interface import Interface
+from zope.interface import Attribute
+
+
+class ISupportStorage(Interface):
+ """ An adapter for sites that handle storage of support requests. """
+ support_storage = Attribute("Conatins the support request saved on the site")
+
+ def __init__(context):
+ """ Object needs a meeting to adapt. """
+
+ def add(message, subject='', name='', email='', meeting=None):
+ """ Add a support request.
+ """
+
+class ISupportRequest(Interface):
+ """ A persistent support request. """
+ created = Attribute("When it was created, in UTC time.")
+ message = Attribute("The message.")
+ subject = Attribute("The subject.")
+ name = Attribute("The name specified.")
+ email = Attribute("The email specified.")
+ meeting = Attribute("The meeting the user was on if any.")
+
+ def __init__(message, subject='', name='', email='', meeting=None):
+ """ Create a support request.
+ """
@@ -0,0 +1,66 @@
+from zope.component import adapts
+from zope.interface import implements
+from persistent import Persistent
+from BTrees.LOBTree import LOBTree
+from betahaus.pyracont.decorators import content_factory
+from betahaus.pyracont.factories import createContent
+
+from voteit.core.models.date_time_util import utcnow
+from voteit.core.models.interfaces import ISiteRoot
+
+from voteit.site.models.interfaces import ISupportStorage
+from voteit.site.models.interfaces import ISupportRequest
+from voteit.site import SiteMF as _
+
+
+class SupportStorage(object):
+ """ An adapter for ISiteRoot that handle feed entries.
+ """
+ implements(ISupportStorage)
+
+ def __init__(self, context):
+ self.context = context
+
+ @property
+ def support_storage(self):
+ if not hasattr(self.context, '__support_storage__'):
+ self.context.__support_storage__ = LOBTree()
+ return self.context.__support_storage__
+
+ def _next_free_key(self):
+ if len(self.support_storage) == 0:
+ return 0
+ return self.support_storage.maxKey()+1
+
+ def add(self, message, subject='', name='', email='', meeting=None):
+ """ Add a support request.
+ """
+ obj = createContent('SupportRequest', message, subject=subject, name=name, email=email, meeting=meeting)
+
+ for i in range(10):
+ k = self._next_free_key()
+ if self.support_storage.insert(k, obj):
+ return
+
+ raise KeyError("Couln't find a free key for support request after 10 retries.") # pragma : no cover
+
+
+@content_factory('SupportRequest', title=_(u"Support request"))
+class SupportRequest(Persistent):
+ implements(ISupportRequest)
+
+ def __init__(self, message, subject='', name='', email='', meeting=None):
+ self.created = utcnow()
+ self.message = message
+ self.subject = subject
+ self.name = name
+ self.email = email
+ self.meeting = meeting
+
+
+def includeme(config):
+ """ Include to activate support storage components.
+ like: config.include('voteit.site.models.support_storage')
+ """
+ #Register SupportRequest adapter
+ config.registry.registerAdapter(SupportStorage, (ISiteRoot,), ISupportStorage)
No changes.
@@ -0,0 +1,94 @@
+import unittest
+from datetime import datetime
+
+from pyramid import testing
+from zope.interface.verify import verifyObject
+from zope.component.interfaces import IFactory
+from zope.component import createObject
+
+
+class SupportStorageTests(unittest.TestCase):
+
+ def setUp(self):
+ self.request = testing.DummyRequest()
+ self.config = testing.setUp(request=self.request)
+ self.config.testing_securitypolicy(userid='some_user',
+ permissive=True)
+
+ def tearDown(self):
+ testing.tearDown()
+
+ def _make_adapted_obj(self):
+ from voteit.core.models.site import SiteRoot
+ from voteit.site.models.support_storage import SupportStorage
+ context = SiteRoot()
+ return SupportStorage(context)
+
+ def _register_support_request_factory(self):
+ #FIXME: Detach more?
+ self.config.scan('voteit.site.models.support_storage')
+
+ def test_interface(self):
+ from voteit.site.models.interfaces import ISupportStorage
+ obj = self._make_adapted_obj()
+ self.assertTrue(verifyObject(ISupportStorage, obj))
+
+ def test_add(self):
+ self._register_support_request_factory()
+ obj = self._make_adapted_obj()
+ meeting = object()
+ obj.add('message', subject='subject', name='name', email='email', meeting=meeting)
+
+ self.assertEqual(len(obj.support_storage), 1)
+ self.assertEqual(obj.support_storage[0].message, 'message')
+ self.assertEqual(obj.support_storage[0].subject, 'subject')
+ self.assertEqual(obj.support_storage[0].name, 'name')
+ self.assertEqual(obj.support_storage[0].email, 'email')
+ self.assertEqual(obj.support_storage[0].meeting, meeting)
+
+ def test_registration_on_include(self):
+ self.config.include('voteit.site.models.support_storage')
+ from voteit.core.models.site import SiteRoot
+ root = SiteRoot()
+ from voteit.site.models.interfaces import ISupportStorage
+ adapter = self.config.registry.queryAdapter(root, ISupportStorage)
+ self.failUnless(ISupportStorage.providedBy(adapter))
+
+
+class FeedEntryTests(unittest.TestCase):
+
+ def setUp(self):
+ self.config = testing.setUp()
+
+ def tearDown(self):
+ testing.tearDown()
+
+ @property
+ def _cut(self):
+ from voteit.site.models.support_storage import SupportRequest
+ return SupportRequest
+
+ def test_interface(self):
+ from voteit.site.models.interfaces import ISupportRequest
+ obj = self._cut('message')
+ self.assertTrue(verifyObject(ISupportRequest, obj))
+
+ def test_construction(self):
+ meeting = object()
+ obj = self._cut('message', subject='subject', name='name', email='email', meeting=meeting)
+ self.assertTrue(isinstance(obj.created, datetime))
+ self.assertEqual(obj.message, 'message')
+ self.assertEqual(obj.subject, 'subject')
+ self.assertEqual(obj.name, 'name')
+ self.assertEqual(obj.email, 'email')
+ self.assertEqual(obj.meeting, meeting)
+
+ def test_factory_registered_on_scan(self):
+ self.config.scan('voteit.site.models.support_storage')
+
+ factory = self.config.registry.queryUtility(IFactory, 'SupportRequest')
+ self.failUnless(IFactory.providedBy(factory))
+ obj = factory('message')
+ self.failUnless(obj)
+ obj = createObject('SupportRequest', 'message')
+ self.failUnless(obj)
@@ -0,0 +1,12 @@
+from pyramid.url import resource_url
+from betahaus.viewcomponent import view_action
+
+from voteit.site import SiteMF as _
+
+
+@view_action('admin_menu', 'support requests', title = _(u"Support requests"), link = "support_requests")
+def generic_root_menu_link(context, request, va, **kw):
+ """ This is for simple menu items for the root """
+ api = kw['api']
+ url = api.resource_url(api.root, request) + va.kwargs['link']
+ return """<li><a href="%s">%s</a></li>""" % (url, api.translate(va.title))
@@ -9,6 +9,7 @@
from pyramid.response import Response
from pyramid_mailer import get_mailer
from pyramid_mailer.message import Message
+from pyramid.traversal import find_root
from betahaus.pyracont.factories import createSchema
from voteit.core import security
@@ -20,6 +21,7 @@
from voteit.core import fanstaticlib
from voteit.site import SiteMF as _
+from voteit.site.models.interfaces import ISupportStorage
class HelpView(BaseView):
@@ -114,6 +116,11 @@ def support(self):
mailer = get_mailer(self.request)
mailer.send(msg)
+
+ # add the message to the support storage
+ root = find_root(self.context)
+ support_storage = self.request.registry.getAdapter(root, ISupportStorage)
+ support_storage.add(appstruct['message'], subject=appstruct['subject'], name=appstruct['name'], email=appstruct['email'], meeting=self.api.meeting)
self.response['message'] = _(u"Message sent to VoteIT")
return Response(render("templates/ajax_success.pt", self.response, request = self.request))
@@ -0,0 +1,19 @@
+from pyramid.view import view_config
+
+from voteit.core import security
+from voteit.core.models.interfaces import ISiteRoot
+from voteit.core.views.base_view import BaseView
+
+from voteit.site import SiteMF as _
+from voteit.site.models.interfaces import ISupportStorage
+
+
+class SupportView(BaseView):
+ @view_config(name = 'support_requests', context=ISiteRoot, renderer="templates/support_requests.pt", permission=security.MANAGE_SERVER, )
+ def support_requests(self):
+
+ adapter = self.request.registry.getAdapter(self.context, ISupportStorage)
+
+ self.response['support_storage'] = adapter.support_storage.values()
+
+ return self.response
@@ -0,0 +1,59 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
+ metal:use-macro="api.main_template.macros['master']"
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+ i18n:domain="voteit.core">
+<body>
+ <div metal:fill-slot="content" class="content_wrapper">
+
+ <h3 i18n:translate="">
+ Showing
+ <span tal:replace="len(support_storage)" i18n:name="count">5</span>
+ support requests
+ </h3>
+
+ <table class="listing">
+ <thead>
+ <tr>
+ <th i18n:translate="" class="heading">Created</th>
+ <th i18n:translate="" class="heading">Subject</th>
+ <th i18n:translate="" class="heading">Message</th>
+ <th i18n:translate="" class="heading">Name</th>
+ <th i18n:translate="" class="heading">Email</th>
+ <th i18n:translate="" class="heading">Meeting</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tal:iterate repeat="support_request support_storage">
+ <tr tal:attributes="class repeat.support_request.odd and 'odd' or 'even'">
+ <td tal:content="api.dt_util.dt_format(support_request.created)|string:-">Created</td>
+ <td tal:content="support_request.subject">Subject</td>
+ <td tal:content="support_request.message">Message</td>
+ <td tal:content="support_request.name">Name</td>
+ <td>
+ <a tal:condition="support_request.email" tal:content="support_request.email"
+ tal:attributes="href 'mailto:%s' % support_request.email">
+ email
+ </a>
+ </td>
+ <td>
+ <a tal:condition="support_request.meeting" tal:content="support_request.meeting"
+ href="${api.resource_url(support_request.meeting, request)}">
+ Meeting
+ </a>
+ </td>
+ </tr>
+ </tal:iterate>
+ </tbody>
+ </table>
+ <br/>
+ <a class="buttonize large"
+ tal:attributes="href api.resource_url(context, request)">
+ <span i18n:translate="">Back</span>
+ </a><br/>
+
+ </div> <!-- content -->
+</body>
+</html>

0 comments on commit d98277b

Please sign in to comment.