Merge branch 'master' into master

This commit is contained in:
Jonathan Barratt 2017-04-06 08:21:43 +07:00 committed by GitHub
commit d843a21ea7
30 changed files with 2767 additions and 1193 deletions

15
.gitignore vendored
View File

@ -1,8 +1,23 @@
*.pyc
/dist/
django_helpdesk.egg-info
demo/*.egg-info
demo/demodesk/*.sqlite3
docs/html/*
docs/doctrees/*
.coverage
.project
.pydevproject
.directory
# ignore demo attachments that user might have added
demo/demodesk/media/helpdesk/attachments/*
!demo/demodesk/media/helpdesk/attachments/DH-3
demo/demodesk/media/helpdesk/attachments/DH-3/*
!demo/demodesk/media/helpdesk/attachments/DH-3/3
!demo/demodesk/media/helpdesk/attachments/DH-3/4
demo/demodesk/media/helpdesk/attachments/DH-3/3/*
demo/demodesk/media/helpdesk/attachments/DH-3/4/*
!demo/demodesk/media/helpdesk/attachments/DH-3/3/someinfo.txt
!demo/demodesk/media/helpdesk/attachments/DH-3/4/helpdesk.png

View File

@ -4,6 +4,7 @@ python:
- "2.7"
- 3.4.4
- "3.5"
- "3.6"
env:
- DJANGO=1.8.17

108
CONTRIBUTING.rst Normal file
View File

@ -0,0 +1,108 @@
Contributing
============
django-helpdesk is an open-source project and as such contributions from the
community are welcomed and encouraged!
Please read these guidelines to get up to speed quickly. If you have any
questions, please file an issue ticket on GitHub. Our main project
repository is available at:
https://github.com/django-helpdesk/django-helpdesk
Licensing
---------
All contributions to django-helpdesk must be under the BSD license documented in
the LICENSE file in the top-level directory of this project.
By submitting a contribution to this project (in any way: via e-mail,
via GitHub forks, attachments, etc), you acknowledge that your contribution is
open-source and licensed under the BSD license.
If you or your organisation does not accept these license terms then we cannot
accept your contribution. Please reconsider!
Translations
------------
Although django-helpdesk has originally been written for the English language,
there are already multiple translations to Spanish, Polish, German and Russian.
More translations are welcomed!
Translations are handled using the excellent Transifex service which is much
easier for most users than manually editing .po files. It also allows
collaborative translation. If you want to help translate django-helpdesk into
languages other than English, we encourage you to make use of our Transifex
project:
http://www.transifex.net/projects/p/django-helpdesk/resource/core/
Once you have translated content via Transifex, please raise an issue on the
project Github page to let us know it's ready to import.
Code changes
------------
Please fork the project on GitHub, make your changes, and log a pull request to
get the changes pulled back into the
master branch of the django-helpdesk repository.
Wherever possible please break git commits up into small chunks that are
specific to a single bit of functionality. For example, a commit should not
contain both new functionality *and* a bugfix; the new function and the bugfix
should be separate commits wherever possible.
Commit messages should also explain *what*, precisely, has been changed.
All commits should include appropriate new or updated tests; see the Tests
section below for more details.
If you have any questions, please start a discussion on the GitHub issue tracker
at
https://github.com/django-helpdesk/django-helpdesk/issues
Tests
-----
Currently, test coverage is very low. We're working on increasing this, and to
make life easier we are using `Travis CI` (http://travis-ci.org/) for continuous
integration. This means that the test suite is run every time a code change is
made, so we can try and make sure we avoid basic bugs and other regressions.
As a general policy, we will only accept new feature commits if they are
accompanied by appropriate unit/functional tests (that is, tests for the
functionality you just added). Bugfixes should also include new unit tests to
ensure the bug has been fixed.
More significant code refactoring must also include proper integration or
validation tests, to be committed BEFORE the refactoring patches. This is to
ensure that the refactored code produces the same results as the previous code
base.
Any further integration or validation tests (tests for the entire
django-helpdesk application) are not required but greatly appreciated until we
can improve our overall test coverage.
Please include tests in the ``tests/`` folder when committing code changes.
If you have any questions about creating or maintaining proper tests, please
start a discussion on the GitHub issue tracker at
https://github.com/django-helpdesk/django-helpdesk/issues
Database schema changes
-----------------------
As well as making your normal code changes to ``models.py``, please generate a
Django migration file and commit it with your code. You will want to use a
command similar to the following::
./manage.py migrate helpdesk --auto [migration_name]
Make sure that ``migration_name`` is a sensible single-string explanation of
what this migration does, such as *add_priority_options* or *add_basket_table*.
This will add a file to the ``migrations/`` folder, which must be committed to
git with your other code changes.

View File

@ -26,6 +26,3 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
EXCEPTIONS
This software is distributed with some third-party software which is not distributed under the above license. See LICENSE.3RDPARTY for further details.

125
Makefile Normal file
View File

@ -0,0 +1,125 @@
# Shortcuts for django-helpdesk testing and development using make
#
# For standard installation of django-helpdesk as a library,
# see INSTALL and the documentation in docs/.
#
# For details about how to develop django-helpdesk,
# see CONTRIBUTING.rst.
PIP = pip3
TOX = tox
#: help - Display callable targets.
.PHONY: help
help:
@echo "django-helpdesk make shortcuts"
@echo "Here are available targets:"
@egrep -o "^#: (.+)" [Mm]akefile | sed 's/#: /* /'
#: develop - Install minimal development utilities for Python3.
.PHONY: develop
develop:
$(PIP) install -e .
#: develop2 - Install minimal development utilities for Python2.
.PHONY: develop2
develop2:
pip2 install -e .
#: clean - Basic cleanup, mostly temporary files.
.PHONY: clean
clean:
find . -name "*.pyc" -delete
find . -name '*.pyo' -delete
find . -name "__pycache__" -delete
#: distclean - Remove local builds, such as *.egg-info.
.PHONY: distclean
distclean: clean
rm -rf *.egg
rm -rf *.egg-info
rm -rf demo/*.egg-info
# remove the django-created database
rm -f demo/demodesk/*.sqlite3
#: maintainer-clean - Remove almost everything that can be re-generated.
.PHONY: maintainer-clean
maintainer-clean: distclean
rm -rf build/
rm -rf dist/
rm -rf .tox/
#: test - Run test suites.
.PHONY: test
test:
mkdir -p var
$(PIP) install -e .[test]
$(TOX)
#: documentation - Build documentation (Sphinx, README, ...).
.PHONY: documentation
documentation: sphinx readme
#: sphinx - Build Sphinx documentation (docs).
.PHONY: sphinx
sphinx:
$(TOX) -e sphinx
#: readme - Build standalone documentation files (README, CONTRIBUTING...).
.PHONY: readme
readme:
$(TOX) -e readme
#: demo - Setup demo project using Python3.
.PHONY: demo
demo:
$(PIP) install -e .
$(PIP) install -e demo
demodesk migrate --noinput
# Create superuser; user will be prompted to manually set a password
# When you get a prompt, enter a password of your choosing.
# We suggest a default of 'Test1234' for the demo project.
demodesk createsuperuser --username admin --email helpdesk@example.com
# Install fixtures
demodesk loaddata emailtemplate.json
demodesk loaddata demo.json
#: demo2 - Setup demo project using Python2.
.PHONY: demo2
demo2:
pip2 install -e .
pip2 install -e demo
demodesk migrate --noinput
# Create superuser; user will be prompted to manually set a password.
# When you get a prompt, enter a password of your choosing.
# We suggest a default of 'Test1234' for the demo project.
demodesk createsuperuser --username admin --email helpdesk@example.com
# Install fixtures (helpdesk templates as well as demo ticket data)
demodesk loaddata emailtemplate.json
demodesk loaddata demo.json
#: rundemo - Run demo server using Python3.
.PHONY: rundemo
rundemo: demo
demodesk runserver 8080
#: rundemo2 - Run demo server using Python2.
.PHONY: rundemo2
rundemo2: demo2
demodesk runserver 8080
#: release - Tag and push to PyPI.
.PHONY: release
release:
$(TOX) -e release

View File

@ -7,65 +7,74 @@ django-helpdesk - A Django powered ticket tracker for small businesses.
.. image:: https://codecov.io/gh/django-helpdesk/django-helpdesk/branch/master/graph/badge.svg
:target: https://codecov.io/gh/django-helpdesk/django-helpdesk
Copyright 2009- Ross Poulton and contributors. All Rights Reserved. See LICENSE for details.
Copyright 2009- Ross Poulton and contributors. All Rights Reserved.
See LICENSE for details.
django-helpdesk was formerly known as Jutda Helpdesk, named after the
company which originally created it. As of January 2011 the name has been
changed to reflect what it really is: a Django-powered ticket tracker with
contributors reaching far beyond Jutda.
Complete documentation is available in the docs/ directory, or online at http://django-helpdesk.readthedocs.org/.
Complete documentation is available in the docs/ directory,
or online at http://django-helpdesk.readthedocs.org/.
You can see a demo installation at http://django-helpdesk-demo.herokuapp.com/
You can see a demo installation at http://django-helpdesk-demo.herokuapp.com/,
or run a demo locally in just a couple steps!
Licensing
---------
See the file 'LICENSE' for licensing terms. Note that django-helpdesk is
distributed with 3rd party products which have their own licenses. See
LICENSE.3RDPARTY for license terms for included packages.
django-helpdesk is licensed under terms of the BSD 3-clause license.
See the file 'LICENSE' for full licensing terms.
Dependencies (pre-flight checklist)
-----------------------------------
Note that django-helpdesk is distributed with 3rd party products which
have their own licenses. See LICENSE.3RDPARTY for license terms for
included packages.
1. Python 2.7 or 3.4+ (3.4+ support is new, please let us know how it goes)
2. Django (1.8+, preferably 1.10)
3. An existing WORKING Django project with database etc. If you
cannot log into the Admin, you won't get this product working.
4. `pip install django-bootstrap-form` and add `bootstrapform` to `settings.INSTALLED_APPS`
5. `pip install django-markdown-deux` and add `markdown_deux` to `settings.INSTALLED_APPS`
6. `pip install email-reply-parser` to get smart email reply handling
7. Add 'django.contrib.sites' to settings.INSTALLED_APPS, ensure there is at least 1 site created.
Demo Quickstart
---------------
django-helpdesk includes a basic demo Django project so that you may easily
get started with testing or developing django-helpdesk. The demo project
resides in the demo/ top-level folder.
It's likely that you can start up a demo project server by running
only the command:
sudo make rundemo
then pointing your web browser at localhost:8080.
For more information and options, please read the demo/README.rst file.
**NOTE REGARDING SQLITE AND SEARCHING:**
If you use sqlite as your database, the search function will not work as
effectively as it will with other databases due to its inability to do
case-insensitive searches. It's recommended that you use PostgreSQL or MySQL
if possible. For more information, see this note in the Django documentation:
The demo project uses sqlite as its database. Sqlite does not allow
case-insensitive searches and so the search function may not work as
effectively as it would on other database such as PostgreSQL or MySQL
that does support case-insensitive searches.
For more information, see this note in the Django documentation:
http://docs.djangoproject.com/en/dev/ref/databases/#sqlite-string-matching
When you try to do a keyword search using sqlite, a message will be displayed
to alert you to this shortcoming. There is no way around it, sorry.
**NOTE REGARDING MySQL:**
If you use MySQL, with most default configurations you will receive an error
when creating the database tables as we populate a number of default templates
in languages other than English.
Installation
------------
You must create the database the holds the django-helpdesk tables using the
UTF-8 collation; see the MySQL manual for more information:
http://dev.mysql.com/doc/refman/5.1/en/charset-database.html
django-helpdesk requires either Python 2.7 or 3.4+, as well as Django 1.8+.
The recommended combination is Python 3.4+ with Django 1.10.
If you do NOT do this step, and you only want to use English-language templates,
you can continue however you will receive a warning when running the 'migrate'
commands.
You can quickly install the latest stable version of django-helpdesk app via pip:
Fresh Django Installations
--------------------------
pip install django-helpdesk
If you're on a brand new Django installation, make sure you do a ``migrate``
**before** adding ``helpdesk`` to your ``INSTALLED_APPS``. This will avoid
errors with trying to create User settings.
You may also check out the master branch on GitHub, and install manually:
python setup.py install
Either way, you will need to add django-helpdesk to an existing Django project.
For further installation information see docs/install.html and docs/configuration.html
Upgrading from previous versions
--------------------------------
@ -80,25 +89,16 @@ migrations, get an up to date version of the code base (eg by using
Lastly, restart your web server software (eg Apache) or FastCGI instance, to
ensure the latest changes are in use.
If you are using django-helpdesk pre-migrations (ie pre-2011) then you're
on your own, sorry.
Unfortunately we are unable to assist if you are upgrading from a
version of django-helpdesk prior to migrations (ie pre-2011).
You can continue to the 'Initial Configuration' area, if needed.
Installation
------------
``pip install django-helpdesk``
For further installation information see docs/install.html and docs/configuration.html
Contributing
------------
If you want to help translate django-helpdesk into languages other than English, we encourage you to make use of our Transifex project.
We're happy to include any type of contribution! This can be back-end
python/django code development, front-end web development
(HTML/Javascript, especially jQuery), or even language translations.
https://www.transifex.com/django-helpdesk/django-helpdesk/
Feel free to request access to contribute your translations.
Pull requests for all other changes are welcome. We're currently trying to add test cases wherever possible, so please continue to include tests with pull requests.
For more information on contributing, please see the CONTRIBUTING.rst file.

110
demo/README.rst Normal file
View File

@ -0,0 +1,110 @@
django-helpdesk Demo Project
============================
This folder contains a demo Django project that
illustrates a simple django-helpdesk installation
with common settings.
This project is *NOT* production ready, but can be
used as a template to get started.
In particular, this should be useful for testing
purposes and for those that want to contribute
to development of django-helpdesk. For more information
on contributing, see the CONTRIBUTING.rst file
in the top level of the django-helpdesk directory.
Running the demo
----------------
By default, the demo is configured for Python 3.
While not recommended, the simplest way to get
started is to simply install django-helpdesk
to your system python package directory.
Ideally, you'd use a virtualenv instead
(see below for details).
To use your system directory, from the top-level
django-helpdesk directory, simply run:
sudo make rundemo
Once the console gives a prompt that the HTTP
server is listening, open your web browser
and navigate to:
localhost:8080
You should see the django-helpdesk public web portal!
If you shut down the server, you can't immediately
re-run the demo because the make commands would
encounter problems trying to re-write the database.
Instead, before running the demo, you will need
to first clean the demo:
sudo make distclean
You may need to use sudo with other make targets too.
*NOTE ON USING VIRTUALENV*
Rather than using the system python, you probably
want to use a virtualenv.
If so, you might change the pip in the makefile
to point to your virtualenv's pip instead
before running:
make rundemo
*NOTE ON USING PYTHON 2*
By default, the demo uses Python 3, as Python 3
will be the recommended version of python for
django-helpdesk and even Django itself in the near future.
However, if you wish to use Python 2, you can
instead run the following:
sudo make rundemo2
Then navigate to the site in a browser as above.
*NOTE ON DJANGO VERISON*
The demo project was also created with Django 1.10
in mind. If you are using a different version of Django,
slight tweaks might be necessary to make the demo work.
*NOTE ON ATTACHMENTS*
The folder:
demo/demodesk/media/helpdesk/attachments
comes pre-populated with a couple of attachments,
to demo how django-helpdesk deals with attachments.
You can look in this folder to see the raw data.
You can also create a different folder for this
and update settings.py, but note that this will
break the demo as some attachments may not be available
unless you migrate the existing data to the
new location.
The demodesk project
--------------------
"demodesk" is the name of our demo Django project.
You probably will want to look at demo/demodesk/config/settings.py
and read the comments, which walk you through a basic
installation with common configuration options.
The top-level Makefile also gives a list of commands so you
can see how to get the project running. Of course,
when you plan to deploy this project, it is recommended
to use a "real" HTTP server like apache or nginx,
and so further configuration will be necessary.
More information can be found in the top-level docs/ folder.

View File

View File

@ -0,0 +1,209 @@
"""
Django settings for django-helpdesk demodesk project.
Generated by 'django-admin startproject' using Django 1.10.2.
For more information on this file, see
https://docs.djangoproject.com/en/1.10/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.10/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '_crkn1+fnzu5$vns_-d+^ayiq%z4k*s!!ag0!mfy36(y!vrazd'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'django.contrib.humanize',
'markdown_deux',
'bootstrapform',
'helpdesk'
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'demodesk.config.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'demodesk.config.wsgi.application'
# django-helpdesk configuration settings
# You can override django-helpdesk's defaults by redefining them here.
# To see what settings are available, see the docs/configuration.rst
# file for more information.
# Some common settings are below.
HELPDESK_DEFAULT_SETTINGS = {
'use_email_as_submitter': True,
'email_on_ticket_assign': True,
'email_on_ticket_change': True,
'login_view_ticketlist': True,
'email_on_ticket_apichange': True,
'preset_replies': True,
'tickets_per_page': 25
}
# Should the public web portal be enabled?
HELPDESK_PUBLIC_ENABLED = True
HELPDESK_VIEW_A_TICKET_PUBLIC = True
HELPDESK_SUBMIT_A_TICKET_PUBLIC = True
# Should the Knowledgebase be enabled?
HELPDESK_KB_ENABLED = True
# Instead of showing the public web portal first,
# we can instead redirect users straight to the login page.
HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = False
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/login/'
# Database
# - by default, we use SQLite3 for the demo, but you can also
# configure MySQL or PostgreSQL, see the docs for more:
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Sites
# - this allows hosting of more than one site from a single server,
# in practice you can probably just leave this default if you only
# host a single site, but read more in the docs:
# https://docs.djangoproject.com/en/1.10/ref/contrib/sites/
SITE_ID = 1
# Sessions
# https://docs.djangoproject.com/en/1.10/topics/http/sessions
SESSION_COOKIE_AGE = 86400 # = 1 day
# For better default security, set these cookie flags, but
# these are likely to cause problems when testing locally
#CSRF_COOKIE_SECURE = True
#SESSION_COOKIE_SECURE = True
#CSRF_COOKIE_HTTPONLY = True
#SESSION_COOKIE_HTTPONLY = True
# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Email
# https://docs.djangoproject.com/en/1.10/topics/email/
# This demo uses the console backend, which simply prints emails to the console
# rather than actually sending them out.
DEFAULT_FROM_EMAIL = 'helpdesk@example.com'
SERVER_EMAIL = 'helpdesk@example.com'
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# If you want to test sending real emails, uncomment and modify the following:
#EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
#EMAIL_HOST = 'smtp.example.com'
#EMAIL_PORT = '25'
# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/
# By default, django-helpdesk uses en, but other languages are also available.
# The most complete translations are: es-MX, ru
# Contribute to our translations via Transifex if you can!
# See CONTRIBUTING.rst for more info.
LANGUAGE_CODE = 'en-US'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
STATIC_URL = '/static/'
# MEDIA_ROOT is where media uploads are stored.
# We set this to a directory to host file attachments created
# with tickets.
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# Fixtures
# https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-FIXTURE_DIRS
# - This is only necessary to make the demo project work, not needed for
# your own projects unless you make your own fixtures
FIXTURE_DIRS = [os.path.join(BASE_DIR, 'fixtures')]

View File

@ -0,0 +1,31 @@
"""django-helpdesk demodesk URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url, include
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
# The following uses the static() helper function,
# which only works when in development mode (using DEBUG).
# For a real deployment, you'd have to properly configure a media server.
# For more information, see:
# https://docs.djangoproject.com/en/1.10/howto/static-files/
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('helpdesk.urls', namespace='helpdesk')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -0,0 +1,16 @@
"""
WSGI config for django-helpdesk demodesk project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demodesk.config.settings")
application = get_wsgi_application()

View File

@ -0,0 +1,18 @@
[
{"model": "helpdesk.queue", "pk": 1, "fields": {"title": "Django Helpdesk", "slug": "DH", "email_address": "django-helpdesk@example.com", "locale": "en-US", "allow_public_submission": true, "allow_email_submission": true, "escalate_days": 5, "new_ticket_cc": "", "updated_ticket_cc": "", "email_box_type": null, "email_box_host": "", "email_box_port": null, "email_box_ssl": false, "email_box_user": "", "email_box_pass": "", "email_box_imap_folder": "", "email_box_local_dir": "", "permission_name": "helpdesk.queue_access_DH", "email_box_interval": 5, "email_box_last_check": null, "socks_proxy_type": null, "socks_proxy_host": null, "socks_proxy_port": null, "logging_type": null, "logging_dir": "", "default_owner": null}},
{"model": "helpdesk.queue", "pk": 2, "fields": {"title": "Some Product", "slug": "SP", "email_address": "sp-help@example.com", "locale": "en-US", "allow_public_submission": true, "allow_email_submission": true, "escalate_days": null, "new_ticket_cc": "", "updated_ticket_cc": "", "email_box_type": null, "email_box_host": "", "email_box_port": null, "email_box_ssl": false, "email_box_user": "", "email_box_pass": "", "email_box_imap_folder": "", "email_box_local_dir": "", "permission_name": "helpdesk.queue_access_SP", "email_box_interval": 5, "email_box_last_check": null, "socks_proxy_type": null, "socks_proxy_host": null, "socks_proxy_port": null, "logging_type": null, "logging_dir": "", "default_owner": null}},
{"model": "helpdesk.ticket", "pk": 1, "fields": {"title": "Some django-helpdesk Problem", "queue": 1, "created": "2017-03-20T04:52:18.321Z", "modified": "2017-03-20T04:52:18.561Z", "submitter_email": "helpdesk@example.com", "assigned_to": null, "status": 1, "on_hold": false, "description": "I'm having some problem with django-helpdesk that I need help with.", "resolution": null, "priority": 3, "due_date": "2017-03-04T00:00:00Z", "last_escalation": null}},
{"model": "helpdesk.followup", "pk": 1, "fields": {"ticket": 1, "date": "2017-03-20T04:52:18.561Z", "title": "Ticket Opened", "comment": "I'm having some problem with django-helpdesk that I need help with.", "public": true, "user": 1, "new_status": null}},
{"model": "helpdesk.ticket", "pk": 2, "fields": {"title": "Something else", "queue": 2, "created": "2017-03-20T04:54:53.001Z", "modified": "2017-03-20T04:54:53.031Z", "submitter_email": "helpdesk@example.com", "assigned_to": null, "status": 1, "on_hold": false, "description": "Something else with some other product. Not a big deal.", "resolution": null, "priority": 4, "due_date": "2017-03-01T00:00:00Z", "last_escalation": null}},
{"model": "helpdesk.followup", "pk": 2, "fields": {"ticket": 2, "date": "2017-03-20T04:54:53.031Z", "title": "Ticket Opened", "comment": "Something else with some other product. Not a big deal.", "public": true, "user": 1, "new_status": null}},
{"model": "helpdesk.ticket", "pk": 3, "fields": {"title": "Something with an attachment", "queue": 1, "created": "2017-03-20T05:14:36.320Z", "modified": "2017-03-20T05:28:28.695Z", "submitter_email": "helpdesk@example.com", "assigned_to": null, "status": 1, "on_hold": false, "description": "WHOA!", "resolution": null, "priority": 1, "due_date": null, "last_escalation": null}},
{"model": "helpdesk.followup", "pk": 3, "fields": {"ticket": 3, "date": "2017-03-20T05:14:36.345Z", "title": "Ticket Opened", "comment": "WHOA!", "public": true, "user": 1, "new_status": null}},
{"model": "helpdesk.attachment", "pk": 1, "fields": {"followup": 3, "file": "helpdesk/attachments/DH-3/3/someinfo.txt", "filename": "someinfo.txt", "mime_type": "text/plain", "size": 56}},
{"model": "helpdesk.followup", "pk": 4, "fields": {"ticket": 3, "date": "2017-03-20T05:28:28.458Z", "title": "Comment", "comment": "An image attachment goes here!", "public": true, "user": 1, "new_status": null}},
{"model": "helpdesk.attachment", "pk": 2, "fields": {"followup": 4, "file": "helpdesk/attachments/DH-3/4/helpdesk.png", "filename": "helpdesk.png", "mime_type": "image/png", "size": 30229}},
{"model": "helpdesk.kbcategory", "pk": 1, "fields": {"title": "KB Cat 1", "slug": "kbcat1", "description": "Some category of KB info"}},
{"model": "helpdesk.kbcategory", "pk": 2, "fields": {"title": "KB Cat 2", "slug": "kbcat2", "description": "Here is another category. Enjoy!"}},
{"model": "helpdesk.kbitem", "pk": 1, "fields": {"category": 1, "title": "Django-Helpdesk", "question": "What is Django-Helpdesk?", "answer": "An open source helpdesk written in python using the awesome django framework.", "votes": 0, "recommendations": 0, "last_updated": "2017-04-02T19:02:17.213Z"}},
{"model": "helpdesk.kbitem", "pk": 2, "fields": {"category": 1, "title": "Contributing to django-helpdesk", "question": "How do I contribute?", "answer": "Read the CONTRIBUTING.md file in the top directory of the django-helpdesk source.", "votes": 0, "recommendations": 0, "last_updated": "2017-04-02T19:02:48.374Z"}},
{"model": "helpdesk.kbitem", "pk": 3, "fields": {"category": 2, "title": "Something Else", "question": "What else?", "answer": "Not sure.", "votes": 0, "recommendations": 0, "last_updated": "2017-04-02T19:02:59.741Z"}}
]

25
demo/demodesk/manage.py Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python
import os
import sys
def main():
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "demodesk.config.settings")
try:
from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
execute_from_command_line(sys.argv)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,3 @@
Here's a report about a bug.
Some stuff would go here.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

51
demo/setup.py Normal file
View File

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
"""Python packaging."""
from __future__ import unicode_literals
from setuptools import setup
import os
here = os.path.abspath(os.path.dirname(__file__))
project_root = os.path.dirname(here)
NAME = 'django-helpdesk-demodesk'
DESCRIPTION = 'A demo Django project using django-helpdesk'
README = open(os.path.join(here, 'README.rst')).read()
VERSION = '0.2.0'
#VERSION = open(os.path.join(project_root, 'VERSION')).read().strip()
AUTHOR = 'django-helpdesk team'
URL = 'https://github.com/django-helpdesk/django-helpdesk'
CLASSIFIERS = ['Development Status :: 4 - Beta',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Framework :: Django']
KEYWORDS = []
PACKAGES = ['demodesk']
REQUIREMENTS = [
'django-helpdesk'
]
ENTRY_POINTS = {
'console_scripts': ['demodesk = demodesk.manage:main']
}
if __name__ == '__main__': # Don't run setup() when we import this module.
setup(name=NAME,
version=VERSION,
description=DESCRIPTION,
long_description=README,
classifiers=CLASSIFIERS,
keywords=' '.join(KEYWORDS),
author=AUTHOR,
url=URL,
license='BSD',
packages=PACKAGES,
include_package_data=True,
zip_safe=False,
install_requires=REQUIREMENTS,
entry_points=ENTRY_POINTS)

View File

@ -1,55 +0,0 @@
Contributing
============
django-helpdesk is an open-source project and as such contributions from the community are welcomed and encouraged.
Licensing
---------
All contributions to django-helpdesk must be under the BSD license documented in our :doc:`license` page. All code submitted (in any way: via e-mail, via GitHub forks, attachments, etc) are assumed to be open-source and licensed under the BSD license.
If you or your organisation does not accept these license terms then we cannot accept your contribution. Please reconsider!
Translations
------------
.. image:: http://www.transifex.net/projects/p/django-helpdesk/resource/core/chart/image_png
Although django-helpdesk has originally been written for the English language, there are already multiple translations to Spanish, Polish, and German and more translations are welcomed.
Translations are handled using the excellent Transifex service which is much easier for most users than manually editing .po files. It also allows collaborative translation. If you want to help translate django-helpdesk into languages other than English, we encourage you to make use of our Transifex project:
http://www.transifex.net/projects/p/django-helpdesk/resource/core/
Once you have translated content via Transifex, please raise an issue on the project Github page to let us know it's ready to import.
Code changes
------------
Please fork the project on GitHub, make your changes, and log a pull request to get the changes pulled back into my repository.
Wherever possible please break git commits up into small chunks that are specific to a single bit of functionality. For example, a commit should not contain both new functionality *and* a bugfix; the new function and the bugfix should be separate commits wherever possible.
Commit messages should also explain *what*, precisely, has been changed.
If you have any questions, please start a discussion on the GitHub issue tracker at https://github.com/django-helpdesk/django-helpdesk/issues
Tests
-----
Currently, test coverage is very low. We're working on increasing this, and to make life easier we are using `Travis CI`_ for continuous integration. This means that the test suite is run every time a code change is made, so we can try and make sure we avoid basic bugs and other regressions.
Please include tests in the ``tests/`` folder when committing code changes.
.. _Travis CI: http://travis-ci.org/
Database schema changes
-----------------------
As well as making your normal code changes to ``models.py``, please generate a Django migration file and commit it with your code. You will want to use a command similar to the following::
./manage.py migrate helpdesk --auto [migration_name]
Make sure that ``migration_name`` is a sensible single-string explanation of what this migration does, such as *add_priority_options* or *add_basket_table*
This will add a file to the ``migrations/`` folder, which must be committed to git with your other code changes.

View File

@ -69,7 +69,7 @@ django-helpdesk is released under the BSD license, however it packages 3rd party
Dependencies
------------
1. Python 2.7+ (or 3.3+)
2. Django (1.7 or newer)
1. Python 2.7+ (or 3.4+)
2. Django (1.8 or newer)
3. An existing **working** Django project with database etc. If you cannot log into the Admin, you won't get this product working! This means you **must** run `syncdb` **before** you add ``helpdesk`` to your ``INSTALLED_APPS``.

View File

@ -29,6 +29,10 @@ Download, extract, and drop ``helpdesk`` into your ``PYTHONPATH``
Adding To Your Django Project
-----------------------------
If you're on a brand new Django installation, make sure you do a ``migrate``
**before** adding ``helpdesk`` to your ``INSTALLED_APPS``. This will avoid
errors with trying to create User settings.
1. Edit your ``settings.py`` file and add ``helpdesk`` to the ``INSTALLED_APPS`` setting. You also need ``django.contrib.admin`` in ``INSTALLED_APPS`` if you haven't already added it. eg::
INSTALLED_APPS = (
@ -115,3 +119,46 @@ Adding To Your Django Project
Also, be aware that if a disk error occurs and the local file is not deleted, the mail may be processed multiple times and generate duplicate tickets until the file is removed. It is recommended to monitor log files for ERRORS when a file is unable to be deleted.
Upgrading from previous versions
--------------------------------
If you are upgrading from a previous version of django-helpdesk that used
migrations, get an up to date version of the code base (eg by using
`git pull` or `pip install --upgrade django-helpdesk`) then migrate the database::
python manage.py migrate helpdesk --db-dry-run # DB untouched
python manage.py migrate helpdesk
Lastly, restart your web server software (eg Apache) or FastCGI instance, to
ensure the latest changes are in use.
Unfortunately we are unable to assist if you are upgrading from a
version of django-helpdesk prior to migrations (ie pre-2011).
You can continue to the 'Initial Configuration' area, if needed.
Notes on database backends
--------------------------
**NOTE REGARDING SQLITE AND SEARCHING:**
If you use sqlite as your database, the search function will not work as
effectively as it will with other databases due to its inability to do
case-insensitive searches. It's recommended that you use PostgreSQL or MySQL
if possible. For more information, see this note in the Django documentation:
http://docs.djangoproject.com/en/dev/ref/databases/#sqlite-string-matching
When you try to do a keyword search using sqlite, a message will be displayed
to alert you to this shortcoming. There is no way around it, sorry.
**NOTE REGARDING MySQL:**
If you use MySQL, with most default configurations you will receive an error
when creating the database tables as we populate a number of default templates
in languages other than English.
You must create the database the holds the django-helpdesk tables using the
UTF-8 collation; see the MySQL manual for more information:
http://dev.mysql.com/doc/refman/5.1/en/charset-database.html
If you do NOT do this step, and you only want to use English-language templates,
you can continue however you will receive a warning when running the 'migrate'
commands.

View File

@ -130,3 +130,212 @@ License for jqPlot
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License for StartBootstrap SB Admin v2.0 theme
----------------------------------------------
::
The MIT License (MIT)
Copyright (c) 2013-2016 Blackrock Digital LLC.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License for Raphael
-------------------
::
The MIT License
Copyright (c) 2008-2010 Dmitry Baranovskiy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License for Morris.js
---------------------
::
Copyright (c) 2013, Olly Smith
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License for DataTables
----------------------
::
Copyright (C) 2008-2016, SpryMedia Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
License for Flot
----------------
::
Copyright (c) 2007-2014 IOLA and Ole Laursen
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
License for Metis Menu
----------------------
::
Copyright (C) 2016, Osman Nuri Okumuş
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
License for Bootstrap CSS
-------------------------
::
Copyright (c) 2011-2016 Twitter, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License for Font Awesome
------------------------
::
Font License
Applies to all desktop and webfont files in the following directory:
font-awesome/fonts/.
License: SIL OFL 1.1
URL: http://scripts.sil.org/OFL
Code License
Applies to all CSS and LESS files in the following directories:
font-awesome/css/, font-awesome/less/, and font-awesome/scss/.
License: MIT License
URL: http://opensource.org/licenses/mit-license.html
Documentation License
Applies to all Font Awesome project files that are not a part of the Font or
Code licenses.
License: CC BY 3.0
URL: http://creativecommons.org/licenses/by/3.0/
Brand Icons
All brand icons are trademarks of their respective owners.
The use of these trademarks does not indicate endorsement of the trademark
holder by Font Awesome, nor vice versa.
Brand icons should only be used to represent the company or product to which
they refer.

View File

@ -1,15 +1,7 @@
Settings
========
First, django-helpdesk needs ``django.core.context_processors.request`` activated, so you must add it to the ``settings.py``. For Django 1.7, add::
from django.conf import global_settings
TEMPLATE_CONTEXT_PROCESSORS = (
global_settings.TEMPLATE_CONTEXT_PROCESSORS +
('django.core.context_processors.request',)
)
For Django 1.8 and onwards, the settings are located in the ``TEMPLATES``, and the ``request`` module has moved. Add the following instead::
First, django-helpdesk needs ``django.core.context_processors.request`` activated, so you must add it to the ``settings.py``. Add the following::
TEMPLATES = [
{

View File

@ -5,6 +5,7 @@
# Translators:
# Translators:
# Alberto Gaona <gaona_consulting@yahoo.com>, 2011
# Andrés Martínez, 2017
# Apizano <apizano@gdl.cinvestav.mx>, 2013
# Apizano <apizano@gdl.cinvestav.mx>, 2012
# Erik Rivera <erik.river@gmail.com>, 2011,2013,2016
@ -14,9 +15,9 @@ msgstr ""
"Project-Id-Version: django-helpdesk\n"
"Report-Msgid-Bugs-To: http://github.com/RossP/django-helpdesk/issues\n"
"POT-Creation-Date: 2014-07-26 14:14+0200\n"
"PO-Revision-Date: 2016-05-11 16:55+0000\n"
"Last-Translator: Erik Rivera <erik.river@gmail.com>\n"
"Language-Team: Spanish (Mexico) (http://www.transifex.com/rossp/django-helpdesk/language/es_MX/)\n"
"PO-Revision-Date: 2017-03-15 20:53+0000\n"
"Last-Translator: Andrés Martínez\n"
"Language-Team: Spanish (Mexico) (http://www.transifex.com/django-helpdesk/django-helpdesk/language/es_MX/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -32,7 +33,7 @@ msgstr ""
#: templates/helpdesk/ticket_list.html:225 views/staff.py:1032
#: views/staff.py:1038 views/staff.py:1044 views/staff.py:1050
msgid "Queue"
msgstr "Colas"
msgstr "Cola"
#: forms.py:137
msgid "Summary of the problem"
@ -577,11 +578,11 @@ msgstr "cambiado de \"%(old_value)s\" a \"%(new_value)s\""
#: models.py:600
msgid "Ticket change"
msgstr ""
msgstr "Cambio en el Ticket"
#: models.py:601
msgid "Ticket changes"
msgstr ""
msgstr "Cambios en el Ticket"
#: models.py:632
msgid "File"
@ -605,11 +606,11 @@ msgstr "Tamaño del archivo en bytes"
#: models.py:665
msgid "Attachment"
msgstr ""
msgstr "Adjunto"
#: models.py:666
msgid "Attachments"
msgstr ""
msgstr "Adjuntos"
#: models.py:685
msgid ""
@ -639,11 +640,11 @@ msgstr "Contexto: {{ ticket }} - ticket de objeto (por ejemplo, {{ ticket.title
#: models.py:705
msgid "Pre-set reply"
msgstr ""
msgstr "Respuesta por defecto"
#: models.py:706
msgid "Pre-set replies"
msgstr ""
msgstr "Respuestas por defecto"
#: models.py:727
msgid ""
@ -657,11 +658,11 @@ msgstr "Fecha en la que la escalada no debe suceder"
#: models.py:746
msgid "Escalation exclusion"
msgstr ""
msgstr "Exclusión escalada"
#: models.py:747
msgid "Escalation exclusions"
msgstr ""
msgstr "Exclusiones escaladas"
#: models.py:760
msgid "Template Name"
@ -712,19 +713,19 @@ msgstr "Locale de esta plantilla"
#: models.py:806
msgid "e-mail template"
msgstr ""
msgstr "Plantilla de e-mail"
#: models.py:807
msgid "e-mail templates"
msgstr ""
msgstr "Plantillas de e-mail"
#: models.py:834
msgid "Knowledge base category"
msgstr ""
msgstr "Categoría de la base de conocimiento"
#: models.py:835
msgid "Knowledge base categories"
msgstr ""
msgstr "Categorías de la base de conocimiento"
#: models.py:849 templates/helpdesk/kb_index.html:11
#: templates/helpdesk/public_homepage.html:11
@ -769,11 +770,11 @@ msgstr "No calificado"
#: models.py:901
msgid "Knowledge base item"
msgstr ""
msgstr "Elemento de la base de conocimiento"
#: models.py:902
msgid "Knowledge base items"
msgstr ""
msgstr "Elementos de la base de conocimiento"
#: models.py:926 templates/helpdesk/ticket_list.html:170
msgid "Query Name"
@ -801,11 +802,11 @@ msgstr "objeto de consulta en crudo. Tenga cuidado con cambiar esto."
#: models.py:950
msgid "Saved search"
msgstr ""
msgstr "Búsqueda guardada"
#: models.py:951
msgid "Saved searches"
msgstr ""
msgstr "Búsquedas guardadas"
#: models.py:966
msgid "Settings Dictionary"
@ -819,7 +820,7 @@ msgstr "Esta es una representación codificada en base 64 de un diccionario de P
#: models.py:993
msgid "User Setting"
msgstr ""
msgstr "Configuración de usuario"
#: models.py:994 templates/helpdesk/navigation.html:37
#: templates/helpdesk/user_settings.html:6
@ -854,11 +855,11 @@ msgstr "¿Desea guardar los correos electrónicos de esta dirección en el buzó
#: models.py:1101
msgid "Ignored e-mail address"
msgstr ""
msgstr "Correo electrónico ignorado"
#: models.py:1102
msgid "Ignored e-mail addresses"
msgstr ""
msgstr "Correos electrónicos ignorados"
#: models.py:1124
msgid "User who wishes to receive updates for this ticket."
@ -1015,19 +1016,19 @@ msgstr "Si está prendido, la forma pública de creación de ticket NO MOSTRARÁ
#: models.py:1273
msgid "Custom field"
msgstr ""
msgstr "Campo personalizado"
#: models.py:1274
msgid "Custom fields"
msgstr ""
msgstr "Campos personalizados"
#: models.py:1297
msgid "Ticket custom field value"
msgstr ""
msgstr "Valor del campo personalizado"
#: models.py:1298
msgid "Ticket custom field values"
msgstr ""
msgstr "Valores del campo personalizado"
#: models.py:1315
msgid "Depends On Ticket"
@ -1035,11 +1036,11 @@ msgstr "Depende del ticket"
#: models.py:1324
msgid "Ticket dependency"
msgstr ""
msgstr "Dependencia de Ticket"
#: models.py:1325
msgid "Ticket dependencies"
msgstr ""
msgstr "Dependencia de Tickets"
#: management/commands/create_usersettings.py:25
msgid ""
@ -1092,7 +1093,7 @@ msgstr "(Actualizado)"
#: templates/helpdesk/attribution.html:2
msgid ""
"<a href='https://github.com/rossp/django-helpdesk'>django-helpdesk</a>."
msgstr ""
msgstr "<a href='https://github.com/rossp/django-helpdesk'>django-helpdesk</a>."
#: templates/helpdesk/base.html:10
msgid "Powered by django-helpdesk"
@ -1143,7 +1144,7 @@ msgstr "Borrar Búsqueda Salvada"
#: templates/helpdesk/confirm_delete_saved_query.html:6
msgid "Delete Query"
msgstr ""
msgstr "Borrar consulta"
#: templates/helpdesk/confirm_delete_saved_query.html:8
#, python-format
@ -1151,13 +1152,13 @@ msgid ""
"Are you sure you want to delete this saved filter "
"(<em>%(query_title)s</em>)? To re-create it, you will need to manually re-"
"filter your ticket listing."
msgstr ""
msgstr "¿Estás seguro que quieres eliminar este filtro guardado (<em>%(query_title)s</em>)? Para volver a crearlo, tendrá que volver a filtrar la lista de Tickets."
#: templates/helpdesk/confirm_delete_saved_query.html:11
msgid ""
"You have shared this query, so other users may be using it. If you delete "
"it, they will have to manually create their own query."
msgstr ""
msgstr " Ha compartido esta consulta para que los otros usuarios pueden usarla. Si la elimina, los otros usuarios deben crear su propia consulta."
#: templates/helpdesk/confirm_delete_saved_query.html:14
#: templates/helpdesk/delete_ticket.html:10
@ -1182,13 +1183,13 @@ msgstr "Enviar un Ticket"
#: templates/helpdesk/create_ticket.html:11
#: templates/helpdesk/edit_ticket.html:11
msgid "Unless otherwise stated, all fields are required."
msgstr ""
msgstr "Se requieren todos los campos, a menos que se indique lo contrario."
#: templates/helpdesk/create_ticket.html:11
#: templates/helpdesk/edit_ticket.html:11
#: templates/helpdesk/public_homepage.html:28
msgid "Please provide as descriptive a title and description as possible."
msgstr ""
msgstr "Por favor incluya un título y una descripción tan explícitas como sea posible."
#: templates/helpdesk/create_ticket.html:30
#: templates/helpdesk/public_homepage.html:55
@ -1212,37 +1213,37 @@ msgstr "Resumen - Servicio de Ayuda"
#: templates/helpdesk/dashboard.html:36
msgid "Current Ticket Stats"
msgstr ""
msgstr "Estado del Ticket"
#: templates/helpdesk/dashboard.html:37
msgid "Average number of days until ticket is closed (all tickets): "
msgstr ""
msgstr "Promedio de días hasta que un Ticket es cerrado (Todos los Tickets):"
#: templates/helpdesk/dashboard.html:38
msgid ""
"Average number of days until ticket is closed (tickets opened in last 60 "
"days): "
msgstr ""
msgstr "Promedio de días hasta que un Ticket es cerrado (Tickets abiertos en los últimos 60 días):"
#: templates/helpdesk/dashboard.html:39
msgid "Click"
msgstr ""
msgstr "Clic"
#: templates/helpdesk/dashboard.html:39
msgid "for detailed average by month."
msgstr ""
msgstr "para el promedio detallado por mes."
#: templates/helpdesk/dashboard.html:40
msgid "Distribution of open tickets, grouped by time period:"
msgstr ""
msgstr "Distribución de Tickets abiertos agrupados por periodos:"
#: templates/helpdesk/dashboard.html:41
msgid "Days since opened"
msgstr ""
msgstr "Periodo"
#: templates/helpdesk/dashboard.html:41
msgid "Number of open tickets"
msgstr ""
msgstr "Número de Tickets abiertos"
#: templates/helpdesk/dashboard.html:57
msgid "All Tickets submitted by you"
@ -1304,7 +1305,7 @@ msgid ""
"Are you sure you want to delete this ticket (<em>%(ticket_title)s</em>)? All"
" traces of the ticket, including followups, attachments, and updates will be"
" irreversibly removed."
msgstr ""
msgstr "¿Está seguro que desea eliminar este Ticket (<em>%(ticket_title)s</em>)? Todos los rastros del Ticket, incluyendo comentarios, archivos adjuntos y actualizaciones serán eliminados de forma irreversible."
#: templates/helpdesk/edit_ticket.html:3
msgid "Edit Ticket"
@ -1312,18 +1313,18 @@ msgstr "Editar Ticket"
#: templates/helpdesk/edit_ticket.html:9
msgid "Edit a Ticket"
msgstr ""
msgstr "Editar un Ticket"
#: templates/helpdesk/edit_ticket.html:13
msgid "Note"
msgstr ""
msgstr "Nota"
#: templates/helpdesk/edit_ticket.html:13
msgid ""
"Editing a ticket does <em>not</em> send an e-mail to the ticket owner or "
"submitter. No new details should be entered, this form should only be used "
"to fix incorrect details or clean up the submission."
msgstr ""
msgstr "La edición de un ticket <em>no</em> envía un correo electrónico al propietario del ticket o remitente. Este formato no es para añadir nuevos datos, sólo se debe utilizar para arreglar datos incorrectos o limpiar el Ticket."
#: templates/helpdesk/edit_ticket.html:33
msgid "Save Changes"
@ -1339,14 +1340,14 @@ msgstr "Ignorar Dirección de E-mail"
msgid ""
"To ignore an e-mail address and prevent any emails from that address "
"creating tickets automatically, enter the e-mail address below."
msgstr ""
msgstr "Para ignorar un correo electrónico y prevenir que cree Tickets automaticamente escríbalo debajo."
#: templates/helpdesk/email_ignore_add.html:10
msgid ""
"You can either enter a whole e-mail address such as "
"<em>email@domain.com</em> or a portion of an e-mail address with a wildcard,"
" such as <em>*@domain.com</em> or <em>user@*</em>."
msgstr ""
msgstr "Puede especificar tanto una dirección de correo completa, por ejemplo <em>email@domain.com</em> o solo una parte de la dirección con un wildcard, como por ejemplo <em>*@dominio.com</em> o <em>usuario@*</em>."
#: templates/helpdesk/email_ignore_del.html:3
msgid "Delete Ignored E-Mail Address"
@ -1354,7 +1355,7 @@ msgstr "Borrar dirección de E-Mail Ignorada"
#: templates/helpdesk/email_ignore_del.html:6
msgid "Un-Ignore E-Mail Address"
msgstr ""
msgstr "No ignorar dirección de correo electrónico"
#: templates/helpdesk/email_ignore_del.html:8
#, python-format
@ -1362,7 +1363,7 @@ msgid ""
"Are you sure you wish to stop removing this email address "
"(<em>%(email_address)s</em>) and allow their e-mails to automatically create"
" tickets in your system? You can re-add this e-mail address at any time."
msgstr ""
msgstr "¿Está seguro que desea dejar de evitar esta dirección de correo (<em>%(email_address)s</em>) y permitir que este correo electrónico cree tickets en el sistema? Puede volver a añadir el correo electrónico en cualquier momento."
#: templates/helpdesk/email_ignore_del.html:10
msgid "Keep Ignoring It"
@ -1383,7 +1384,7 @@ msgid ""
"<h2>Ignored E-Mail Addresses</h2>\n"
"\n"
"<p>The following e-mail addresses are currently being ignored by the incoming e-mail processor. You can <a href='add/'>add a new e-mail address to the list</a> or delete any of the items below as required.</p>"
msgstr ""
msgstr "\n<h2>Correos electrónicos ignorados</h2>\n\n<p>Los siguientes correos electrónicos esta siendo ignorados. Usted puede <a href='add/'>añadir un nuevo correo electrónico a la lista</a> o eliminar cualquiera de los elementos debajo como requiera.</p>"
#: templates/helpdesk/email_ignore_list.html:13
msgid "Date Added"
@ -1406,7 +1407,7 @@ msgstr "Mantener"
msgid ""
"<strong>Note:</strong> If the 'Keep' option is not selected, emails sent "
"from that address will be deleted permanently."
msgstr ""
msgstr "<strong>Nota:</strong> Si la opción 'Mantener' no está seleccionada, los e-mail enviados de esa dirección serán borrados de manera permanente."
#: templates/helpdesk/followup_edit.html:2
msgid "Edit followup"
@ -1453,7 +1454,7 @@ msgid ""
"We have listed a number of knowledgebase articles for your perusal in the "
"following categories. Please check to see if any of these articles address "
"your problem prior to opening a support ticket."
msgstr ""
msgstr "Hemos listado una serie de artículos de la base de conocimiento para usted en las siguientes categorías. Por favor, revise para ver si alguno de estos artículos se refieren a su problema antes de abrir un Ticket de soporte."
#: templates/helpdesk/kb_index.html:10
#: templates/helpdesk/public_homepage.html:10
@ -1471,7 +1472,7 @@ msgid ""
"View <a href='%(category_url)s'>other <em>%(category_title)s</em> "
"articles</a>, or continue <a href='../'>viewing other knowledgebase "
"articles</a>."
msgstr ""
msgstr "Ver <a href='%(category_url)s'>otros <em>%(category_title)s</em> articulos</a>, o continuar <a href='../'>otros artículos de la base de conocimiento</a>."
#: templates/helpdesk/kb_item.html:18
msgid "Feedback"
@ -1525,11 +1526,11 @@ msgstr "Estadisticas"
#: templates/helpdesk/navigation.html:24
msgid "Saved Query"
msgstr ""
msgstr "Consulta guardada"
#: templates/helpdesk/navigation.html:39
msgid "Change password"
msgstr ""
msgstr "Cambiar contraseña"
#: templates/helpdesk/navigation.html:50
msgid "Search..."
@ -1564,7 +1565,7 @@ msgstr "Artículos de la Base de Conocimientos"
#: templates/helpdesk/public_homepage.html:28
msgid "All fields are required."
msgstr ""
msgstr "Se requieren todos los campos."
#: templates/helpdesk/public_homepage.html:66
msgid "Please use button at upper right to login first."
@ -1586,7 +1587,7 @@ msgstr "No es posible abrir el Ticket"
#: templates/helpdesk/public_spam.html:5
msgid "Sorry, but there has been an error trying to submit your ticket."
msgstr ""
msgstr "Lo sentimos, hubo un error enviando tu Ticket."
#: templates/helpdesk/public_spam.html:6
msgid ""
@ -1594,13 +1595,13 @@ msgid ""
"unable to save it. If this is not spam, please press back and re-type your "
"message. Be careful to avoid sounding 'spammy', and if you have heaps of "
"links please try removing them if possible."
msgstr ""
msgstr "Nuestro sistema ha catalogado su envío como <strong>spam</strong>, por lo que no podemos guardarlo. Si no es spam, por favor presione atrás y reingrese su mensaje. Intente no ingresar palabras que puedan sonar a spam, y si tiene enlaces en su mensaje trate de eliminarlas si es posible."
#: templates/helpdesk/public_spam.html:7
msgid ""
"We are sorry for any inconvenience, however this check is required to avoid "
"our helpdesk resources being overloaded by spammers."
msgstr ""
msgstr "Lamentamos cualquier inconveniente, sin embargo, la confirmación es requerida para evitar que nuestros recursos sean sobrecargados por spammers."
#: templates/helpdesk/public_view_form.html:8
msgid "Error:"
@ -1681,12 +1682,12 @@ msgstr "Reportes por Fila"
#: templates/helpdesk/report_index.html:27 views/staff.py:1049
msgid "Days until ticket closed by Month"
msgstr ""
msgstr "Días hasta que el Ticket se cierre por mes"
#: templates/helpdesk/report_output.html:19
msgid ""
"You can run this query on filtered data by using one of your saved queries."
msgstr ""
msgstr "Usted puede ejecutar esta consulta con filtros usando alguna de sus consultas guardadas."
#: templates/helpdesk/report_output.html:21
msgid "Select Query:"
@ -1700,7 +1701,7 @@ msgstr "Filtrar reporte"
msgid ""
"Want to filter this report to just show a subset of data? Go to the Ticket "
"List, filter your query, and save your query."
msgstr ""
msgstr "¿Desea filtrar este reporte para mostrar para mostrar solo un subconjunto de datos? Vaya a Lista de Tickets, realice el filtro y guarde la consulta."
#: templates/helpdesk/rss_list.html:6
msgid ""
@ -1708,13 +1709,13 @@ msgid ""
"preferred RSS software. With the exception of the 'Latest Activity' feed, "
"all feeds provide information only on Open and Reopened cases. This ensures "
"your RSS reader isn't full of information about closed or historical tasks."
msgstr ""
msgstr "Las siguientes fuentes de RSS están disponibles para usted para ser utilizadas con su herramienta de RSS preferida. A excepción de la fuente de 'Última actividad', todas las fuentes RSS solo proveen información de casos Abiertos y Reabiertos. Esto le asegura que su lector RSS no se llena con información de tareas cerradas o históricas."
#: templates/helpdesk/rss_list.html:10
msgid ""
"A summary of your open tickets - useful for getting alerted to new tickets "
"opened for you"
msgstr ""
msgstr "Resumen de sus Tickets abiertos - Útil para saber si hay nuevos Tickets abiertos para usted"
#: templates/helpdesk/rss_list.html:12
msgid "Latest Activity"
@ -1738,7 +1739,7 @@ msgid ""
"all tickets, for each of the queues in your helpdesk. For example, if you "
"manage the staff who utilise a particular queue, this may be used to view "
"new tickets coming into that queue."
msgstr ""
msgstr "Estas fuentes RSS le permiten ver un resumen ya sea de sus propios tickets o de todos los tickets de las colas de su helpdesk. Por ejemplo, si eres el supervisor del personal que utiliza una cola en particular, estas fuentes RSS pueden ser utilizadas para ver los nuevos tickets que arriban a esa cola."
#: templates/helpdesk/rss_list.html:23
msgid "Per-Queue Feeds"
@ -1758,7 +1759,7 @@ msgstr "Cambiar la Configuración del Sistema"
#: templates/helpdesk/system_settings.html:8
msgid "The following items can be maintained by you or other superusers:"
msgstr ""
msgstr "Los siguientes elemtenos pueden ser administrados por usted o por otros super usuarios:"
#: templates/helpdesk/system_settings.html:11
msgid "E-Mail Ignore list"
@ -1770,19 +1771,19 @@ msgstr "Mantenimiento a colas"
#: templates/helpdesk/system_settings.html:13
msgid "Maintain Pre-Set Replies"
msgstr ""
msgstr "Administrar respuestas por defecto"
#: templates/helpdesk/system_settings.html:14
msgid "Maintain Knowledgebase Categories"
msgstr ""
msgstr "Administrar las categorías de la base de conocimiento"
#: templates/helpdesk/system_settings.html:15
msgid "Maintain Knowledgebase Items"
msgstr ""
msgstr "Administrar los elemento de la base de conocimiento"
#: templates/helpdesk/system_settings.html:16
msgid "Maintain E-Mail Templates"
msgstr ""
msgstr "Administrar las plantillas de correo electrónico"
#: templates/helpdesk/system_settings.html:17
msgid "Maintain Users"
@ -1820,7 +1821,7 @@ msgstr "(Opcional)"
msgid ""
"Selecting a pre-set reply will over-write your comment below. You can then "
"modify the pre-set reply to your liking before saving this update."
msgstr ""
msgstr "Seleccionando una respuesta por defecto, se sobre escriben sus comentarios a continuación. Puede modificar la respuesta por defecto a su gusto antes de guardar esta actualización."
#: templates/helpdesk/ticket.html:131
msgid "Comment / Resolution"
@ -1830,13 +1831,13 @@ msgstr "Comentario / Resolución"
msgid ""
"You can insert ticket and queue details in your message. For more "
"information, see the <a href='../../help/context/'>context help page</a>."
msgstr ""
msgstr "Puede insertar Tickets y detalles de cola en su mensaje. Para obtener más información, consulte la <a href='../../help/context/'>página de ayuda</a> ."
#: templates/helpdesk/ticket.html:136
msgid ""
"This ticket cannot be resolved or closed until the tickets it depends on are"
" resolved."
msgstr ""
msgstr "Este Ticket no puede ser resuelto o cerrado hasta que sus dependencias sean resueltas."
#: templates/helpdesk/ticket.html:166
msgid "Is this update public?"
@ -1846,11 +1847,11 @@ msgstr "¿Esta actualización es pública?"
msgid ""
"If this is public, the submitter will be e-mailed your comment or "
"resolution."
msgstr ""
msgstr "Si esto es público, se enviará un correo electrónico al remitente con su comentario o resolución."
#: templates/helpdesk/ticket.html:172
msgid "Change Further Details &raquo;"
msgstr ""
msgstr "Cambie más detalles &raquo;"
#: templates/helpdesk/ticket.html:181 templates/helpdesk/ticket_list.html:68
#: templates/helpdesk/ticket_list.html:97
@ -1860,11 +1861,11 @@ msgstr "Dueño"
#: templates/helpdesk/ticket.html:182
msgid "Unassign"
msgstr ""
msgstr "No asignado"
#: templates/helpdesk/ticket.html:193
msgid "Attach File(s) &raquo;"
msgstr ""
msgstr "Adjuntar archivo(s) &raquo"
#: templates/helpdesk/ticket.html:199
msgid "Attach a File"
@ -1876,7 +1877,7 @@ msgstr "Actualizar este Ticket"
#: templates/helpdesk/ticket_cc_add.html:3
msgid "Add Ticket CC"
msgstr ""
msgstr "Agregar CC a TIcket"
#: templates/helpdesk/ticket_cc_add.html:5
msgid ""
@ -1884,15 +1885,15 @@ msgid ""
"<h2>Add Ticket CC</h2>\n"
"\n"
"<p>To automatically send an email to a user or e-mail address when this ticket is updated, select the user or enter an e-mail address below.</p>"
msgstr ""
msgstr "\n<h2>Añadir CC al Ticket</h2>\n\n<p>Para enviar un e-mail automático a un usuario o dirección de correo cuando este ticket sea actualizado, seleccione el usuario o ingrese una dirección de correo abajo.</p>"
#: templates/helpdesk/ticket_cc_add.html:21
msgid "Save Ticket CC"
msgstr ""
msgstr "Guardar CC de Ticket"
#: templates/helpdesk/ticket_cc_del.html:3
msgid "Delete Ticket CC"
msgstr ""
msgstr "Borrar CC de Ticket"
#: templates/helpdesk/ticket_cc_del.html:5
#, python-format
@ -1901,7 +1902,7 @@ msgid ""
"<h2>Delete Ticket CC</h2>\n"
"\n"
"<p>Are you sure you wish to delete this email address (<em>%(email_address)s</em>) from the CC list for this ticket? They will stop receiving updates.</p>\n"
msgstr ""
msgstr "\n<h2>Borrar CC del Ticket</h2>\n\n<p>¿Está seguro de que desea eliminar esta dirección de correo (<em>%(email_address)s</em>) de la lista CC para este ticket? Esta dirección dejará de recibir actualizaciones.</p>\n"
#: templates/helpdesk/ticket_cc_del.html:11
#: templates/helpdesk/ticket_dependency_del.html:11
@ -1915,7 +1916,7 @@ msgstr "Si, Eliminar"
#: templates/helpdesk/ticket_cc_list.html:3
msgid "Ticket CC Settings"
msgstr ""
msgstr "Ajustes de CC del Ticket"
#: templates/helpdesk/ticket_cc_list.html:5
#, python-format
@ -1926,11 +1927,11 @@ msgid ""
"<p>The following people will receive an e-mail whenever <em><a href='../'>%(ticket_title)s</a></em> is updated. Some people can also view or edit the ticket via the public ticket views.</p>\n"
"\n"
"<p>You can <a href='add/'>add a new e-mail address to the list</a> or delete any of the items below as required.</p>"
msgstr ""
msgstr "\n<h2>Configuración de CC del Ticket</h2>\n\n<p>Las siguientes personas recibirán un e-mail cada que el ticket <em><a href='../'>%(ticket_title)s</a></em> se actualice. Algunas personas también pueden ver o editar el ticket a través de las vistas públicas de tickets.</p>\n\n<p>Usted puede <a href='add/'>añadir una nueva dirección de correo electrónico a la lista</a> o borrar uno de los elementos abajo, como lo requiera.</p>"
#: templates/helpdesk/ticket_cc_list.html:14
msgid "Ticket CC List"
msgstr ""
msgstr "Lista de CC del Ticket"
#: templates/helpdesk/ticket_cc_list.html:15
msgid "View?"
@ -1955,15 +1956,15 @@ msgid ""
"<h2>Add Ticket Dependency</h2>\n"
"\n"
"<p>Adding a dependency will stop you resolving this ticket until the dependent ticket has been resolved or closed.</p>"
msgstr ""
msgstr "\n<h2>Agregar dependencia de Ticket</h2>\n\n<p>Al añadir una dependencia no se podrá resolver este Ticket hasta que la dependencia haya sido resuelta o esté cerrada.</p>"
#: templates/helpdesk/ticket_dependency_add.html:21
msgid "Save Ticket Dependency"
msgstr ""
msgstr "Guardar dependencia del Ticket"
#: templates/helpdesk/ticket_dependency_del.html:3
msgid "Delete Ticket Dependency"
msgstr ""
msgstr "Eliminar dependencia del Ticket"
#: templates/helpdesk/ticket_dependency_del.html:5
msgid ""
@ -1971,15 +1972,15 @@ msgid ""
"<h2>Delete Ticket Dependency</h2>\n"
"\n"
"<p>Are you sure you wish to remove the dependency on this ticket?</p>\n"
msgstr ""
msgstr "\n<h2>Eliminar dependencia de Ticket</h2>\n\n<p>¿Está seguro que desea eliminar la dependencia en este Ticket?</p>\n"
#: templates/helpdesk/ticket_desc_table.html:7
msgid "Unhold"
msgstr ""
msgstr "Reanudar"
#: templates/helpdesk/ticket_desc_table.html:7
msgid "Hold"
msgstr ""
msgstr "Suspender"
#: templates/helpdesk/ticket_desc_table.html:9
#, python-format
@ -2006,17 +2007,17 @@ msgstr "Administrar"
msgid ""
"Click here to add / remove people who should receive an e-mail whenever this"
" ticket is updated."
msgstr ""
msgstr "Haga clic aquí para añadir / remover personas que reciben un e-mail cada vez que este Ticket es actualizado."
#: templates/helpdesk/ticket_desc_table.html:53
msgid "Subscribe"
msgstr ""
msgstr "Suscribirse"
#: templates/helpdesk/ticket_desc_table.html:53
msgid ""
"Click here to subscribe yourself to this ticket, if you want to receive an "
"e-mail whenever this ticket is updated."
msgstr ""
msgstr "Haga clic aquí si quiere recibir un correo electrónico cada vez que este Ticket sea actualizado"
#: templates/helpdesk/ticket_desc_table.html:57
msgid "Dependencies"
@ -2044,7 +2045,7 @@ msgid ""
"Click on 'Add Dependency', if you want to make this ticket dependent on "
"another ticket. A ticket may not be closed until all tickets it depends on "
"are closed."
msgstr ""
msgstr "Hacer clic en 'Añadir dependencia' hace que este Ticket dependa de otro. Un Ticket no puede ser cerrado hasta que todas sus dependencias estén cerradas."
#: templates/helpdesk/ticket_list.html:59
msgid "Change Query"
@ -2113,7 +2114,7 @@ msgstr "Usar el formato de fechas YYYY-MM-DD, por ejemplo: 2011-05-29"
msgid ""
"Keywords are case-insensitive, and will be looked for in the title, body and"
" submitter fields."
msgstr ""
msgstr "Las palabras claves no son sensibles a mayúsculas, y serán buscadas en el título, el cuerpo o los campos del remitente."
#: templates/helpdesk/ticket_list.html:144
msgid "Apply Filter"
@ -2122,14 +2123,14 @@ msgstr "Aplicar Filtro"
#: templates/helpdesk/ticket_list.html:146
#, python-format
msgid "You are currently viewing saved query <strong>\"%(query_name)s\"</strong>."
msgstr ""
msgstr "Viendo la consulta <strong>\"%(query_name)s\"</strong>."
#: templates/helpdesk/ticket_list.html:149
#, python-format
msgid ""
"<a href='../reports/?saved_query=%(query_id)s'>Run a report</a> on this "
"query to see stats and charts for the data listed below."
msgstr ""
msgstr "<a href='../reports/?saved_query=%(query_id)s'>Ejecutar un reporte</a> en esta consultar para ver estadísticas y gráficas de los datos listados abajo."
#: templates/helpdesk/ticket_list.html:162
#: templates/helpdesk/ticket_list.html:181
@ -2141,7 +2142,7 @@ msgid ""
"This name appears in the drop-down list of saved queries. If you share your "
"query, other users will see this name, so choose something clear and "
"descriptive!"
msgstr ""
msgstr "Este nombre aparece en la la lista desplegable de consultas guardadas. Si usted comparte esta consulta, otros usuarios verán este nombre, por tanto escoja uno claro y descriptivo."
#: templates/helpdesk/ticket_list.html:174
msgid "Shared?"
@ -2234,7 +2235,7 @@ msgstr "Cambiar ajustes de usuario"
msgid ""
"Use the following options to change the way your helpdesk system works for "
"you. These settings do not impact any other user."
msgstr ""
msgstr "Use las siguientes opciones para cambiar la manera en que el sistema helpdesk trabaja para usted. Estas configuraciones solo lo afectarán a usted."
#: templates/helpdesk/user_settings.html:14
msgid "Save Options"
@ -2259,7 +2260,7 @@ msgstr "Ingresar a Helpdesk"
#: templates/helpdesk/registration/login.html:14
msgid "To log in simply enter your username and password below."
msgstr ""
msgstr "Para ingresar escriba su nombre y contraseña."
#: templates/helpdesk/registration/login.html:17
msgid "Your username and password didn't match. Please try again."

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@ scripts/get_email.py - Designed to be run from cron, this script checks the
helpdesk, creating tickets from the new messages (or
adding to existing tickets if needed)
"""
from __future__ import unicode_literals
from datetime import timedelta
import email
@ -158,7 +159,7 @@ def process_queue(q, logger):
msgNum = msg.split(" ")[0]
logger.info("Processing message %s" % msgNum)
full_message = "\n".join(server.retr(msgNum)[1])
full_message = encoding.force_text("\n".join(server.retr(msgNum)[1]), errors='replace')
ticket = ticket_from_message(message=full_message, queue=q, logger=logger)
if ticket:
@ -198,7 +199,8 @@ def process_queue(q, logger):
for num in msgnums:
logger.info("Processing message %s" % num)
status, data = server.fetch(num, '(RFC822)')
ticket = ticket_from_message(message=encoding.smart_text(data[0][1], errors='replace'), queue=q, logger=logger)
full_message = encoding.force_text(data[0][1], errors='replace')
ticket = ticket_from_message(message=full_message, queue=q, logger=logger)
if ticket:
server.store(num, '+FLAGS', '\\Deleted')
logger.info("Successfully processed message %s, deleted from IMAP server" % num)
@ -218,7 +220,8 @@ def process_queue(q, logger):
for i, m in enumerate(mail, 1):
logger.info("Processing message %d" % i)
with open(m, 'r') as f:
ticket = ticket_from_message(message=f.read(), queue=q, logger=logger)
full_message = encoding.force_text(f.read(), errors='replace')
ticket = ticket_from_message(message=full_message, queue=q, logger=logger)
if ticket:
logger.info("Successfully processed message %d, ticket/comment created." % i)
try:
@ -235,9 +238,9 @@ def decodeUnknown(charset, string):
if six.PY2:
if not charset:
try:
return string.decode('utf-8', 'ignore')
return string.decode('utf-8', 'replace')
except:
return string.decode('iso8859-1', 'ignore')
return string.decode('iso8859-1', 'replace')
return unicode(string, charset)
elif six.PY3:
if type(string) is not str:
@ -251,7 +254,7 @@ def decodeUnknown(charset, string):
def decode_mail_headers(string):
decoded = email.header.decode_header(string)
decoded = email.header.decode_header(string) if six.PY3 else email.header.decode_header(string.encode('utf-8'))
if six.PY2:
return u' '.join([unicode(msg, charset or 'utf-8') for msg, charset in decoded])
elif six.PY3:
@ -260,7 +263,7 @@ def decode_mail_headers(string):
def ticket_from_message(message, queue, logger):
# 'message' must be an RFC822 formatted message.
message = email.message_from_string(message.encode('utf-8') if six.PY2 else message)
message = email.message_from_string(message) if six.PY3 else email.message_from_string(message.encode('utf-8'))
subject = message.get('subject', _('Created from e-mail'))
subject = decode_mail_headers(decodeUnknown(message.get_charset(), subject))
for affix in STRIPPED_SUBJECT_STRINGS:
@ -305,6 +308,8 @@ def ticket_from_message(message, queue, logger):
body = EmailReplyParser.parse_reply(
decodeUnknown(part.get_content_charset(), part.get_payload(decode=True))
)
# workaround to get unicode text out rather than escaped text
body = body.encode('ascii').decode('unicode_escape') if six.PY3 else body.encode('utf-8')
logger.debug("Discovered plain text MIME part")
else:
files.append(

View File

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2017-03-08 17:51
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('helpdesk', '0015_expand_permission_name_size'),
]
operations = [
migrations.AlterModelOptions(
name='attachment',
options={'ordering': ('filename',), 'verbose_name': 'Attachment', 'verbose_name_plural': 'Attachments'},
),
migrations.AlterModelOptions(
name='emailtemplate',
options={'ordering': ('template_name', 'locale'), 'verbose_name': 'e-mail template', 'verbose_name_plural': 'e-mail templates'},
),
migrations.AlterModelOptions(
name='followup',
options={'ordering': ('date',), 'verbose_name': 'Follow-up', 'verbose_name_plural': 'Follow-ups'},
),
migrations.AlterModelOptions(
name='kbcategory',
options={'ordering': ('title',), 'verbose_name': 'Knowledge base category', 'verbose_name_plural': 'Knowledge base categories'},
),
migrations.AlterModelOptions(
name='kbitem',
options={'ordering': ('title',), 'verbose_name': 'Knowledge base item', 'verbose_name_plural': 'Knowledge base items'},
),
migrations.AlterModelOptions(
name='presetreply',
options={'ordering': ('name',), 'verbose_name': 'Pre-set reply', 'verbose_name_plural': 'Pre-set replies'},
),
migrations.AlterUniqueTogether(
name='ticketcustomfieldvalue',
unique_together=set([('ticket', 'field')]),
),
]

View File

@ -22,7 +22,9 @@
<p>{{ item.question }}</p>
</div>
<div class="panel-footer">
<p>{% blocktrans %}View <a href='{{ item.get_absolute_url }}'>Answer <i class="fa fa-arrow-right"></i></a>{% endblocktrans %}</p>
<p>
{% blocktrans with item.get_absolute_url as url %}View <a href='{{ url }}'>Answer <i class="fa fa-arrow-right"></i></a>{% endblocktrans %}
</p>
<div class="well well-sm">
<p>{% trans 'Rating' %}: {{ item.score }}</p>
<p>{% trans 'Last Update' %}: {{ item.last_updated|naturaltime }}</p>

View File

@ -1,4 +1,8 @@
from helpdesk.models import Queue, Ticket
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from helpdesk.models import Queue, Ticket, FollowUp, Attachment
from django.test import TestCase
from django.core.management import call_command
from django.utils import six
@ -40,7 +44,7 @@ class GetEmailCommonTests(TestCase):
class GetEmailParametricTemplate(object):
"""TestCase that checks email functionality accross methods and socks configs."""
"""TestCase that checks email functionality across methods and socks configs."""
def setUp(self):
@ -52,7 +56,8 @@ class GetEmailParametricTemplate(object):
"allow_email_submission": True,
"email_box_type": self.method,
"logging_dir": self.temp_logdir,
"logging_type": 'none'}
"logging_type": 'none'
}
if self.method == 'local':
kwargs["email_box_local_dir"] = '/var/lib/mail/helpdesk/'
@ -71,11 +76,16 @@ class GetEmailParametricTemplate(object):
rmtree(self.temp_logdir)
def test_read_email(self):
"""Tests reading emails from a queue and creating tickets.
def test_read_plain_email(self):
"""Tests reading plain text emails from a queue and creating tickets.
For each email source supported, we mock the backend to provide
authenticly formatted responses containing our test data."""
test_email = "To: update.public@example.com\nFrom: comment@example.com\nSubject: Some Comment\n\nThis is the helpdesk comment via email."
authentically formatted responses containing our test data."""
# example email text from Django docs: https://docs.djangoproject.com/en/1.10/ref/unicode/
test_email_from = "Arnbjörg Ráðormsdóttir <arnbjorg@example.com>"
test_email_subject = "My visit to Sør-Trøndelag"
test_email_body = "Unicode helpdesk comment with an s-hat (ŝ) via email."
test_email = "To: helpdesk@example.com\nFrom: " + test_email_from + "\nSubject: " + test_email_subject + "\n\n" + test_email_body
test_mail_len = len(test_email)
if self.socks:
@ -130,11 +140,133 @@ class GetEmailParametricTemplate(object):
ticket1 = get_object_or_404(Ticket, pk=1)
self.assertEqual(ticket1.ticket_for_url, "QQ-%s" % ticket1.id)
self.assertEqual(ticket1.description, "This is the helpdesk comment via email.")
self.assertEqual(ticket1.title, test_email_subject)
self.assertEqual(ticket1.description, test_email_body)
ticket2 = get_object_or_404(Ticket, pk=2)
self.assertEqual(ticket2.ticket_for_url, "QQ-%s" % ticket2.id)
self.assertEqual(ticket2.description, "This is the helpdesk comment via email.")
self.assertEqual(ticket2.title, test_email_subject)
self.assertEqual(ticket2.description, test_email_body)
def test_read_html_multipart_email(self):
"""Tests reading multipart MIME (HTML body and plain text alternative)
emails from a queue and creating tickets.
For each email source supported, we mock the backend to provide
authentically formatted responses containing our test data."""
# example email text from Python docs: https://docs.python.org/3/library/email-examples.html
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
me = "my@example.com"
you = "your@example.com"
subject = "Link"
# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = subject
msg['From'] = me
msg['To'] = you
# Create the body of the message (a plain-text and an HTML version).
text = "Hi!\nHow are you?\nHere is the link you wanted:\nhttps://www.python.org"
html = """\
<html>
<head></head>
<body>
<p>Hi!<br>
How are you?<br>
Here is the <a href="https://www.python.org">link</a> you wanted.
</p>
</body>
</html>
"""
# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part1)
msg.attach(part2)
test_mail_len = len(msg)
if self.socks:
from socks import ProxyConnectionError
with self.assertRaisesRegexp(ProxyConnectionError, '%s:%s' % (unrouted_socks_server, unused_port)):
call_command('get_email')
else:
# Test local email reading
if self.method == 'local':
with mock.patch('helpdesk.management.commands.get_email.listdir') as mocked_listdir, \
mock.patch('helpdesk.management.commands.get_email.isfile') as mocked_isfile, \
mock.patch('builtins.open' if six.PY3 else '__builtin__.open', mock.mock_open(read_data=msg.as_string())):
mocked_isfile.return_value = True
mocked_listdir.return_value = ['filename1', 'filename2']
call_command('get_email')
mocked_listdir.assert_called_with('/var/lib/mail/helpdesk/')
mocked_isfile.assert_any_call('/var/lib/mail/helpdesk/filename1')
mocked_isfile.assert_any_call('/var/lib/mail/helpdesk/filename2')
elif self.method == 'pop3':
# mock poplib.POP3's list and retr methods to provide responses as per RFC 1939
pop3_emails = {
'1': ("+OK", msg.as_string().split('\n')),
'2': ("+OK", msg.as_string().split('\n')),
}
pop3_mail_list = ("+OK 2 messages", ("1 %d" % test_mail_len, "2 %d" % test_mail_len))
mocked_poplib_server = mock.Mock()
mocked_poplib_server.list = mock.Mock(return_value=pop3_mail_list)
mocked_poplib_server.retr = mock.Mock(side_effect=lambda x: pop3_emails[x])
with mock.patch('helpdesk.management.commands.get_email.poplib', autospec=True) as mocked_poplib:
mocked_poplib.POP3 = mock.Mock(return_value=mocked_poplib_server)
call_command('get_email')
elif self.method == 'imap':
# mock imaplib.IMAP4's search and fetch methods with responses from RFC 3501
imap_emails = {
"1": ("OK", (("1", msg.as_string()),)),
"2": ("OK", (("2", msg.as_string()),)),
}
imap_mail_list = ("OK", ("1 2",))
mocked_imaplib_server = mock.Mock()
mocked_imaplib_server.search = mock.Mock(return_value=imap_mail_list)
# we ignore the second arg as the data item/mime-part is constant (RFC822)
mocked_imaplib_server.fetch = mock.Mock(side_effect=lambda x, _: imap_emails[x])
with mock.patch('helpdesk.management.commands.get_email.imaplib', autospec=True) as mocked_imaplib:
mocked_imaplib.IMAP4 = mock.Mock(return_value=mocked_imaplib_server)
call_command('get_email')
ticket1 = get_object_or_404(Ticket, pk=1)
self.assertEqual(ticket1.ticket_for_url, "QQ-%s" % ticket1.id)
self.assertEqual(ticket1.title, subject)
# plain text should become description
self.assertEqual(ticket1.description, text)
# HTML MIME part should be attached to follow up
followup1 = get_object_or_404(FollowUp, pk=1)
self.assertEqual(followup1.ticket.id, 1)
attach1 = get_object_or_404(Attachment, pk=1)
self.assertEqual(attach1.followup.id, 1)
self.assertEqual(attach1.filename, 'email_html_body.html')
ticket2 = get_object_or_404(Ticket, pk=2)
self.assertEqual(ticket2.ticket_for_url, "QQ-%s" % ticket2.id)
self.assertEqual(ticket2.title, subject)
# plain text should become description
self.assertEqual(ticket2.description, text)
# HTML MIME part should be attached to follow up
followup2 = get_object_or_404(FollowUp, pk=2)
self.assertEqual(followup2.ticket.id, 2)
attach2 = get_object_or_404(Attachment, pk=2)
self.assertEqual(attach2.followup.id, 2)
self.assertEqual(attach2.filename, 'email_html_body.html')
# build matrix of test cases

View File

@ -126,16 +126,24 @@ setup(
description="Django-powered ticket tracker for your helpdesk",
long_description=LONG_DESCRIPTION,
classifiers=[
"Development Status :: 4 - Beta",
"Programming Language :: Python",
"Topic :: Software Development :: Libraries :: Python Modules",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Framework :: Django",
"Framework :: Django :: 1.8",
"Framework :: Django :: 1.9",
"Framework :: Django :: 1.10",
"Environment :: Web Environment",
"Operating System :: OS Independent",
"Intended Audience :: Customer Service",
"License :: OSI Approved :: BSD License",
"Natural Language :: English",
"Topic :: Office/Business",
"Topic :: Software Development :: Bug Tracking",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Office/Business",
"Natural Language :: English",
],
keywords=['django', 'helpdesk', 'django-helpdesk', 'tickets', 'incidents',
'cases', 'bugs', 'track', 'support'],