├── .gitignore ├── LICENSE ├── README.md ├── main ├── __init__.py ├── admin.py ├── forms.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ └── get_email.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── templates │ ├── main │ │ ├── all-tickets.html │ │ ├── archive.html │ │ ├── attachment_add.html │ │ ├── base.html │ │ ├── followup_edit.html │ │ ├── inbox.html │ │ ├── my-tickets.html │ │ ├── settings.html │ │ ├── ticket_detail.html │ │ └── ticket_edit.html │ └── registration │ │ └── login.html ├── tests.py └── views.py ├── manage.py ├── requirements.txt ├── screenshots ├── screenshot_all_open_tickets.png ├── screenshot_archive.png ├── screenshot_detail_view.png ├── screenshot_inbox.png ├── screenshot_landing_page.png ├── screenshot_login.png └── screenshot_my_tickets.png ├── static ├── 500.html ├── bootstrap │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ └── bootstrap.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js ├── css │ ├── frontpage.css │ ├── print.css │ └── style.css ├── font-awesome │ ├── css │ │ ├── font-awesome.css │ │ └── font-awesome.min.css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ └── fontawesome-webfont.woff │ ├── less │ │ ├── bordered-pulled.less │ │ ├── core.less │ │ ├── fixed-width.less │ │ ├── font-awesome.less │ │ ├── icons.less │ │ ├── larger.less │ │ ├── list.less │ │ ├── mixins.less │ │ ├── path.less │ │ ├── rotated-flipped.less │ │ ├── spinning.less │ │ ├── stacked.less │ │ └── variables.less │ └── scss │ │ ├── _bordered-pulled.scss │ │ ├── _core.scss │ │ ├── _fixed-width.scss │ │ ├── _icons.scss │ │ ├── _larger.scss │ │ ├── _list.scss │ │ ├── _mixins.scss │ │ ├── _path.scss │ │ ├── _rotated-flipped.scss │ │ ├── _spinning.scss │ │ ├── _stacked.scss │ │ ├── _variables.scss │ │ └── font-awesome.scss ├── img │ └── frontpage │ │ └── mt-fuji-477832_1280.jpg ├── jquery │ └── jquery-1.11.1.min.js └── js │ └── jquery.hotkeys.js └── tickets ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled python files 2 | *.py[cod] 3 | 4 | # emacs temp files 5 | *~ 6 | [#]*[#] 7 | .\#* 8 | 9 | # pycharm settings 10 | .idea/ 11 | 12 | # sphinx build folder 13 | doc/_build 14 | 15 | # OS generated files 16 | .DS_Store? 17 | 18 | # no media files in repo 19 | media/ 20 | 21 | # database not in repo 22 | db.sqlite3 23 | 24 | # bash script to set environment variables 25 | env.sh 26 | 27 | # static root folder for local deployments 28 | static_root 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Hendrik Sünkler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A simple ticketing application 2 | ============================== 3 | 4 | `django-tickets` is a simple MIT-licensed ticketing application written in Python/Django. Some of the features are: 5 | 6 | - creation of new tickets via web interface or via email 7 | - followups on tickets 8 | - file attachments for tickets 9 | - assign tickets to users 10 | - email notifications for new assignments, followups and closed tickets 11 | 12 | The application was written to serve my special needs. It is not intended to grow up to a kitchen sink. But I will add some features in the future. Feel free to use and modify it, if it is interesting for you. 13 | 14 | What does it look like? 15 | ======================= 16 | 17 | `django-tickets` uses a simple Bootstrap template. Nothing fancy. 18 | 19 | ![Landing Page](screenshots/screenshot_landing_page.png?raw=true "Landing Page") 20 | ![My tickets](screenshots/screenshot_my_tickets.png?raw=true "My tickets") 21 | 22 | Installation 23 | ============ 24 | 25 | Sensitive and installation dependent information is expected in environment variables. You can use a bash script like this one: 26 | 27 | ``` 28 | #!/usr/bin/env bash 29 | 30 | export DJANGO_SECRET_KEY="xxx" 31 | export DJANGO_PRODUCTION_DOMAIN="xxx" 32 | 33 | # log file 34 | export DJANGO_LOG_FILE="xxx" 35 | 36 | # static and media files dir in production 37 | export DJANGO_STATIC_ROOT="static_root/" 38 | export DJANGO_MEDIA_ROOT="xxx" 39 | 40 | # User who gets django's email notifications (ADMINS/MANAGERS), see settings.py 41 | export DJANGO_ADMIN_NAME="xxx" 42 | export DJANGO_ADMIN_EMAIL="xxx" 43 | 44 | # Django email configuration 45 | export DJANGO_EMAIL_HOST="xxx" 46 | export DJANGO_EMAIL_HOST_USER="xxx" 47 | export DJANGO_EMAIL_HOST_PASSWORD="xxx" 48 | 49 | # ticket email inbox, see 'main/management/commands/get_email.py' 50 | export DJANGO_TICKET_INBOX_SERVER="xxx" 51 | export DJANGO_TICKET_INBOX_USER="xxx" 52 | export DJANGO_TICKET_INBOX_PASSWORD="xxx" 53 | 54 | # email notifications to admin, see 'main/management/commands/get_email.py' 55 | export DJANGO_TICKET_EMAIL_NOTIFICATIONS_FROM="xxx" 56 | export DJANGO_TICKET_EMAIL_NOTIFICATIONS_TO="xxx" 57 | ``` 58 | 59 | Please note that `django-tickets` is **not** packaged as a reusable django app; it's a **complete django project**. So just clone the repository and install the dependencies via pip and the application including user authentication is ready to go. 60 | 61 | ``` 62 | $ git clone https://github.com/suenkler/django-tickets.git 63 | $ cd django-tickets 64 | $ pip install -r requirements.txt 65 | $ source env.sh 66 | $ ./manage.py migrate 67 | $ ./manage.py collectstatic 68 | $ ./manage.py createsuperuser 69 | $ ./manage.py runserver 70 | ``` 71 | 72 | To check the IMAP account for new messages and create tickets out of these messages, use the management command `get_email`: 73 | 74 | ``` 75 | $ ./manage.py get_email 76 | ``` 77 | -------------------------------------------------------------------------------- /main/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/main/__init__.py -------------------------------------------------------------------------------- /main/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import Ticket, FollowUp, Attachment 3 | 4 | 5 | class TicketAdmin(admin.ModelAdmin): 6 | list_display = ('id', 7 | 'title', 8 | 'description', 9 | 'assigned_to', 10 | 'created', 11 | 'updated',) 12 | 13 | 14 | # Register Models 15 | admin.site.register(Ticket, TicketAdmin) 16 | admin.site.register(FollowUp) 17 | admin.site.register(Attachment) 18 | -------------------------------------------------------------------------------- /main/forms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django import forms 4 | from django.contrib.auth.models import User 5 | 6 | from .models import Ticket, FollowUp, Attachment 7 | 8 | 9 | class UserSettingsForm(forms.ModelForm): 10 | 11 | class Meta: 12 | model = User 13 | fields = ('first_name', 'last_name', 'email',) 14 | 15 | 16 | class TicketCreateForm(forms.ModelForm): 17 | class Meta: 18 | model = Ticket 19 | fields = ('title', 'description') 20 | 21 | 22 | class TicketEditForm(forms.ModelForm): 23 | class Meta: 24 | model = Ticket 25 | fields = ('title', 'owner', 'description', 26 | 'status', 'waiting_for', 'assigned_to') 27 | 28 | 29 | class FollowupForm(forms.ModelForm): 30 | 31 | class Meta: 32 | model = FollowUp 33 | fields = ('ticket', 'title', 'text', 'user') 34 | 35 | 36 | class AttachmentForm(forms.ModelForm): 37 | class Meta: 38 | model = Attachment 39 | fields = ('file',) 40 | -------------------------------------------------------------------------------- /main/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/main/management/__init__.py -------------------------------------------------------------------------------- /main/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/main/management/commands/__init__.py -------------------------------------------------------------------------------- /main/management/commands/get_email.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file was derived from: 3 | https://github.com/rossp/django-helpdesk/blob/master/helpdesk/management/commands/get_email.py 4 | 5 | Copyright notice for that original file: 6 | 7 | Copyright (c) 2008, Ross Poulton (Trading as Jutda) 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without modification, 11 | are permitted provided that the following conditions are met: 12 | 13 | 1. Redistributions of source code must retain the above copyright 14 | notice, this list of conditions and the following disclaimer. 15 | 16 | 2. Redistributions in binary form must reproduce the above copyright 17 | notice, this list of conditions and the following disclaimer in the 18 | documentation and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of Ross Poulton, Jutda, nor the names of any 21 | of its contributors may be used to endorse or promote products 22 | derived from this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 25 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | """ 35 | 36 | import email 37 | import imaplib 38 | import mimetypes 39 | import re 40 | import os 41 | from email.header import decode_header 42 | from email.utils import parseaddr, collapse_rfc2231_value 43 | from optparse import make_option 44 | from email_reply_parser import EmailReplyParser 45 | from django.core.files.base import ContentFile 46 | from django.core.management.base import BaseCommand 47 | 48 | from django.contrib.auth.models import User 49 | 50 | try: 51 | from django.utils import timezone 52 | except ImportError: 53 | from datetime import datetime as timezone 54 | 55 | from main.models import Ticket, Attachment, FollowUp 56 | 57 | 58 | class Command(BaseCommand): 59 | def __init__(self): 60 | BaseCommand.__init__(self) 61 | 62 | self.option_list += ( 63 | make_option( 64 | '--quiet', '-q', 65 | default=False, 66 | action='store_true', 67 | help='Hide details about each message as they are processed.'), 68 | ) 69 | 70 | help = 'Process email inbox and create tickets.' 71 | 72 | def handle(self, *args, **options): 73 | quiet = options.get('quiet', False) 74 | process_inbox(quiet=quiet) 75 | 76 | 77 | def process_inbox(quiet=False): 78 | """ 79 | Process IMAP inbox 80 | """ 81 | server = imaplib.IMAP4_SSL(os.environ["DJANGO_TICKET_INBOX_SERVER"], 993) 82 | server.login(os.environ["DJANGO_TICKET_INBOX_USER"], os.environ["DJANGO_TICKET_INBOX_PASSWORD"]) 83 | server.select("INBOX") 84 | status, data = server.search(None, 'NOT', 'DELETED') 85 | if data: 86 | msgnums = data[0].split() 87 | for num in msgnums: 88 | status, data = server.fetch(num, '(RFC822)') 89 | ticket = ticket_from_message(message=data[0][1], quiet=quiet) 90 | if ticket: 91 | server.store(num, '+FLAGS', '\\Deleted') 92 | server.expunge() 93 | server.close() 94 | server.logout() 95 | 96 | 97 | def decodeUnknown(charset, string): 98 | if not charset: 99 | try: 100 | return string.decode('utf-8', 'ignore') 101 | except: 102 | return string.decode('iso8859-1', 'ignore') 103 | return unicode(string, charset) 104 | 105 | 106 | def decode_mail_headers(string): 107 | decoded = decode_header(string) 108 | return u' '.join([unicode(msg, charset or 'utf-8') for msg, charset in decoded]) 109 | 110 | 111 | def ticket_from_message(message, quiet): 112 | """ 113 | Create a ticket or a followup (if ticket id in subject) 114 | """ 115 | msg = message 116 | message = email.message_from_string(msg) 117 | subject = message.get('subject', 'Created from e-mail') 118 | subject = decode_mail_headers(decodeUnknown(message.get_charset(), subject)) 119 | sender = message.get('from', ('Unknown Sender')) 120 | sender = decode_mail_headers(decodeUnknown(message.get_charset(), sender)) 121 | sender_email = parseaddr(sender)[1] 122 | body_plain, body_html = '', '' 123 | 124 | matchobj = re.match(r".*\["+"-(?P\d+)\]", subject) 125 | if matchobj: 126 | # This is a reply or forward. 127 | ticket = matchobj.group('id') 128 | else: 129 | ticket = None 130 | 131 | counter = 0 132 | files = [] 133 | 134 | for part in message.walk(): 135 | if part.get_content_maintype() == 'multipart': 136 | continue 137 | 138 | name = part.get_param("name") 139 | if name: 140 | name = collapse_rfc2231_value(name) 141 | 142 | if part.get_content_maintype() == 'text' and name == None: 143 | if part.get_content_subtype() == 'plain': 144 | body_plain = EmailReplyParser.parse_reply(decodeUnknown(part.get_content_charset(), part.get_payload(decode=True))) 145 | else: 146 | body_html = part.get_payload(decode=True) 147 | else: 148 | if not name: 149 | ext = mimetypes.guess_extension(part.get_content_type()) 150 | name = "part-%i%s" % (counter, ext) 151 | 152 | files.append({ 153 | 'filename': name, 154 | 'content': part.get_payload(decode=True), 155 | 'type': part.get_content_type()}, 156 | ) 157 | 158 | counter += 1 159 | 160 | if body_plain: 161 | body = body_plain 162 | else: 163 | body = 'No plain-text email body available. Please see attachment email_html_body.html.' 164 | 165 | if body_html: 166 | files.append({ 167 | 'filename': 'email_html_body.html', 168 | 'content': body_html, 169 | 'type': 'text/html', 170 | }) 171 | 172 | now = timezone.now() 173 | 174 | if ticket: 175 | try: 176 | t = Ticket.objects.get(id=ticket) 177 | new = False 178 | except Ticket.DoesNotExist: 179 | ticket = None 180 | 181 | if ticket == None: 182 | 183 | # set owner depending on sender_email 184 | # list of all email addresses from the user model 185 | users = User.objects.all() 186 | email_addresses = [] 187 | for user in users: 188 | email_addresses.append(user.email) 189 | 190 | ############################################################ 191 | # if ticket id in subject => new followup instead of new ticket 192 | tickets = Ticket.objects.all() 193 | ticket_ids = [] 194 | for ticket in tickets: 195 | ticket_ids.append(ticket.id) 196 | 197 | # extract id from subject 198 | subject_id = re.search(r'\[#(\d*)\]\s.*', subject) 199 | try: 200 | subject_id = subject_id.group(1) 201 | except: 202 | subject_id = "0000" # no valid id 203 | 204 | # if there was an ID in the subject, create followup 205 | if int(subject_id) in ticket_ids: 206 | 207 | if sender_email in email_addresses: 208 | f = FollowUp( 209 | title=subject, 210 | created=now, 211 | text=body, 212 | ticket=Ticket.objects.get(id=subject_id), 213 | user=User.objects.get(email=sender_email), 214 | ) 215 | else: 216 | f = FollowUp( 217 | title=subject, 218 | created=now, 219 | text=body, 220 | ticket=Ticket.objects.get(id=subject_id), 221 | ) 222 | 223 | f.save() 224 | 225 | # if no ID in the subject, create ticket 226 | else: 227 | 228 | # if known sender, set also the field owner 229 | if sender_email in email_addresses: 230 | t = Ticket( 231 | title=subject, 232 | status="TODO", 233 | created=now, 234 | description=body, 235 | owner=User.objects.get(email=sender_email), 236 | ) 237 | # if unknown sender, skip the field owner 238 | else: 239 | t = Ticket( 240 | title=subject, 241 | status="TODO", 242 | created=now, 243 | description=body, 244 | ) 245 | 246 | t.save() 247 | 248 | from django.core.mail import send_mail 249 | notification_subject = "[#" + str(t.id) + "] New ticket created" 250 | notification_body = "Hi,\n\na new ticket was created: http://localhost:8000/ticket/" \ 251 | + str(t.id) + "/" 252 | send_mail(notification_subject, notification_body, os.environ["DJANGO_TICKET_EMAIL_NOTIFICATIONS_FROM"], 253 | [os.environ["DJANGO_TICKET_EMAIL_NOTIFICATIONS_TO"]], fail_silently=False) 254 | 255 | ############################################################ 256 | 257 | new = True 258 | update = '' 259 | 260 | elif t.status == Ticket.CLOSED_STATUS: 261 | t.status = Ticket.REOPENED_STATUS 262 | t.save() 263 | 264 | # files of followups should be assigned to the corresponding ticket 265 | for file in files: 266 | 267 | if file['content']: 268 | 269 | filename = file['filename'].encode('ascii', 'replace').replace(' ', '_') 270 | filename = re.sub('[^a-zA-Z0-9._-]+', '', filename) 271 | 272 | # if followup 273 | if int(subject_id) in ticket_ids: 274 | a = Attachment( 275 | ticket=Ticket.objects.get(id=subject_id), 276 | filename=filename, 277 | #mime_type=file['type'], 278 | #size=len(file['content']), 279 | ) 280 | 281 | # if new ticket 282 | else: 283 | a = Attachment( 284 | ticket=t, 285 | filename=filename, 286 | #mime_type=file['type'], 287 | #size=len(file['content']), 288 | ) 289 | 290 | a.file.save(filename, ContentFile(file['content']), save=False) 291 | a.save() 292 | 293 | if not quiet: 294 | print " - %s" % filename 295 | 296 | if int(subject_id) in ticket_ids: 297 | return f 298 | else: 299 | return t 300 | 301 | 302 | if __name__ == '__main__': 303 | process_email() 304 | -------------------------------------------------------------------------------- /main/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import unicode_literals 3 | 4 | from django.db import models, migrations 5 | import main.models 6 | import django.utils.timezone 7 | from django.conf import settings 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Attachment', 19 | fields=[ 20 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 21 | ('file', models.FileField(upload_to=main.models.attachment_path, max_length=1000, verbose_name=b'File')), 22 | ('filename', models.CharField(max_length=1000, verbose_name=b'Filename')), 23 | ('created', models.DateTimeField(auto_now_add=True)), 24 | ], 25 | options={ 26 | 'verbose_name': 'Attachment', 27 | 'verbose_name_plural': 'Attachments', 28 | }, 29 | ), 30 | migrations.CreateModel( 31 | name='FollowUp', 32 | fields=[ 33 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 34 | ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name=b'Date')), 35 | ('title', models.CharField(max_length=200, verbose_name=b'Title')), 36 | ('text', models.TextField(null=True, verbose_name=b'Text', blank=True)), 37 | ('created', models.DateTimeField(auto_now_add=True)), 38 | ('modified', models.DateTimeField(auto_now=True)), 39 | ], 40 | options={ 41 | 'ordering': ['-modified'], 42 | }, 43 | ), 44 | migrations.CreateModel( 45 | name='Ticket', 46 | fields=[ 47 | ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 48 | ('title', models.CharField(max_length=255, verbose_name=b'Title')), 49 | ('description', models.TextField(null=True, verbose_name=b'Description', blank=True)), 50 | ('status', models.CharField(blank=True, max_length=255, null=True, verbose_name=b'Status', choices=[(b'TODO', b'TODO'), (b'IN PROGRESS', b'IN PROGRESS'), (b'WAITING', b'WAITING'), (b'DONE', b'DONE')])), 51 | ('closed_date', models.DateTimeField(null=True, blank=True)), 52 | ('created', models.DateTimeField(auto_now_add=True)), 53 | ('updated', models.DateTimeField(auto_now=True)), 54 | ('assigned_to', models.ForeignKey(related_name='assigned_to', verbose_name=b'Assigned to', blank=True, to=settings.AUTH_USER_MODEL, null=True)), 55 | ('owner', models.ForeignKey(related_name='owner', verbose_name=b'Owner', blank=True, to=settings.AUTH_USER_MODEL, null=True)), 56 | ('waiting_for', models.ForeignKey(related_name='waiting_for', verbose_name=b'Waiting For', blank=True, to=settings.AUTH_USER_MODEL, null=True)), 57 | ], 58 | ), 59 | migrations.AddField( 60 | model_name='followup', 61 | name='ticket', 62 | field=models.ForeignKey(verbose_name=b'Ticket', to='main.Ticket'), 63 | ), 64 | migrations.AddField( 65 | model_name='followup', 66 | name='user', 67 | field=models.ForeignKey(verbose_name=b'User', blank=True, to=settings.AUTH_USER_MODEL, null=True), 68 | ), 69 | migrations.AddField( 70 | model_name='attachment', 71 | name='ticket', 72 | field=models.ForeignKey(verbose_name=b'Ticket', to='main.Ticket'), 73 | ), 74 | migrations.AddField( 75 | model_name='attachment', 76 | name='user', 77 | field=models.ForeignKey(verbose_name=b'User', blank=True, to=settings.AUTH_USER_MODEL, null=True), 78 | ), 79 | ] 80 | -------------------------------------------------------------------------------- /main/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/main/migrations/__init__.py -------------------------------------------------------------------------------- /main/models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.db import models 4 | from django.contrib.auth.models import User 5 | 6 | try: 7 | from django.utils import timezone 8 | except ImportError: 9 | from datetime import datetime as timezone 10 | 11 | 12 | def user_unicode(self): 13 | """ 14 | return 'last_name, first_name' for User by default 15 | """ 16 | return u'%s, %s' % (self.last_name, self.first_name) 17 | 18 | 19 | User.__unicode__ = user_unicode 20 | 21 | 22 | class Ticket(models.Model): 23 | 24 | title = models.CharField('Title', max_length=255) 25 | 26 | owner = models.ForeignKey(User, 27 | related_name='owner', 28 | blank=True, 29 | null=True, 30 | verbose_name='Owner') 31 | 32 | description = models.TextField('Description', blank=True, null=True) 33 | 34 | STATUS_CHOICES = ( 35 | ('TODO', 'TODO'), 36 | ('IN PROGRESS', 'IN PROGRESS'), 37 | ('WAITING', 'WAITING'), 38 | ('DONE', 'DONE'), 39 | ) 40 | status = models.CharField('Status', 41 | choices=STATUS_CHOICES, 42 | max_length=255, 43 | blank=True, 44 | null=True) 45 | 46 | waiting_for = models.ForeignKey(User, 47 | related_name='waiting_for', 48 | blank=True, 49 | null=True, 50 | verbose_name='Waiting For') 51 | 52 | # set in view when status changed to "DONE" 53 | closed_date = models.DateTimeField(blank=True, null=True) 54 | 55 | assigned_to = models.ForeignKey(User, 56 | related_name='assigned_to', 57 | blank=True, 58 | null=True, 59 | verbose_name='Assigned to') 60 | 61 | created = models.DateTimeField(auto_now_add=True) 62 | updated = models.DateTimeField(auto_now=True) 63 | 64 | def __unicode__(self): 65 | return str(self.id) 66 | 67 | 68 | class FollowUp(models.Model): 69 | """ 70 | A FollowUp is a comment to a ticket. 71 | """ 72 | ticket = models.ForeignKey(Ticket, verbose_name='Ticket') 73 | date = models.DateTimeField('Date', default=timezone.now) 74 | title = models.CharField('Title', max_length=200,) 75 | text = models.TextField('Text', blank=True, null=True,) 76 | user = models.ForeignKey(User, blank=True, null=True, verbose_name='User') 77 | created = models.DateTimeField(auto_now_add=True) 78 | modified = models.DateTimeField(auto_now=True) 79 | 80 | class Meta: 81 | ordering = ['-modified', ] 82 | 83 | 84 | def attachment_path(instance, filename): 85 | """ 86 | Provide a file path that will help prevent files being overwritten, by 87 | putting attachments in a folder off attachments for ticket/followup_id/. 88 | """ 89 | import os 90 | from django.conf import settings 91 | os.umask(0) 92 | path = 'tickets/%s' % instance.ticket.id 93 | print(path) 94 | att_path = os.path.join(settings.MEDIA_ROOT, path) 95 | if settings.DEFAULT_FILE_STORAGE == "django.core.files. \ 96 | storage.FileSystemStorage": 97 | if not os.path.exists(att_path): 98 | os.makedirs(att_path, 0777) 99 | return os.path.join(path, filename) 100 | 101 | 102 | class Attachment(models.Model): 103 | ticket = models.ForeignKey(Ticket, verbose_name='Ticket') 104 | 105 | file = models.FileField('File', 106 | upload_to=attachment_path, 107 | max_length=1000) 108 | 109 | filename = models.CharField('Filename', max_length=1000) 110 | 111 | user = models.ForeignKey(User, 112 | blank=True, 113 | null=True, 114 | verbose_name='User') 115 | 116 | created = models.DateTimeField(auto_now_add=True) 117 | 118 | def get_upload_to(self, field_attname): 119 | """ Get upload_to path specific to this item """ 120 | if not self.id: 121 | return u'' 122 | return u'../media/tickets/%s' % ( 123 | self.ticket.id, 124 | ) 125 | 126 | class Meta: 127 | # ordering = ['filename', ] 128 | verbose_name = 'Attachment' 129 | verbose_name_plural = 'Attachments' 130 | -------------------------------------------------------------------------------- /main/templates/main/all-tickets.html: -------------------------------------------------------------------------------- 1 | {% extends "main/base.html" %} 2 | 3 | {% block title %}Tickets - All tickets{% endblock %} 4 | 5 | {% block header_icon %}{% endblock %} 6 | {% block headline %}All open Tickets{% endblock %} 7 | {% block head-message %}Overview of all open tickets in the system{% endblock %} 8 | 9 | {% block content %} 10 | 11 | 12 | 13 | 14 | 20 | 21 |
22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | {% for ticket in tickets %} 42 | 43 | 44 | 56 | 57 | 58 | 59 | 60 | 61 | {% endfor %} 62 |
IDStatusOwnerAssigneeTitleDescription
{{ ticket.id }}{% if ticket.status == "TODO" %} 45 | TODO 46 | {% elif ticket.status == "IN PROGRESS" %} 47 | IN PROGRESS 48 | {% elif ticket.status == "WAITING" %} 49 | WAITING 50 | {% elif ticket.status == "DONE" %} 51 | DONE 52 | {% else %} 53 | {{ ticket.status }} 54 | {% endif %} 55 | {{ ticket.owner }}{% if ticket.assigned_to %}{{ ticket.assigned_to }}{% else %}---{% endif %}{{ ticket.title }}{{ ticket.description }}
63 | 64 | 65 |
66 |
67 | 68 | {% endblock %} -------------------------------------------------------------------------------- /main/templates/main/archive.html: -------------------------------------------------------------------------------- 1 | {% extends "main/base.html" %} 2 | 3 | {% block title %}Tickets - Archive{% endblock %} 4 | 5 | {% block header_icon %}{% endblock %} 6 | {% block headline %}Archive{% endblock %} 7 | {% block head-message %}Overview of all closed tickets in the system{% endblock %} 8 | 9 | {% block content %} 10 | 11 | 12 | 13 | 14 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | {% for ticket in tickets %} 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | {% endfor %} 50 |
IDOwnerAssigneeTitleDescriptionClosed
{{ ticket.id }}{{ ticket.owner }}{{ ticket.assigned_to }}{{ ticket.title }}{{ ticket.description }}{{ ticket.closed_date|date:"d.m.Y, G:i" }}
51 | 52 | 53 |
54 |
55 | 56 | {% endblock %} -------------------------------------------------------------------------------- /main/templates/main/attachment_add.html: -------------------------------------------------------------------------------- 1 | {% extends "main/base.html" %} 2 | 3 | {% block title %}Tickets - Add attachment{% endblock %} 4 | 5 | {% block header_icon %}{% endblock %} 6 | {% block headline %}Add Attachment{% endblock %} 7 | {% block head-message %}Please fill out the form{% endblock %} 8 | 9 | {% block content %} 10 | 11 | {% load crispy_forms_tags %} 12 | 13 | 14 | 15 |
16 | {% csrf_token %} 17 | {{ form | crispy }} 18 | 19 |
20 | 21 | {% endblock %} 22 | 23 | -------------------------------------------------------------------------------- /main/templates/main/base.html: -------------------------------------------------------------------------------- 1 | {% load staticfiles %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | {% block title %}{% endblock %} 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 61 | 62 | 63 | 64 |
65 | 66 |
67 |
68 | 69 |
70 |
71 |
{% block header_icon %}{% endblock %}
72 |

{% block headline %}{% endblock %}

73 |

{% block head-message %}{% endblock %}

74 |
75 |
76 | 77 |
78 |
79 | 80 | {% block breadcrum %} 81 | {% endblock %} 82 | 83 | {% block content %} 84 | {% endblock %} 85 | 86 |
87 | 88 | 89 | 100 | 101 |
102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /main/templates/main/followup_edit.html: -------------------------------------------------------------------------------- 1 | {% extends "main/base.html" %} 2 | 3 | {% block title %}Tickets - Edit followup{% endblock %} 4 | 5 | {% block header_icon %}{% endblock %} 6 | {% block headline %}{% if 'edit' in request.path %}Edit Followup{% else %}Create new Followup{% endif %}{% endblock %} 7 | {% block head-message %}Please fill out the form{% endblock %} 8 | 9 | {% block content %} 10 | 11 | {% load crispy_forms_tags %} 12 | 13 | {% if 'edit' in request.path %} 14 | 15 | 16 | 17 |
18 | {% csrf_token %} 19 | {{ form | crispy }} 20 | 21 |
22 | {% else %} 23 | 24 | 25 |
26 | {% csrf_token %} 27 | {{ form | crispy }} 28 | 29 |
30 | {% endif %} 31 | 32 | {% endblock %} 33 | 34 | -------------------------------------------------------------------------------- /main/templates/main/inbox.html: -------------------------------------------------------------------------------- 1 | {% extends "main/base.html" %} 2 | 3 | {% block title %}Tickets - Inbox{% endblock %} 4 | 5 | {% block header_icon %}{% endblock %} 6 | {% block headline %}Incoming Tickets{% endblock %} 7 | {% block head-message %}Feel free to pick up tickets on your own{% endblock %} 8 | 9 | 10 | {% block content %} 11 | 12 | 13 | 14 | 15 | 21 | 22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | {% for ticket in tickets_unassigned %} 41 | 42 | 43 | 44 | 45 | 46 | 47 | {% endfor %} 48 | 49 |
IDOwnerTitleDescription
{{ ticket.id }}{{ ticket.owner.first_name }} {{ ticket.owner.last_name }}{{ ticket.title }}{{ ticket.description }}
50 | 51 | 52 |
53 |
54 | 55 | {% endblock %} 56 | -------------------------------------------------------------------------------- /main/templates/main/my-tickets.html: -------------------------------------------------------------------------------- 1 | {% extends "main/base.html" %} 2 | 3 | {% block title %}Tickets - My tickets{% endblock %} 4 | 5 | {% block header_icon %}{% endblock %} 6 | {% block headline %}My Tickets{% endblock %} 7 | {% block head-message %}Tickets assigned to you personally{% endblock %} 8 | 9 | {% block content %} 10 | 11 | 12 | 13 | 14 | 20 | 21 |
22 |
23 | 24 | 25 | 26 | {% if tickets_waiting %} 27 | 28 | 69 | 70 | {% endif %} 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | {% for ticket in tickets %} 89 | 90 | 91 | 103 | 104 | 105 | 106 | 107 | {% endfor %} 108 | 109 | 110 | 111 |
IDStatusOwnerTitleDescription
{{ ticket.id }}{% if ticket.status == "TODO" %} 92 | TODO 93 | {% elif ticket.status == "IN PROGRESS" %} 94 | IN PROGRESS 95 | {% elif ticket.status == "WAITING" %} 96 | WAITING 97 | {% elif ticket.status == "DONE" %} 98 | DONE 99 | {% else %} 100 | {{ ticket.status }} 101 | {% endif %} 102 | {{ ticket.owner }}{{ ticket.title }}{{ ticket.description }}
112 | 113 | 114 |
115 |
116 | 117 | {% endblock %} 118 | -------------------------------------------------------------------------------- /main/templates/main/settings.html: -------------------------------------------------------------------------------- 1 | {% extends "main/base.html" %} 2 | 3 | {% block title %}Tickets - Settings{% endblock %} 4 | 5 | {% block header_icon %}{% endblock %} 6 | {% block headline %}Settings{% endblock %} 7 | {% block head-message %}Please adjust your settings{% endblock %} 8 | 9 | {% block content %} 10 | {% load staticfiles %} 11 | 12 |
13 |
14 | 15 | {% load crispy_forms_tags %} 16 | 17 |
18 | {% csrf_token %} 19 | 20 | {{ form_user|crispy }} 21 |
22 |
23 |
24 | 25 |
26 |
27 | 28 | 29 |
30 |
31 | 32 | {% endblock %} 33 | -------------------------------------------------------------------------------- /main/templates/main/ticket_detail.html: -------------------------------------------------------------------------------- 1 | {% extends "main/base.html" %} 2 | 3 | {% block header_icon %}{% endblock %} 4 | {% block headline %}Ticket #{{ticket.id}}{% endblock %} 5 | {% block head-message %}Everything you need to know about this ticket{% endblock %} 6 | 7 | {% block title %}Tickets - Details of ticket #{{ ticket.id }}{% endblock %} 8 | 9 | {% block content %} 10 | 11 | 22 | 23 | 24 | 25 |
26 |
27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
Status{% if ticket.status == "TODO" %}TODO{% elif ticket.status == "DONE" %}DONE{% elif ticket.status == "WAITING" %}WAITING{% elif ticket.status == "IN PROGRESS" %}IN PROGRESS{% endif %}
Assigned to{% if ticket.assigned_to %}{{ ticket.assigned_to.first_name }} {{ ticket.assigned_to.last_name }}{% else %}---{% endif %}
Owner{{ ticket.owner.first_name }} {{ ticket.owner.last_name }}
Title{{ ticket.title }}
Description{{ ticket.description}}
54 | 55 |
56 |
57 | 58 | {% if attachments %} 59 |

Attachments

60 | 65 | {% endif %} 66 | 67 |
68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 81 | 82 |

Followups

83 | {% if followups %} 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | {% for followup in followups %} 95 | 96 | 99 | 100 | 101 | 102 | 103 | {% endfor %} 104 | 105 |
UserTextModified
97 | 98 | {{ followup.user.first_name }} {{ followup.user.last_name }}{{ followup.text }}{{ followup.modified|date:"d.m.Y, G:i" }}
106 | 107 | {% else %} 108 |

no followup so far...

109 | {% endif %} 110 | 111 | 112 | {% endblock %} 113 | 114 | -------------------------------------------------------------------------------- /main/templates/main/ticket_edit.html: -------------------------------------------------------------------------------- 1 | {% extends "main/base.html" %} 2 | 3 | {% block header_icon %}{% endblock %} 4 | {% block headline %}{% if 'edit' in request.path %}Edit ticket{% else %}Create new ticket{% endif %}{% endblock %} 5 | {% block head-message %}Please fill out the form below{% endblock %} 6 | 7 | {% block title %}{% if 'edit' in request.path %}Tickets - Edit ticket{% else %}Tickets - Create new ticket{% endif %}{% endblock %} 8 | 9 | {% block content %} 10 | 11 | {% load crispy_forms_tags %} 12 | 13 | {% if 'edit' in request.path %} 14 | 15 | 16 | 17 |
18 | {% csrf_token %} 19 | {{ form | crispy }} 20 | 21 |
22 | {% else %} 23 | 24 | 25 |
26 | {% csrf_token %} 27 | {{ form | crispy }} 28 | 29 |
30 | {% endif %} 31 | 32 | {% endblock %} 33 | 34 | -------------------------------------------------------------------------------- /main/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% load staticfiles %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Django tickets 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 41 | 42 | 43 | 53 | 54 |
55 | 56 |
57 |
58 |

Web based

59 |

This is a web based ticketing application. So there is no need for local installations on the working stations of the users (besides a web browser).

60 |
61 |
62 |

Multi User

63 |

It is a multi user application. Every user can create tickets, assign tickets to other users, comment tickets, change the ticket status and so on.

64 |
65 |
66 |

Email integration

67 |

One of the main features is the ability to create new tickets via email. The app checks an IMAP account for new email regularly and creates a ticket for every email found in the inbox.

68 |
69 |
70 | 71 |
72 |
73 |

Security

74 |

Django is innately a very secure web framework. But there are some best practices of the django community that enhance security. In this application I tried to implement these good security best practices.

75 |
76 |
77 |

Python/Django

78 |

The application is based on the programming language Python and the web framework Django.

79 |
80 |
81 |

Minimal Feature Set

82 |

By now, this is just a very simple app with a minimal features set. It is not intended to grow up to a kitchen sink. But I will add some features in the future.

83 |
84 |
85 | 86 |
87 | 88 | 89 | 90 | 91 | 92 |
93 | 103 |
104 | 105 | 106 | 107 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 154 | 155 | 156 | 158 | 159 | 160 | 161 | 162 | 163 | {% if form.errors %} 164 | 178 | {% endif %} 179 | 180 | 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /main/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /main/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.shortcuts import render, render_to_response, redirect 4 | from django.template import RequestContext 5 | from django.contrib.auth.models import User 6 | from django.http import HttpResponseRedirect 7 | from django.utils import timezone 8 | from django.core.mail import send_mail 9 | 10 | from .models import Ticket, Attachment, FollowUp 11 | from .forms import UserSettingsForm 12 | from .forms import TicketCreateForm, TicketEditForm, \ 13 | FollowupForm, AttachmentForm 14 | 15 | # Logging 16 | import logging 17 | logger = logging.getLogger(__name__) 18 | 19 | 20 | def inbox_view(request): 21 | 22 | users = User.objects.all() 23 | tickets_unassigned = Ticket.objects.all().exclude(assigned_to__in=users) 24 | tickets_assigned = Ticket.objects.filter(assigned_to__in=users) 25 | 26 | return render_to_response('main/inbox.html', 27 | {"tickets_assigned": tickets_assigned, 28 | "tickets_unassigned": tickets_unassigned, }, 29 | context_instance=RequestContext(request)) 30 | 31 | 32 | def my_tickets_view(request): 33 | 34 | tickets = Ticket.objects.filter(assigned_to=request.user) \ 35 | .exclude(status__exact="DONE") 36 | tickets_waiting = Ticket.objects.filter(waiting_for=request.user) \ 37 | .filter(status__exact="WAITING") 38 | 39 | return render_to_response('main/my-tickets.html', 40 | {"tickets": tickets, 41 | "tickets_waiting": tickets_waiting}, 42 | context_instance=RequestContext(request)) 43 | 44 | 45 | def all_tickets_view(request): 46 | 47 | tickets_open = Ticket.objects.all().exclude(status__exact="DONE") 48 | 49 | return render_to_response('main/all-tickets.html', 50 | {"tickets": tickets_open, }, 51 | context_instance=RequestContext(request)) 52 | 53 | 54 | def archive_view(request): 55 | 56 | tickets_closed = Ticket.objects.filter(status__exact="DONE") 57 | 58 | return render_to_response('main/archive.html', 59 | {"tickets": tickets_closed, }, 60 | context_instance=RequestContext(request)) 61 | 62 | 63 | def usersettings_update_view(request): 64 | 65 | user = request.user 66 | 67 | if request.method == 'POST': 68 | # create a form instance and populate it with data from the request: 69 | form_user = UserSettingsForm(request.POST) 70 | 71 | # check whether it's valid: 72 | if form_user.is_valid(): 73 | 74 | # Save User model fields 75 | user.first_name = request.POST['first_name'] 76 | user.last_name = request.POST['last_name'] 77 | user.save() 78 | 79 | # redirect to the index page 80 | return HttpResponseRedirect(request.GET.get('next', '/inbox/')) 81 | 82 | # if a GET (or any other method) we'll create a blank form 83 | else: 84 | form_user = UserSettingsForm(instance=user) 85 | 86 | return render(request, 'main/settings.html', {'form_user': form_user, }) 87 | 88 | 89 | def ticket_create_view(request): 90 | 91 | if request.POST: 92 | form = TicketCreateForm(request.POST) 93 | 94 | if form.is_valid(): 95 | 96 | obj = form.save() 97 | # set owner 98 | obj.owner = request.user 99 | obj.status = "TODO" 100 | obj.save() 101 | 102 | return redirect('inbox') 103 | 104 | else: 105 | form = TicketCreateForm() 106 | 107 | return render(request, 108 | 'main/ticket_edit.html', 109 | {'form': form, }) 110 | 111 | 112 | def ticket_edit_view(request, pk): 113 | 114 | data = Ticket.objects.get(id=pk) 115 | 116 | if request.POST: 117 | form = TicketEditForm(request.POST, instance=data) 118 | if form.is_valid(): 119 | 120 | # set field closed_date to now() if status changed to "DONE" 121 | if form.cleaned_data['status'] == "DONE": 122 | data.closed_date = timezone.now() 123 | 124 | form.save() 125 | 126 | return redirect('inbox') 127 | 128 | else: 129 | form = TicketEditForm(instance=data) 130 | 131 | return render(request, 132 | 'main/ticket_edit.html', 133 | {'form': form, }) 134 | 135 | 136 | def ticket_detail_view(request, pk): 137 | 138 | ticket = Ticket.objects.get(id=pk) 139 | attachments = Attachment.objects.filter(ticket=ticket) 140 | followups = FollowUp.objects.filter(ticket=ticket) 141 | 142 | return render(request, 143 | 'main/ticket_detail.html', 144 | {'ticket': ticket, 145 | 'attachments': attachments, 146 | 'followups': followups, }) 147 | 148 | 149 | def followup_create_view(request): 150 | 151 | if request.POST: 152 | 153 | form = FollowupForm(request.POST) 154 | 155 | if form.is_valid(): 156 | form.save() 157 | 158 | ticket = Ticket.objects.get(id=request.POST['ticket']) 159 | # mail notification to owner of ticket 160 | notification_subject = "[#" + str(ticket.id) + "] New followup" 161 | notification_body = "Hi,\n\n new followup created for ticket #" \ 162 | + str(ticket.id) \ 163 | + " (http://localhost:8000/ticket/" \ 164 | + str(ticket.id) \ 165 | + "/)\n\nTitle: " + form.data['title'] \ 166 | + "\n\n" + form.data['text'] 167 | 168 | send_mail(notification_subject, notification_body, 'test@test.tld', 169 | [ticket.owner.email], fail_silently=False) 170 | 171 | return redirect('inbox') 172 | 173 | else: 174 | form = FollowupForm(initial={'ticket': request.GET.get('ticket'), 175 | 'user': request.user}) 176 | 177 | return render(request, 178 | 'main/followup_edit.html', 179 | {'form': form, }) 180 | 181 | 182 | def followup_edit_view(request, pk): 183 | 184 | data = FollowUp.objects.get(id=pk) 185 | 186 | if request.POST: 187 | form = FollowupForm(request.POST, instance=data) 188 | if form.is_valid(): 189 | form.save() 190 | 191 | return redirect('inbox') 192 | 193 | else: 194 | form = FollowupForm(instance=data) 195 | 196 | return render(request, 197 | 'main/followup_edit.html', 198 | {'form': form, }) 199 | 200 | 201 | def attachment_create_view(request): 202 | 203 | if request.POST: 204 | form = AttachmentForm(request.POST, request.FILES) 205 | 206 | if form.is_valid(): 207 | attachment = Attachment( 208 | ticket=Ticket.objects.get(id=request.GET['ticket']), 209 | file=request.FILES['file'], 210 | filename=request.FILES['file'].name, 211 | user=request.user 212 | # mime_type=form.file.get_content_type(), 213 | # size=len(form.file), 214 | ) 215 | attachment.save() 216 | 217 | return redirect('inbox') 218 | 219 | else: 220 | form = AttachmentForm() 221 | 222 | return render(request, 223 | 'main/attachment_add.html', 224 | {'form': form, }) 225 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tickets.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==1.8.4 2 | argparse==1.2.1 3 | django-crispy-forms==1.5.1 4 | email-reply-parser==0.3.0 5 | wsgiref==0.1.2 6 | -------------------------------------------------------------------------------- /screenshots/screenshot_all_open_tickets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/screenshots/screenshot_all_open_tickets.png -------------------------------------------------------------------------------- /screenshots/screenshot_archive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/screenshots/screenshot_archive.png -------------------------------------------------------------------------------- /screenshots/screenshot_detail_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/screenshots/screenshot_detail_view.png -------------------------------------------------------------------------------- /screenshots/screenshot_inbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/screenshots/screenshot_inbox.png -------------------------------------------------------------------------------- /screenshots/screenshot_landing_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/screenshots/screenshot_landing_page.png -------------------------------------------------------------------------------- /screenshots/screenshot_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/screenshots/screenshot_login.png -------------------------------------------------------------------------------- /screenshots/screenshot_my_tickets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/screenshots/screenshot_my_tickets.png -------------------------------------------------------------------------------- /static/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | bepartners 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | 24 | 25 | 26 | 38 | 39 |
40 | 41 |
42 |
43 |
44 |
45 |

Entschuldigung!

46 |
Es ist ein Fehler aufgetreten. Unsere Entwickler wurden per E-Mail über diesen Vorfall informiert und werden das Problem schnellstmöglich beheben.

Bei Fragen kontaktieren Sie uns gerne per E-Mail.
47 |
48 |
49 |
50 |
51 | 52 |
53 | 54 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /static/bootstrap/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default, 8 | .btn-primary, 9 | .btn-success, 10 | .btn-info, 11 | .btn-warning, 12 | .btn-danger { 13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); 14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 16 | } 17 | .btn-default:active, 18 | .btn-primary:active, 19 | .btn-success:active, 20 | .btn-info:active, 21 | .btn-warning:active, 22 | .btn-danger:active, 23 | .btn-default.active, 24 | .btn-primary.active, 25 | .btn-success.active, 26 | .btn-info.active, 27 | .btn-warning.active, 28 | .btn-danger.active { 29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 31 | } 32 | .btn-default .badge, 33 | .btn-primary .badge, 34 | .btn-success .badge, 35 | .btn-info .badge, 36 | .btn-warning .badge, 37 | .btn-danger .badge { 38 | text-shadow: none; 39 | } 40 | .btn:active, 41 | .btn.active { 42 | background-image: none; 43 | } 44 | .btn-default { 45 | text-shadow: 0 1px 0 #fff; 46 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 47 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); 48 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); 49 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 50 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 51 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 52 | background-repeat: repeat-x; 53 | border-color: #dbdbdb; 54 | border-color: #ccc; 55 | } 56 | .btn-default:hover, 57 | .btn-default:focus { 58 | background-color: #e0e0e0; 59 | background-position: 0 -15px; 60 | } 61 | .btn-default:active, 62 | .btn-default.active { 63 | background-color: #e0e0e0; 64 | border-color: #dbdbdb; 65 | } 66 | .btn-default:disabled, 67 | .btn-default[disabled] { 68 | background-color: #e0e0e0; 69 | background-image: none; 70 | } 71 | .btn-primary { 72 | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 73 | background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 74 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2)); 75 | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); 76 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); 77 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 78 | background-repeat: repeat-x; 79 | border-color: #2b669a; 80 | } 81 | .btn-primary:hover, 82 | .btn-primary:focus { 83 | background-color: #2d6ca2; 84 | background-position: 0 -15px; 85 | } 86 | .btn-primary:active, 87 | .btn-primary.active { 88 | background-color: #2d6ca2; 89 | border-color: #2b669a; 90 | } 91 | .btn-primary:disabled, 92 | .btn-primary[disabled] { 93 | background-color: #2d6ca2; 94 | background-image: none; 95 | } 96 | .btn-success { 97 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 98 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); 99 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); 100 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 101 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 102 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 103 | background-repeat: repeat-x; 104 | border-color: #3e8f3e; 105 | } 106 | .btn-success:hover, 107 | .btn-success:focus { 108 | background-color: #419641; 109 | background-position: 0 -15px; 110 | } 111 | .btn-success:active, 112 | .btn-success.active { 113 | background-color: #419641; 114 | border-color: #3e8f3e; 115 | } 116 | .btn-success:disabled, 117 | .btn-success[disabled] { 118 | background-color: #419641; 119 | background-image: none; 120 | } 121 | .btn-info { 122 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 123 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 124 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); 125 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 126 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 127 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 128 | background-repeat: repeat-x; 129 | border-color: #28a4c9; 130 | } 131 | .btn-info:hover, 132 | .btn-info:focus { 133 | background-color: #2aabd2; 134 | background-position: 0 -15px; 135 | } 136 | .btn-info:active, 137 | .btn-info.active { 138 | background-color: #2aabd2; 139 | border-color: #28a4c9; 140 | } 141 | .btn-info:disabled, 142 | .btn-info[disabled] { 143 | background-color: #2aabd2; 144 | background-image: none; 145 | } 146 | .btn-warning { 147 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 148 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 149 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); 150 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 151 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 152 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 153 | background-repeat: repeat-x; 154 | border-color: #e38d13; 155 | } 156 | .btn-warning:hover, 157 | .btn-warning:focus { 158 | background-color: #eb9316; 159 | background-position: 0 -15px; 160 | } 161 | .btn-warning:active, 162 | .btn-warning.active { 163 | background-color: #eb9316; 164 | border-color: #e38d13; 165 | } 166 | .btn-warning:disabled, 167 | .btn-warning[disabled] { 168 | background-color: #eb9316; 169 | background-image: none; 170 | } 171 | .btn-danger { 172 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 173 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 174 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); 175 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 176 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 177 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 178 | background-repeat: repeat-x; 179 | border-color: #b92c28; 180 | } 181 | .btn-danger:hover, 182 | .btn-danger:focus { 183 | background-color: #c12e2a; 184 | background-position: 0 -15px; 185 | } 186 | .btn-danger:active, 187 | .btn-danger.active { 188 | background-color: #c12e2a; 189 | border-color: #b92c28; 190 | } 191 | .btn-danger:disabled, 192 | .btn-danger[disabled] { 193 | background-color: #c12e2a; 194 | background-image: none; 195 | } 196 | .thumbnail, 197 | .img-thumbnail { 198 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 199 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 200 | } 201 | .dropdown-menu > li > a:hover, 202 | .dropdown-menu > li > a:focus { 203 | background-color: #e8e8e8; 204 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 205 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 206 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 207 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 208 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 209 | background-repeat: repeat-x; 210 | } 211 | .dropdown-menu > .active > a, 212 | .dropdown-menu > .active > a:hover, 213 | .dropdown-menu > .active > a:focus { 214 | background-color: #357ebd; 215 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 216 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); 217 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); 218 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 220 | background-repeat: repeat-x; 221 | } 222 | .navbar-default { 223 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); 224 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); 225 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); 226 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); 227 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 228 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 229 | background-repeat: repeat-x; 230 | border-radius: 4px; 231 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 232 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 233 | } 234 | .navbar-default .navbar-nav > .open > a, 235 | .navbar-default .navbar-nav > .active > a { 236 | background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 237 | background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); 238 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); 239 | background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); 240 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); 241 | background-repeat: repeat-x; 242 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 243 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 244 | } 245 | .navbar-brand, 246 | .navbar-nav > li > a { 247 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); 248 | } 249 | .navbar-inverse { 250 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 251 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); 252 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); 253 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 254 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 255 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 256 | background-repeat: repeat-x; 257 | } 258 | .navbar-inverse .navbar-nav > .open > a, 259 | .navbar-inverse .navbar-nav > .active > a { 260 | background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); 261 | background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); 262 | background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); 263 | background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); 264 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); 265 | background-repeat: repeat-x; 266 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 267 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 268 | } 269 | .navbar-inverse .navbar-brand, 270 | .navbar-inverse .navbar-nav > li > a { 271 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); 272 | } 273 | .navbar-static-top, 274 | .navbar-fixed-top, 275 | .navbar-fixed-bottom { 276 | border-radius: 0; 277 | } 278 | .alert { 279 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); 280 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 281 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 282 | } 283 | .alert-success { 284 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 285 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 286 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); 287 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 288 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 289 | background-repeat: repeat-x; 290 | border-color: #b2dba1; 291 | } 292 | .alert-info { 293 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 294 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 295 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); 296 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 297 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 298 | background-repeat: repeat-x; 299 | border-color: #9acfea; 300 | } 301 | .alert-warning { 302 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 303 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 304 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); 305 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 306 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 307 | background-repeat: repeat-x; 308 | border-color: #f5e79e; 309 | } 310 | .alert-danger { 311 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 312 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 313 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); 314 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 315 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 316 | background-repeat: repeat-x; 317 | border-color: #dca7a7; 318 | } 319 | .progress { 320 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 321 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 322 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); 323 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 324 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 325 | background-repeat: repeat-x; 326 | } 327 | .progress-bar { 328 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); 329 | background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%); 330 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9)); 331 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 332 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 333 | background-repeat: repeat-x; 334 | } 335 | .progress-bar-success { 336 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 337 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); 338 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); 339 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 340 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 341 | background-repeat: repeat-x; 342 | } 343 | .progress-bar-info { 344 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 345 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 346 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); 347 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 348 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 349 | background-repeat: repeat-x; 350 | } 351 | .progress-bar-warning { 352 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 353 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 354 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); 355 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 356 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 357 | background-repeat: repeat-x; 358 | } 359 | .progress-bar-danger { 360 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 361 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); 362 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); 363 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 364 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 365 | background-repeat: repeat-x; 366 | } 367 | .progress-bar-striped { 368 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 369 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 370 | background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 371 | } 372 | .list-group { 373 | border-radius: 4px; 374 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 375 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 376 | } 377 | .list-group-item.active, 378 | .list-group-item.active:hover, 379 | .list-group-item.active:focus { 380 | text-shadow: 0 -1px 0 #3071a9; 381 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); 382 | background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%); 383 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3)); 384 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); 385 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); 386 | background-repeat: repeat-x; 387 | border-color: #3278b3; 388 | } 389 | .list-group-item.active .badge, 390 | .list-group-item.active:hover .badge, 391 | .list-group-item.active:focus .badge { 392 | text-shadow: none; 393 | } 394 | .panel { 395 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 396 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 397 | } 398 | .panel-default > .panel-heading { 399 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 400 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 401 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 402 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 403 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 404 | background-repeat: repeat-x; 405 | } 406 | .panel-primary > .panel-heading { 407 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 408 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); 409 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); 410 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 411 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 412 | background-repeat: repeat-x; 413 | } 414 | .panel-success > .panel-heading { 415 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 416 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 417 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); 418 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 419 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 420 | background-repeat: repeat-x; 421 | } 422 | .panel-info > .panel-heading { 423 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 424 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 425 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); 426 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 427 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 428 | background-repeat: repeat-x; 429 | } 430 | .panel-warning > .panel-heading { 431 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 432 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 433 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); 434 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 435 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 436 | background-repeat: repeat-x; 437 | } 438 | .panel-danger > .panel-heading { 439 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 440 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 441 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); 442 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 443 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 444 | background-repeat: repeat-x; 445 | } 446 | .well { 447 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 448 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 449 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); 450 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 451 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 452 | background-repeat: repeat-x; 453 | border-color: #dcdcdc; 454 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 455 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 456 | } 457 | /*# sourceMappingURL=bootstrap-theme.css.map */ 458 | -------------------------------------------------------------------------------- /static/bootstrap/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-default .badge,.btn-primary .badge,.btn-success .badge,.btn-info .badge,.btn-warning .badge,.btn-danger .badge{text-shadow:none}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-o-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#2d6ca2));background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-primary:disabled,.btn-primary[disabled]{background-color:#2d6ca2;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-o-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3071a9));background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-o-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3278b3));background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);background-repeat:repeat-x;border-color:#3278b3}.list-group-item.active .badge,.list-group-item.active:hover .badge,.list-group-item.active:focus .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/static/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/static/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /static/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/static/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /static/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /static/css/frontpage.css: -------------------------------------------------------------------------------- 1 | @import "//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css"; 2 | 3 | body { 4 | padding-top: 50px; 5 | } 6 | .starter-template { 7 | padding: 40px 15px; 8 | text-align: center; 9 | } 10 | .footer { 11 | padding-top: 40px; 12 | padding-bottom: 40px; 13 | margin-top: 40px; 14 | border-top: 1px solid #eee; 15 | } 16 | .alert { 17 | margin-bottom: 0; 18 | } 19 | .help-block { 20 | display: none; 21 | } 22 | .navbar-form { 23 | margin-right: 0; 24 | } 25 | /* Home page styling */ 26 | .corporate-jumbo { 27 | background-image: url('/static/img/frontpage/mt-fuji-477832_1280.jpg'); 28 | background-repeat: no-repeat; 29 | background-attachment: fixed; 30 | background-position: 0 0; 31 | -webkit-background-size: cover; 32 | background-size: cover; 33 | color: #f5f5f5; 34 | } 35 | .corporate-jumbo .well { 36 | background-color: rgba(245, 245, 245, .7); 37 | } 38 | .corporate-jumbo p, .corporate-jumbo h1 { 39 | color: #eee; 40 | text-shadow: 0px 0px 2px black; 41 | } 42 | .corporate-jumbo p { 43 | font-weight: 500; 44 | } 45 | .corporate-jumbo .well legend { 46 | color: #333; 47 | } 48 | .contact-banner { 49 | padding: 100px 0; 50 | background: #e0e0e0; 51 | margin-top: 100px; 52 | } 53 | .footer a:hover { 54 | text-decoration: none; 55 | } 56 | 57 | 58 | /* Login Form */ 59 | 60 | .form-signin { 61 | max-width: 330px; 62 | padding: 15px; 63 | margin: 0 auto; 64 | } 65 | .form-signin .form-signin-heading, 66 | .form-signin .checkbox { 67 | margin-bottom: 10px; 68 | } 69 | .form-signin .checkbox { 70 | font-weight: normal; 71 | } 72 | .form-signin .form-control { 73 | position: relative; 74 | height: auto; 75 | -webkit-box-sizing: border-box; 76 | -moz-box-sizing: border-box; 77 | box-sizing: border-box; 78 | padding: 10px; 79 | font-size: 16px; 80 | } 81 | .form-signin .form-control:focus { 82 | z-index: 2; 83 | } 84 | .form-signin input[type="text"] { 85 | margin-bottom: -1px; 86 | border-bottom-right-radius: 0; 87 | border-bottom-left-radius: 0; 88 | } 89 | .form-signin input[type="password"] { 90 | margin-bottom: 10px; 91 | border-top-left-radius: 0; 92 | border-top-right-radius: 0; 93 | } 94 | -------------------------------------------------------------------------------- /static/css/print.css: -------------------------------------------------------------------------------- 1 | .jumbotron { display: none; } 2 | .breadcrumb { display: none; } 3 | .dropdown { display: none; } 4 | 5 | 6 | /* Bootstrap druckt die URLs in Klammern hinter die Links. 7 | Das wird folgendermaßen verhindert */ 8 | a[href]:after { 9 | content: none !important; 10 | } 11 | -------------------------------------------------------------------------------- /static/css/style.css: -------------------------------------------------------------------------------- 1 | 2 | body { padding-top: 50px; } 3 | 4 | #title { font-size: 35px; } 5 | 6 | #header_icon { float: left; padding: 20px; } 7 | #header_subtitle { color: #737373; } 8 | 9 | .jumbotron h1 {font-size: 45px; } 10 | 11 | 12 | 13 | /* Anpassungen des Standard Bootstrap CSS */ 14 | 15 | 16 | /* Größe und Ausrichtung der Überschriften */ 17 | 18 | .page-header { 19 | padding-bottom: 9px; 20 | margin: 24px 0px 20px; 21 | border-bottom: 1px solid #EEE; 22 | } 23 | 24 | .page-header h1 { font-size: 32px; } 25 | /* ========================= */ 26 | 27 | h2 { font-size: 25px; } 28 | 29 | 30 | .hs-infobox { 31 | margin-right: 0px; 32 | margin-left: 0px; 33 | margin-top: 20px; 34 | margin-bottom: 10px; 35 | background-color: #EEE; 36 | border-color: #DDD; 37 | border-width: 1px; 38 | border-radius: 4px 4px 0px 0px; 39 | box-shadow: none; 40 | position: relative; 41 | padding: 10px 10px 10px; 42 | border-style: solid; 43 | } 44 | 45 | .hs-infobox-title { color: #959595; 46 | text-transform: uppercase; 47 | letter-spacing: 1px; 48 | font-weight: bold; 49 | font-size: 12px; 50 | margin-bottom: 10px; 51 | } 52 | 53 | .hs-infobox ul { list-style-type: square; padding-left: 25px; } 54 | 55 | .hs-infobox ul > li { 56 | color: #9f9f9f; 57 | } 58 | 59 | .hs-infobox ul > li > span { 60 | color: black; 61 | } 62 | 63 | .hs-generate-button { float: right; margin-top: 20px; } 64 | 65 | /* Bearbeiten-Links in der Fragebogen-Übersicht */ 66 | 67 | .hs-edit-link { font-size: 16px; } 68 | .hs-edit-link:hover { color: grey; } 69 | 70 | 71 | .navbar .fa { font-size: 18px; } 72 | 73 | 74 | -------------------------------------------------------------------------------- /static/font-awesome/css/font-awesome.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.2.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"} -------------------------------------------------------------------------------- /static/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/static/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /static/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/static/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /static/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/static/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /static/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/static/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /static/font-awesome/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .pull-right { float: right; } 11 | .pull-left { float: left; } 12 | 13 | .@{fa-css-prefix} { 14 | &.pull-left { margin-right: .3em; } 15 | &.pull-right { margin-left: .3em; } 16 | } 17 | -------------------------------------------------------------------------------- /static/font-awesome/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal 14px/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | } 12 | -------------------------------------------------------------------------------- /static/font-awesome/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /static/font-awesome/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "spinning.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | -------------------------------------------------------------------------------- /static/font-awesome/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /static/font-awesome/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /static/font-awesome/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal 14px/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | } 12 | 13 | .fa-icon-rotate(@degrees, @rotation) { 14 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation); 15 | -webkit-transform: rotate(@degrees); 16 | -ms-transform: rotate(@degrees); 17 | transform: rotate(@degrees); 18 | } 19 | 20 | .fa-icon-flip(@horiz, @vert, @rotation) { 21 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1); 22 | -webkit-transform: scale(@horiz, @vert); 23 | -ms-transform: scale(@horiz, @vert); 24 | transform: scale(@horiz, @vert); 25 | } 26 | -------------------------------------------------------------------------------- /static/font-awesome/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 9 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 10 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 11 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 12 | font-weight: normal; 13 | font-style: normal; 14 | } 15 | -------------------------------------------------------------------------------- /static/font-awesome/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /static/font-awesome/less/spinning.less: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | @-webkit-keyframes fa-spin { 10 | 0% { 11 | -webkit-transform: rotate(0deg); 12 | transform: rotate(0deg); 13 | } 14 | 100% { 15 | -webkit-transform: rotate(359deg); 16 | transform: rotate(359deg); 17 | } 18 | } 19 | 20 | @keyframes fa-spin { 21 | 0% { 22 | -webkit-transform: rotate(0deg); 23 | transform: rotate(0deg); 24 | } 25 | 100% { 26 | -webkit-transform: rotate(359deg); 27 | transform: rotate(359deg); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /static/font-awesome/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /static/font-awesome/less/variables.less: -------------------------------------------------------------------------------- 1 | // Variables 2 | // -------------------------- 3 | 4 | @fa-font-path: "../fonts"; 5 | //@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts"; // for referencing Bootstrap CDN font files directly 6 | @fa-css-prefix: fa; 7 | @fa-version: "4.2.0"; 8 | @fa-border-color: #eee; 9 | @fa-inverse: #fff; 10 | @fa-li-width: (30em / 14); 11 | 12 | @fa-var-adjust: "\f042"; 13 | @fa-var-adn: "\f170"; 14 | @fa-var-align-center: "\f037"; 15 | @fa-var-align-justify: "\f039"; 16 | @fa-var-align-left: "\f036"; 17 | @fa-var-align-right: "\f038"; 18 | @fa-var-ambulance: "\f0f9"; 19 | @fa-var-anchor: "\f13d"; 20 | @fa-var-android: "\f17b"; 21 | @fa-var-angellist: "\f209"; 22 | @fa-var-angle-double-down: "\f103"; 23 | @fa-var-angle-double-left: "\f100"; 24 | @fa-var-angle-double-right: "\f101"; 25 | @fa-var-angle-double-up: "\f102"; 26 | @fa-var-angle-down: "\f107"; 27 | @fa-var-angle-left: "\f104"; 28 | @fa-var-angle-right: "\f105"; 29 | @fa-var-angle-up: "\f106"; 30 | @fa-var-apple: "\f179"; 31 | @fa-var-archive: "\f187"; 32 | @fa-var-area-chart: "\f1fe"; 33 | @fa-var-arrow-circle-down: "\f0ab"; 34 | @fa-var-arrow-circle-left: "\f0a8"; 35 | @fa-var-arrow-circle-o-down: "\f01a"; 36 | @fa-var-arrow-circle-o-left: "\f190"; 37 | @fa-var-arrow-circle-o-right: "\f18e"; 38 | @fa-var-arrow-circle-o-up: "\f01b"; 39 | @fa-var-arrow-circle-right: "\f0a9"; 40 | @fa-var-arrow-circle-up: "\f0aa"; 41 | @fa-var-arrow-down: "\f063"; 42 | @fa-var-arrow-left: "\f060"; 43 | @fa-var-arrow-right: "\f061"; 44 | @fa-var-arrow-up: "\f062"; 45 | @fa-var-arrows: "\f047"; 46 | @fa-var-arrows-alt: "\f0b2"; 47 | @fa-var-arrows-h: "\f07e"; 48 | @fa-var-arrows-v: "\f07d"; 49 | @fa-var-asterisk: "\f069"; 50 | @fa-var-at: "\f1fa"; 51 | @fa-var-automobile: "\f1b9"; 52 | @fa-var-backward: "\f04a"; 53 | @fa-var-ban: "\f05e"; 54 | @fa-var-bank: "\f19c"; 55 | @fa-var-bar-chart: "\f080"; 56 | @fa-var-bar-chart-o: "\f080"; 57 | @fa-var-barcode: "\f02a"; 58 | @fa-var-bars: "\f0c9"; 59 | @fa-var-beer: "\f0fc"; 60 | @fa-var-behance: "\f1b4"; 61 | @fa-var-behance-square: "\f1b5"; 62 | @fa-var-bell: "\f0f3"; 63 | @fa-var-bell-o: "\f0a2"; 64 | @fa-var-bell-slash: "\f1f6"; 65 | @fa-var-bell-slash-o: "\f1f7"; 66 | @fa-var-bicycle: "\f206"; 67 | @fa-var-binoculars: "\f1e5"; 68 | @fa-var-birthday-cake: "\f1fd"; 69 | @fa-var-bitbucket: "\f171"; 70 | @fa-var-bitbucket-square: "\f172"; 71 | @fa-var-bitcoin: "\f15a"; 72 | @fa-var-bold: "\f032"; 73 | @fa-var-bolt: "\f0e7"; 74 | @fa-var-bomb: "\f1e2"; 75 | @fa-var-book: "\f02d"; 76 | @fa-var-bookmark: "\f02e"; 77 | @fa-var-bookmark-o: "\f097"; 78 | @fa-var-briefcase: "\f0b1"; 79 | @fa-var-btc: "\f15a"; 80 | @fa-var-bug: "\f188"; 81 | @fa-var-building: "\f1ad"; 82 | @fa-var-building-o: "\f0f7"; 83 | @fa-var-bullhorn: "\f0a1"; 84 | @fa-var-bullseye: "\f140"; 85 | @fa-var-bus: "\f207"; 86 | @fa-var-cab: "\f1ba"; 87 | @fa-var-calculator: "\f1ec"; 88 | @fa-var-calendar: "\f073"; 89 | @fa-var-calendar-o: "\f133"; 90 | @fa-var-camera: "\f030"; 91 | @fa-var-camera-retro: "\f083"; 92 | @fa-var-car: "\f1b9"; 93 | @fa-var-caret-down: "\f0d7"; 94 | @fa-var-caret-left: "\f0d9"; 95 | @fa-var-caret-right: "\f0da"; 96 | @fa-var-caret-square-o-down: "\f150"; 97 | @fa-var-caret-square-o-left: "\f191"; 98 | @fa-var-caret-square-o-right: "\f152"; 99 | @fa-var-caret-square-o-up: "\f151"; 100 | @fa-var-caret-up: "\f0d8"; 101 | @fa-var-cc: "\f20a"; 102 | @fa-var-cc-amex: "\f1f3"; 103 | @fa-var-cc-discover: "\f1f2"; 104 | @fa-var-cc-mastercard: "\f1f1"; 105 | @fa-var-cc-paypal: "\f1f4"; 106 | @fa-var-cc-stripe: "\f1f5"; 107 | @fa-var-cc-visa: "\f1f0"; 108 | @fa-var-certificate: "\f0a3"; 109 | @fa-var-chain: "\f0c1"; 110 | @fa-var-chain-broken: "\f127"; 111 | @fa-var-check: "\f00c"; 112 | @fa-var-check-circle: "\f058"; 113 | @fa-var-check-circle-o: "\f05d"; 114 | @fa-var-check-square: "\f14a"; 115 | @fa-var-check-square-o: "\f046"; 116 | @fa-var-chevron-circle-down: "\f13a"; 117 | @fa-var-chevron-circle-left: "\f137"; 118 | @fa-var-chevron-circle-right: "\f138"; 119 | @fa-var-chevron-circle-up: "\f139"; 120 | @fa-var-chevron-down: "\f078"; 121 | @fa-var-chevron-left: "\f053"; 122 | @fa-var-chevron-right: "\f054"; 123 | @fa-var-chevron-up: "\f077"; 124 | @fa-var-child: "\f1ae"; 125 | @fa-var-circle: "\f111"; 126 | @fa-var-circle-o: "\f10c"; 127 | @fa-var-circle-o-notch: "\f1ce"; 128 | @fa-var-circle-thin: "\f1db"; 129 | @fa-var-clipboard: "\f0ea"; 130 | @fa-var-clock-o: "\f017"; 131 | @fa-var-close: "\f00d"; 132 | @fa-var-cloud: "\f0c2"; 133 | @fa-var-cloud-download: "\f0ed"; 134 | @fa-var-cloud-upload: "\f0ee"; 135 | @fa-var-cny: "\f157"; 136 | @fa-var-code: "\f121"; 137 | @fa-var-code-fork: "\f126"; 138 | @fa-var-codepen: "\f1cb"; 139 | @fa-var-coffee: "\f0f4"; 140 | @fa-var-cog: "\f013"; 141 | @fa-var-cogs: "\f085"; 142 | @fa-var-columns: "\f0db"; 143 | @fa-var-comment: "\f075"; 144 | @fa-var-comment-o: "\f0e5"; 145 | @fa-var-comments: "\f086"; 146 | @fa-var-comments-o: "\f0e6"; 147 | @fa-var-compass: "\f14e"; 148 | @fa-var-compress: "\f066"; 149 | @fa-var-copy: "\f0c5"; 150 | @fa-var-copyright: "\f1f9"; 151 | @fa-var-credit-card: "\f09d"; 152 | @fa-var-crop: "\f125"; 153 | @fa-var-crosshairs: "\f05b"; 154 | @fa-var-css3: "\f13c"; 155 | @fa-var-cube: "\f1b2"; 156 | @fa-var-cubes: "\f1b3"; 157 | @fa-var-cut: "\f0c4"; 158 | @fa-var-cutlery: "\f0f5"; 159 | @fa-var-dashboard: "\f0e4"; 160 | @fa-var-database: "\f1c0"; 161 | @fa-var-dedent: "\f03b"; 162 | @fa-var-delicious: "\f1a5"; 163 | @fa-var-desktop: "\f108"; 164 | @fa-var-deviantart: "\f1bd"; 165 | @fa-var-digg: "\f1a6"; 166 | @fa-var-dollar: "\f155"; 167 | @fa-var-dot-circle-o: "\f192"; 168 | @fa-var-download: "\f019"; 169 | @fa-var-dribbble: "\f17d"; 170 | @fa-var-dropbox: "\f16b"; 171 | @fa-var-drupal: "\f1a9"; 172 | @fa-var-edit: "\f044"; 173 | @fa-var-eject: "\f052"; 174 | @fa-var-ellipsis-h: "\f141"; 175 | @fa-var-ellipsis-v: "\f142"; 176 | @fa-var-empire: "\f1d1"; 177 | @fa-var-envelope: "\f0e0"; 178 | @fa-var-envelope-o: "\f003"; 179 | @fa-var-envelope-square: "\f199"; 180 | @fa-var-eraser: "\f12d"; 181 | @fa-var-eur: "\f153"; 182 | @fa-var-euro: "\f153"; 183 | @fa-var-exchange: "\f0ec"; 184 | @fa-var-exclamation: "\f12a"; 185 | @fa-var-exclamation-circle: "\f06a"; 186 | @fa-var-exclamation-triangle: "\f071"; 187 | @fa-var-expand: "\f065"; 188 | @fa-var-external-link: "\f08e"; 189 | @fa-var-external-link-square: "\f14c"; 190 | @fa-var-eye: "\f06e"; 191 | @fa-var-eye-slash: "\f070"; 192 | @fa-var-eyedropper: "\f1fb"; 193 | @fa-var-facebook: "\f09a"; 194 | @fa-var-facebook-square: "\f082"; 195 | @fa-var-fast-backward: "\f049"; 196 | @fa-var-fast-forward: "\f050"; 197 | @fa-var-fax: "\f1ac"; 198 | @fa-var-female: "\f182"; 199 | @fa-var-fighter-jet: "\f0fb"; 200 | @fa-var-file: "\f15b"; 201 | @fa-var-file-archive-o: "\f1c6"; 202 | @fa-var-file-audio-o: "\f1c7"; 203 | @fa-var-file-code-o: "\f1c9"; 204 | @fa-var-file-excel-o: "\f1c3"; 205 | @fa-var-file-image-o: "\f1c5"; 206 | @fa-var-file-movie-o: "\f1c8"; 207 | @fa-var-file-o: "\f016"; 208 | @fa-var-file-pdf-o: "\f1c1"; 209 | @fa-var-file-photo-o: "\f1c5"; 210 | @fa-var-file-picture-o: "\f1c5"; 211 | @fa-var-file-powerpoint-o: "\f1c4"; 212 | @fa-var-file-sound-o: "\f1c7"; 213 | @fa-var-file-text: "\f15c"; 214 | @fa-var-file-text-o: "\f0f6"; 215 | @fa-var-file-video-o: "\f1c8"; 216 | @fa-var-file-word-o: "\f1c2"; 217 | @fa-var-file-zip-o: "\f1c6"; 218 | @fa-var-files-o: "\f0c5"; 219 | @fa-var-film: "\f008"; 220 | @fa-var-filter: "\f0b0"; 221 | @fa-var-fire: "\f06d"; 222 | @fa-var-fire-extinguisher: "\f134"; 223 | @fa-var-flag: "\f024"; 224 | @fa-var-flag-checkered: "\f11e"; 225 | @fa-var-flag-o: "\f11d"; 226 | @fa-var-flash: "\f0e7"; 227 | @fa-var-flask: "\f0c3"; 228 | @fa-var-flickr: "\f16e"; 229 | @fa-var-floppy-o: "\f0c7"; 230 | @fa-var-folder: "\f07b"; 231 | @fa-var-folder-o: "\f114"; 232 | @fa-var-folder-open: "\f07c"; 233 | @fa-var-folder-open-o: "\f115"; 234 | @fa-var-font: "\f031"; 235 | @fa-var-forward: "\f04e"; 236 | @fa-var-foursquare: "\f180"; 237 | @fa-var-frown-o: "\f119"; 238 | @fa-var-futbol-o: "\f1e3"; 239 | @fa-var-gamepad: "\f11b"; 240 | @fa-var-gavel: "\f0e3"; 241 | @fa-var-gbp: "\f154"; 242 | @fa-var-ge: "\f1d1"; 243 | @fa-var-gear: "\f013"; 244 | @fa-var-gears: "\f085"; 245 | @fa-var-gift: "\f06b"; 246 | @fa-var-git: "\f1d3"; 247 | @fa-var-git-square: "\f1d2"; 248 | @fa-var-github: "\f09b"; 249 | @fa-var-github-alt: "\f113"; 250 | @fa-var-github-square: "\f092"; 251 | @fa-var-gittip: "\f184"; 252 | @fa-var-glass: "\f000"; 253 | @fa-var-globe: "\f0ac"; 254 | @fa-var-google: "\f1a0"; 255 | @fa-var-google-plus: "\f0d5"; 256 | @fa-var-google-plus-square: "\f0d4"; 257 | @fa-var-google-wallet: "\f1ee"; 258 | @fa-var-graduation-cap: "\f19d"; 259 | @fa-var-group: "\f0c0"; 260 | @fa-var-h-square: "\f0fd"; 261 | @fa-var-hacker-news: "\f1d4"; 262 | @fa-var-hand-o-down: "\f0a7"; 263 | @fa-var-hand-o-left: "\f0a5"; 264 | @fa-var-hand-o-right: "\f0a4"; 265 | @fa-var-hand-o-up: "\f0a6"; 266 | @fa-var-hdd-o: "\f0a0"; 267 | @fa-var-header: "\f1dc"; 268 | @fa-var-headphones: "\f025"; 269 | @fa-var-heart: "\f004"; 270 | @fa-var-heart-o: "\f08a"; 271 | @fa-var-history: "\f1da"; 272 | @fa-var-home: "\f015"; 273 | @fa-var-hospital-o: "\f0f8"; 274 | @fa-var-html5: "\f13b"; 275 | @fa-var-ils: "\f20b"; 276 | @fa-var-image: "\f03e"; 277 | @fa-var-inbox: "\f01c"; 278 | @fa-var-indent: "\f03c"; 279 | @fa-var-info: "\f129"; 280 | @fa-var-info-circle: "\f05a"; 281 | @fa-var-inr: "\f156"; 282 | @fa-var-instagram: "\f16d"; 283 | @fa-var-institution: "\f19c"; 284 | @fa-var-ioxhost: "\f208"; 285 | @fa-var-italic: "\f033"; 286 | @fa-var-joomla: "\f1aa"; 287 | @fa-var-jpy: "\f157"; 288 | @fa-var-jsfiddle: "\f1cc"; 289 | @fa-var-key: "\f084"; 290 | @fa-var-keyboard-o: "\f11c"; 291 | @fa-var-krw: "\f159"; 292 | @fa-var-language: "\f1ab"; 293 | @fa-var-laptop: "\f109"; 294 | @fa-var-lastfm: "\f202"; 295 | @fa-var-lastfm-square: "\f203"; 296 | @fa-var-leaf: "\f06c"; 297 | @fa-var-legal: "\f0e3"; 298 | @fa-var-lemon-o: "\f094"; 299 | @fa-var-level-down: "\f149"; 300 | @fa-var-level-up: "\f148"; 301 | @fa-var-life-bouy: "\f1cd"; 302 | @fa-var-life-buoy: "\f1cd"; 303 | @fa-var-life-ring: "\f1cd"; 304 | @fa-var-life-saver: "\f1cd"; 305 | @fa-var-lightbulb-o: "\f0eb"; 306 | @fa-var-line-chart: "\f201"; 307 | @fa-var-link: "\f0c1"; 308 | @fa-var-linkedin: "\f0e1"; 309 | @fa-var-linkedin-square: "\f08c"; 310 | @fa-var-linux: "\f17c"; 311 | @fa-var-list: "\f03a"; 312 | @fa-var-list-alt: "\f022"; 313 | @fa-var-list-ol: "\f0cb"; 314 | @fa-var-list-ul: "\f0ca"; 315 | @fa-var-location-arrow: "\f124"; 316 | @fa-var-lock: "\f023"; 317 | @fa-var-long-arrow-down: "\f175"; 318 | @fa-var-long-arrow-left: "\f177"; 319 | @fa-var-long-arrow-right: "\f178"; 320 | @fa-var-long-arrow-up: "\f176"; 321 | @fa-var-magic: "\f0d0"; 322 | @fa-var-magnet: "\f076"; 323 | @fa-var-mail-forward: "\f064"; 324 | @fa-var-mail-reply: "\f112"; 325 | @fa-var-mail-reply-all: "\f122"; 326 | @fa-var-male: "\f183"; 327 | @fa-var-map-marker: "\f041"; 328 | @fa-var-maxcdn: "\f136"; 329 | @fa-var-meanpath: "\f20c"; 330 | @fa-var-medkit: "\f0fa"; 331 | @fa-var-meh-o: "\f11a"; 332 | @fa-var-microphone: "\f130"; 333 | @fa-var-microphone-slash: "\f131"; 334 | @fa-var-minus: "\f068"; 335 | @fa-var-minus-circle: "\f056"; 336 | @fa-var-minus-square: "\f146"; 337 | @fa-var-minus-square-o: "\f147"; 338 | @fa-var-mobile: "\f10b"; 339 | @fa-var-mobile-phone: "\f10b"; 340 | @fa-var-money: "\f0d6"; 341 | @fa-var-moon-o: "\f186"; 342 | @fa-var-mortar-board: "\f19d"; 343 | @fa-var-music: "\f001"; 344 | @fa-var-navicon: "\f0c9"; 345 | @fa-var-newspaper-o: "\f1ea"; 346 | @fa-var-openid: "\f19b"; 347 | @fa-var-outdent: "\f03b"; 348 | @fa-var-pagelines: "\f18c"; 349 | @fa-var-paint-brush: "\f1fc"; 350 | @fa-var-paper-plane: "\f1d8"; 351 | @fa-var-paper-plane-o: "\f1d9"; 352 | @fa-var-paperclip: "\f0c6"; 353 | @fa-var-paragraph: "\f1dd"; 354 | @fa-var-paste: "\f0ea"; 355 | @fa-var-pause: "\f04c"; 356 | @fa-var-paw: "\f1b0"; 357 | @fa-var-paypal: "\f1ed"; 358 | @fa-var-pencil: "\f040"; 359 | @fa-var-pencil-square: "\f14b"; 360 | @fa-var-pencil-square-o: "\f044"; 361 | @fa-var-phone: "\f095"; 362 | @fa-var-phone-square: "\f098"; 363 | @fa-var-photo: "\f03e"; 364 | @fa-var-picture-o: "\f03e"; 365 | @fa-var-pie-chart: "\f200"; 366 | @fa-var-pied-piper: "\f1a7"; 367 | @fa-var-pied-piper-alt: "\f1a8"; 368 | @fa-var-pinterest: "\f0d2"; 369 | @fa-var-pinterest-square: "\f0d3"; 370 | @fa-var-plane: "\f072"; 371 | @fa-var-play: "\f04b"; 372 | @fa-var-play-circle: "\f144"; 373 | @fa-var-play-circle-o: "\f01d"; 374 | @fa-var-plug: "\f1e6"; 375 | @fa-var-plus: "\f067"; 376 | @fa-var-plus-circle: "\f055"; 377 | @fa-var-plus-square: "\f0fe"; 378 | @fa-var-plus-square-o: "\f196"; 379 | @fa-var-power-off: "\f011"; 380 | @fa-var-print: "\f02f"; 381 | @fa-var-puzzle-piece: "\f12e"; 382 | @fa-var-qq: "\f1d6"; 383 | @fa-var-qrcode: "\f029"; 384 | @fa-var-question: "\f128"; 385 | @fa-var-question-circle: "\f059"; 386 | @fa-var-quote-left: "\f10d"; 387 | @fa-var-quote-right: "\f10e"; 388 | @fa-var-ra: "\f1d0"; 389 | @fa-var-random: "\f074"; 390 | @fa-var-rebel: "\f1d0"; 391 | @fa-var-recycle: "\f1b8"; 392 | @fa-var-reddit: "\f1a1"; 393 | @fa-var-reddit-square: "\f1a2"; 394 | @fa-var-refresh: "\f021"; 395 | @fa-var-remove: "\f00d"; 396 | @fa-var-renren: "\f18b"; 397 | @fa-var-reorder: "\f0c9"; 398 | @fa-var-repeat: "\f01e"; 399 | @fa-var-reply: "\f112"; 400 | @fa-var-reply-all: "\f122"; 401 | @fa-var-retweet: "\f079"; 402 | @fa-var-rmb: "\f157"; 403 | @fa-var-road: "\f018"; 404 | @fa-var-rocket: "\f135"; 405 | @fa-var-rotate-left: "\f0e2"; 406 | @fa-var-rotate-right: "\f01e"; 407 | @fa-var-rouble: "\f158"; 408 | @fa-var-rss: "\f09e"; 409 | @fa-var-rss-square: "\f143"; 410 | @fa-var-rub: "\f158"; 411 | @fa-var-ruble: "\f158"; 412 | @fa-var-rupee: "\f156"; 413 | @fa-var-save: "\f0c7"; 414 | @fa-var-scissors: "\f0c4"; 415 | @fa-var-search: "\f002"; 416 | @fa-var-search-minus: "\f010"; 417 | @fa-var-search-plus: "\f00e"; 418 | @fa-var-send: "\f1d8"; 419 | @fa-var-send-o: "\f1d9"; 420 | @fa-var-share: "\f064"; 421 | @fa-var-share-alt: "\f1e0"; 422 | @fa-var-share-alt-square: "\f1e1"; 423 | @fa-var-share-square: "\f14d"; 424 | @fa-var-share-square-o: "\f045"; 425 | @fa-var-shekel: "\f20b"; 426 | @fa-var-sheqel: "\f20b"; 427 | @fa-var-shield: "\f132"; 428 | @fa-var-shopping-cart: "\f07a"; 429 | @fa-var-sign-in: "\f090"; 430 | @fa-var-sign-out: "\f08b"; 431 | @fa-var-signal: "\f012"; 432 | @fa-var-sitemap: "\f0e8"; 433 | @fa-var-skype: "\f17e"; 434 | @fa-var-slack: "\f198"; 435 | @fa-var-sliders: "\f1de"; 436 | @fa-var-slideshare: "\f1e7"; 437 | @fa-var-smile-o: "\f118"; 438 | @fa-var-soccer-ball-o: "\f1e3"; 439 | @fa-var-sort: "\f0dc"; 440 | @fa-var-sort-alpha-asc: "\f15d"; 441 | @fa-var-sort-alpha-desc: "\f15e"; 442 | @fa-var-sort-amount-asc: "\f160"; 443 | @fa-var-sort-amount-desc: "\f161"; 444 | @fa-var-sort-asc: "\f0de"; 445 | @fa-var-sort-desc: "\f0dd"; 446 | @fa-var-sort-down: "\f0dd"; 447 | @fa-var-sort-numeric-asc: "\f162"; 448 | @fa-var-sort-numeric-desc: "\f163"; 449 | @fa-var-sort-up: "\f0de"; 450 | @fa-var-soundcloud: "\f1be"; 451 | @fa-var-space-shuttle: "\f197"; 452 | @fa-var-spinner: "\f110"; 453 | @fa-var-spoon: "\f1b1"; 454 | @fa-var-spotify: "\f1bc"; 455 | @fa-var-square: "\f0c8"; 456 | @fa-var-square-o: "\f096"; 457 | @fa-var-stack-exchange: "\f18d"; 458 | @fa-var-stack-overflow: "\f16c"; 459 | @fa-var-star: "\f005"; 460 | @fa-var-star-half: "\f089"; 461 | @fa-var-star-half-empty: "\f123"; 462 | @fa-var-star-half-full: "\f123"; 463 | @fa-var-star-half-o: "\f123"; 464 | @fa-var-star-o: "\f006"; 465 | @fa-var-steam: "\f1b6"; 466 | @fa-var-steam-square: "\f1b7"; 467 | @fa-var-step-backward: "\f048"; 468 | @fa-var-step-forward: "\f051"; 469 | @fa-var-stethoscope: "\f0f1"; 470 | @fa-var-stop: "\f04d"; 471 | @fa-var-strikethrough: "\f0cc"; 472 | @fa-var-stumbleupon: "\f1a4"; 473 | @fa-var-stumbleupon-circle: "\f1a3"; 474 | @fa-var-subscript: "\f12c"; 475 | @fa-var-suitcase: "\f0f2"; 476 | @fa-var-sun-o: "\f185"; 477 | @fa-var-superscript: "\f12b"; 478 | @fa-var-support: "\f1cd"; 479 | @fa-var-table: "\f0ce"; 480 | @fa-var-tablet: "\f10a"; 481 | @fa-var-tachometer: "\f0e4"; 482 | @fa-var-tag: "\f02b"; 483 | @fa-var-tags: "\f02c"; 484 | @fa-var-tasks: "\f0ae"; 485 | @fa-var-taxi: "\f1ba"; 486 | @fa-var-tencent-weibo: "\f1d5"; 487 | @fa-var-terminal: "\f120"; 488 | @fa-var-text-height: "\f034"; 489 | @fa-var-text-width: "\f035"; 490 | @fa-var-th: "\f00a"; 491 | @fa-var-th-large: "\f009"; 492 | @fa-var-th-list: "\f00b"; 493 | @fa-var-thumb-tack: "\f08d"; 494 | @fa-var-thumbs-down: "\f165"; 495 | @fa-var-thumbs-o-down: "\f088"; 496 | @fa-var-thumbs-o-up: "\f087"; 497 | @fa-var-thumbs-up: "\f164"; 498 | @fa-var-ticket: "\f145"; 499 | @fa-var-times: "\f00d"; 500 | @fa-var-times-circle: "\f057"; 501 | @fa-var-times-circle-o: "\f05c"; 502 | @fa-var-tint: "\f043"; 503 | @fa-var-toggle-down: "\f150"; 504 | @fa-var-toggle-left: "\f191"; 505 | @fa-var-toggle-off: "\f204"; 506 | @fa-var-toggle-on: "\f205"; 507 | @fa-var-toggle-right: "\f152"; 508 | @fa-var-toggle-up: "\f151"; 509 | @fa-var-trash: "\f1f8"; 510 | @fa-var-trash-o: "\f014"; 511 | @fa-var-tree: "\f1bb"; 512 | @fa-var-trello: "\f181"; 513 | @fa-var-trophy: "\f091"; 514 | @fa-var-truck: "\f0d1"; 515 | @fa-var-try: "\f195"; 516 | @fa-var-tty: "\f1e4"; 517 | @fa-var-tumblr: "\f173"; 518 | @fa-var-tumblr-square: "\f174"; 519 | @fa-var-turkish-lira: "\f195"; 520 | @fa-var-twitch: "\f1e8"; 521 | @fa-var-twitter: "\f099"; 522 | @fa-var-twitter-square: "\f081"; 523 | @fa-var-umbrella: "\f0e9"; 524 | @fa-var-underline: "\f0cd"; 525 | @fa-var-undo: "\f0e2"; 526 | @fa-var-university: "\f19c"; 527 | @fa-var-unlink: "\f127"; 528 | @fa-var-unlock: "\f09c"; 529 | @fa-var-unlock-alt: "\f13e"; 530 | @fa-var-unsorted: "\f0dc"; 531 | @fa-var-upload: "\f093"; 532 | @fa-var-usd: "\f155"; 533 | @fa-var-user: "\f007"; 534 | @fa-var-user-md: "\f0f0"; 535 | @fa-var-users: "\f0c0"; 536 | @fa-var-video-camera: "\f03d"; 537 | @fa-var-vimeo-square: "\f194"; 538 | @fa-var-vine: "\f1ca"; 539 | @fa-var-vk: "\f189"; 540 | @fa-var-volume-down: "\f027"; 541 | @fa-var-volume-off: "\f026"; 542 | @fa-var-volume-up: "\f028"; 543 | @fa-var-warning: "\f071"; 544 | @fa-var-wechat: "\f1d7"; 545 | @fa-var-weibo: "\f18a"; 546 | @fa-var-weixin: "\f1d7"; 547 | @fa-var-wheelchair: "\f193"; 548 | @fa-var-wifi: "\f1eb"; 549 | @fa-var-windows: "\f17a"; 550 | @fa-var-won: "\f159"; 551 | @fa-var-wordpress: "\f19a"; 552 | @fa-var-wrench: "\f0ad"; 553 | @fa-var-xing: "\f168"; 554 | @fa-var-xing-square: "\f169"; 555 | @fa-var-yahoo: "\f19e"; 556 | @fa-var-yelp: "\f1e9"; 557 | @fa-var-yen: "\f157"; 558 | @fa-var-youtube: "\f167"; 559 | @fa-var-youtube-play: "\f16a"; 560 | @fa-var-youtube-square: "\f166"; 561 | 562 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .pull-right { float: right; } 11 | .pull-left { float: left; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.pull-left { margin-right: .3em; } 15 | &.pull-right { margin-left: .3em; } 16 | } 17 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal 14px/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | } 12 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal 14px/1 FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | } 12 | 13 | @mixin fa-icon-rotate($degrees, $rotation) { 14 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 15 | -webkit-transform: rotate($degrees); 16 | -ms-transform: rotate($degrees); 17 | transform: rotate($degrees); 18 | } 19 | 20 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 21 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 22 | -webkit-transform: scale($horiz, $vert); 23 | -ms-transform: scale($horiz, $vert); 24 | transform: scale($horiz, $vert); 25 | } 26 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 9 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 10 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 11 | //src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 12 | font-weight: normal; 13 | font-style: normal; 14 | } 15 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_spinning.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | @-webkit-keyframes fa-spin { 10 | 0% { 11 | -webkit-transform: rotate(0deg); 12 | transform: rotate(0deg); 13 | } 14 | 100% { 15 | -webkit-transform: rotate(359deg); 16 | transform: rotate(359deg); 17 | } 18 | } 19 | 20 | @keyframes fa-spin { 21 | 0% { 22 | -webkit-transform: rotate(0deg); 23 | transform: rotate(0deg); 24 | } 25 | 100% { 26 | -webkit-transform: rotate(359deg); 27 | transform: rotate(359deg); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /static/font-awesome/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | // Variables 2 | // -------------------------- 3 | 4 | $fa-font-path: "../fonts" !default; 5 | //$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts" !default; // for referencing Bootstrap CDN font files directly 6 | $fa-css-prefix: fa !default; 7 | $fa-version: "4.2.0" !default; 8 | $fa-border-color: #eee !default; 9 | $fa-inverse: #fff !default; 10 | $fa-li-width: (30em / 14) !default; 11 | 12 | $fa-var-adjust: "\f042"; 13 | $fa-var-adn: "\f170"; 14 | $fa-var-align-center: "\f037"; 15 | $fa-var-align-justify: "\f039"; 16 | $fa-var-align-left: "\f036"; 17 | $fa-var-align-right: "\f038"; 18 | $fa-var-ambulance: "\f0f9"; 19 | $fa-var-anchor: "\f13d"; 20 | $fa-var-android: "\f17b"; 21 | $fa-var-angellist: "\f209"; 22 | $fa-var-angle-double-down: "\f103"; 23 | $fa-var-angle-double-left: "\f100"; 24 | $fa-var-angle-double-right: "\f101"; 25 | $fa-var-angle-double-up: "\f102"; 26 | $fa-var-angle-down: "\f107"; 27 | $fa-var-angle-left: "\f104"; 28 | $fa-var-angle-right: "\f105"; 29 | $fa-var-angle-up: "\f106"; 30 | $fa-var-apple: "\f179"; 31 | $fa-var-archive: "\f187"; 32 | $fa-var-area-chart: "\f1fe"; 33 | $fa-var-arrow-circle-down: "\f0ab"; 34 | $fa-var-arrow-circle-left: "\f0a8"; 35 | $fa-var-arrow-circle-o-down: "\f01a"; 36 | $fa-var-arrow-circle-o-left: "\f190"; 37 | $fa-var-arrow-circle-o-right: "\f18e"; 38 | $fa-var-arrow-circle-o-up: "\f01b"; 39 | $fa-var-arrow-circle-right: "\f0a9"; 40 | $fa-var-arrow-circle-up: "\f0aa"; 41 | $fa-var-arrow-down: "\f063"; 42 | $fa-var-arrow-left: "\f060"; 43 | $fa-var-arrow-right: "\f061"; 44 | $fa-var-arrow-up: "\f062"; 45 | $fa-var-arrows: "\f047"; 46 | $fa-var-arrows-alt: "\f0b2"; 47 | $fa-var-arrows-h: "\f07e"; 48 | $fa-var-arrows-v: "\f07d"; 49 | $fa-var-asterisk: "\f069"; 50 | $fa-var-at: "\f1fa"; 51 | $fa-var-automobile: "\f1b9"; 52 | $fa-var-backward: "\f04a"; 53 | $fa-var-ban: "\f05e"; 54 | $fa-var-bank: "\f19c"; 55 | $fa-var-bar-chart: "\f080"; 56 | $fa-var-bar-chart-o: "\f080"; 57 | $fa-var-barcode: "\f02a"; 58 | $fa-var-bars: "\f0c9"; 59 | $fa-var-beer: "\f0fc"; 60 | $fa-var-behance: "\f1b4"; 61 | $fa-var-behance-square: "\f1b5"; 62 | $fa-var-bell: "\f0f3"; 63 | $fa-var-bell-o: "\f0a2"; 64 | $fa-var-bell-slash: "\f1f6"; 65 | $fa-var-bell-slash-o: "\f1f7"; 66 | $fa-var-bicycle: "\f206"; 67 | $fa-var-binoculars: "\f1e5"; 68 | $fa-var-birthday-cake: "\f1fd"; 69 | $fa-var-bitbucket: "\f171"; 70 | $fa-var-bitbucket-square: "\f172"; 71 | $fa-var-bitcoin: "\f15a"; 72 | $fa-var-bold: "\f032"; 73 | $fa-var-bolt: "\f0e7"; 74 | $fa-var-bomb: "\f1e2"; 75 | $fa-var-book: "\f02d"; 76 | $fa-var-bookmark: "\f02e"; 77 | $fa-var-bookmark-o: "\f097"; 78 | $fa-var-briefcase: "\f0b1"; 79 | $fa-var-btc: "\f15a"; 80 | $fa-var-bug: "\f188"; 81 | $fa-var-building: "\f1ad"; 82 | $fa-var-building-o: "\f0f7"; 83 | $fa-var-bullhorn: "\f0a1"; 84 | $fa-var-bullseye: "\f140"; 85 | $fa-var-bus: "\f207"; 86 | $fa-var-cab: "\f1ba"; 87 | $fa-var-calculator: "\f1ec"; 88 | $fa-var-calendar: "\f073"; 89 | $fa-var-calendar-o: "\f133"; 90 | $fa-var-camera: "\f030"; 91 | $fa-var-camera-retro: "\f083"; 92 | $fa-var-car: "\f1b9"; 93 | $fa-var-caret-down: "\f0d7"; 94 | $fa-var-caret-left: "\f0d9"; 95 | $fa-var-caret-right: "\f0da"; 96 | $fa-var-caret-square-o-down: "\f150"; 97 | $fa-var-caret-square-o-left: "\f191"; 98 | $fa-var-caret-square-o-right: "\f152"; 99 | $fa-var-caret-square-o-up: "\f151"; 100 | $fa-var-caret-up: "\f0d8"; 101 | $fa-var-cc: "\f20a"; 102 | $fa-var-cc-amex: "\f1f3"; 103 | $fa-var-cc-discover: "\f1f2"; 104 | $fa-var-cc-mastercard: "\f1f1"; 105 | $fa-var-cc-paypal: "\f1f4"; 106 | $fa-var-cc-stripe: "\f1f5"; 107 | $fa-var-cc-visa: "\f1f0"; 108 | $fa-var-certificate: "\f0a3"; 109 | $fa-var-chain: "\f0c1"; 110 | $fa-var-chain-broken: "\f127"; 111 | $fa-var-check: "\f00c"; 112 | $fa-var-check-circle: "\f058"; 113 | $fa-var-check-circle-o: "\f05d"; 114 | $fa-var-check-square: "\f14a"; 115 | $fa-var-check-square-o: "\f046"; 116 | $fa-var-chevron-circle-down: "\f13a"; 117 | $fa-var-chevron-circle-left: "\f137"; 118 | $fa-var-chevron-circle-right: "\f138"; 119 | $fa-var-chevron-circle-up: "\f139"; 120 | $fa-var-chevron-down: "\f078"; 121 | $fa-var-chevron-left: "\f053"; 122 | $fa-var-chevron-right: "\f054"; 123 | $fa-var-chevron-up: "\f077"; 124 | $fa-var-child: "\f1ae"; 125 | $fa-var-circle: "\f111"; 126 | $fa-var-circle-o: "\f10c"; 127 | $fa-var-circle-o-notch: "\f1ce"; 128 | $fa-var-circle-thin: "\f1db"; 129 | $fa-var-clipboard: "\f0ea"; 130 | $fa-var-clock-o: "\f017"; 131 | $fa-var-close: "\f00d"; 132 | $fa-var-cloud: "\f0c2"; 133 | $fa-var-cloud-download: "\f0ed"; 134 | $fa-var-cloud-upload: "\f0ee"; 135 | $fa-var-cny: "\f157"; 136 | $fa-var-code: "\f121"; 137 | $fa-var-code-fork: "\f126"; 138 | $fa-var-codepen: "\f1cb"; 139 | $fa-var-coffee: "\f0f4"; 140 | $fa-var-cog: "\f013"; 141 | $fa-var-cogs: "\f085"; 142 | $fa-var-columns: "\f0db"; 143 | $fa-var-comment: "\f075"; 144 | $fa-var-comment-o: "\f0e5"; 145 | $fa-var-comments: "\f086"; 146 | $fa-var-comments-o: "\f0e6"; 147 | $fa-var-compass: "\f14e"; 148 | $fa-var-compress: "\f066"; 149 | $fa-var-copy: "\f0c5"; 150 | $fa-var-copyright: "\f1f9"; 151 | $fa-var-credit-card: "\f09d"; 152 | $fa-var-crop: "\f125"; 153 | $fa-var-crosshairs: "\f05b"; 154 | $fa-var-css3: "\f13c"; 155 | $fa-var-cube: "\f1b2"; 156 | $fa-var-cubes: "\f1b3"; 157 | $fa-var-cut: "\f0c4"; 158 | $fa-var-cutlery: "\f0f5"; 159 | $fa-var-dashboard: "\f0e4"; 160 | $fa-var-database: "\f1c0"; 161 | $fa-var-dedent: "\f03b"; 162 | $fa-var-delicious: "\f1a5"; 163 | $fa-var-desktop: "\f108"; 164 | $fa-var-deviantart: "\f1bd"; 165 | $fa-var-digg: "\f1a6"; 166 | $fa-var-dollar: "\f155"; 167 | $fa-var-dot-circle-o: "\f192"; 168 | $fa-var-download: "\f019"; 169 | $fa-var-dribbble: "\f17d"; 170 | $fa-var-dropbox: "\f16b"; 171 | $fa-var-drupal: "\f1a9"; 172 | $fa-var-edit: "\f044"; 173 | $fa-var-eject: "\f052"; 174 | $fa-var-ellipsis-h: "\f141"; 175 | $fa-var-ellipsis-v: "\f142"; 176 | $fa-var-empire: "\f1d1"; 177 | $fa-var-envelope: "\f0e0"; 178 | $fa-var-envelope-o: "\f003"; 179 | $fa-var-envelope-square: "\f199"; 180 | $fa-var-eraser: "\f12d"; 181 | $fa-var-eur: "\f153"; 182 | $fa-var-euro: "\f153"; 183 | $fa-var-exchange: "\f0ec"; 184 | $fa-var-exclamation: "\f12a"; 185 | $fa-var-exclamation-circle: "\f06a"; 186 | $fa-var-exclamation-triangle: "\f071"; 187 | $fa-var-expand: "\f065"; 188 | $fa-var-external-link: "\f08e"; 189 | $fa-var-external-link-square: "\f14c"; 190 | $fa-var-eye: "\f06e"; 191 | $fa-var-eye-slash: "\f070"; 192 | $fa-var-eyedropper: "\f1fb"; 193 | $fa-var-facebook: "\f09a"; 194 | $fa-var-facebook-square: "\f082"; 195 | $fa-var-fast-backward: "\f049"; 196 | $fa-var-fast-forward: "\f050"; 197 | $fa-var-fax: "\f1ac"; 198 | $fa-var-female: "\f182"; 199 | $fa-var-fighter-jet: "\f0fb"; 200 | $fa-var-file: "\f15b"; 201 | $fa-var-file-archive-o: "\f1c6"; 202 | $fa-var-file-audio-o: "\f1c7"; 203 | $fa-var-file-code-o: "\f1c9"; 204 | $fa-var-file-excel-o: "\f1c3"; 205 | $fa-var-file-image-o: "\f1c5"; 206 | $fa-var-file-movie-o: "\f1c8"; 207 | $fa-var-file-o: "\f016"; 208 | $fa-var-file-pdf-o: "\f1c1"; 209 | $fa-var-file-photo-o: "\f1c5"; 210 | $fa-var-file-picture-o: "\f1c5"; 211 | $fa-var-file-powerpoint-o: "\f1c4"; 212 | $fa-var-file-sound-o: "\f1c7"; 213 | $fa-var-file-text: "\f15c"; 214 | $fa-var-file-text-o: "\f0f6"; 215 | $fa-var-file-video-o: "\f1c8"; 216 | $fa-var-file-word-o: "\f1c2"; 217 | $fa-var-file-zip-o: "\f1c6"; 218 | $fa-var-files-o: "\f0c5"; 219 | $fa-var-film: "\f008"; 220 | $fa-var-filter: "\f0b0"; 221 | $fa-var-fire: "\f06d"; 222 | $fa-var-fire-extinguisher: "\f134"; 223 | $fa-var-flag: "\f024"; 224 | $fa-var-flag-checkered: "\f11e"; 225 | $fa-var-flag-o: "\f11d"; 226 | $fa-var-flash: "\f0e7"; 227 | $fa-var-flask: "\f0c3"; 228 | $fa-var-flickr: "\f16e"; 229 | $fa-var-floppy-o: "\f0c7"; 230 | $fa-var-folder: "\f07b"; 231 | $fa-var-folder-o: "\f114"; 232 | $fa-var-folder-open: "\f07c"; 233 | $fa-var-folder-open-o: "\f115"; 234 | $fa-var-font: "\f031"; 235 | $fa-var-forward: "\f04e"; 236 | $fa-var-foursquare: "\f180"; 237 | $fa-var-frown-o: "\f119"; 238 | $fa-var-futbol-o: "\f1e3"; 239 | $fa-var-gamepad: "\f11b"; 240 | $fa-var-gavel: "\f0e3"; 241 | $fa-var-gbp: "\f154"; 242 | $fa-var-ge: "\f1d1"; 243 | $fa-var-gear: "\f013"; 244 | $fa-var-gears: "\f085"; 245 | $fa-var-gift: "\f06b"; 246 | $fa-var-git: "\f1d3"; 247 | $fa-var-git-square: "\f1d2"; 248 | $fa-var-github: "\f09b"; 249 | $fa-var-github-alt: "\f113"; 250 | $fa-var-github-square: "\f092"; 251 | $fa-var-gittip: "\f184"; 252 | $fa-var-glass: "\f000"; 253 | $fa-var-globe: "\f0ac"; 254 | $fa-var-google: "\f1a0"; 255 | $fa-var-google-plus: "\f0d5"; 256 | $fa-var-google-plus-square: "\f0d4"; 257 | $fa-var-google-wallet: "\f1ee"; 258 | $fa-var-graduation-cap: "\f19d"; 259 | $fa-var-group: "\f0c0"; 260 | $fa-var-h-square: "\f0fd"; 261 | $fa-var-hacker-news: "\f1d4"; 262 | $fa-var-hand-o-down: "\f0a7"; 263 | $fa-var-hand-o-left: "\f0a5"; 264 | $fa-var-hand-o-right: "\f0a4"; 265 | $fa-var-hand-o-up: "\f0a6"; 266 | $fa-var-hdd-o: "\f0a0"; 267 | $fa-var-header: "\f1dc"; 268 | $fa-var-headphones: "\f025"; 269 | $fa-var-heart: "\f004"; 270 | $fa-var-heart-o: "\f08a"; 271 | $fa-var-history: "\f1da"; 272 | $fa-var-home: "\f015"; 273 | $fa-var-hospital-o: "\f0f8"; 274 | $fa-var-html5: "\f13b"; 275 | $fa-var-ils: "\f20b"; 276 | $fa-var-image: "\f03e"; 277 | $fa-var-inbox: "\f01c"; 278 | $fa-var-indent: "\f03c"; 279 | $fa-var-info: "\f129"; 280 | $fa-var-info-circle: "\f05a"; 281 | $fa-var-inr: "\f156"; 282 | $fa-var-instagram: "\f16d"; 283 | $fa-var-institution: "\f19c"; 284 | $fa-var-ioxhost: "\f208"; 285 | $fa-var-italic: "\f033"; 286 | $fa-var-joomla: "\f1aa"; 287 | $fa-var-jpy: "\f157"; 288 | $fa-var-jsfiddle: "\f1cc"; 289 | $fa-var-key: "\f084"; 290 | $fa-var-keyboard-o: "\f11c"; 291 | $fa-var-krw: "\f159"; 292 | $fa-var-language: "\f1ab"; 293 | $fa-var-laptop: "\f109"; 294 | $fa-var-lastfm: "\f202"; 295 | $fa-var-lastfm-square: "\f203"; 296 | $fa-var-leaf: "\f06c"; 297 | $fa-var-legal: "\f0e3"; 298 | $fa-var-lemon-o: "\f094"; 299 | $fa-var-level-down: "\f149"; 300 | $fa-var-level-up: "\f148"; 301 | $fa-var-life-bouy: "\f1cd"; 302 | $fa-var-life-buoy: "\f1cd"; 303 | $fa-var-life-ring: "\f1cd"; 304 | $fa-var-life-saver: "\f1cd"; 305 | $fa-var-lightbulb-o: "\f0eb"; 306 | $fa-var-line-chart: "\f201"; 307 | $fa-var-link: "\f0c1"; 308 | $fa-var-linkedin: "\f0e1"; 309 | $fa-var-linkedin-square: "\f08c"; 310 | $fa-var-linux: "\f17c"; 311 | $fa-var-list: "\f03a"; 312 | $fa-var-list-alt: "\f022"; 313 | $fa-var-list-ol: "\f0cb"; 314 | $fa-var-list-ul: "\f0ca"; 315 | $fa-var-location-arrow: "\f124"; 316 | $fa-var-lock: "\f023"; 317 | $fa-var-long-arrow-down: "\f175"; 318 | $fa-var-long-arrow-left: "\f177"; 319 | $fa-var-long-arrow-right: "\f178"; 320 | $fa-var-long-arrow-up: "\f176"; 321 | $fa-var-magic: "\f0d0"; 322 | $fa-var-magnet: "\f076"; 323 | $fa-var-mail-forward: "\f064"; 324 | $fa-var-mail-reply: "\f112"; 325 | $fa-var-mail-reply-all: "\f122"; 326 | $fa-var-male: "\f183"; 327 | $fa-var-map-marker: "\f041"; 328 | $fa-var-maxcdn: "\f136"; 329 | $fa-var-meanpath: "\f20c"; 330 | $fa-var-medkit: "\f0fa"; 331 | $fa-var-meh-o: "\f11a"; 332 | $fa-var-microphone: "\f130"; 333 | $fa-var-microphone-slash: "\f131"; 334 | $fa-var-minus: "\f068"; 335 | $fa-var-minus-circle: "\f056"; 336 | $fa-var-minus-square: "\f146"; 337 | $fa-var-minus-square-o: "\f147"; 338 | $fa-var-mobile: "\f10b"; 339 | $fa-var-mobile-phone: "\f10b"; 340 | $fa-var-money: "\f0d6"; 341 | $fa-var-moon-o: "\f186"; 342 | $fa-var-mortar-board: "\f19d"; 343 | $fa-var-music: "\f001"; 344 | $fa-var-navicon: "\f0c9"; 345 | $fa-var-newspaper-o: "\f1ea"; 346 | $fa-var-openid: "\f19b"; 347 | $fa-var-outdent: "\f03b"; 348 | $fa-var-pagelines: "\f18c"; 349 | $fa-var-paint-brush: "\f1fc"; 350 | $fa-var-paper-plane: "\f1d8"; 351 | $fa-var-paper-plane-o: "\f1d9"; 352 | $fa-var-paperclip: "\f0c6"; 353 | $fa-var-paragraph: "\f1dd"; 354 | $fa-var-paste: "\f0ea"; 355 | $fa-var-pause: "\f04c"; 356 | $fa-var-paw: "\f1b0"; 357 | $fa-var-paypal: "\f1ed"; 358 | $fa-var-pencil: "\f040"; 359 | $fa-var-pencil-square: "\f14b"; 360 | $fa-var-pencil-square-o: "\f044"; 361 | $fa-var-phone: "\f095"; 362 | $fa-var-phone-square: "\f098"; 363 | $fa-var-photo: "\f03e"; 364 | $fa-var-picture-o: "\f03e"; 365 | $fa-var-pie-chart: "\f200"; 366 | $fa-var-pied-piper: "\f1a7"; 367 | $fa-var-pied-piper-alt: "\f1a8"; 368 | $fa-var-pinterest: "\f0d2"; 369 | $fa-var-pinterest-square: "\f0d3"; 370 | $fa-var-plane: "\f072"; 371 | $fa-var-play: "\f04b"; 372 | $fa-var-play-circle: "\f144"; 373 | $fa-var-play-circle-o: "\f01d"; 374 | $fa-var-plug: "\f1e6"; 375 | $fa-var-plus: "\f067"; 376 | $fa-var-plus-circle: "\f055"; 377 | $fa-var-plus-square: "\f0fe"; 378 | $fa-var-plus-square-o: "\f196"; 379 | $fa-var-power-off: "\f011"; 380 | $fa-var-print: "\f02f"; 381 | $fa-var-puzzle-piece: "\f12e"; 382 | $fa-var-qq: "\f1d6"; 383 | $fa-var-qrcode: "\f029"; 384 | $fa-var-question: "\f128"; 385 | $fa-var-question-circle: "\f059"; 386 | $fa-var-quote-left: "\f10d"; 387 | $fa-var-quote-right: "\f10e"; 388 | $fa-var-ra: "\f1d0"; 389 | $fa-var-random: "\f074"; 390 | $fa-var-rebel: "\f1d0"; 391 | $fa-var-recycle: "\f1b8"; 392 | $fa-var-reddit: "\f1a1"; 393 | $fa-var-reddit-square: "\f1a2"; 394 | $fa-var-refresh: "\f021"; 395 | $fa-var-remove: "\f00d"; 396 | $fa-var-renren: "\f18b"; 397 | $fa-var-reorder: "\f0c9"; 398 | $fa-var-repeat: "\f01e"; 399 | $fa-var-reply: "\f112"; 400 | $fa-var-reply-all: "\f122"; 401 | $fa-var-retweet: "\f079"; 402 | $fa-var-rmb: "\f157"; 403 | $fa-var-road: "\f018"; 404 | $fa-var-rocket: "\f135"; 405 | $fa-var-rotate-left: "\f0e2"; 406 | $fa-var-rotate-right: "\f01e"; 407 | $fa-var-rouble: "\f158"; 408 | $fa-var-rss: "\f09e"; 409 | $fa-var-rss-square: "\f143"; 410 | $fa-var-rub: "\f158"; 411 | $fa-var-ruble: "\f158"; 412 | $fa-var-rupee: "\f156"; 413 | $fa-var-save: "\f0c7"; 414 | $fa-var-scissors: "\f0c4"; 415 | $fa-var-search: "\f002"; 416 | $fa-var-search-minus: "\f010"; 417 | $fa-var-search-plus: "\f00e"; 418 | $fa-var-send: "\f1d8"; 419 | $fa-var-send-o: "\f1d9"; 420 | $fa-var-share: "\f064"; 421 | $fa-var-share-alt: "\f1e0"; 422 | $fa-var-share-alt-square: "\f1e1"; 423 | $fa-var-share-square: "\f14d"; 424 | $fa-var-share-square-o: "\f045"; 425 | $fa-var-shekel: "\f20b"; 426 | $fa-var-sheqel: "\f20b"; 427 | $fa-var-shield: "\f132"; 428 | $fa-var-shopping-cart: "\f07a"; 429 | $fa-var-sign-in: "\f090"; 430 | $fa-var-sign-out: "\f08b"; 431 | $fa-var-signal: "\f012"; 432 | $fa-var-sitemap: "\f0e8"; 433 | $fa-var-skype: "\f17e"; 434 | $fa-var-slack: "\f198"; 435 | $fa-var-sliders: "\f1de"; 436 | $fa-var-slideshare: "\f1e7"; 437 | $fa-var-smile-o: "\f118"; 438 | $fa-var-soccer-ball-o: "\f1e3"; 439 | $fa-var-sort: "\f0dc"; 440 | $fa-var-sort-alpha-asc: "\f15d"; 441 | $fa-var-sort-alpha-desc: "\f15e"; 442 | $fa-var-sort-amount-asc: "\f160"; 443 | $fa-var-sort-amount-desc: "\f161"; 444 | $fa-var-sort-asc: "\f0de"; 445 | $fa-var-sort-desc: "\f0dd"; 446 | $fa-var-sort-down: "\f0dd"; 447 | $fa-var-sort-numeric-asc: "\f162"; 448 | $fa-var-sort-numeric-desc: "\f163"; 449 | $fa-var-sort-up: "\f0de"; 450 | $fa-var-soundcloud: "\f1be"; 451 | $fa-var-space-shuttle: "\f197"; 452 | $fa-var-spinner: "\f110"; 453 | $fa-var-spoon: "\f1b1"; 454 | $fa-var-spotify: "\f1bc"; 455 | $fa-var-square: "\f0c8"; 456 | $fa-var-square-o: "\f096"; 457 | $fa-var-stack-exchange: "\f18d"; 458 | $fa-var-stack-overflow: "\f16c"; 459 | $fa-var-star: "\f005"; 460 | $fa-var-star-half: "\f089"; 461 | $fa-var-star-half-empty: "\f123"; 462 | $fa-var-star-half-full: "\f123"; 463 | $fa-var-star-half-o: "\f123"; 464 | $fa-var-star-o: "\f006"; 465 | $fa-var-steam: "\f1b6"; 466 | $fa-var-steam-square: "\f1b7"; 467 | $fa-var-step-backward: "\f048"; 468 | $fa-var-step-forward: "\f051"; 469 | $fa-var-stethoscope: "\f0f1"; 470 | $fa-var-stop: "\f04d"; 471 | $fa-var-strikethrough: "\f0cc"; 472 | $fa-var-stumbleupon: "\f1a4"; 473 | $fa-var-stumbleupon-circle: "\f1a3"; 474 | $fa-var-subscript: "\f12c"; 475 | $fa-var-suitcase: "\f0f2"; 476 | $fa-var-sun-o: "\f185"; 477 | $fa-var-superscript: "\f12b"; 478 | $fa-var-support: "\f1cd"; 479 | $fa-var-table: "\f0ce"; 480 | $fa-var-tablet: "\f10a"; 481 | $fa-var-tachometer: "\f0e4"; 482 | $fa-var-tag: "\f02b"; 483 | $fa-var-tags: "\f02c"; 484 | $fa-var-tasks: "\f0ae"; 485 | $fa-var-taxi: "\f1ba"; 486 | $fa-var-tencent-weibo: "\f1d5"; 487 | $fa-var-terminal: "\f120"; 488 | $fa-var-text-height: "\f034"; 489 | $fa-var-text-width: "\f035"; 490 | $fa-var-th: "\f00a"; 491 | $fa-var-th-large: "\f009"; 492 | $fa-var-th-list: "\f00b"; 493 | $fa-var-thumb-tack: "\f08d"; 494 | $fa-var-thumbs-down: "\f165"; 495 | $fa-var-thumbs-o-down: "\f088"; 496 | $fa-var-thumbs-o-up: "\f087"; 497 | $fa-var-thumbs-up: "\f164"; 498 | $fa-var-ticket: "\f145"; 499 | $fa-var-times: "\f00d"; 500 | $fa-var-times-circle: "\f057"; 501 | $fa-var-times-circle-o: "\f05c"; 502 | $fa-var-tint: "\f043"; 503 | $fa-var-toggle-down: "\f150"; 504 | $fa-var-toggle-left: "\f191"; 505 | $fa-var-toggle-off: "\f204"; 506 | $fa-var-toggle-on: "\f205"; 507 | $fa-var-toggle-right: "\f152"; 508 | $fa-var-toggle-up: "\f151"; 509 | $fa-var-trash: "\f1f8"; 510 | $fa-var-trash-o: "\f014"; 511 | $fa-var-tree: "\f1bb"; 512 | $fa-var-trello: "\f181"; 513 | $fa-var-trophy: "\f091"; 514 | $fa-var-truck: "\f0d1"; 515 | $fa-var-try: "\f195"; 516 | $fa-var-tty: "\f1e4"; 517 | $fa-var-tumblr: "\f173"; 518 | $fa-var-tumblr-square: "\f174"; 519 | $fa-var-turkish-lira: "\f195"; 520 | $fa-var-twitch: "\f1e8"; 521 | $fa-var-twitter: "\f099"; 522 | $fa-var-twitter-square: "\f081"; 523 | $fa-var-umbrella: "\f0e9"; 524 | $fa-var-underline: "\f0cd"; 525 | $fa-var-undo: "\f0e2"; 526 | $fa-var-university: "\f19c"; 527 | $fa-var-unlink: "\f127"; 528 | $fa-var-unlock: "\f09c"; 529 | $fa-var-unlock-alt: "\f13e"; 530 | $fa-var-unsorted: "\f0dc"; 531 | $fa-var-upload: "\f093"; 532 | $fa-var-usd: "\f155"; 533 | $fa-var-user: "\f007"; 534 | $fa-var-user-md: "\f0f0"; 535 | $fa-var-users: "\f0c0"; 536 | $fa-var-video-camera: "\f03d"; 537 | $fa-var-vimeo-square: "\f194"; 538 | $fa-var-vine: "\f1ca"; 539 | $fa-var-vk: "\f189"; 540 | $fa-var-volume-down: "\f027"; 541 | $fa-var-volume-off: "\f026"; 542 | $fa-var-volume-up: "\f028"; 543 | $fa-var-warning: "\f071"; 544 | $fa-var-wechat: "\f1d7"; 545 | $fa-var-weibo: "\f18a"; 546 | $fa-var-weixin: "\f1d7"; 547 | $fa-var-wheelchair: "\f193"; 548 | $fa-var-wifi: "\f1eb"; 549 | $fa-var-windows: "\f17a"; 550 | $fa-var-won: "\f159"; 551 | $fa-var-wordpress: "\f19a"; 552 | $fa-var-wrench: "\f0ad"; 553 | $fa-var-xing: "\f168"; 554 | $fa-var-xing-square: "\f169"; 555 | $fa-var-yahoo: "\f19e"; 556 | $fa-var-yelp: "\f1e9"; 557 | $fa-var-yen: "\f157"; 558 | $fa-var-youtube: "\f167"; 559 | $fa-var-youtube-play: "\f16a"; 560 | $fa-var-youtube-square: "\f166"; 561 | 562 | -------------------------------------------------------------------------------- /static/font-awesome/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "spinning"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | -------------------------------------------------------------------------------- /static/img/frontpage/mt-fuji-477832_1280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/static/img/frontpage/mt-fuji-477832_1280.jpg -------------------------------------------------------------------------------- /static/js/jquery.hotkeys.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true*/ 2 | /*jslint jquery: true*/ 3 | 4 | /* 5 | * jQuery Hotkeys Plugin 6 | * Copyright 2010, John Resig 7 | * Dual licensed under the MIT or GPL Version 2 licenses. 8 | * 9 | * Based upon the plugin by Tzury Bar Yochay: 10 | * http://github.com/tzuryby/hotkeys 11 | * 12 | * Original idea by: 13 | * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ 14 | */ 15 | 16 | /* 17 | * One small change is: now keys are passed by object { keys: '...' } 18 | * Might be useful, when you want to pass some other data to your handler 19 | */ 20 | 21 | (function(jQuery) { 22 | 23 | jQuery.hotkeys = { 24 | version: "0.8", 25 | 26 | specialKeys: { 27 | 8: "backspace", 28 | 9: "tab", 29 | 10: "return", 30 | 13: "return", 31 | 16: "shift", 32 | 17: "ctrl", 33 | 18: "alt", 34 | 19: "pause", 35 | 20: "capslock", 36 | 27: "esc", 37 | 32: "space", 38 | 33: "pageup", 39 | 34: "pagedown", 40 | 35: "end", 41 | 36: "home", 42 | 37: "left", 43 | 38: "up", 44 | 39: "right", 45 | 40: "down", 46 | 45: "insert", 47 | 46: "del", 48 | 59: ";", 49 | 61: "=", 50 | 96: "0", 51 | 97: "1", 52 | 98: "2", 53 | 99: "3", 54 | 100: "4", 55 | 101: "5", 56 | 102: "6", 57 | 103: "7", 58 | 104: "8", 59 | 105: "9", 60 | 106: "*", 61 | 107: "+", 62 | 109: "-", 63 | 110: ".", 64 | 111: "/", 65 | 112: "f1", 66 | 113: "f2", 67 | 114: "f3", 68 | 115: "f4", 69 | 116: "f5", 70 | 117: "f6", 71 | 118: "f7", 72 | 119: "f8", 73 | 120: "f9", 74 | 121: "f10", 75 | 122: "f11", 76 | 123: "f12", 77 | 144: "numlock", 78 | 145: "scroll", 79 | 173: "-", 80 | 186: ";", 81 | 187: "=", 82 | 188: ",", 83 | 189: "-", 84 | 190: ".", 85 | 191: "/", 86 | 192: "`", 87 | 219: "[", 88 | 220: "\\", 89 | 221: "]", 90 | 222: "'" 91 | }, 92 | 93 | shiftNums: { 94 | "`": "~", 95 | "1": "!", 96 | "2": "@", 97 | "3": "#", 98 | "4": "$", 99 | "5": "%", 100 | "6": "^", 101 | "7": "&", 102 | "8": "*", 103 | "9": "(", 104 | "0": ")", 105 | "-": "_", 106 | "=": "+", 107 | ";": ": ", 108 | "'": "\"", 109 | ",": "<", 110 | ".": ">", 111 | "/": "?", 112 | "\\": "|" 113 | }, 114 | 115 | // excludes: button, checkbox, file, hidden, image, password, radio, reset, search, submit, url 116 | textAcceptingInputTypes: [ 117 | "text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", 118 | "datetime-local", "search", "color", "tel"], 119 | 120 | options: { 121 | filterTextInputs: true 122 | } 123 | }; 124 | 125 | function keyHandler(handleObj) { 126 | if (typeof handleObj.data === "string") { 127 | handleObj.data = { 128 | keys: handleObj.data 129 | }; 130 | } 131 | 132 | // Only care when a possible input has been specified 133 | if (!handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string") { 134 | return; 135 | } 136 | 137 | var origHandler = handleObj.handler, 138 | keys = handleObj.data.keys.toLowerCase().split(" "); 139 | 140 | handleObj.handler = function(event) { 141 | // Don't fire in text-accepting inputs that we didn't directly bind to 142 | if (this !== event.target && (/textarea|select/i.test(event.target.nodeName) || 143 | (jQuery.hotkeys.options.filterTextInputs && 144 | jQuery.inArray(event.target.type, jQuery.hotkeys.textAcceptingInputTypes) > -1))) { 145 | return; 146 | } 147 | 148 | var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[event.which], 149 | character = String.fromCharCode(event.which).toLowerCase(), 150 | modif = "", 151 | possible = {}; 152 | 153 | jQuery.each(["alt", "ctrl", "shift"], function(index, specialKey) { 154 | 155 | if (event[specialKey + 'Key'] && special !== specialKey) { 156 | modif += specialKey + '+'; 157 | } 158 | }); 159 | 160 | // metaKey is triggered off ctrlKey erronously 161 | if (event.metaKey && !event.ctrlKey && special !== "meta") { 162 | modif += "meta+"; 163 | } 164 | 165 | if (event.metaKey && special !== "meta" && modif.indexOf("alt+ctrl+shift+") > -1) { 166 | modif = modif.replace("alt+ctrl+shift+", "hyper+"); 167 | } 168 | 169 | if (special) { 170 | possible[modif + special] = true; 171 | } 172 | else { 173 | possible[modif + character] = true; 174 | possible[modif + jQuery.hotkeys.shiftNums[character]] = true; 175 | 176 | // "$" can be triggered as "Shift+4" or "Shift+$" or just "$" 177 | if (modif === "shift+") { 178 | possible[jQuery.hotkeys.shiftNums[character]] = true; 179 | } 180 | } 181 | 182 | for (var i = 0, l = keys.length; i < l; i++) { 183 | if (possible[keys[i]]) { 184 | return origHandler.apply(this, arguments); 185 | } 186 | } 187 | }; 188 | } 189 | 190 | jQuery.each(["keydown", "keyup", "keypress"], function() { 191 | jQuery.event.special[this] = { 192 | add: keyHandler 193 | }; 194 | }); 195 | 196 | })(jQuery || this.jQuery || window.jQuery); 197 | -------------------------------------------------------------------------------- /tickets/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suenkler/django-tickets/6394e234e5909dd8c0f5f6e4cdd8827e0c25c06a/tickets/__init__.py -------------------------------------------------------------------------------- /tickets/settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 4 | import os 5 | import socket 6 | # request.path in templates: 7 | from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP 8 | 9 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 10 | 11 | SECRET_KEY = os.environ["DJANGO_SECRET_KEY"] 12 | 13 | if socket.gethostname() == os.environ["DJANGO_PRODUCTION_DOMAIN"]: 14 | DEBUG = False 15 | TEMPLATE_DEBUG = False 16 | ALLOWED_HOSTS = ['*'] 17 | # SSL/HTTPS 18 | SESSION_COOKIE_SECURE = True 19 | CSRF_COOKIE_SECURE = True 20 | else: 21 | DEBUG = True 22 | TEMPLATE_DEBUG = True 23 | 24 | # Application definition 25 | 26 | INSTALLED_APPS = ( 27 | 'django.contrib.admin', 28 | 'django.contrib.auth', 29 | 'django.contrib.contenttypes', 30 | 'django.contrib.sessions', 31 | 'django.contrib.messages', 32 | 'django.contrib.staticfiles', 33 | 'crispy_forms', 34 | 'main', 35 | ) 36 | 37 | TEMPLATE_CONTEXT_PROCESSORS = TCP + ( 38 | 'django.core.context_processors.request', 39 | ) 40 | 41 | MIDDLEWARE_CLASSES = ( 42 | 'django.contrib.sessions.middleware.SessionMiddleware', 43 | 'django.middleware.common.CommonMiddleware', 44 | 'django.middleware.csrf.CsrfViewMiddleware', 45 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 46 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 47 | 'django.contrib.messages.middleware.MessageMiddleware', 48 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 49 | ) 50 | 51 | ROOT_URLCONF = 'tickets.urls' 52 | 53 | WSGI_APPLICATION = 'tickets.wsgi.application' 54 | 55 | # Database 56 | 57 | DATABASES = { 58 | 'default': { 59 | 'ENGINE': 'django.db.backends.sqlite3', 60 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 61 | } 62 | } 63 | 64 | # Internationalization 65 | 66 | LANGUAGE_CODE = 'en-us' 67 | 68 | TIME_ZONE = 'Europe/Berlin' 69 | 70 | USE_I18N = True 71 | 72 | USE_L10N = True 73 | 74 | USE_TZ = True 75 | 76 | # Static files (CSS, JavaScript, Images) 77 | 78 | STATIC_URL = '/static/' 79 | STATIC_ROOT = os.environ["DJANGO_STATIC_ROOT"] 80 | 81 | STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'), ) 82 | 83 | MEDIA_URL = '/media/' 84 | MEDIA_ROOT = os.environ["DJANGO_MEDIA_ROOT"] 85 | 86 | # On login do not redirect to "/accounts/profile/" but "/inbox/" 87 | LOGIN_REDIRECT_URL = "/inbox/" 88 | 89 | # in urls.py the function "logout_then_login" is used to log out 90 | # changing the default value from "/accounts/login/" to "/" 91 | LOGIN_URL = "/" 92 | 93 | # Django Crispy Forms 94 | CRISPY_TEMPLATE_PACK = 'bootstrap3' 95 | 96 | # Define who gets code error notifications. 97 | # When DEBUG=False and a view raises an exception, 98 | # Django will email these people with the full exception information. 99 | ADMINS = ((os.environ["DJANGO_ADMIN_NAME"], 100 | os.environ["DJANGO_ADMIN_EMAIL"]), ) 101 | 102 | # Specifies who should get broken link notifications when 103 | # BrokenLinkEmailsMiddleware is enabled. 104 | MANAGERS = ((os.environ["DJANGO_ADMIN_NAME"], 105 | os.environ["DJANGO_ADMIN_EMAIL"]), ) 106 | 107 | # Email delivery to local Postfix-Installation 108 | EMAIL_HOST = os.environ["DJANGO_EMAIL_HOST"] 109 | EMAIL_HOST_USER = os.environ["DJANGO_EMAIL_HOST_USER"] 110 | EMAIL_HOST_PASSWORD = os.environ["DJANGO_EMAIL_HOST_PASSWORD"] 111 | 112 | # Logging 113 | LOGGING = { 114 | 'version': 1, 115 | 'disable_existing_loggers': False, 116 | 'formatters': { 117 | 'verbose': { 118 | 'format': "[%(asctime)s] %(levelname)s \ 119 | [%(name)s:%(lineno)s] %(message)s", 120 | 'datefmt': "%d/%b/%Y %H:%M:%S" 121 | }, 122 | 'simple': { 123 | 'format': '%(levelname)s %(message)s' 124 | }, 125 | }, 126 | 'handlers': { 127 | 'file': { 128 | 'level': 'INFO', 129 | 'class': 'logging.FileHandler', 130 | 'filename': os.environ["DJANGO_LOG_FILE"], 131 | 'formatter': 'verbose' 132 | }, 133 | 'mail_admins': { 134 | 'level': 'ERROR', 135 | 'class': 'django.utils.log.AdminEmailHandler', 136 | } 137 | }, 138 | 'loggers': { 139 | 'django': { 140 | 'handlers': ['file'], 141 | 'propagate': True, 142 | 'level': 'INFO', 143 | }, 144 | 'django.request': { 145 | 'handlers': ['mail_admins'], 146 | 'level': 'ERROR', 147 | 'propagate': False, 148 | }, 149 | 'main': { 150 | 'handlers': ['file'], 151 | 'level': 'INFO', 152 | }, 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /tickets/urls.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.conf.urls import patterns, include, url 4 | from django.contrib import admin 5 | 6 | import main.views 7 | from django.contrib.auth.decorators import login_required 8 | 9 | # to include media files at the end 10 | from django.conf import settings 11 | from django.conf.urls.static import static 12 | 13 | urlpatterns = patterns( 14 | '', 15 | 16 | # Login and settings pages 17 | url(r'^$', 'django.contrib.auth.views.login'), 18 | 19 | url(r'^logout/$', 'django.contrib.auth.views.logout_then_login'), 20 | 21 | url(r'^settings/$', 22 | login_required(main.views.usersettings_update_view), 23 | name='user-settings'), 24 | 25 | # Django admin 26 | url(r'^admin/', include(admin.site.urls)), 27 | 28 | # create new ticket 29 | url(r'^ticket/new/$', 30 | login_required(main.views.ticket_create_view), 31 | name='ticket_new'), 32 | 33 | # edit ticket 34 | url(r'^ticket/edit/(?P\d+)/$', 35 | login_required(main.views.ticket_edit_view), 36 | name='ticket_edit'), 37 | 38 | # view ticket 39 | url(r'^ticket/(?P\d+)/$', 40 | login_required(main.views.ticket_detail_view), 41 | name='ticket_detail'), 42 | 43 | # create new followup 44 | url(r'^followup/new/$', 45 | login_required(main.views.followup_create_view), 46 | name='followup_new'), 47 | 48 | # edit followup 49 | url(r'^followup/edit/(?P\d+)/$', 50 | login_required(main.views.followup_edit_view), 51 | name='followup_edit'), 52 | 53 | # create new attachment 54 | url(r'^attachment/new/$', 55 | login_required(main.views.attachment_create_view), 56 | name='attachment_new'), 57 | 58 | # ticket overviews 59 | url(r'^inbox/$', 60 | login_required(main.views.inbox_view), 61 | name='inbox'), 62 | 63 | url(r'^my-tickets/$', 64 | login_required(main.views.my_tickets_view), 65 | name='my-tickets'), 66 | 67 | url(r'^all-tickets/$', 68 | login_required(main.views.all_tickets_view), 69 | name='all-tickets'), 70 | 71 | url(r'^archive/$', 72 | login_required(main.views.archive_view), 73 | name='archive'), 74 | 75 | ) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 76 | -------------------------------------------------------------------------------- /tickets/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for tickets project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tickets.settings") 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | application = get_wsgi_application() 15 | --------------------------------------------------------------------------------