Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
saving the support request on the site
close #62
- Loading branch information
1 parent
41a7a2b
commit d98277b
Showing
10 changed files
with
285 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"> | ||
</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> |