mirror of
https://github.com/jazzband/django-analytical.git
synced 2026-03-16 22:20:25 +00:00
Add UserVoice service
This commit is contained in:
parent
8e115b3c65
commit
fb98371a01
8 changed files with 385 additions and 127 deletions
|
|
@ -1,3 +1,7 @@
|
|||
Version 0.12.0
|
||||
--------------
|
||||
* Add support for the UserVoice service.
|
||||
|
||||
Version 0.11.3
|
||||
--------------
|
||||
* Added support for Gaug.es (Steven Skoczen)
|
||||
|
|
|
|||
144
README.rst
144
README.rst
|
|
@ -1,71 +1,73 @@
|
|||
django-analytical
|
||||
=================
|
||||
|
||||
The django-analytical application integrates analytics services into a
|
||||
Django_ project.
|
||||
|
||||
Using an analytics service with a Django project means adding Javascript
|
||||
tracking code to the project templates. Of course, every service has
|
||||
its own specific installation instructions. Furthermore, you need to
|
||||
include your unique identifiers, which then end up in the templates.
|
||||
Not very nice.
|
||||
|
||||
This application hides the details of the different analytics services
|
||||
behind a generic interface, and keeps personal information and
|
||||
configuration out of the templates. Its goal is to make the basic
|
||||
set-up very simple, while allowing advanced users to customize tracking.
|
||||
Each service is set up as recommended by the services themselves, using
|
||||
an asynchronous version of the Javascript code if possible.
|
||||
|
||||
Currently supported services:
|
||||
|
||||
* `Chartbeat`_ traffic analysis
|
||||
* `Clicky`_ traffic analysis
|
||||
* `Crazy Egg`_ visual click tracking
|
||||
* `Gaug.es`_ realtime traffic tracking
|
||||
* `Google Analytics`_ traffic analysis
|
||||
* `GoSquared`_ traffic monitoring
|
||||
* `HubSpot`_ inbound marketing
|
||||
* `KISSinsights`_ feedback surveys
|
||||
* `KISSmetrics`_ funnel analysis
|
||||
* `Mixpanel`_ event tracking
|
||||
* `Olark`_ visitor chat
|
||||
* `Optimizely`_ A/B testing
|
||||
* `Performable`_ web analytics and landing pages
|
||||
* `Reinvigorate`_ visitor tracking
|
||||
* `SnapEngage`_ live chat
|
||||
* `Spring Metrics`_ conversion tracking
|
||||
* `Woopra`_ web analytics
|
||||
|
||||
The documentation can be found in the ``docs`` directory or `read
|
||||
online`_. The source code and issue tracker are generously `hosted by
|
||||
GitHub`_.
|
||||
|
||||
If you want to help out with the development of django-analytical, by
|
||||
posting detailed bug reports, proposing new features or other analytics
|
||||
services to support, or suggesting documentation improvements, use the
|
||||
`issue tracker`_. If you want to get your hands dirty, great! Clone
|
||||
the repository, make changes and send a pull request. Please do create
|
||||
an issue to discuss your plans.
|
||||
|
||||
.. _Django: http://www.djangoproject.com/
|
||||
.. _Chartbeat: http://www.chartbeat.com/
|
||||
.. _Clicky: http://getclicky.com/
|
||||
.. _`Crazy Egg`: http://www.crazyegg.com/
|
||||
.. _`Google Analytics`: http://www.google.com/analytics/
|
||||
.. _`Gaug.es`: http://www.gaug.es/
|
||||
.. _GoSquared: http://www.gosquared.com/
|
||||
.. _HubSpot: http://www.hubspot.com/
|
||||
.. _KISSinsights: http://www.kissinsights.com/
|
||||
.. _KISSmetrics: http://www.kissmetrics.com/
|
||||
.. _Mixpanel: http://www.mixpanel.com/
|
||||
.. _Olark: http://www.olark.com/
|
||||
.. _Optimizely: http://www.optimizely.com/
|
||||
.. _Performable: http://www.performable.com/
|
||||
.. _Reinvigorate: http://www.reinvigorate.com/
|
||||
.. _SnapEngage: http://www.snapengage.com/
|
||||
.. _`Spring Metrics`: http://www.springmetrics.com/
|
||||
.. _Woopra: http://www.woopra.com/
|
||||
.. _`read online`: http://packages.python.org/django-analytical/
|
||||
.. _`hosted by GitHub`: http://github.com/jcassee/django-analytical
|
||||
.. _`issue tracker`: http://github.com/jcassee/django-analytical/issues
|
||||
django-analytical
|
||||
=================
|
||||
|
||||
The django-analytical application integrates analytics services into a
|
||||
Django_ project.
|
||||
|
||||
Using an analytics service with a Django project means adding Javascript
|
||||
tracking code to the project templates. Of course, every service has
|
||||
its own specific installation instructions. Furthermore, you need to
|
||||
include your unique identifiers, which then end up in the templates.
|
||||
Not very nice.
|
||||
|
||||
This application hides the details of the different analytics services
|
||||
behind a generic interface, and keeps personal information and
|
||||
configuration out of the templates. Its goal is to make the basic
|
||||
set-up very simple, while allowing advanced users to customize tracking.
|
||||
Each service is set up as recommended by the services themselves, using
|
||||
an asynchronous version of the Javascript code if possible.
|
||||
|
||||
Currently supported services:
|
||||
|
||||
* `Chartbeat`_ traffic analysis
|
||||
* `Clicky`_ traffic analysis
|
||||
* `Crazy Egg`_ visual click tracking
|
||||
* `Gaug.es`_ realtime traffic tracking
|
||||
* `Google Analytics`_ traffic analysis
|
||||
* `GoSquared`_ traffic monitoring
|
||||
* `HubSpot`_ inbound marketing
|
||||
* `KISSinsights`_ feedback surveys
|
||||
* `KISSmetrics`_ funnel analysis
|
||||
* `Mixpanel`_ event tracking
|
||||
* `Olark`_ visitor chat
|
||||
* `Optimizely`_ A/B testing
|
||||
* `Performable`_ web analytics and landing pages
|
||||
* `Reinvigorate`_ visitor tracking
|
||||
* `SnapEngage`_ live chat
|
||||
* `Spring Metrics`_ conversion tracking
|
||||
* `UserVoice`_ user feedback and helpdesk
|
||||
* `Woopra`_ web analytics
|
||||
|
||||
The documentation can be found in the ``docs`` directory or `read
|
||||
online`_. The source code and issue tracker are generously `hosted by
|
||||
GitHub`_.
|
||||
|
||||
If you want to help out with the development of django-analytical, by
|
||||
posting detailed bug reports, proposing new features or other analytics
|
||||
services to support, or suggesting documentation improvements, use the
|
||||
`issue tracker`_. If you want to get your hands dirty, great! Clone
|
||||
the repository, make changes and send a pull request. Please do create
|
||||
an issue to discuss your plans.
|
||||
|
||||
.. _`Django`: http://www.djangoproject.com/
|
||||
.. _`Chartbeat`: http://www.chartbeat.com/
|
||||
.. _`Clicky`: http://getclicky.com/
|
||||
.. _`Crazy Egg`: http://www.crazyegg.com/
|
||||
.. _`Google Analytics`: http://www.google.com/analytics/
|
||||
.. _`GoSquared`: http://www.gosquared.com/
|
||||
.. _`HubSpot`: http://www.hubspot.com/
|
||||
.. _`KISSinsights`: http://www.kissinsights.com/
|
||||
.. _`KISSmetrics`: http://www.kissmetrics.com/
|
||||
.. _`Mixpanel`: http://www.mixpanel.com/
|
||||
.. _`Olark`: http://www.olark.com/
|
||||
.. _`Optimizely`: http://www.optimizely.com/
|
||||
.. _`Performable`: http://www.performable.com/
|
||||
.. _`Reinvigorate`: http://www.reinvigorate.com/
|
||||
.. _`SnapEngage`: http://www.snapengage.com/
|
||||
.. _`Spring Metrics`: http://www.springmetrics.com/
|
||||
.. _`UserVoice`: http://www.uservoice.com/
|
||||
.. _`Woopra`: http://www.woopra.com/
|
||||
|
||||
.. _`read online`: http://packages.python.org/django-analytical/
|
||||
.. _`hosted by GitHub`: http://github.com/jcassee/django-analytical
|
||||
.. _`issue tracker`: http://github.com/jcassee/django-analytical/issues
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ Django_ project. See the ``docs`` directory for more information.
|
|||
|
||||
__author__ = "Joost Cassee"
|
||||
__email__ = "joost@cassee.net"
|
||||
__version__ = "0.11.3"
|
||||
__version__ = "0.12.0"
|
||||
__copyright__ = "Copyright (C) 2011 Joost Cassee and others"
|
||||
__license__ = "MIT License"
|
||||
|
|
|
|||
112
analytical/templatetags/uservoice.py
Normal file
112
analytical/templatetags/uservoice.py
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
"""
|
||||
UserVoice template tags.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import re
|
||||
|
||||
from django.template import Library, Node, TemplateSyntaxError, Variable
|
||||
from django.utils import simplejson
|
||||
|
||||
from analytical.utils import get_identity, get_required_setting
|
||||
|
||||
|
||||
WIDGET_KEY_RE = re.compile(r'^[a-zA-Z0-9]*$')
|
||||
TRACKING_CODE = """
|
||||
<script type="text/javascript">
|
||||
var uvOptions = %(options)s;
|
||||
(function() {
|
||||
var uv = document.createElement('script'); uv.type = 'text/javascript'; uv.async = true;
|
||||
uv.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'widget.uservoice.com/%(widget_key)s.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(uv, s);
|
||||
})();
|
||||
</script>
|
||||
"""
|
||||
LINK_CODE = "UserVoice.showPopupWidget(%s);"
|
||||
|
||||
|
||||
register = Library()
|
||||
|
||||
|
||||
@register.tag
|
||||
def uservoice(parser, token):
|
||||
"""
|
||||
UserVoice tracking template tag.
|
||||
|
||||
Renders Javascript code to track page visits. You must supply
|
||||
your UserVoice Widget Key in the ``USERVOICE_WIDGET_KEY``
|
||||
setting or the ``uservoice_widget_key`` template context variable.
|
||||
"""
|
||||
bits = token.split_contents()
|
||||
if len(bits) > 1:
|
||||
raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
|
||||
return UserVoiceNode()
|
||||
|
||||
class UserVoiceNode(Node):
|
||||
def __init__(self):
|
||||
self.default_widget_key = get_required_setting('USERVOICE_WIDGET_KEY',
|
||||
WIDGET_KEY_RE, "must be an alphanumeric string")
|
||||
|
||||
def render(self, context):
|
||||
widget_key = context.get('uservoice_widget_key')
|
||||
if not widget_key:
|
||||
widget_key = self.default_widget_key
|
||||
if not widget_key:
|
||||
return ''
|
||||
options = {}
|
||||
options['enabled'] = context.get('uservoice_show_tab', True)
|
||||
options['custom_fields'] = context.get('uservoice_fields', {})
|
||||
identity = get_identity(context, 'uservoice')
|
||||
if identity is not None:
|
||||
# Enable SSO
|
||||
pass
|
||||
html = TRACKING_CODE % {'widget_key': widget_key,
|
||||
'options': simplejson.dumps(options)}
|
||||
return html
|
||||
|
||||
|
||||
@register.tag
|
||||
def uservoice_link(parser, token):
|
||||
"""
|
||||
UserVoice link template tag.
|
||||
|
||||
Renders the Javascript link to launch the UserVoice widget. For
|
||||
example::
|
||||
|
||||
<a href="#" onclick="{% uservoice_popup %}; return false;">Feedback</a>
|
||||
|
||||
The tag accepts an optional argument specifying the key of the widget you
|
||||
want to show::
|
||||
|
||||
<a href="#" onclick="{% uservoice_popup 'XXXXXXXXXXXXXXXXXXXX' %}; return false;">Helpdesk</a>
|
||||
|
||||
If you add this tag without a widget key, the default feedback tab will be
|
||||
hidden.
|
||||
"""
|
||||
bits = token.split_contents()
|
||||
if len(bits) == 1:
|
||||
return UserVoiceLinkNode()
|
||||
if len(bits) == 2:
|
||||
return UserVoiceKeyLinkNode(bits[1])
|
||||
raise TemplateSyntaxError("'%s' takes at most one argument" % bits[0])
|
||||
|
||||
class UserVoiceLinkNode(Node):
|
||||
def render(self, context):
|
||||
context['uservoice_show_tab'] = False
|
||||
return LINK_CODE % ''
|
||||
|
||||
class UserVoiceKeyLinkNode(Node):
|
||||
def __init__(self, widget_key):
|
||||
self.widget_key = Variable(widget_key)
|
||||
|
||||
def render(self, context):
|
||||
vars = {}
|
||||
if self.widget_key:
|
||||
vars['widget_key'] = self.widget_key.resolve(context)
|
||||
return LINK_CODE % simplejson.dumps(vars)
|
||||
|
||||
|
||||
def contribute_to_analytical(add_node):
|
||||
UserVoiceNode() # ensure properly configured
|
||||
add_node('body_bottom', UserVoiceNode)
|
||||
|
|
@ -19,5 +19,6 @@ from analytical.tests.test_tag_performable import *
|
|||
from analytical.tests.test_tag_reinvigorate import *
|
||||
from analytical.tests.test_tag_snapengage import *
|
||||
from analytical.tests.test_tag_spring_metrics import *
|
||||
from analytical.tests.test_tag_uservoice import *
|
||||
from analytical.tests.test_tag_woopra import *
|
||||
from analytical.tests.test_utils import *
|
||||
|
|
|
|||
93
analytical/tests/test_tag_uservoice.py
Normal file
93
analytical/tests/test_tag_uservoice.py
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
"""
|
||||
Tests for the UserVoice tags and filters.
|
||||
"""
|
||||
|
||||
from django.contrib.auth.models import User, AnonymousUser
|
||||
from django.http import HttpRequest
|
||||
from django.template import Context
|
||||
|
||||
from analytical.templatetags.uservoice import UserVoiceNode
|
||||
from analytical.tests.utils import TagTestCase, override_settings, \
|
||||
SETTING_DELETED
|
||||
from analytical.utils import AnalyticalException
|
||||
|
||||
|
||||
@override_settings(USERVOICE_WIDGET_KEY='abcdefghijklmnopqrst')
|
||||
class UserVoiceTagTestCase(TagTestCase):
|
||||
"""
|
||||
Tests for the ``uservoice`` template tag.
|
||||
"""
|
||||
|
||||
def test_node(self):
|
||||
r = UserVoiceNode().render(Context())
|
||||
self.assertTrue("'widget.uservoice.com/abcdefghijklmnopqrst.js'" in r,
|
||||
r)
|
||||
|
||||
def test_tag(self):
|
||||
r = self.render_tag('uservoice', 'uservoice')
|
||||
self.assertTrue("'widget.uservoice.com/abcdefghijklmnopqrst.js'" in r,
|
||||
r)
|
||||
|
||||
@override_settings(USERVOICE_WIDGET_KEY=SETTING_DELETED)
|
||||
def test_no_key(self):
|
||||
self.assertRaises(AnalyticalException, UserVoiceNode)
|
||||
|
||||
@override_settings(USERVOICE_WIDGET_KEY='abcdefgh ijklmnopqrst')
|
||||
def test_invalid_key(self):
|
||||
self.assertRaises(AnalyticalException, UserVoiceNode)
|
||||
|
||||
@override_settings(USERVOICE_WIDGET_KEY='')
|
||||
def test_empty_key(self):
|
||||
r = UserVoiceNode().render(Context())
|
||||
self.assertFalse("widget.uservoice.com" in r, r)
|
||||
|
||||
@override_settings(USERVOICE_WIDGET_KEY='')
|
||||
def test_overridden_empty_key(self):
|
||||
vars = {'uservoice_widget_key': 'bcdefghijklmnopqrstu'}
|
||||
r = UserVoiceNode().render(Context(vars))
|
||||
self.assertTrue("'widget.uservoice.com/bcdefghijklmnopqrstu.js'" in r,
|
||||
r)
|
||||
|
||||
def test_overridden_key(self):
|
||||
vars = {'uservoice_widget_key': 'defghijklmnopqrstuvw'}
|
||||
r = UserVoiceNode().render(Context(vars))
|
||||
self.assertTrue("'widget.uservoice.com/defghijklmnopqrstuvw.js'" in r,
|
||||
r)
|
||||
|
||||
def test_link(self):
|
||||
r = self.render_tag('uservoice', 'uservoice_link')
|
||||
self.assertEqual(r, "UserVoice.showPopupWidget();")
|
||||
|
||||
def test_link_with_key(self):
|
||||
r = self.render_tag('uservoice',
|
||||
'uservoice_link "efghijklmnopqrstuvwx"')
|
||||
self.assertEqual(r, 'UserVoice.showPopupWidget({"widget_key": '
|
||||
'"efghijklmnopqrstuvwx"});')
|
||||
|
||||
def test_link_disables_tab(self):
|
||||
r = self.render_template(
|
||||
'{% load uservoice %}{% uservoice_link %}{% uservoice %}')
|
||||
self.assertTrue("UserVoice.showPopupWidget();" in r, r)
|
||||
self.assertTrue('"enabled": false' in r, r)
|
||||
self.assertTrue("'widget.uservoice.com/abcdefghijklmnopqrst.js'" in r,
|
||||
r)
|
||||
|
||||
def test_link_with_key_enables_tab(self):
|
||||
r = self.render_template('{% load uservoice %}'
|
||||
'{% uservoice_link "efghijklmnopqrstuvwx" %}{% uservoice %}')
|
||||
self.assertTrue('UserVoice.showPopupWidget({"widget_key": '
|
||||
'"efghijklmnopqrstuvwx"});' in r, r)
|
||||
self.assertTrue('"enabled": true' in r, r)
|
||||
self.assertTrue("'widget.uservoice.com/abcdefghijklmnopqrst.js'" in r,
|
||||
r)
|
||||
|
||||
def test_custom_fields(self):
|
||||
vars = {
|
||||
'uservoice_fields': {
|
||||
'field1': 'val1',
|
||||
'field2': 'val2',
|
||||
}
|
||||
}
|
||||
r = UserVoiceNode().render(Context(vars))
|
||||
self.assertTrue('"custom_fields": {"field2": "val2", "field1": "val1"}'
|
||||
in r, r)
|
||||
|
|
@ -149,3 +149,13 @@ class TagTestCase(TestCase):
|
|||
else:
|
||||
context = Context(vars)
|
||||
return t.render(context)
|
||||
|
||||
def render_template(self, template, vars=None, request=None):
|
||||
if vars is None:
|
||||
vars = {}
|
||||
t = Template(template)
|
||||
if request is not None:
|
||||
context = RequestContext(request, vars)
|
||||
else:
|
||||
context = Context(vars)
|
||||
return t.render(context)
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ UserVoice -- user feedback and helpdesk
|
|||
=======================================
|
||||
|
||||
UserVoice_ makes it simple for your customers to give, discuss, and vote
|
||||
for feedback. An unobtrusive feedback button allows visitors to easily
|
||||
for feedback. An unobtrusive feedback tab allows visitors to easily
|
||||
submit and discuss ideas without having to sign up for a new account.
|
||||
The best ideas are delivered to you based on customer votes.
|
||||
|
||||
.. _UserVoice: http://www.uservoice.com/
|
||||
|
||||
|
||||
.. _uservoice-installation:
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
|
|
@ -26,7 +28,7 @@ This step is only needed if you are not using the generic
|
|||
The UserVoice Javascript code is inserted into templates using a
|
||||
template tag. Load the :mod:`uservoice` template tag library and insert
|
||||
the :ttag:`uservoice` tag. Because every page that you want to have
|
||||
the feedback button to appear on must have the tag, it is useful to add
|
||||
the feedback tab to appear on must have the tag, it is useful to add
|
||||
it to your base template. Insert the tag at the bottom of the HTML
|
||||
body::
|
||||
|
||||
|
|
@ -42,61 +44,74 @@ body::
|
|||
Configuration
|
||||
=============
|
||||
|
||||
Before you can use the UserVoice integration, you must first set your
|
||||
account name.
|
||||
Before you can use the UserVoice integration, you must first set the
|
||||
widget key.
|
||||
|
||||
|
||||
Setting the account name
|
||||
------------------------
|
||||
Setting the widget key
|
||||
----------------------
|
||||
|
||||
In order to load the Javascript code, you need to set your UserVoice
|
||||
account name. The account name is the username you use to log into
|
||||
UserVoice with. Set :const:`USERVOICE_ACCOUNT_NAME` in the project
|
||||
:file:`settings.py` file::
|
||||
In order to use the feedback widget, you need to configure which widget
|
||||
you want to show. You can find the widget keys in the *Channels* tab on
|
||||
your UserVoice *Settings* page. Under the *Javascript Widget* heading,
|
||||
find the Javascript embed code of the widget. The widget key is the
|
||||
alphanumerical string contained in the URL of the script imported by the
|
||||
embed code::
|
||||
|
||||
USERVOICE_ACCOUNT_NAME = 'XXXXX'
|
||||
<script type="text/javascript">
|
||||
var uvOptions = {};
|
||||
(function() {
|
||||
var uv = document.createElement('script'); uv.type = 'text/javascript'; uv.async = true;
|
||||
uv.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'widget.uservoice.com/XXXXXXXXXXXXXXXXXXXX.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(uv, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
If you do not set the account name, the feedback button will not be
|
||||
rendered.
|
||||
(The widget key is shown as ``XXXXXXXXXXXXXXXXXXXX``.)
|
||||
|
||||
The default widget
|
||||
..................
|
||||
|
||||
.. _uservoice-hide:
|
||||
Often you will use the same widget throughout your website. The default
|
||||
widget key is configured by setting :const:`USERVOICE_WIDGET_KEY` in
|
||||
the project :file:`settings.py` file::
|
||||
|
||||
Hiding the feedback button
|
||||
--------------------------
|
||||
USERVOICE_WIDGET_KEY = 'XXXXXXXXXXXXXXXXXXXX'
|
||||
|
||||
The feedback button is shown on every page that has the template tag.
|
||||
You can hide the button by default by setting :const:`USERVOICE_SHOW`
|
||||
in the project :file:`settings.py` file::
|
||||
If the setting is present but empty, no widget is shown by default. This
|
||||
is useful if you want to set a widget using a template context variable,
|
||||
as the setting must be present for the generic :ttag:`analytical.*` tags
|
||||
to work.
|
||||
|
||||
USERVOICE_SHOW = False
|
||||
Per-view widget
|
||||
...............
|
||||
|
||||
The feedback button is also automatically hidden if you add a custom
|
||||
link to launch the widget by using the :ttag:`uservoice_link` template
|
||||
tag. (See :ref:`uservoice-link`.) The :ttag:`uservoice` tag must
|
||||
appear below it in the template, but its preferredlocation is the bottom
|
||||
of the body HTML anyway.
|
||||
Iou can set the widget key in a view using the ``uservoice_widget_key``
|
||||
template context variable::
|
||||
|
||||
You can hide the feedback button for a specific view you can do so by
|
||||
passing the ``uservoice_show`` context variable::
|
||||
|
||||
context = RequestContext({'uservoice_show': False})
|
||||
context = RequestContext({'uservoice_widget_key': 'XXXXXXXXXXXXXXXXXXXX'})
|
||||
return some_template.render(context)
|
||||
|
||||
If you show or hide the feedback button based on some computable
|
||||
condition, you may want to set variables in a context processor that you
|
||||
add to the :data:`TEMPLATE_CONTEXT_PROCESSORS` list in
|
||||
:file:`settings.py`::
|
||||
The widget key passed in the context variable overrides the default
|
||||
widget key.
|
||||
|
||||
def uservoice_show_to_staff(request):
|
||||
Setting the widget key in a context processor
|
||||
.............................................
|
||||
|
||||
You can also set the widget keys in a context processor that you add to
|
||||
the :data:`TEMPLATE_CONTEXT_PROCESSORS` list in :file:`settings.py`.
|
||||
For example, to show a specific widget to logged in users::
|
||||
|
||||
def uservoice_widget_key(request):
|
||||
try:
|
||||
return {'uservoice_show': request.user.is_staff()}
|
||||
if request.user.is_authenticated():
|
||||
return {'uservoice_widget_key': 'XXXXXXXXXXXXXXXXXXXX'}
|
||||
except AttributeError:
|
||||
return {}
|
||||
pass
|
||||
return {}
|
||||
|
||||
Just remember that if you set the same context variable in the
|
||||
:class:`~django.template.context.RequestContext` constructor and in a
|
||||
context processor, the latter clobbers the former.
|
||||
The widget key passed in the context variable overrides both the default
|
||||
and the per-view widget key.
|
||||
|
||||
|
||||
.. _uservoice-link:
|
||||
|
|
@ -104,26 +119,49 @@ context processor, the latter clobbers the former.
|
|||
Using a custom link
|
||||
-------------------
|
||||
|
||||
Instead of showing the default button, you can make the UserVoice widget
|
||||
launch when a visitor clicks a link or on some other event occurs. Use
|
||||
the :ttag:`uservoice_link` in your template to render the Javascript
|
||||
code to launch the widget::
|
||||
Instead of showing the default feedback tab, you can make the UserVoice
|
||||
widget launch when a visitor clicks a link or when some other event
|
||||
occurs. Use the :ttag:`uservoice_popup` tag in your template to render
|
||||
the Javascript code to launch the widget::
|
||||
|
||||
<a href="{% uservoice_link %}" title="Open feedback & support dialog (powered by UserVoice)">feedback & support</a>
|
||||
<a href="#" onclick="{% uservoice_popup %}; return false;">Feedback</a>
|
||||
|
||||
If you use this tag and the :ttag:`uservoice` tag appears below it in
|
||||
the HTML, the default button is automatically hidden. See
|
||||
:ref:`uservoice-link`.
|
||||
the HTML, the default tab is automatically hidden. (The preferred
|
||||
location of the :ttag:`uservoice` is the bottom of the body HTML, so
|
||||
this usually works automatically. See :ref:`uservoice-installation`.)
|
||||
|
||||
You can explicitly hide the feedback tab by setting the
|
||||
``uservoice_show_tab`` context variable to :const:``False``::
|
||||
|
||||
context = RequestContext({'uservoice_show_tab': False})
|
||||
return some_template.render(context)
|
||||
|
||||
However, instead consider only setting the widget key in the views you
|
||||
do want to show the widget on.
|
||||
|
||||
|
||||
Showing a second widget
|
||||
.......................
|
||||
|
||||
Use the :ttag:`uservoice_popup` tag with a widget_key to display a
|
||||
different widget that the one configured in the
|
||||
:const:`USERVOICE_WIDGET_KEY` setting or the ``uservoice_widget_key``
|
||||
template context variable::
|
||||
|
||||
<a href="#" onclick="{% uservoice_popup 'XXXXXXXXXXXXXXXXXXXX' %}; return false;">Helpdesk</a>
|
||||
|
||||
In this case, the default widget tab is not hidden.
|
||||
|
||||
|
||||
Passing custom data into the helpdesk
|
||||
-------------------------------------
|
||||
|
||||
You can pass custom data through your widget and into the ticketing
|
||||
system. First create custom fields in your `Ticket settings`_ page.
|
||||
system. First create custom fields in your *Tickets* settings page.
|
||||
Deselect *Display on contact form* in the edit dialog for those fields
|
||||
you intend to use from Django. You can now pass values for this field
|
||||
by passing the :data:`uservoice_fields` context variables to the
|
||||
you intend to use from Django. You can set values for this field by
|
||||
passing the :data:`uservoice_fields` context variables to the
|
||||
template::
|
||||
|
||||
uservoice_fields = {
|
||||
|
|
@ -139,15 +177,13 @@ context processor will clobber all fields set in the
|
|||
:class:`~django.template.context.RequestContext` constructor.
|
||||
|
||||
|
||||
.. _`Ticket settings`: https://cassee.uservoice.com/admin/settings#/tickets
|
||||
|
||||
|
||||
|
||||
Using Single Sign-On
|
||||
--------------------
|
||||
|
||||
If your websites authenticates users, you can allow them to use
|
||||
UserVoice without having to create an account.
|
||||
If your websites authenticates users, you will be able to let them give
|
||||
feedback without having to create a UserVoice account.
|
||||
|
||||
*This feature is in development*
|
||||
|
||||
See also :ref:`identifying-visitors`.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue