├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── media_cdn ├── 2 │ ├── Screen_Shot_2016-01-10_at_4.51.14_PM.png │ └── Screen_Shot_2016-01-10_at_4.51.14_PM_c9ifrfF.png ├── 11 │ └── try_django_19_1_of_38.png ├── 14 │ └── Screen_Shot_2016-01-10_at_4.51.14_PM.png └── None │ ├── car.jpg │ ├── car_7py0UuC.jpg │ ├── car_GtgVSbO.jpg │ ├── car_HAuHK9u.jpg │ ├── car_HwaoHbO.jpg │ ├── car_NXoNUde.jpg │ ├── car_Q0HUqw8.jpg │ ├── car_QRSz8Zw.jpg │ ├── car_QlSvxHz.jpg │ ├── car_TyQAwKk.jpg │ ├── car_UvnCCMP.jpg │ ├── car_WxmqsOG.jpg │ ├── car_eK6dnfp.jpg │ ├── car_jJqtDJp.jpg │ ├── car_kbhlfRu.jpg │ ├── car_l8DNbMR.jpg │ ├── car_lFiHy6u.jpg │ └── car_nlzOnm3.jpg ├── requirements.txt ├── src ├── .DS_Store ├── crud.md ├── db.sqlite3 ├── manage.py ├── posts │ ├── .DS_Store │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── .DS_Store │ │ ├── 0001_initial.py │ │ ├── 0002_post_user.py │ │ ├── 0003_auto_20160105_2205.py │ │ └── __init__.py │ ├── models.py │ ├── templatetags │ │ ├── __init__.py │ │ └── urlify.py │ ├── tests.py │ ├── urls.py │ ├── utils.py │ └── views.py ├── static │ └── css │ │ └── base.css ├── templates │ ├── base.html │ ├── messages_display.html │ ├── post_detail.html │ ├── post_form.html │ └── post_list.html └── trydjango19 │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── static_cdn ├── admin │ ├── css │ │ ├── base.css │ │ ├── changelists.css │ │ ├── dashboard.css │ │ ├── fonts.css │ │ ├── forms.css │ │ ├── login.css │ │ ├── rtl.css │ │ └── widgets.css │ ├── fonts │ │ ├── LICENSE.txt │ │ ├── README.txt │ │ ├── Roboto-Bold-webfont.woff │ │ ├── Roboto-Light-webfont.woff │ │ └── Roboto-Regular-webfont.woff │ ├── img │ │ ├── LICENSE │ │ ├── README.txt │ │ ├── calendar-icons.svg │ │ ├── gis │ │ │ ├── move_vertex_off.svg │ │ │ └── move_vertex_on.svg │ │ ├── icon-addlink.svg │ │ ├── icon-alert.svg │ │ ├── icon-calendar.svg │ │ ├── icon-changelink.svg │ │ ├── icon-clock.svg │ │ ├── icon-deletelink.svg │ │ ├── icon-no.svg │ │ ├── icon-unknown-alt.svg │ │ ├── icon-unknown.svg │ │ ├── icon-yes.svg │ │ ├── inline-delete.svg │ │ ├── search.svg │ │ ├── selector-icons.svg │ │ ├── sorting-icons.svg │ │ ├── tooltag-add.svg │ │ └── tooltag-arrowright.svg │ └── js │ │ ├── SelectBox.js │ │ ├── SelectFilter2.js │ │ ├── actions.js │ │ ├── actions.min.js │ │ ├── admin │ │ ├── DateTimeShortcuts.js │ │ └── RelatedObjectLookups.js │ │ ├── calendar.js │ │ ├── collapse.js │ │ ├── collapse.min.js │ │ ├── core.js │ │ ├── inlines.js │ │ ├── inlines.min.js │ │ ├── jquery.init.js │ │ ├── prepopulate.js │ │ ├── prepopulate.min.js │ │ ├── timeparse.js │ │ ├── urlify.js │ │ └── vendor │ │ ├── jquery │ │ ├── LICENSE-JQUERY.txt │ │ ├── jquery.js │ │ └── jquery.min.js │ │ └── xregexp │ │ ├── LICENSE-XREGEXP.txt │ │ └── xregexp.min.js └── css │ └── base.css ├── trydjango19.sublime-project └── trydjango19.sublime-workspace /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | include/ 3 | lib/ 4 | pip-selfcheck.json 5 | 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | env/ 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *,cover 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | 58 | # Sphinx documentation 59 | docs/_build/ 60 | 61 | # PyBuilder 62 | target/ 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Coding For Entrepreneurs 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Try Django 1.9 Logo](https://cfe-static.s3.amazonaws.com/media/try-django-19/images/try_django_19.png) 2 | 3 | # Try Django 1.9 4 | 5 | Try Django 1.9 is an introduction to Django version 1.9 by creating a simple, yet robust, Django blog. This series covers a variety of Django basics as well as Django 1.9 specific material. Created by Team CFE @ http://joincfe.com. 6 | 7 | The tutorial videos are available on our [YouTube channel](http://joincfe.com/youtube) and ad-free on [Coding for Entrepreneurs](http://joincfe.com/projects/). 8 | 9 | Subscribe to our [YouTube Channel]() 10 | 11 | Thanks for watching! 12 | 13 | Team CFE 14 | 15 | 16 | ## Lecture Code 17 | The tutorial code below is the final code from the end of each tutorial video. Each link below is tied directly to the tutorial's title. Please note that some videos will not have code reference code. 18 | 19 | [4 - Versions & Install](../../tree/31fdd791b674e329369de3557432805d8d14d4b9) 20 | 21 | [5 - Superuser & Admin](../../tree/2424c5b052a7adb4f9400d283c9ead1414b6449e) 22 | 23 | [6 - First App & Model](../../tree/10e740127a6c8f9f72ed767aca3550bc7b39bb5c) 24 | 25 | [7 - Model to Admin](../../tree/2ef2adb7e6359fad3591b3cae93759fc98a3b49c) 26 | 27 | [8 - Customize Admin](../../tree/085b103837a7b596343e65bac794d437a5c51285) 28 | 29 | [9 - CRUD](../../tree/1c181ed0295971379a411e681f12dcb8dc167998) 30 | 31 | [10 - Writing our first View](../../tree/40bd59132892e4fefabd00cf536a33670c6de859) 32 | 33 | [12 - Mapping URLs to Views](../../tree/f60287df9e375edb1cc4fb87e565a6c0c226b676) 34 | 35 | [13 - In App URLs](../../tree/3518441f53779a5f0c1e3bae006b025b8320c791) 36 | 37 | [14 - Django Templates](../../tree/2922ecbe05b32df227e51238581f35989f1863f0) 38 | 39 | [15 - Template Context](../../tree/30aaebb3e9cff8e81be18da0c82ee3ea3489348d) 40 | 41 | [16 - QuerySet Basics](../../tree/4ea20b6d10f18845fefdf284d7cd190bfeac1f72) 42 | 43 | [17 - Get Item or 404 Query](../../tree/4b2c3a5b5ad0d66c65685dba51dea776dd48f08a) 44 | 45 | [18 - Dyanmic Url Routing & Patterns](../../tree/c05ef6fdb86c42f14dda608bd2f732ed5a81e454) 46 | 47 | [19 - URL Links & Get Absolute URL](../../tree/42d795ec9878d121da3011233c3a53792fb1efea) 48 | 49 | [20 - Model Form & Create View](../../tree/5595f5717ff9967abdb3bd5060a625c52410d16c) 50 | 51 | [21 - Instance Update View](../../tree/34d887aee14e98f363eb9b2d2f82e62622945851) 52 | 53 | [22 - Django Messages Framework](../../tree/49d23b328799ffc6c858253a21e4b3298d18a620) 54 | 55 | [23 - Delete View](../../tree/754e4d86fb3682be3cd77fd99592cdb16b186f8e) 56 | 57 | [24 - Templates & Inheritance](../../tree/a581cf1ea920794b04117c15ed4d695abebcd555) 58 | 59 | [25 - Setup Static Files - CSS - Javascript - Images in Django](../../tree/adcc96bb9e014a948ed86d1ae43243deb6565b08) 60 | 61 | [26 - Implment Bootstrap](../../tree/c6455a94391723caa306fbfccfac50a761e79cea) 62 | 63 | [27 - Pagination by QuerySet](../../tree/23d29efefefd3124b9beca80e1307570c7239741) 64 | 65 | [28 - File Uploads with FileField and ImageField](../../tree/a4fc0f83cc01b14272bb762bcc7df4a3768ea0f3) 66 | 67 | [29 - SlugField](../../tree/a701914c7a1bd677fd7e8905bb44d2bcf1a26794) 68 | 69 | [30 - Social Share Links](../../tree/711e883a61a6067e9d3f533c43bcca9dcf72e606) 70 | 71 | [31 - Custom Template Tag](../../tree/a168e8549fa8eb1b00ddcc11d1d735872cbf8810) 72 | 73 | [32 - Basic User Permissions](../../tree/be179a0936c3676d61385075900fd5bfbc4ae391) 74 | 75 | [33 - Associate User to Post with a Foreign Key](../../tree/87773b59e475a40861b306d350ae5292b349e633) 76 | 77 | [34 - Using Facebook Comments](../../tree/00bb8c91b639ed73e59b0f4926f757d04b14cf77) 78 | 79 | [35 - Item Publish Date & Draft](../../tree/3219e78ab1d38f3c90a65f9bfc3155d224237835) 80 | 81 | [36 - Model Managers & Handling Drafts](../../tree/f3038795c8145476262258b0b6db6f11b9dd7bca) 82 | 83 | [37 - Search Posts](../../tree/2e140665355611a54725eb9804655de6ae6276e7) 84 | 85 | [Final Try Django 1.8 Code](../../tree/2e140665355611a54725eb9804655de6ae6276e7) 86 | 87 | 88 | -------------------------------------------------------------------------------- /media_cdn/11/try_django_19_1_of_38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/11/try_django_19_1_of_38.png -------------------------------------------------------------------------------- /media_cdn/14/Screen_Shot_2016-01-10_at_4.51.14_PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/14/Screen_Shot_2016-01-10_at_4.51.14_PM.png -------------------------------------------------------------------------------- /media_cdn/2/Screen_Shot_2016-01-10_at_4.51.14_PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/2/Screen_Shot_2016-01-10_at_4.51.14_PM.png -------------------------------------------------------------------------------- /media_cdn/2/Screen_Shot_2016-01-10_at_4.51.14_PM_c9ifrfF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/2/Screen_Shot_2016-01-10_at_4.51.14_PM_c9ifrfF.png -------------------------------------------------------------------------------- /media_cdn/None/car.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_7py0UuC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_7py0UuC.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_GtgVSbO.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_GtgVSbO.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_HAuHK9u.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_HAuHK9u.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_HwaoHbO.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_HwaoHbO.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_NXoNUde.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_NXoNUde.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_Q0HUqw8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_Q0HUqw8.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_QRSz8Zw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_QRSz8Zw.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_QlSvxHz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_QlSvxHz.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_TyQAwKk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_TyQAwKk.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_UvnCCMP.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_UvnCCMP.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_WxmqsOG.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_WxmqsOG.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_eK6dnfp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_eK6dnfp.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_jJqtDJp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_jJqtDJp.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_kbhlfRu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_kbhlfRu.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_l8DNbMR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_l8DNbMR.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_lFiHy6u.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_lFiHy6u.jpg -------------------------------------------------------------------------------- /media_cdn/None/car_nlzOnm3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/media_cdn/None/car_nlzOnm3.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==1.9 2 | Pillow==3.1.0 3 | wheel==0.24.0 4 | -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/src/.DS_Store -------------------------------------------------------------------------------- /src/crud.md: -------------------------------------------------------------------------------- 1 | CREATE -- POST -- Make New 2 | RETRIEVE -- GET -- List / Search 3 | UPDATE -- PUT/PATCH -- Edit 4 | DELETE -- DELETE -- Delete 5 | 6 | -------------------------------------------------------------------------------- /src/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/src/db.sqlite3 -------------------------------------------------------------------------------- /src/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", "trydjango19.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /src/posts/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/src/posts/.DS_Store -------------------------------------------------------------------------------- /src/posts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/src/posts/__init__.py -------------------------------------------------------------------------------- /src/posts/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | from .models import Post 5 | 6 | class PostModelAdmin(admin.ModelAdmin): 7 | list_display = ["title", "updated", "timestamp"] 8 | list_display_links = ["updated"] 9 | list_editable = ["title"] 10 | list_filter = ["updated", "timestamp"] 11 | 12 | search_fields = ["title", "content"] 13 | class Meta: 14 | model = Post 15 | 16 | 17 | admin.site.register(Post, PostModelAdmin) -------------------------------------------------------------------------------- /src/posts/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PostsConfig(AppConfig): 5 | name = 'posts' 6 | -------------------------------------------------------------------------------- /src/posts/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | 4 | from .models import Post 5 | 6 | 7 | class PostForm(forms.ModelForm): 8 | class Meta: 9 | model = Post 10 | fields = [ 11 | "title", 12 | "content", 13 | "image", 14 | "draft", 15 | "publish", 16 | ] -------------------------------------------------------------------------------- /src/posts/migrations/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/src/posts/migrations/.DS_Store -------------------------------------------------------------------------------- /src/posts/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9 on 2016-01-05 01:12 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import posts.models 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Post', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('title', models.CharField(max_length=120)), 22 | ('slug', models.SlugField(unique=True)), 23 | ('image', models.ImageField(blank=True, height_field='height_field', null=True, upload_to=posts.models.upload_location, width_field='width_field')), 24 | ('height_field', models.IntegerField(default=0)), 25 | ('width_field', models.IntegerField(default=0)), 26 | ('content', models.TextField()), 27 | ('updated', models.DateTimeField(auto_now=True)), 28 | ('timestamp', models.DateTimeField(auto_now_add=True)), 29 | ], 30 | options={ 31 | 'ordering': ['-timestamp', '-updated'], 32 | }, 33 | ), 34 | ] 35 | -------------------------------------------------------------------------------- /src/posts/migrations/0002_post_user.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9 on 2016-01-05 03:11 3 | from __future__ import unicode_literals 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ('posts', '0001_initial'), 15 | ] 16 | 17 | operations = [ 18 | migrations.AddField( 19 | model_name='post', 20 | name='user', 21 | field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /src/posts/migrations/0003_auto_20160105_2205.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.9 on 2016-01-05 22:05 3 | from __future__ import unicode_literals 4 | 5 | import datetime 6 | from django.db import migrations, models 7 | from django.utils.timezone import utc 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | ('posts', '0002_post_user'), 14 | ] 15 | 16 | operations = [ 17 | migrations.AddField( 18 | model_name='post', 19 | name='draft', 20 | field=models.BooleanField(default=False), 21 | ), 22 | migrations.AddField( 23 | model_name='post', 24 | name='publish', 25 | field=models.DateField(default=datetime.datetime(2016, 1, 5, 22, 5, 13, 37350, tzinfo=utc)), 26 | preserve_default=False, 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /src/posts/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/src/posts/migrations/__init__.py -------------------------------------------------------------------------------- /src/posts/models.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.conf import settings 4 | from django.core.urlresolvers import reverse 5 | from django.db import models 6 | from django.db.models.signals import pre_save 7 | from django.utils import timezone 8 | 9 | from django.utils.text import slugify 10 | # Create your models here. 11 | # MVC MODEL VIEW CONTROLLER 12 | 13 | 14 | #Post.objects.all().published() 15 | #Post.objects.create(user=user, title="Some time") 16 | 17 | class PostQuerySet(models.query.QuerySet): 18 | def not_draft(self): 19 | return self.filter(draft=False) 20 | 21 | def published(self): 22 | return self.filter(publish__lte=timezone.now()).not_draft() 23 | 24 | class PostManager(models.Manager): 25 | def get_queryset(self, *args, **kwargs): 26 | return PostQuerySet(self.model, using=self._db) 27 | 28 | def active(self, *args, **kwargs): 29 | # Post.objects.all() = super(PostManager, self).all() 30 | return self.get_queryset().published() 31 | 32 | 33 | def upload_location(instance, filename): 34 | #filebase, extension = filename.split(".") 35 | #return "%s/%s.%s" %(instance.id, instance.id, extension) 36 | PostModel = instance.__class__ 37 | new_id = PostModel.objects.order_by("id").last().id + 1 38 | """ 39 | instance.__class__ gets the model Post. We must use this method because the model is defined below. 40 | Then create a queryset ordered by the "id"s of each object, 41 | Then we get the last object in the queryset with `.last()` 42 | Which will give us the most recently created Model instance 43 | We add 1 to it, so we get what should be the same id as the the post we are creating. 44 | """ 45 | return "%s/%s" %(new_id, filename) 46 | 47 | class Post(models.Model): 48 | user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1) 49 | title = models.CharField(max_length=120) 50 | slug = models.SlugField(unique=True) 51 | image = models.ImageField(upload_to=upload_location, 52 | null=True, 53 | blank=True, 54 | width_field="width_field", 55 | height_field="height_field") 56 | height_field = models.IntegerField(default=0) 57 | width_field = models.IntegerField(default=0) 58 | content = models.TextField() 59 | draft = models.BooleanField(default=False) 60 | publish = models.DateField(auto_now=False, auto_now_add=False) 61 | updated = models.DateTimeField(auto_now=True, auto_now_add=False) 62 | timestamp = models.DateTimeField(auto_now=False, auto_now_add=True) 63 | 64 | objects = PostManager() 65 | 66 | def __unicode__(self): 67 | return self.title 68 | 69 | def __str__(self): 70 | return self.title 71 | 72 | def get_absolute_url(self): 73 | return reverse("posts:detail", kwargs={"slug": self.slug}) 74 | 75 | class Meta: 76 | ordering = ["-timestamp", "-updated"] 77 | 78 | # @property 79 | # def title(self): 80 | # return "Title" 81 | 82 | 83 | 84 | def create_slug(instance, new_slug=None): 85 | slug = slugify(instance.title) 86 | if new_slug is not None: 87 | slug = new_slug 88 | qs = Post.objects.filter(slug=slug).order_by("-id") 89 | exists = qs.exists() 90 | if exists: 91 | new_slug = "%s-%s" %(slug, qs.first().id) 92 | return create_slug(instance, new_slug=new_slug) 93 | return slug 94 | 95 | 96 | ''' 97 | unique_slug_generator from Django Code Review #2 on joincfe.com/youtube/ 98 | ''' 99 | from .utils import unique_slug_generator 100 | 101 | def pre_save_post_receiver(sender, instance, *args, **kwargs): 102 | if not instance.slug: 103 | # instance.slug = create_slug(instance) 104 | instance.slug = unique_slug_generator(instance) 105 | 106 | 107 | 108 | pre_save.connect(pre_save_post_receiver, sender=Post) 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /src/posts/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/src/posts/templatetags/__init__.py -------------------------------------------------------------------------------- /src/posts/templatetags/urlify.py: -------------------------------------------------------------------------------- 1 | try: 2 | from urllib import quote_plus #python 2 3 | except: 4 | pass 5 | 6 | try: 7 | from urllib.parse import quote_plus #python 3 8 | except: 9 | pass 10 | 11 | 12 | from django import template 13 | 14 | register = template.Library() 15 | 16 | @register.filter 17 | def urlify(value): 18 | return quote_plus(value) 19 | -------------------------------------------------------------------------------- /src/posts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /src/posts/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from django.contrib import admin 3 | 4 | from .views import ( 5 | post_list, 6 | post_create, 7 | post_detail, 8 | post_update, 9 | post_delete, 10 | PostDetailView 11 | ) 12 | 13 | urlpatterns = [ 14 | url(r'^$', post_list, name='list'), 15 | url(r'^create/$', post_create), 16 | #url(r'^(?P[\w-]+)/$', post_detail, name='detail'), 17 | url(r'^(?P[\w-]+)/$', PostDetailView.as_view(), name='detail'), #Django Code Review #3 on joincfe.com/youtube/ 18 | url(r'^(?P[\w-]+)/edit/$', post_update, name='update'), 19 | url(r'^(?P[\w-]+)/delete/$', post_delete), 20 | #url(r'^posts/$', ".views."), 21 | ] 22 | -------------------------------------------------------------------------------- /src/posts/utils.py: -------------------------------------------------------------------------------- 1 | from django.utils.text import slugify 2 | 3 | ''' 4 | random_string_generator is located here: 5 | http://joincfe.com/blog/random-string-generator-in-python/ 6 | ''' 7 | import random 8 | import string 9 | 10 | def random_string_generator(size=10, chars=string.ascii_lowercase + string.digits): 11 | return ''.join(random.choice(chars) for _ in range(size)) 12 | 13 | def unique_slug_generator(instance, new_slug=None): 14 | """ 15 | This is for a Django project and it assumes your instance 16 | has a model with a slug field and a title character (char) field. 17 | """ 18 | if new_slug is not None: 19 | slug = new_slug 20 | else: 21 | slug = slugify(instance.title) 22 | 23 | Klass = instance.__class__ 24 | qs_exists = Klass.objects.filter(slug=slug).exists() 25 | if qs_exists: 26 | new_slug = "{slug}-{randstr}".format( 27 | slug=slug, 28 | randstr=random_string_generator(size=4) 29 | ) 30 | return unique_slug_generator(instance, new_slug=new_slug) 31 | return slug 32 | -------------------------------------------------------------------------------- /src/posts/views.py: -------------------------------------------------------------------------------- 1 | try: 2 | from urllib import quote_plus #python 2 3 | except: 4 | pass 5 | 6 | try: 7 | from urllib.parse import quote_plus #python 3 8 | except: 9 | pass 10 | 11 | from django.contrib import messages 12 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger 13 | from django.db.models import Q 14 | from django.http import HttpResponse, HttpResponseRedirect, Http404 15 | from django.shortcuts import render, get_object_or_404, redirect 16 | from django.utils import timezone 17 | 18 | from .forms import PostForm 19 | from .models import Post 20 | 21 | def post_create(request): 22 | if not request.user.is_staff or not request.user.is_superuser: 23 | raise Http404 24 | 25 | form = PostForm(request.POST or None, request.FILES or None) 26 | if form.is_valid(): 27 | instance = form.save(commit=False) 28 | instance.user = request.user 29 | instance.save() 30 | # message success 31 | messages.success(request, "Successfully Created") 32 | return HttpResponseRedirect(instance.get_absolute_url()) 33 | context = { 34 | "form": form, 35 | } 36 | return render(request, "post_form.html", context) 37 | 38 | ''' 39 | Created for Django Code Review 40 | ''' 41 | 42 | from django.views.generic import DetailView 43 | 44 | class PostDetailView(DetailView): 45 | template_name = 'post_detail.html' 46 | 47 | def get_object(self, *args, **kwargs): 48 | slug = self.kwargs.get("slug") 49 | instance = get_object_or_404(Post, slug=slug) 50 | if instance.publish > timezone.now().date() or instance.draft: 51 | if not self.request.user.is_staff or not self.request.user.is_superuser: 52 | raise Http404 53 | return instance 54 | 55 | def get_context_data(self, *args, **kwargs): 56 | context = super(PostDetailView, self).get_context_data(*args, **kwargs) 57 | instance = context['object'] 58 | context['share_string'] = quote_plus(instance.content) 59 | return context 60 | 61 | # in urls.py --> PostDetailView.as_view() instead of post_detail 62 | 63 | 64 | def post_detail(request, slug=None): 65 | instance = get_object_or_404(Post, slug=slug) 66 | if instance.publish > timezone.now().date() or instance.draft: 67 | if not request.user.is_staff or not request.user.is_superuser: 68 | raise Http404 69 | share_string = quote_plus(instance.content) 70 | context = { 71 | "title": instance.title, 72 | "instance": instance, 73 | "share_string": share_string, 74 | } 75 | return render(request, "post_detail.html", context) 76 | 77 | def post_list(request): 78 | today = timezone.now().date() 79 | queryset_list = Post.objects.active() #.order_by("-timestamp") 80 | if request.user.is_staff or request.user.is_superuser: 81 | queryset_list = Post.objects.all() 82 | 83 | query = request.GET.get("q") 84 | if query: 85 | queryset_list = queryset_list.filter( 86 | Q(title__icontains=query)| 87 | Q(content__icontains=query)| 88 | Q(user__first_name__icontains=query) | 89 | Q(user__last_name__icontains=query) 90 | ).distinct() 91 | paginator = Paginator(queryset_list, 8) # Show 25 contacts per page 92 | page_request_var = "page" 93 | page = request.GET.get(page_request_var) 94 | try: 95 | queryset = paginator.page(page) 96 | except PageNotAnInteger: 97 | # If page is not an integer, deliver first page. 98 | queryset = paginator.page(1) 99 | except EmptyPage: 100 | # If page is out of range (e.g. 9999), deliver last page of results. 101 | queryset = paginator.page(paginator.num_pages) 102 | 103 | 104 | context = { 105 | "object_list": queryset, 106 | "title": "List", 107 | "page_request_var": page_request_var, 108 | "today": today, 109 | } 110 | return render(request, "post_list.html", context) 111 | 112 | 113 | 114 | 115 | 116 | def post_update(request, slug=None): 117 | if not request.user.is_staff or not request.user.is_superuser: 118 | raise Http404 119 | instance = get_object_or_404(Post, slug=slug) 120 | form = PostForm(request.POST or None, request.FILES or None, instance=instance) 121 | if form.is_valid(): 122 | instance = form.save(commit=False) 123 | instance.save() 124 | messages.success(request, "Item Saved", extra_tags='html_safe') 125 | return HttpResponseRedirect(instance.get_absolute_url()) 126 | 127 | context = { 128 | "title": instance.title, 129 | "instance": instance, 130 | "form":form, 131 | } 132 | return render(request, "post_form.html", context) 133 | 134 | 135 | 136 | def post_delete(request, slug=None): 137 | if not request.user.is_staff or not request.user.is_superuser: 138 | raise Http404 139 | instance = get_object_or_404(Post, slug=slug) 140 | instance.delete() 141 | messages.success(request, "Successfully deleted") 142 | return redirect("posts:list") 143 | -------------------------------------------------------------------------------- /src/static/css/base.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: #777777; 3 | } -------------------------------------------------------------------------------- /src/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load staticfiles %} 2 | 3 | 4 | 5 | {% block head_title %}Try Django 1.9{% endblock head_title %} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 |
20 | 27 | 28 | 29 | 30 | {% include "messages_display.html" %} 31 |
32 | {% block content %}{% endblock content %} 33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/templates/messages_display.html: -------------------------------------------------------------------------------- 1 | {% if messages %} 2 |
3 | 4 |
    5 | {% for message in messages %} 6 | {% if "html_safe" in message.tags %}{{ message|safe }}{% else %}{{ message }}{% endif %} 7 | {% endfor %} 8 |
9 | 10 |
11 | {% endif %} -------------------------------------------------------------------------------- /src/templates/post_detail.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load urlify %} 3 | 4 | {% block head_title %} 5 | {{ object.title }} | {{ block.super }} 6 | {% endblock head_title %} 7 | 8 | 9 | 10 | {% block content %} 11 |
12 | {% if object.image %} 13 | 14 | {% endif %} 15 |

{{ object.title }} {% if object.draft %}Draft {% endif %}{{ object.publish }}

16 | {% if object.user.get_full_name %} 17 |

Author: {{ object.user.get_full_name }}

18 | {% endif %} 19 | 20 |

21 |
22 |

23 | 24 | 43 |
44 |
45 | 46 | {{ object.content|linebreaks }} 47 | 48 |
49 |
50 |
51 | 52 |
53 |
54 |
55 | 56 | 57 | {% endblock content %} 58 | -------------------------------------------------------------------------------- /src/templates/post_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | 4 | {% block content %} 5 |
6 |

Form

7 | 8 |
{% csrf_token %} 9 | {{ form.as_p }} 10 | 11 |
12 |
13 | {% endblock content %} -------------------------------------------------------------------------------- /src/templates/post_list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 | 4 | 5 |
6 |

{{ title }}

7 |
8 | 9 | 10 |
11 | {% for obj in object_list %} 12 |
13 |
14 |
15 | {% if obj.image %} 16 | 17 | {% endif %} 18 |
19 | {% if obj.draft %}

Staff only: Draft

{% endif %} {% if obj.publish > today %}

Staff Only: Future Post

{% endif %} 20 |

{{ obj.title }} {{ obj.publish }}

21 | {% if obj.user.get_full_name %}

Author: {{ obj.user.get_full_name }}

{% endif %} 22 |

{{ obj.content|linebreaks|truncatechars:120 }}

23 |

View

24 |
25 |
26 |
27 |
28 |
29 | {% endfor %} 30 | 31 | 32 | 47 | 48 | 49 | 50 | 51 |
52 | 53 | {% endblock content %} -------------------------------------------------------------------------------- /src/trydjango19/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/src/trydjango19/__init__.py -------------------------------------------------------------------------------- /src/trydjango19/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for trydjango19 project. 3 | 4 | Generated by 'django-admin startproject' using Django 1.9. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.9/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/1.9/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | # BASE_DIR = "/Users/jmitch/desktop/trydjango19/src/" 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'sm@g)(fbwdh5wc*xe@j++m9rh^uza5se9a57c5ptwkg*b@ki0x' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'posts', 41 | ] 42 | 43 | MIDDLEWARE_CLASSES = [ 44 | 'django.middleware.security.SecurityMiddleware', 45 | 'django.contrib.sessions.middleware.SessionMiddleware', 46 | 'django.middleware.common.CommonMiddleware', 47 | 'django.middleware.csrf.CsrfViewMiddleware', 48 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 49 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 50 | 'django.contrib.messages.middleware.MessageMiddleware', 51 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 52 | ] 53 | 54 | ROOT_URLCONF = 'trydjango19.urls' 55 | 56 | TEMPLATES = [ 57 | { 58 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 59 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 60 | 'APP_DIRS': True, 61 | 'OPTIONS': { 62 | 'context_processors': [ 63 | 'django.template.context_processors.debug', 64 | 'django.template.context_processors.request', 65 | 'django.contrib.auth.context_processors.auth', 66 | 'django.contrib.messages.context_processors.messages', 67 | ], 68 | }, 69 | }, 70 | ] 71 | 72 | WSGI_APPLICATION = 'trydjango19.wsgi.application' 73 | 74 | 75 | # Database 76 | # https://docs.djangoproject.com/en/1.9/ref/settings/#databases 77 | 78 | DATABASES = { 79 | 'default': { 80 | 'ENGINE': 'django.db.backends.sqlite3', 81 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 82 | } 83 | } 84 | 85 | 86 | # Password validation 87 | # https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators 88 | 89 | AUTH_PASSWORD_VALIDATORS = [ 90 | { 91 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 92 | }, 93 | { 94 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 95 | }, 96 | { 97 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 98 | }, 99 | { 100 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 101 | }, 102 | ] 103 | 104 | 105 | # Internationalization 106 | # https://docs.djangoproject.com/en/1.9/topics/i18n/ 107 | 108 | LANGUAGE_CODE = 'en-us' 109 | 110 | TIME_ZONE = 'UTC' 111 | 112 | USE_I18N = True 113 | 114 | USE_L10N = True 115 | 116 | USE_TZ = True 117 | 118 | 119 | # Static files (CSS, JavaScript, Images) 120 | # https://docs.djangoproject.com/en/1.9/howto/static-files/ 121 | 122 | STATIC_URL = '/static/' 123 | 124 | 125 | STATICFILES_DIRS = [ 126 | os.path.join(BASE_DIR, "static"), 127 | #'/var/www/static/', 128 | ] 129 | 130 | STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static_cdn") 131 | 132 | MEDIA_URL = "/media/" 133 | MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "media_cdn") 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /src/trydjango19/urls.py: -------------------------------------------------------------------------------- 1 | """trydjango19 URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.9/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Add an import: from blog import urls as blog_urls 14 | 2. Import the include() function: from django.conf.urls import url, include 15 | 3. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) 16 | """ 17 | from django.conf import settings 18 | from django.conf.urls import include, url 19 | from django.conf.urls.static import static 20 | from django.contrib import admin 21 | 22 | urlpatterns = [ 23 | url(r'^admin/', admin.site.urls), 24 | url(r'^posts/', include("posts.urls", namespace='posts')), 25 | #url(r'^posts/$', ".views."), 26 | ] 27 | 28 | if settings.DEBUG: 29 | urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) 30 | urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -------------------------------------------------------------------------------- /src/trydjango19/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for trydjango19 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.9/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "trydjango19.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /static_cdn/admin/css/changelists.css: -------------------------------------------------------------------------------- 1 | /* CHANGELISTS */ 2 | 3 | #changelist { 4 | position: relative; 5 | width: 100%; 6 | } 7 | 8 | #changelist table { 9 | width: 100%; 10 | } 11 | 12 | .change-list .hiddenfields { display:none; } 13 | 14 | .change-list .filtered table { 15 | border-right: none; 16 | } 17 | 18 | .change-list .filtered { 19 | min-height: 400px; 20 | } 21 | 22 | .change-list .filtered .results, .change-list .filtered .paginator, 23 | .filtered #toolbar, .filtered div.xfull { 24 | margin-right: 280px; 25 | width: auto; 26 | } 27 | 28 | .change-list .filtered table tbody th { 29 | padding-right: 1em; 30 | } 31 | 32 | #changelist-form .results { 33 | overflow-x: auto; 34 | } 35 | 36 | #changelist .toplinks { 37 | border-bottom: 1px solid #ddd; 38 | } 39 | 40 | #changelist .paginator { 41 | color: #666; 42 | border-bottom: 1px solid #eee; 43 | background: #fff; 44 | overflow: hidden; 45 | } 46 | 47 | /* CHANGELIST TABLES */ 48 | 49 | #changelist table thead th { 50 | padding: 0; 51 | white-space: nowrap; 52 | vertical-align: middle; 53 | } 54 | 55 | #changelist table thead th.action-checkbox-column { 56 | width: 1.5em; 57 | text-align: center; 58 | } 59 | 60 | #changelist table tbody td.action-checkbox { 61 | text-align: center; 62 | } 63 | 64 | #changelist table tfoot { 65 | color: #666; 66 | } 67 | 68 | /* TOOLBAR */ 69 | 70 | #changelist #toolbar { 71 | padding: 8px 10px; 72 | margin-bottom: 15px; 73 | border-top: 1px solid #eee; 74 | border-bottom: 1px solid #eee; 75 | background: #f8f8f8; 76 | color: #666; 77 | } 78 | 79 | #changelist #toolbar form input { 80 | border-radius: 4px; 81 | font-size: 14px; 82 | padding: 5px; 83 | color: #333; 84 | } 85 | 86 | #changelist #toolbar form #searchbar { 87 | height: 19px; 88 | border: 1px solid #ccc; 89 | padding: 2px 5px; 90 | margin: 0; 91 | vertical-align: top; 92 | font-size: 13px; 93 | } 94 | 95 | #changelist #toolbar form #searchbar:focus { 96 | border-color: #999; 97 | } 98 | 99 | #changelist #toolbar form input[type="submit"] { 100 | border: 1px solid #ccc; 101 | padding: 2px 10px; 102 | margin: 0; 103 | vertical-align: middle; 104 | background: #fff; 105 | box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; 106 | cursor: pointer; 107 | color: #333; 108 | } 109 | 110 | #changelist #toolbar form input[type="submit"]:focus, 111 | #changelist #toolbar form input[type="submit"]:hover { 112 | border-color: #999; 113 | } 114 | 115 | #changelist #changelist-search img { 116 | vertical-align: middle; 117 | margin-right: 4px; 118 | } 119 | 120 | /* FILTER COLUMN */ 121 | 122 | #changelist-filter { 123 | position: absolute; 124 | top: 0; 125 | right: 0; 126 | z-index: 1000; 127 | width: 240px; 128 | background: #f8f8f8; 129 | border-left: none; 130 | margin: 0; 131 | } 132 | 133 | #changelist-filter h2 { 134 | font-size: 14px; 135 | text-transform: uppercase; 136 | letter-spacing: 0.5px; 137 | padding: 5px 15px; 138 | margin-bottom: 12px; 139 | border-bottom: none; 140 | } 141 | 142 | #changelist-filter h3 { 143 | font-weight: 400; 144 | font-size: 14px; 145 | padding: 0 15px; 146 | margin-bottom: 10px; 147 | } 148 | 149 | #changelist-filter ul { 150 | margin: 5px 0; 151 | padding: 0 15px 15px; 152 | border-bottom: 1px solid #eaeaea; 153 | } 154 | 155 | #changelist-filter ul:last-child { 156 | border-bottom: none; 157 | padding-bottom: none; 158 | } 159 | 160 | #changelist-filter li { 161 | list-style-type: none; 162 | margin-left: 0; 163 | padding-left: 0; 164 | } 165 | 166 | #changelist-filter a { 167 | display: block; 168 | color: #999; 169 | } 170 | 171 | #changelist-filter li.selected { 172 | border-left: 5px solid #eaeaea; 173 | padding-left: 10px; 174 | margin-left: -15px; 175 | } 176 | 177 | #changelist-filter li.selected a { 178 | color: #5b80b2; 179 | } 180 | 181 | #changelist-filter a:focus, #changelist-filter a:hover, 182 | #changelist-filter li.selected a:focus, 183 | #changelist-filter li.selected a:hover { 184 | color: #036; 185 | } 186 | 187 | /* DATE DRILLDOWN */ 188 | 189 | .change-list ul.toplinks { 190 | display: block; 191 | float: left; 192 | padding: 0; 193 | margin: 0; 194 | width: 100%; 195 | } 196 | 197 | .change-list ul.toplinks li { 198 | padding: 3px 6px; 199 | font-weight: bold; 200 | list-style-type: none; 201 | display: inline-block; 202 | } 203 | 204 | .change-list ul.toplinks .date-back a { 205 | color: #999; 206 | } 207 | 208 | .change-list ul.toplinks .date-back a:focus, 209 | .change-list ul.toplinks .date-back a:hover { 210 | color: #036; 211 | } 212 | 213 | /* PAGINATOR */ 214 | 215 | .paginator { 216 | font-size: 13px; 217 | padding-top: 10px; 218 | padding-bottom: 10px; 219 | line-height: 22px; 220 | margin: 0; 221 | border-top: 1px solid #ddd; 222 | } 223 | 224 | .paginator a:link, .paginator a:visited { 225 | padding: 2px 6px; 226 | background: #79aec8; 227 | text-decoration: none; 228 | color: #fff; 229 | } 230 | 231 | .paginator a.showall { 232 | padding: 0; 233 | border: none; 234 | background: none; 235 | color: #5b80b2; 236 | } 237 | 238 | .paginator a.showall:focus, .paginator a.showall:hover { 239 | background: none; 240 | color: #036; 241 | } 242 | 243 | .paginator .end { 244 | margin-right: 6px; 245 | } 246 | 247 | .paginator .this-page { 248 | padding: 2px 6px; 249 | font-weight: bold; 250 | font-size: 13px; 251 | vertical-align: top; 252 | } 253 | 254 | .paginator a:focus, .paginator a:hover { 255 | color: white; 256 | background: #036; 257 | } 258 | 259 | /* ACTIONS */ 260 | 261 | .filtered .actions { 262 | margin-right: 280px; 263 | border-right: none; 264 | } 265 | 266 | #changelist table input { 267 | margin: 0; 268 | vertical-align: baseline; 269 | } 270 | 271 | #changelist table tbody tr.selected { 272 | background-color: #FFFFCC; 273 | } 274 | 275 | #changelist .actions { 276 | padding: 10px; 277 | background: #fff; 278 | border-top: none; 279 | border-bottom: none; 280 | line-height: 24px; 281 | color: #999; 282 | } 283 | 284 | #changelist .actions.selected { 285 | background: #fffccf; 286 | border-top: 1px solid #fffee8; 287 | border-bottom: 1px solid #edecd6; 288 | } 289 | 290 | #changelist .actions span.all, 291 | #changelist .actions span.action-counter, 292 | #changelist .actions span.clear, 293 | #changelist .actions span.question { 294 | font-size: 13px; 295 | margin: 0 0.5em; 296 | display: none; 297 | } 298 | 299 | #changelist .actions:last-child { 300 | border-bottom: none; 301 | } 302 | 303 | #changelist .actions select { 304 | vertical-align: top; 305 | height: 24px; 306 | background: none; 307 | border: 1px solid #ccc; 308 | border-radius: 4px; 309 | font-size: 14px; 310 | padding: 0 0 0 4px; 311 | margin: 0; 312 | margin-left: 10px; 313 | } 314 | 315 | #changelist .actions select:focus { 316 | border-color: #999; 317 | } 318 | 319 | #changelist .actions label { 320 | display: inline-block; 321 | vertical-align: middle; 322 | font-size: 13px; 323 | } 324 | 325 | #changelist .actions .button { 326 | font-size: 13px; 327 | border: 1px solid #ccc; 328 | border-radius: 4px; 329 | background: #fff; 330 | box-shadow: 0 -15px 20px -10px rgba(0, 0, 0, 0.15) inset; 331 | cursor: pointer; 332 | height: 24px; 333 | line-height: 1; 334 | padding: 4px 8px; 335 | margin: 0; 336 | color: #333; 337 | } 338 | 339 | #changelist .actions .button:focus, #changelist .actions .button:hover { 340 | border-color: #999; 341 | } 342 | -------------------------------------------------------------------------------- /static_cdn/admin/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* DASHBOARD */ 2 | 3 | .dashboard .module table th { 4 | width: 100%; 5 | } 6 | 7 | .dashboard .module table td { 8 | white-space: nowrap; 9 | } 10 | 11 | .dashboard .module table td a { 12 | display: block; 13 | padding-right: .6em; 14 | } 15 | 16 | /* RECENT ACTIONS MODULE */ 17 | 18 | .module ul.actionlist { 19 | margin-left: 0; 20 | } 21 | 22 | ul.actionlist li { 23 | list-style-type: none; 24 | } 25 | 26 | ul.actionlist li { 27 | overflow: hidden; 28 | text-overflow: ellipsis; 29 | -o-text-overflow: ellipsis; 30 | } 31 | -------------------------------------------------------------------------------- /static_cdn/admin/css/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Roboto'; 3 | src: url('../fonts/Roboto-Bold-webfont.woff'); 4 | font-weight: 700; 5 | font-style: normal; 6 | } 7 | 8 | @font-face { 9 | font-family: 'Roboto'; 10 | src: url('../fonts/Roboto-Regular-webfont.woff'); 11 | font-weight: 400; 12 | font-style: normal; 13 | } 14 | 15 | @font-face { 16 | font-family: 'Roboto'; 17 | src: url('../fonts/Roboto-Light-webfont.woff'); 18 | font-weight: 300; 19 | font-style: normal; 20 | } 21 | -------------------------------------------------------------------------------- /static_cdn/admin/css/forms.css: -------------------------------------------------------------------------------- 1 | @import url('widgets.css'); 2 | 3 | /* FORM ROWS */ 4 | 5 | .form-row { 6 | overflow: hidden; 7 | padding: 10px; 8 | font-size: 13px; 9 | border-bottom: 1px solid #eee; 10 | } 11 | 12 | .form-row img, .form-row input { 13 | vertical-align: middle; 14 | } 15 | 16 | .form-row label input[type="checkbox"] { 17 | margin-top: 0; 18 | vertical-align: 0; 19 | } 20 | 21 | form .form-row p { 22 | padding-left: 0; 23 | } 24 | 25 | .hidden { 26 | display: none; 27 | } 28 | 29 | /* FORM LABELS */ 30 | 31 | label { 32 | font-weight: normal; 33 | color: #666; 34 | font-size: 13px; 35 | } 36 | 37 | .required label, label.required { 38 | font-weight: bold; 39 | color: #333; 40 | } 41 | 42 | /* RADIO BUTTONS */ 43 | 44 | form ul.radiolist li { 45 | list-style-type: none; 46 | } 47 | 48 | form ul.radiolist label { 49 | float: none; 50 | display: inline; 51 | } 52 | 53 | form ul.radiolist input[type="radio"] { 54 | margin: -2px 4px 0 0; 55 | padding: 0; 56 | } 57 | 58 | form ul.inline { 59 | margin-left: 0; 60 | padding: 0; 61 | } 62 | 63 | form ul.inline li { 64 | float: left; 65 | padding-right: 7px; 66 | } 67 | 68 | /* ALIGNED FIELDSETS */ 69 | 70 | .aligned label { 71 | display: block; 72 | padding: 4px 10px 0 0; 73 | float: left; 74 | width: 160px; 75 | word-wrap: break-word; 76 | line-height: 1; 77 | } 78 | 79 | .aligned label:not(.vCheckboxLabel):after { 80 | content: ''; 81 | display: inline-block; 82 | vertical-align: middle; 83 | height: 26px; 84 | } 85 | 86 | .aligned label + p { 87 | padding: 6px 0; 88 | margin-top: 0; 89 | margin-bottom: 0; 90 | margin-left: 170px; 91 | } 92 | 93 | .aligned ul label { 94 | display: inline; 95 | float: none; 96 | width: auto; 97 | } 98 | 99 | .aligned .form-row input { 100 | margin-bottom: 0; 101 | } 102 | 103 | .colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField { 104 | width: 350px; 105 | } 106 | 107 | form .aligned ul { 108 | margin-left: 160px; 109 | padding-left: 10px; 110 | } 111 | 112 | form .aligned ul.radiolist { 113 | display: inline-block; 114 | margin: 0; 115 | padding: 0; 116 | } 117 | 118 | form .aligned p.help { 119 | clear: left; 120 | margin-top: 0; 121 | margin-left: 160px; 122 | padding-left: 10px; 123 | } 124 | 125 | form .aligned label + p.help { 126 | margin-left: 0; 127 | padding-left: 0; 128 | } 129 | 130 | form .aligned p.help:last-child { 131 | margin-bottom: 0; 132 | padding-bottom: 0; 133 | } 134 | 135 | form .aligned input + p.help, 136 | form .aligned textarea + p.help, 137 | form .aligned select + p.help { 138 | margin-left: 160px; 139 | padding-left: 10px; 140 | } 141 | 142 | form .aligned ul li { 143 | list-style: none; 144 | } 145 | 146 | form .aligned table p { 147 | margin-left: 0; 148 | padding-left: 0; 149 | } 150 | 151 | .aligned .vCheckboxLabel { 152 | float: none; 153 | width: auto; 154 | display: inline-block; 155 | vertical-align: -3px; 156 | padding: 0 0 5px 5px; 157 | } 158 | 159 | .aligned .vCheckboxLabel + p.help { 160 | margin-top: -4px; 161 | } 162 | 163 | .colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField { 164 | width: 610px; 165 | } 166 | 167 | .checkbox-row p.help { 168 | margin-left: 0; 169 | padding-left: 0; 170 | } 171 | 172 | fieldset .field-box { 173 | float: left; 174 | margin-right: 20px; 175 | } 176 | 177 | /* WIDE FIELDSETS */ 178 | 179 | .wide label { 180 | width: 200px; 181 | } 182 | 183 | form .wide p, form .wide input + p.help { 184 | margin-left: 200px; 185 | } 186 | 187 | form .wide p.help { 188 | padding-left: 38px; 189 | } 190 | 191 | .colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField { 192 | width: 450px; 193 | } 194 | 195 | /* COLLAPSED FIELDSETS */ 196 | 197 | fieldset.collapsed * { 198 | display: none; 199 | } 200 | 201 | fieldset.collapsed h2, fieldset.collapsed { 202 | display: block; 203 | } 204 | 205 | fieldset.collapsed { 206 | border: 1px solid #eee; 207 | border-radius: 4px; 208 | overflow: hidden; 209 | } 210 | 211 | fieldset.collapsed h2 { 212 | background: #f8f8f8; 213 | color: #666; 214 | } 215 | 216 | fieldset .collapse-toggle { 217 | color: #fff; 218 | } 219 | 220 | fieldset.collapsed .collapse-toggle { 221 | background: transparent; 222 | display: inline; 223 | color: #447e9b; 224 | } 225 | 226 | /* MONOSPACE TEXTAREAS */ 227 | 228 | fieldset.monospace textarea { 229 | font-family: "Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace; 230 | } 231 | 232 | /* SUBMIT ROW */ 233 | 234 | .submit-row { 235 | padding: 12px 14px; 236 | margin: 0 0 20px; 237 | background: #f8f8f8; 238 | border: 1px solid #eee; 239 | border-radius: 4px; 240 | text-align: right; 241 | overflow: hidden; 242 | } 243 | 244 | body.popup .submit-row { 245 | overflow: auto; 246 | } 247 | 248 | .submit-row input { 249 | height: 35px; 250 | line-height: 15px; 251 | margin: 0 0 0 5px; 252 | } 253 | 254 | .submit-row input.default { 255 | margin: 0 0 0 8px; 256 | text-transform: uppercase; 257 | } 258 | 259 | .submit-row p { 260 | margin: 0.3em; 261 | } 262 | 263 | .submit-row p.deletelink-box { 264 | float: left; 265 | margin: 0; 266 | } 267 | 268 | .submit-row a.deletelink { 269 | display: block; 270 | background: #ba2121; 271 | border-radius: 4px; 272 | padding: 10px 15px; 273 | height: 15px; 274 | line-height: 15px; 275 | color: #fff; 276 | } 277 | 278 | .submit-row a.deletelink:focus, 279 | .submit-row a.deletelink:hover, 280 | .submit-row a.deletelink:active { 281 | background: #a41515; 282 | } 283 | 284 | /* CUSTOM FORM FIELDS */ 285 | 286 | .vSelectMultipleField { 287 | vertical-align: top; 288 | } 289 | 290 | .vCheckboxField { 291 | border: none; 292 | } 293 | 294 | .vDateField, .vTimeField { 295 | margin-right: 2px; 296 | margin-bottom: 4px; 297 | } 298 | 299 | .vDateField { 300 | min-width: 6.85em; 301 | } 302 | 303 | .vTimeField { 304 | min-width: 4.7em; 305 | } 306 | 307 | .vURLField { 308 | width: 30em; 309 | } 310 | 311 | .vLargeTextField, .vXMLLargeTextField { 312 | width: 48em; 313 | } 314 | 315 | .flatpages-flatpage #id_content { 316 | height: 40.2em; 317 | } 318 | 319 | .module table .vPositiveSmallIntegerField { 320 | width: 2.2em; 321 | } 322 | 323 | .vTextField { 324 | width: 20em; 325 | } 326 | 327 | .vIntegerField { 328 | width: 5em; 329 | } 330 | 331 | .vBigIntegerField { 332 | width: 10em; 333 | } 334 | 335 | .vForeignKeyRawIdAdminField { 336 | width: 5em; 337 | } 338 | 339 | /* INLINES */ 340 | 341 | .inline-group { 342 | padding: 0; 343 | margin: 0 0 30px; 344 | } 345 | 346 | .inline-group thead th { 347 | padding: 8px 10px; 348 | } 349 | 350 | .inline-group .aligned label { 351 | width: 160px; 352 | } 353 | 354 | .inline-related { 355 | position: relative; 356 | } 357 | 358 | .inline-related h3 { 359 | margin: 0; 360 | color: #666; 361 | padding: 5px; 362 | font-size: 13px; 363 | background: #f8f8f8; 364 | border-top: 1px solid #eee; 365 | border-bottom: 1px solid #eee; 366 | } 367 | 368 | .inline-related h3 span.delete { 369 | float: right; 370 | } 371 | 372 | .inline-related h3 span.delete label { 373 | margin-left: 2px; 374 | font-size: 11px; 375 | } 376 | 377 | .inline-related fieldset { 378 | margin: 0; 379 | background: #fff; 380 | border: none; 381 | width: 100%; 382 | } 383 | 384 | .inline-related fieldset.module h3 { 385 | margin: 0; 386 | padding: 2px 5px 3px 5px; 387 | font-size: 11px; 388 | text-align: left; 389 | font-weight: bold; 390 | background: #bcd; 391 | color: #fff; 392 | } 393 | 394 | .inline-group .tabular fieldset.module { 395 | border: none; 396 | } 397 | 398 | .inline-related.tabular fieldset.module table { 399 | width: 100%; 400 | } 401 | 402 | .last-related fieldset { 403 | border: none; 404 | } 405 | 406 | .inline-group .tabular tr.has_original td { 407 | padding-top: 2em; 408 | } 409 | 410 | .inline-group .tabular tr td.original { 411 | padding: 2px 0 0 0; 412 | width: 0; 413 | _position: relative; 414 | } 415 | 416 | .inline-group .tabular th.original { 417 | width: 0px; 418 | padding: 0; 419 | } 420 | 421 | .inline-group .tabular td.original p { 422 | position: absolute; 423 | left: 0; 424 | height: 1.1em; 425 | padding: 2px 9px; 426 | overflow: hidden; 427 | font-size: 9px; 428 | font-weight: bold; 429 | color: #666; 430 | _width: 700px; 431 | } 432 | 433 | .inline-group ul.tools { 434 | padding: 0; 435 | margin: 0; 436 | list-style: none; 437 | } 438 | 439 | .inline-group ul.tools li { 440 | display: inline; 441 | padding: 0 5px; 442 | } 443 | 444 | .inline-group div.add-row, 445 | .inline-group .tabular tr.add-row td { 446 | color: #666; 447 | background: #f8f8f8; 448 | padding: 8px 10px; 449 | border-bottom: 1px solid #eee; 450 | } 451 | 452 | .inline-group .tabular tr.add-row td { 453 | padding: 8px 10px; 454 | border-bottom: 1px solid #eee; 455 | } 456 | 457 | .inline-group ul.tools a.add, 458 | .inline-group div.add-row a, 459 | .inline-group .tabular tr.add-row td a { 460 | background: url(../img/icon-addlink.svg) 0 1px no-repeat; 461 | padding-left: 16px; 462 | font-size: 12px; 463 | } 464 | 465 | .empty-form { 466 | display: none; 467 | } 468 | 469 | /* RELATED FIELD ADD ONE / LOOKUP */ 470 | 471 | .add-another, .related-lookup { 472 | margin-left: 5px; 473 | display: inline-block; 474 | vertical-align: middle; 475 | background-repeat: no-repeat; 476 | background-size: 14px; 477 | } 478 | 479 | .add-another { 480 | width: 16px; 481 | height: 16px; 482 | background-image: url(../img/icon-addlink.svg); 483 | } 484 | 485 | .related-lookup { 486 | width: 16px; 487 | height: 16px; 488 | background-image: url(../img/search.svg); 489 | } 490 | 491 | form .related-widget-wrapper ul { 492 | display: inline-block; 493 | margin-left: 0; 494 | padding-left: 0; 495 | } 496 | 497 | .clearable-file-input input { 498 | margin-top: 0; 499 | } 500 | -------------------------------------------------------------------------------- /static_cdn/admin/css/login.css: -------------------------------------------------------------------------------- 1 | /* LOGIN FORM */ 2 | 3 | body.login { 4 | background: #f8f8f8; 5 | } 6 | 7 | .login #header { 8 | height: auto; 9 | padding: 5px 16px; 10 | } 11 | 12 | .login #header h1 { 13 | font-size: 18px; 14 | } 15 | 16 | .login #header h1 a { 17 | color: #fff; 18 | } 19 | 20 | .login #content { 21 | padding: 20px 20px 0; 22 | } 23 | 24 | .login #container { 25 | background: #fff; 26 | border: 1px solid #eaeaea; 27 | border-radius: 4px; 28 | overflow: hidden; 29 | width: 28em; 30 | min-width: 300px; 31 | margin: 100px auto; 32 | } 33 | 34 | .login #content-main { 35 | width: 100%; 36 | } 37 | 38 | .login .form-row { 39 | padding: 4px 0; 40 | float: left; 41 | width: 100%; 42 | border-bottom: none; 43 | } 44 | 45 | .login .form-row label { 46 | padding-right: 0.5em; 47 | line-height: 2em; 48 | font-size: 1em; 49 | clear: both; 50 | color: #333; 51 | } 52 | 53 | .login .form-row #id_username, .login .form-row #id_password { 54 | clear: both; 55 | padding: 8px; 56 | width: 100%; 57 | -webkit-box-sizing: border-box; 58 | -moz-box-sizing: border-box; 59 | box-sizing: border-box; 60 | } 61 | 62 | .login span.help { 63 | font-size: 10px; 64 | display: block; 65 | } 66 | 67 | .login .submit-row { 68 | clear: both; 69 | padding: 1em 0 0 9.4em; 70 | margin: 0; 71 | border: none; 72 | background: none; 73 | text-align: left; 74 | } 75 | 76 | .login .password-reset-link { 77 | text-align: center; 78 | } 79 | -------------------------------------------------------------------------------- /static_cdn/admin/css/rtl.css: -------------------------------------------------------------------------------- 1 | body { 2 | direction: rtl; 3 | } 4 | 5 | /* LOGIN */ 6 | 7 | .login .form-row { 8 | float: right; 9 | } 10 | 11 | .login .form-row label { 12 | float: right; 13 | padding-left: 0.5em; 14 | padding-right: 0; 15 | text-align: left; 16 | } 17 | 18 | .login .submit-row { 19 | clear: both; 20 | padding: 1em 9.4em 0 0; 21 | } 22 | 23 | /* GLOBAL */ 24 | 25 | th { 26 | text-align: right; 27 | } 28 | 29 | .module h2, .module caption { 30 | text-align: right; 31 | } 32 | 33 | .module ul, .module ol { 34 | margin-left: 0; 35 | margin-right: 1.5em; 36 | } 37 | 38 | .addlink, .changelink { 39 | padding-left: 0; 40 | padding-right: 16px; 41 | background-position: 100% 1px; 42 | } 43 | 44 | .deletelink { 45 | padding-left: 0; 46 | padding-right: 16px; 47 | background-position: 100% 1px; 48 | } 49 | 50 | .object-tools { 51 | float: left; 52 | } 53 | 54 | thead th:first-child, 55 | tfoot td:first-child { 56 | border-left: none; 57 | } 58 | 59 | /* LAYOUT */ 60 | 61 | #user-tools { 62 | right: auto; 63 | left: 0; 64 | text-align: left; 65 | } 66 | 67 | div.breadcrumbs { 68 | text-align: right; 69 | } 70 | 71 | #content-main { 72 | float: right; 73 | } 74 | 75 | #content-related { 76 | float: left; 77 | margin-left: -300px; 78 | margin-right: auto; 79 | } 80 | 81 | .colMS { 82 | margin-left: 300px; 83 | margin-right: 0; 84 | } 85 | 86 | /* SORTABLE TABLES */ 87 | 88 | table thead th.sorted .sortoptions { 89 | float: left; 90 | } 91 | 92 | thead th.sorted .text { 93 | padding-right: 0; 94 | padding-left: 42px; 95 | } 96 | 97 | /* dashboard styles */ 98 | 99 | .dashboard .module table td a { 100 | padding-left: .6em; 101 | padding-right: 16px; 102 | } 103 | 104 | /* changelists styles */ 105 | 106 | .change-list .filtered table { 107 | border-left: none; 108 | border-right: 0px none; 109 | } 110 | 111 | #changelist-filter { 112 | right: auto; 113 | left: 0; 114 | border-left: none; 115 | border-right: none; 116 | } 117 | 118 | .change-list .filtered .results, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { 119 | margin-right: 0; 120 | margin-left: 280px; 121 | } 122 | 123 | #changelist-filter li.selected { 124 | border-left: none; 125 | padding-left: 10px; 126 | margin-left: 0; 127 | border-right: 5px solid #eaeaea; 128 | padding-right: 10px; 129 | margin-right: -15px; 130 | } 131 | 132 | .filtered .actions { 133 | margin-left: 280px; 134 | margin-right: 0; 135 | } 136 | 137 | #changelist table tbody td:first-child, #changelist table tbody th:first-child { 138 | border-right: none; 139 | border-left: none; 140 | } 141 | 142 | /* FORMS */ 143 | 144 | .aligned label { 145 | padding: 0 0 3px 1em; 146 | float: right; 147 | } 148 | 149 | .submit-row { 150 | text-align: left 151 | } 152 | 153 | .submit-row p.deletelink-box { 154 | float: right; 155 | } 156 | 157 | .submit-row input.default { 158 | margin-left: 0; 159 | } 160 | 161 | .vDateField, .vTimeField { 162 | margin-left: 2px; 163 | } 164 | 165 | .aligned .form-row input { 166 | margin-left: 5px; 167 | } 168 | 169 | form ul.inline li { 170 | float: right; 171 | padding-right: 0; 172 | padding-left: 7px; 173 | } 174 | 175 | input[type=submit].default, .submit-row input.default { 176 | float: left; 177 | } 178 | 179 | fieldset .field-box { 180 | float: right; 181 | margin-left: 20px; 182 | margin-right: 0; 183 | } 184 | 185 | .errorlist li { 186 | background-position: 100% 12px; 187 | padding: 0; 188 | } 189 | 190 | .errornote { 191 | background-position: 100% 12px; 192 | padding: 10px 12px; 193 | } 194 | 195 | /* WIDGETS */ 196 | 197 | .calendarnav-previous { 198 | top: 0; 199 | left: auto; 200 | right: 10px; 201 | } 202 | 203 | .calendarnav-next { 204 | top: 0; 205 | right: auto; 206 | left: 10px; 207 | } 208 | 209 | .calendar caption, .calendarbox h2 { 210 | text-align: center; 211 | } 212 | 213 | .selector { 214 | float: right; 215 | } 216 | 217 | .selector .selector-filter { 218 | text-align: right; 219 | } 220 | 221 | .inline-deletelink { 222 | float: left; 223 | } 224 | 225 | form .form-row p.datetime { 226 | overflow: hidden; 227 | } 228 | 229 | /* MISC */ 230 | 231 | .inline-related h2, .inline-group h2 { 232 | text-align: right 233 | } 234 | 235 | .inline-related h3 span.delete { 236 | padding-right: 20px; 237 | padding-left: inherit; 238 | left: 10px; 239 | right: inherit; 240 | float:left; 241 | } 242 | 243 | .inline-related h3 span.delete label { 244 | margin-left: inherit; 245 | margin-right: 2px; 246 | } 247 | 248 | /* IE7 specific bug fixes */ 249 | 250 | div.colM { 251 | position: relative; 252 | } 253 | 254 | .submit-row input { 255 | float: left; 256 | } 257 | -------------------------------------------------------------------------------- /static_cdn/admin/css/widgets.css: -------------------------------------------------------------------------------- 1 | /* SELECTOR (FILTER INTERFACE) */ 2 | 3 | .selector { 4 | width: 800px; 5 | float: left; 6 | } 7 | 8 | .selector select { 9 | width: 380px; 10 | height: 17.2em; 11 | } 12 | 13 | .selector-available, .selector-chosen { 14 | float: left; 15 | width: 380px; 16 | text-align: center; 17 | margin-bottom: 5px; 18 | } 19 | 20 | .selector-chosen select { 21 | border-top: none; 22 | } 23 | 24 | .selector-available h2, .selector-chosen h2 { 25 | border: 1px solid #ccc; 26 | border-radius: 4px 4px 0 0; 27 | } 28 | 29 | .selector-chosen h2 { 30 | background: #79aec8; 31 | color: #fff; 32 | } 33 | 34 | .selector .selector-available h2 { 35 | background: #f8f8f8; 36 | color: #666; 37 | } 38 | 39 | .selector .selector-filter { 40 | background: white; 41 | border: 1px solid #ccc; 42 | border-width: 0 1px; 43 | padding: 8px; 44 | color: #999; 45 | font-size: 10px; 46 | margin: 0; 47 | text-align: left; 48 | } 49 | 50 | .selector .selector-filter label, 51 | .inline-group .aligned .selector .selector-filter label { 52 | float: left; 53 | margin: 7px 0 0; 54 | width: 18px; 55 | height: 18px; 56 | padding: 0; 57 | overflow: hidden; 58 | line-height: 1; 59 | } 60 | 61 | .selector .selector-available input { 62 | width: 320px; 63 | margin-left: 8px; 64 | } 65 | 66 | .selector ul.selector-chooser { 67 | float: left; 68 | width: 22px; 69 | background-color: #eee; 70 | border-radius: 10px; 71 | margin: 10em 5px 0 5px; 72 | padding: 0; 73 | } 74 | 75 | .selector-chooser li { 76 | margin: 0; 77 | padding: 3px; 78 | list-style-type: none; 79 | } 80 | 81 | .selector select { 82 | padding: 0 10px; 83 | margin: 0 0 10px; 84 | border-radius: 0 0 4px 4px; 85 | } 86 | 87 | .selector-add, .selector-remove { 88 | width: 16px; 89 | height: 16px; 90 | display: block; 91 | text-indent: -3000px; 92 | overflow: hidden; 93 | cursor: default; 94 | opacity: 0.3; 95 | } 96 | 97 | .active.selector-add, .active.selector-remove { 98 | opacity: 1; 99 | } 100 | 101 | .active.selector-add:hover, .active.selector-remove:hover { 102 | cursor: pointer; 103 | } 104 | 105 | .selector-add { 106 | background: url(../img/selector-icons.svg) 0 -96px no-repeat; 107 | } 108 | 109 | .active.selector-add:focus, .active.selector-add:hover { 110 | background-position: 0 -112px; 111 | } 112 | 113 | .selector-remove { 114 | background: url(../img/selector-icons.svg) 0 -64px no-repeat; 115 | } 116 | 117 | .active.selector-remove:focus, .active.selector-remove:hover { 118 | background-position: 0 -80px; 119 | } 120 | 121 | a.selector-chooseall, a.selector-clearall { 122 | display: inline-block; 123 | height: 16px; 124 | text-align: left; 125 | margin: 1px auto 3px; 126 | overflow: hidden; 127 | font-weight: bold; 128 | line-height: 16px; 129 | color: #666; 130 | text-decoration: none; 131 | opacity: 0.3; 132 | } 133 | 134 | a.active.selector-chooseall:focus, a.active.selector-clearall:focus, 135 | a.active.selector-chooseall:hover, a.active.selector-clearall:hover { 136 | color: #447e9b; 137 | } 138 | 139 | a.active.selector-chooseall, a.active.selector-clearall { 140 | opacity: 1; 141 | } 142 | 143 | a.active.selector-chooseall:hover, a.active.selector-clearall:hover { 144 | cursor: pointer; 145 | } 146 | 147 | a.selector-chooseall { 148 | padding: 0 18px 0 0; 149 | background: url(../img/selector-icons.svg) right -160px no-repeat; 150 | cursor: default; 151 | } 152 | 153 | a.active.selector-chooseall:focus, a.active.selector-chooseall:hover { 154 | background-position: 100% -176px; 155 | } 156 | 157 | a.selector-clearall { 158 | padding: 0 0 0 18px; 159 | background: url(../img/selector-icons.svg) 0 -128px no-repeat; 160 | cursor: default; 161 | } 162 | 163 | a.active.selector-clearall:focus, a.active.selector-clearall:hover { 164 | background-position: 0 -144px; 165 | } 166 | 167 | /* STACKED SELECTORS */ 168 | 169 | .stacked { 170 | float: left; 171 | width: 490px; 172 | } 173 | 174 | .stacked select { 175 | width: 480px; 176 | height: 10.1em; 177 | } 178 | 179 | .stacked .selector-available, .stacked .selector-chosen { 180 | width: 480px; 181 | } 182 | 183 | .stacked .selector-available { 184 | margin-bottom: 0; 185 | } 186 | 187 | .stacked .selector-available input { 188 | width: 422px; 189 | } 190 | 191 | .stacked ul.selector-chooser { 192 | height: 22px; 193 | width: 50px; 194 | margin: 0 0 10px 40%; 195 | background-color: #eee; 196 | border-radius: 10px; 197 | } 198 | 199 | .stacked .selector-chooser li { 200 | float: left; 201 | padding: 3px 3px 3px 5px; 202 | } 203 | 204 | .stacked .selector-chooseall, .stacked .selector-clearall { 205 | display: none; 206 | } 207 | 208 | .stacked .selector-add { 209 | background: url(../img/selector-icons.svg) 0 -32px no-repeat; 210 | cursor: default; 211 | } 212 | 213 | .stacked .active.selector-add { 214 | background-position: 0 -48px; 215 | cursor: pointer; 216 | } 217 | 218 | .stacked .selector-remove { 219 | background: url(../img/selector-icons.svg) 0 0 no-repeat; 220 | cursor: default; 221 | } 222 | 223 | .stacked .active.selector-remove { 224 | background-position: 0 -16px; 225 | cursor: pointer; 226 | } 227 | 228 | .selector .help-icon { 229 | background: url(../img/icon-unknown.svg) 0 0 no-repeat; 230 | display: inline-block; 231 | vertical-align: middle; 232 | margin: -2px 0 0 2px; 233 | width: 13px; 234 | height: 13px; 235 | } 236 | 237 | .selector .selector-chosen .help-icon { 238 | background: url(../img/icon-unknown-alt.svg) 0 0 no-repeat; 239 | } 240 | 241 | .selector .search-label-icon { 242 | background: url(../img/search.svg) 0 0 no-repeat; 243 | display: inline-block; 244 | height: 18px; 245 | width: 18px; 246 | } 247 | 248 | /* DATE AND TIME */ 249 | 250 | p.datetime { 251 | line-height: 20px; 252 | margin: 0; 253 | padding: 0; 254 | color: #666; 255 | font-weight: bold; 256 | } 257 | 258 | .datetime span { 259 | white-space: nowrap; 260 | font-weight: normal; 261 | font-size: 11px; 262 | color: #ccc; 263 | } 264 | 265 | .datetime input, .form-row .datetime input.vDateField, .form-row .datetime input.vTimeField { 266 | min-width: 0; 267 | margin-left: 5px; 268 | margin-bottom: 4px; 269 | } 270 | 271 | table p.datetime { 272 | font-size: 11px; 273 | margin-left: 0; 274 | padding-left: 0; 275 | } 276 | 277 | .datetimeshortcuts .clock-icon, .datetimeshortcuts .date-icon { 278 | position: relative; 279 | display: inline-block; 280 | vertical-align: middle; 281 | height: 16px; 282 | width: 16px; 283 | overflow: hidden; 284 | } 285 | 286 | .datetimeshortcuts .clock-icon { 287 | background: url(../img/icon-clock.svg) 0 0 no-repeat; 288 | } 289 | 290 | .datetimeshortcuts a:focus .clock-icon, 291 | .datetimeshortcuts a:hover .clock-icon { 292 | background-position: 0 -16px; 293 | } 294 | 295 | .datetimeshortcuts .date-icon { 296 | background: url(../img/icon-calendar.svg) 0 0 no-repeat; 297 | top: -1px; 298 | } 299 | 300 | .datetimeshortcuts a:focus .date-icon, 301 | .datetimeshortcuts a:hover .date-icon { 302 | background-position: 0 -16px; 303 | } 304 | 305 | .timezonewarning { 306 | font-size: 11px; 307 | color: #999; 308 | } 309 | 310 | /* URL */ 311 | 312 | p.url { 313 | line-height: 20px; 314 | margin: 0; 315 | padding: 0; 316 | color: #666; 317 | font-size: 11px; 318 | font-weight: bold; 319 | } 320 | 321 | .url a { 322 | font-weight: normal; 323 | } 324 | 325 | /* FILE UPLOADS */ 326 | 327 | p.file-upload { 328 | line-height: 20px; 329 | margin: 0; 330 | padding: 0; 331 | color: #666; 332 | font-size: 11px; 333 | font-weight: bold; 334 | } 335 | 336 | .aligned p.file-upload { 337 | margin-left: 170px; 338 | } 339 | 340 | .file-upload a { 341 | font-weight: normal; 342 | } 343 | 344 | .file-upload .deletelink { 345 | margin-left: 5px; 346 | } 347 | 348 | span.clearable-file-input label { 349 | color: #333; 350 | font-size: 11px; 351 | display: inline; 352 | float: none; 353 | } 354 | 355 | /* CALENDARS & CLOCKS */ 356 | 357 | .calendarbox, .clockbox { 358 | margin: 5px auto; 359 | font-size: 12px; 360 | width: 19em; 361 | text-align: center; 362 | background: white; 363 | border: 1px solid #ddd; 364 | border-radius: 4px; 365 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); 366 | overflow: hidden; 367 | position: relative; 368 | } 369 | 370 | .clockbox { 371 | width: auto; 372 | } 373 | 374 | .calendar { 375 | margin: 0; 376 | padding: 0; 377 | } 378 | 379 | .calendar table { 380 | margin: 0; 381 | padding: 0; 382 | border-collapse: collapse; 383 | background: white; 384 | width: 100%; 385 | } 386 | 387 | .calendar caption, .calendarbox h2 { 388 | margin: 0; 389 | text-align: center; 390 | border-top: none; 391 | background: #f5dd5d; 392 | font-weight: 700; 393 | font-size: 12px; 394 | color: #333; 395 | } 396 | 397 | .calendar th { 398 | padding: 8px 5px; 399 | background: #f8f8f8; 400 | border-bottom: 1px solid #ddd; 401 | font-weight: 400; 402 | font-size: 12px; 403 | text-align: center; 404 | color: #666; 405 | } 406 | 407 | .calendar td { 408 | font-weight: 400; 409 | font-size: 12px; 410 | text-align: center; 411 | padding: 0; 412 | border-top: 1px solid #eee; 413 | border-bottom: none; 414 | } 415 | 416 | .calendar td.selected a { 417 | background: #79aec8; 418 | color: #fff; 419 | } 420 | 421 | .calendar td.nonday { 422 | background: #f8f8f8; 423 | } 424 | 425 | .calendar td.today a { 426 | font-weight: 700; 427 | } 428 | 429 | .calendar td a, .timelist a { 430 | display: block; 431 | font-weight: 400; 432 | padding: 6px; 433 | text-decoration: none; 434 | color: #444; 435 | } 436 | 437 | .calendar td a:focus, .timelist a:focus, 438 | .calendar td a:hover, .timelist a:hover { 439 | background: #79aec8; 440 | color: white; 441 | } 442 | 443 | .calendar td a:active, .timelist a:active { 444 | background: #417690; 445 | color: white; 446 | } 447 | 448 | .calendarnav { 449 | font-size: 10px; 450 | text-align: center; 451 | color: #ccc; 452 | margin: 0; 453 | padding: 1px 3px; 454 | } 455 | 456 | .calendarnav a:link, #calendarnav a:visited, 457 | #calendarnav a:focus, #calendarnav a:hover { 458 | color: #999; 459 | } 460 | 461 | .calendar-shortcuts { 462 | background: white; 463 | font-size: 11px; 464 | line-height: 11px; 465 | border-top: 1px solid #eee; 466 | padding: 8px 0; 467 | color: #ccc; 468 | } 469 | 470 | .calendarbox .calendarnav-previous, .calendarbox .calendarnav-next { 471 | display: block; 472 | position: absolute; 473 | top: 8px; 474 | width: 15px; 475 | height: 15px; 476 | text-indent: -9999px; 477 | padding: 0; 478 | } 479 | 480 | .calendarnav-previous { 481 | left: 10px; 482 | background: url(../img/calendar-icons.svg) 0 0 no-repeat; 483 | } 484 | 485 | .calendarbox .calendarnav-previous:focus, 486 | .calendarbox .calendarnav-previous:hover { 487 | background-position: 0 -15px; 488 | } 489 | 490 | .calendarnav-next { 491 | right: 10px; 492 | background: url(../img/calendar-icons.svg) 0 -30px no-repeat; 493 | } 494 | 495 | .calendarbox .calendarnav-next:focus, 496 | .calendarbox .calendarnav-next:hover { 497 | background-position: 0 -45px; 498 | } 499 | 500 | .calendar-cancel { 501 | margin: 0; 502 | padding: 4px 0; 503 | font-size: 12px; 504 | background: #eee; 505 | border-top: 1px solid #ddd; 506 | color: #333; 507 | } 508 | 509 | .calendar-cancel:focus, .calendar-cancel:hover { 510 | background: #ddd; 511 | } 512 | 513 | .calendar-cancel a { 514 | color: black; 515 | display: block; 516 | } 517 | 518 | ul.timelist, .timelist li { 519 | list-style-type: none; 520 | margin: 0; 521 | padding: 0; 522 | } 523 | 524 | .timelist a { 525 | padding: 2px; 526 | } 527 | 528 | /* EDIT INLINE */ 529 | 530 | .inline-deletelink { 531 | float: right; 532 | text-indent: -9999px; 533 | background: url(../img/inline-delete.svg) 0 0 no-repeat; 534 | width: 16px; 535 | height: 16px; 536 | border: 0px none; 537 | } 538 | 539 | .inline-deletelink:focus, .inline-deletelink:hover { 540 | cursor: pointer; 541 | } 542 | 543 | /* RELATED WIDGET WRAPPER */ 544 | .related-widget-wrapper { 545 | float: left; /* display properly in form rows with multiple fields */ 546 | overflow: hidden; /* clear floated contents */ 547 | } 548 | 549 | .related-widget-wrapper-link { 550 | opacity: 0.3; 551 | } 552 | 553 | .related-widget-wrapper-link:link { 554 | opacity: .8; 555 | } 556 | 557 | .related-widget-wrapper-link:link:focus, 558 | .related-widget-wrapper-link:link:hover { 559 | opacity: 1; 560 | } 561 | 562 | select + .related-widget-wrapper-link, 563 | .related-widget-wrapper-link + .related-widget-wrapper-link { 564 | margin-left: 7px; 565 | } 566 | -------------------------------------------------------------------------------- /static_cdn/admin/fonts/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /static_cdn/admin/fonts/README.txt: -------------------------------------------------------------------------------- 1 | Roboto webfont source: https://www.google.com/fonts/specimen/Roboto 2 | Weights used in this project: Light (300), Regular (400), Bold (700) 3 | -------------------------------------------------------------------------------- /static_cdn/admin/fonts/Roboto-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/static_cdn/admin/fonts/Roboto-Bold-webfont.woff -------------------------------------------------------------------------------- /static_cdn/admin/fonts/Roboto-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/static_cdn/admin/fonts/Roboto-Light-webfont.woff -------------------------------------------------------------------------------- /static_cdn/admin/fonts/Roboto-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingforentrepreneurs/try-django-19/0e53ea133762ffa13e68717672dda5e0084b4504/static_cdn/admin/fonts/Roboto-Regular-webfont.woff -------------------------------------------------------------------------------- /static_cdn/admin/img/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Code Charm Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /static_cdn/admin/img/README.txt: -------------------------------------------------------------------------------- 1 | All icons are taken from Font Awesome (http://fontawesome.io/) project. 2 | The Font Awesome font is licensed under the SIL OFL 1.1: 3 | - http://scripts.sil.org/OFL 4 | 5 | SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG 6 | Font-Awesome-SVG-PNG is licensed under the MIT license (see file license 7 | in current folder). 8 | -------------------------------------------------------------------------------- /static_cdn/admin/img/calendar-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /static_cdn/admin/img/gis/move_vertex_off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static_cdn/admin/img/gis/move_vertex_on.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static_cdn/admin/img/icon-addlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/icon-alert.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/icon-calendar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /static_cdn/admin/img/icon-changelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/icon-clock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /static_cdn/admin/img/icon-deletelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/icon-no.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/icon-unknown-alt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/icon-unknown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/inline-delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/selector-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /static_cdn/admin/img/sorting-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /static_cdn/admin/img/tooltag-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/img/tooltag-arrowright.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /static_cdn/admin/js/SelectBox.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | var SelectBox = { 4 | cache: {}, 5 | init: function(id) { 6 | var box = document.getElementById(id); 7 | var node; 8 | SelectBox.cache[id] = []; 9 | var cache = SelectBox.cache[id]; 10 | for (var i = 0, j = box.options.length; i < j; i++) { 11 | node = box.options[i]; 12 | cache.push({value: node.value, text: node.text, displayed: 1}); 13 | } 14 | }, 15 | redisplay: function(id) { 16 | // Repopulate HTML select box from cache 17 | var box = document.getElementById(id); 18 | var node; 19 | box.options.length = 0; // clear all options 20 | var cache = SelectBox.cache[id]; 21 | for (var i = 0, j = cache.length; i < j; i++) { 22 | node = cache[i]; 23 | if (node.displayed) { 24 | var new_option = new Option(node.text, node.value, false, false); 25 | // Shows a tooltip when hovering over the option 26 | new_option.setAttribute("title", node.text); 27 | box.options[box.options.length] = new_option; 28 | } 29 | } 30 | }, 31 | filter: function(id, text) { 32 | // Redisplay the HTML select box, displaying only the choices containing ALL 33 | // the words in text. (It's an AND search.) 34 | var tokens = text.toLowerCase().split(/\s+/); 35 | var node, token; 36 | var cache = SelectBox.cache[id]; 37 | for (var i = 0, j = cache.length; i < j; i++) { 38 | node = cache[i]; 39 | node.displayed = 1; 40 | var numTokens = tokens.length; 41 | for (var k = 0; k < numTokens; k++) { 42 | token = tokens[k]; 43 | if (node.text.toLowerCase().indexOf(token) === -1) { 44 | node.displayed = 0; 45 | } 46 | } 47 | } 48 | SelectBox.redisplay(id); 49 | }, 50 | delete_from_cache: function(id, value) { 51 | var node, delete_index = null; 52 | var cache = SelectBox.cache[id]; 53 | for (var i = 0, j = cache.length; i < j; i++) { 54 | node = cache[i]; 55 | if (node.value === value) { 56 | delete_index = i; 57 | break; 58 | } 59 | } 60 | var k = cache.length - 1; 61 | for (i = delete_index; i < k; i++) { 62 | cache[i] = cache[i + 1]; 63 | } 64 | cache.length--; 65 | }, 66 | add_to_cache: function(id, option) { 67 | SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1}); 68 | }, 69 | cache_contains: function(id, value) { 70 | // Check if an item is contained in the cache 71 | var node; 72 | var cache = SelectBox.cache[id]; 73 | for (var i = 0, j = cache.length; i < j; i++) { 74 | node = cache[i]; 75 | if (node.value === value) { 76 | return true; 77 | } 78 | } 79 | return false; 80 | }, 81 | move: function(from, to) { 82 | var from_box = document.getElementById(from); 83 | var option; 84 | var boxOptions = from_box.options; 85 | for (var i = 0, j = boxOptions.length; i < j; i++) { 86 | option = boxOptions[i]; 87 | if (option.selected && SelectBox.cache_contains(from, option.value)) { 88 | SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1}); 89 | SelectBox.delete_from_cache(from, option.value); 90 | } 91 | } 92 | SelectBox.redisplay(from); 93 | SelectBox.redisplay(to); 94 | }, 95 | move_all: function(from, to) { 96 | var from_box = document.getElementById(from); 97 | var option; 98 | var boxOptions = from_box.options; 99 | for (var i = 0, j = boxOptions.length; i < j; i++) { 100 | option = boxOptions[i]; 101 | if (SelectBox.cache_contains(from, option.value)) { 102 | SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1}); 103 | SelectBox.delete_from_cache(from, option.value); 104 | } 105 | } 106 | SelectBox.redisplay(from); 107 | SelectBox.redisplay(to); 108 | }, 109 | sort: function(id) { 110 | SelectBox.cache[id].sort(function(a, b) { 111 | a = a.text.toLowerCase(); 112 | b = b.text.toLowerCase(); 113 | try { 114 | if (a > b) { 115 | return 1; 116 | } 117 | if (a < b) { 118 | return -1; 119 | } 120 | } 121 | catch (e) { 122 | // silently fail on IE 'unknown' exception 123 | } 124 | return 0; 125 | } ); 126 | }, 127 | select_all: function(id) { 128 | var box = document.getElementById(id); 129 | for (var i = 0; i < box.options.length; i++) { 130 | box.options[i].selected = 'selected'; 131 | } 132 | } 133 | }; 134 | window.SelectBox = SelectBox; 135 | })(); 136 | -------------------------------------------------------------------------------- /static_cdn/admin/js/SelectFilter2.js: -------------------------------------------------------------------------------- 1 | /*global SelectBox, addEvent, gettext, interpolate, quickElement, SelectFilter*/ 2 | /* 3 | SelectFilter2 - Turns a multiple-select box into a filter interface. 4 | 5 | Requires core.js, SelectBox.js and addevent.js. 6 | */ 7 | (function($) { 8 | 'use strict'; 9 | function findForm(node) { 10 | // returns the node of the form containing the given node 11 | if (node.tagName.toLowerCase() !== 'form') { 12 | return findForm(node.parentNode); 13 | } 14 | return node; 15 | } 16 | 17 | window.SelectFilter = { 18 | init: function(field_id, field_name, is_stacked) { 19 | if (field_id.match(/__prefix__/)) { 20 | // Don't initialize on empty forms. 21 | return; 22 | } 23 | var from_box = document.getElementById(field_id); 24 | from_box.id += '_from'; // change its ID 25 | from_box.className = 'filtered'; 26 | 27 | var ps = from_box.parentNode.getElementsByTagName('p'); 28 | for (var i = 0; i < ps.length; i++) { 29 | if (ps[i].className.indexOf("info") !== -1) { 30 | // Remove

, because it just gets in the way. 31 | from_box.parentNode.removeChild(ps[i]); 32 | } else if (ps[i].className.indexOf("help") !== -1) { 33 | // Move help text up to the top so it isn't below the select 34 | // boxes or wrapped off on the side to the right of the add 35 | // button: 36 | from_box.parentNode.insertBefore(ps[i], from_box.parentNode.firstChild); 37 | } 38 | } 39 | 40 | //

or
41 | var selector_div = quickElement('div', from_box.parentNode); 42 | selector_div.className = is_stacked ? 'selector stacked' : 'selector'; 43 | 44 | //
45 | var selector_available = quickElement('div', selector_div); 46 | selector_available.className = 'selector-available'; 47 | var title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name])); 48 | quickElement( 49 | 'span', title_available, '', 50 | 'class', 'help help-tooltip help-icon', 51 | 'title', interpolate( 52 | gettext( 53 | 'This is the list of available %s. You may choose some by ' + 54 | 'selecting them in the box below and then clicking the ' + 55 | '"Choose" arrow between the two boxes.' 56 | ), 57 | [field_name] 58 | ) 59 | ); 60 | 61 | var filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter'); 62 | filter_p.className = 'selector-filter'; 63 | 64 | var search_filter_label = quickElement('label', filter_p, '', 'for', field_id + '_input'); 65 | 66 | quickElement( 67 | 'span', search_filter_label, '', 68 | 'class', 'help-tooltip search-label-icon', 69 | 'title', interpolate(gettext("Type into this box to filter down the list of available %s."), [field_name]) 70 | ); 71 | 72 | filter_p.appendChild(document.createTextNode(' ')); 73 | 74 | var filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter")); 75 | filter_input.id = field_id + '_input'; 76 | 77 | selector_available.appendChild(from_box); 78 | var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', 'javascript:void(0);', 'id', field_id + '_add_all_link'); 79 | choose_all.className = 'selector-chooseall'; 80 | 81 | //
    82 | var selector_chooser = quickElement('ul', selector_div); 83 | selector_chooser.className = 'selector-chooser'; 84 | var add_link = quickElement('a', quickElement('li', selector_chooser), gettext('Choose'), 'title', gettext('Choose'), 'href', 'javascript:void(0);', 'id', field_id + '_add_link'); 85 | add_link.className = 'selector-add'; 86 | var remove_link = quickElement('a', quickElement('li', selector_chooser), gettext('Remove'), 'title', gettext('Remove'), 'href', 'javascript:void(0);', 'id', field_id + '_remove_link'); 87 | remove_link.className = 'selector-remove'; 88 | 89 | //
    90 | var selector_chosen = quickElement('div', selector_div); 91 | selector_chosen.className = 'selector-chosen'; 92 | var title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name])); 93 | quickElement( 94 | 'span', title_chosen, '', 95 | 'class', 'help help-tooltip help-icon', 96 | 'title', interpolate( 97 | gettext( 98 | 'This is the list of chosen %s. You may remove some by ' + 99 | 'selecting them in the box below and then clicking the ' + 100 | '"Remove" arrow between the two boxes.' 101 | ), 102 | [field_name] 103 | ) 104 | ); 105 | 106 | var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name')); 107 | to_box.className = 'filtered'; 108 | var clear_all = quickElement('a', selector_chosen, gettext('Remove all'), 'title', interpolate(gettext('Click to remove all chosen %s at once.'), [field_name]), 'href', 'javascript:void(0);', 'id', field_id + '_remove_all_link'); 109 | clear_all.className = 'selector-clearall'; 110 | 111 | from_box.setAttribute('name', from_box.getAttribute('name') + '_old'); 112 | 113 | // Set up the JavaScript event handlers for the select box filter interface 114 | addEvent(choose_all, 'click', function() { SelectBox.move_all(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); }); 115 | addEvent(add_link, 'click', function() { SelectBox.move(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); }); 116 | addEvent(remove_link, 'click', function() { SelectBox.move(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); }); 117 | addEvent(clear_all, 'click', function() { SelectBox.move_all(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); }); 118 | addEvent(filter_input, 'keypress', function(e) { SelectFilter.filter_key_press(e, field_id); }); 119 | addEvent(filter_input, 'keyup', function(e) { SelectFilter.filter_key_up(e, field_id); }); 120 | addEvent(filter_input, 'keydown', function(e) { SelectFilter.filter_key_down(e, field_id); }); 121 | addEvent(from_box, 'change', function(e) { SelectFilter.refresh_icons(field_id); }); 122 | addEvent(to_box, 'change', function(e) { SelectFilter.refresh_icons(field_id); }); 123 | addEvent(from_box, 'dblclick', function() { SelectBox.move(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); }); 124 | addEvent(to_box, 'dblclick', function() { SelectBox.move(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); }); 125 | addEvent(findForm(from_box), 'submit', function() { SelectBox.select_all(field_id + '_to'); }); 126 | SelectBox.init(field_id + '_from'); 127 | SelectBox.init(field_id + '_to'); 128 | // Move selected from_box options to to_box 129 | SelectBox.move(field_id + '_from', field_id + '_to'); 130 | 131 | if (!is_stacked) { 132 | // In horizontal mode, give the same height to the two boxes. 133 | var j_from_box = $(from_box); 134 | var j_to_box = $(to_box); 135 | var resize_filters = function() { j_to_box.height($(filter_p).outerHeight() + j_from_box.outerHeight()); }; 136 | if (j_from_box.outerHeight() > 0) { 137 | resize_filters(); // This fieldset is already open. Resize now. 138 | } else { 139 | // This fieldset is probably collapsed. Wait for its 'show' event. 140 | j_to_box.closest('fieldset').one('show.fieldset', resize_filters); 141 | } 142 | } 143 | 144 | // Initial icon refresh 145 | SelectFilter.refresh_icons(field_id); 146 | }, 147 | refresh_icons: function(field_id) { 148 | var from = $('#' + field_id + '_from'); 149 | var to = $('#' + field_id + '_to'); 150 | var is_from_selected = from.find('option:selected').length > 0; 151 | var is_to_selected = to.find('option:selected').length > 0; 152 | // Active if at least one item is selected 153 | $('#' + field_id + '_add_link').toggleClass('active', is_from_selected); 154 | $('#' + field_id + '_remove_link').toggleClass('active', is_to_selected); 155 | // Active if the corresponding box isn't empty 156 | $('#' + field_id + '_add_all_link').toggleClass('active', from.find('option').length > 0); 157 | $('#' + field_id + '_remove_all_link').toggleClass('active', to.find('option').length > 0); 158 | }, 159 | filter_key_press: function(event, field_id) { 160 | var from = document.getElementById(field_id + '_from'); 161 | // don't submit form if user pressed Enter 162 | if ((event.which && event.which === 13) || (event.keyCode && event.keyCode === 13)) { 163 | from.selectedIndex = 0; 164 | SelectBox.move(field_id + '_from', field_id + '_to'); 165 | from.selectedIndex = 0; 166 | event.preventDefault(); 167 | return false; 168 | } 169 | }, 170 | filter_key_up: function(event, field_id) { 171 | var from = document.getElementById(field_id + '_from'); 172 | var temp = from.selectedIndex; 173 | SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value); 174 | from.selectedIndex = temp; 175 | return true; 176 | }, 177 | filter_key_down: function(event, field_id) { 178 | var from = document.getElementById(field_id + '_from'); 179 | // right arrow -- move across 180 | if ((event.which && event.which === 39) || (event.keyCode && event.keyCode === 39)) { 181 | var old_index = from.selectedIndex; 182 | SelectBox.move(field_id + '_from', field_id + '_to'); 183 | from.selectedIndex = (old_index === from.length) ? from.length - 1 : old_index; 184 | return false; 185 | } 186 | // down arrow -- wrap around 187 | if ((event.which && event.which === 40) || (event.keyCode && event.keyCode === 40)) { 188 | from.selectedIndex = (from.length === from.selectedIndex + 1) ? 0 : from.selectedIndex + 1; 189 | } 190 | // up arrow -- wrap around 191 | if ((event.which && event.which === 38) || (event.keyCode && event.keyCode === 38)) { 192 | from.selectedIndex = (from.selectedIndex === 0) ? from.length - 1 : from.selectedIndex - 1; 193 | } 194 | return true; 195 | } 196 | }; 197 | 198 | })(django.jQuery); 199 | -------------------------------------------------------------------------------- /static_cdn/admin/js/actions.js: -------------------------------------------------------------------------------- 1 | /*global _actions_icnt, gettext, interpolate, ngettext*/ 2 | (function($) { 3 | 'use strict'; 4 | var lastChecked; 5 | 6 | $.fn.actions = function(opts) { 7 | var options = $.extend({}, $.fn.actions.defaults, opts); 8 | var actionCheckboxes = $(this); 9 | var list_editable_changed = false; 10 | var showQuestion = function() { 11 | $(options.acrossClears).hide(); 12 | $(options.acrossQuestions).show(); 13 | $(options.allContainer).hide(); 14 | }, 15 | showClear = function() { 16 | $(options.acrossClears).show(); 17 | $(options.acrossQuestions).hide(); 18 | $(options.actionContainer).toggleClass(options.selectedClass); 19 | $(options.allContainer).show(); 20 | $(options.counterContainer).hide(); 21 | }, 22 | reset = function() { 23 | $(options.acrossClears).hide(); 24 | $(options.acrossQuestions).hide(); 25 | $(options.allContainer).hide(); 26 | $(options.counterContainer).show(); 27 | }, 28 | clearAcross = function() { 29 | reset(); 30 | $(options.acrossInput).val(0); 31 | $(options.actionContainer).removeClass(options.selectedClass); 32 | }, 33 | checker = function(checked) { 34 | if (checked) { 35 | showQuestion(); 36 | } else { 37 | reset(); 38 | } 39 | $(actionCheckboxes).prop("checked", checked) 40 | .parent().parent().toggleClass(options.selectedClass, checked); 41 | }, 42 | updateCounter = function() { 43 | var sel = $(actionCheckboxes).filter(":checked").length; 44 | // _actions_icnt is defined in the generated HTML 45 | // and contains the total amount of objects in the queryset 46 | $(options.counterContainer).html(interpolate( 47 | ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), { 48 | sel: sel, 49 | cnt: _actions_icnt 50 | }, true)); 51 | $(options.allToggle).prop("checked", function() { 52 | var value; 53 | if (sel === actionCheckboxes.length) { 54 | value = true; 55 | showQuestion(); 56 | } else { 57 | value = false; 58 | clearAcross(); 59 | } 60 | return value; 61 | }); 62 | }; 63 | // Show counter by default 64 | $(options.counterContainer).show(); 65 | // Check state of checkboxes and reinit state if needed 66 | $(this).filter(":checked").each(function(i) { 67 | $(this).parent().parent().toggleClass(options.selectedClass); 68 | updateCounter(); 69 | if ($(options.acrossInput).val() === 1) { 70 | showClear(); 71 | } 72 | }); 73 | $(options.allToggle).show().click(function() { 74 | checker($(this).prop("checked")); 75 | updateCounter(); 76 | }); 77 | $("a", options.acrossQuestions).click(function(event) { 78 | event.preventDefault(); 79 | $(options.acrossInput).val(1); 80 | showClear(); 81 | }); 82 | $("a", options.acrossClears).click(function(event) { 83 | event.preventDefault(); 84 | $(options.allToggle).prop("checked", false); 85 | clearAcross(); 86 | checker(0); 87 | updateCounter(); 88 | }); 89 | lastChecked = null; 90 | $(actionCheckboxes).click(function(event) { 91 | if (!event) { event = window.event; } 92 | var target = event.target ? event.target : event.srcElement; 93 | if (lastChecked && $.data(lastChecked) !== $.data(target) && event.shiftKey === true) { 94 | var inrange = false; 95 | $(lastChecked).prop("checked", target.checked) 96 | .parent().parent().toggleClass(options.selectedClass, target.checked); 97 | $(actionCheckboxes).each(function() { 98 | if ($.data(this) === $.data(lastChecked) || $.data(this) === $.data(target)) { 99 | inrange = (inrange) ? false : true; 100 | } 101 | if (inrange) { 102 | $(this).prop("checked", target.checked) 103 | .parent().parent().toggleClass(options.selectedClass, target.checked); 104 | } 105 | }); 106 | } 107 | $(target).parent().parent().toggleClass(options.selectedClass, target.checked); 108 | lastChecked = target; 109 | updateCounter(); 110 | }); 111 | $('form#changelist-form table#result_list tr').find('td:gt(0) :input').change(function() { 112 | list_editable_changed = true; 113 | }); 114 | $('form#changelist-form button[name="index"]').click(function(event) { 115 | if (list_editable_changed) { 116 | return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.")); 117 | } 118 | }); 119 | $('form#changelist-form input[name="_save"]').click(function(event) { 120 | var action_changed = false; 121 | $('select option:selected', options.actionContainer).each(function() { 122 | if ($(this).val()) { 123 | action_changed = true; 124 | } 125 | }); 126 | if (action_changed) { 127 | if (list_editable_changed) { 128 | return confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.")); 129 | } else { 130 | return confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button.")); 131 | } 132 | } 133 | }); 134 | }; 135 | /* Setup plugin defaults */ 136 | $.fn.actions.defaults = { 137 | actionContainer: "div.actions", 138 | counterContainer: "span.action-counter", 139 | allContainer: "div.actions span.all", 140 | acrossInput: "div.actions input.select-across", 141 | acrossQuestions: "div.actions span.question", 142 | acrossClears: "div.actions span.clear", 143 | allToggle: "#action-toggle", 144 | selectedClass: "selected" 145 | }; 146 | })(django.jQuery); 147 | -------------------------------------------------------------------------------- /static_cdn/admin/js/actions.min.js: -------------------------------------------------------------------------------- 1 | (function(a){var f;a.fn.actions=function(q){var b=a.extend({},a.fn.actions.defaults,q),g=a(this),e=!1,k=function(){a(b.acrossClears).hide();a(b.acrossQuestions).show();a(b.allContainer).hide()},l=function(){a(b.acrossClears).show();a(b.acrossQuestions).hide();a(b.actionContainer).toggleClass(b.selectedClass);a(b.allContainer).show();a(b.counterContainer).hide()},m=function(){a(b.acrossClears).hide();a(b.acrossQuestions).hide();a(b.allContainer).hide();a(b.counterContainer).show()},n=function(){m(); 2 | a(b.acrossInput).val(0);a(b.actionContainer).removeClass(b.selectedClass)},p=function(c){c?k():m();a(g).prop("checked",c).parent().parent().toggleClass(b.selectedClass,c)},h=function(){var c=a(g).filter(":checked").length;a(b.counterContainer).html(interpolate(ngettext("%(sel)s of %(cnt)s selected","%(sel)s of %(cnt)s selected",c),{sel:c,cnt:_actions_icnt},!0));a(b.allToggle).prop("checked",function(){var a;c===g.length?(a=!0,k()):(a=!1,n());return a})};a(b.counterContainer).show();a(this).filter(":checked").each(function(c){a(this).parent().parent().toggleClass(b.selectedClass); 3 | h();1===a(b.acrossInput).val()&&l()});a(b.allToggle).show().click(function(){p(a(this).prop("checked"));h()});a("a",b.acrossQuestions).click(function(c){c.preventDefault();a(b.acrossInput).val(1);l()});a("a",b.acrossClears).click(function(c){c.preventDefault();a(b.allToggle).prop("checked",!1);n();p(0);h()});f=null;a(g).click(function(c){c||(c=window.event);var d=c.target?c.target:c.srcElement;if(f&&a.data(f)!==a.data(d)&&!0===c.shiftKey){var e=!1;a(f).prop("checked",d.checked).parent().parent().toggleClass(b.selectedClass, 4 | d.checked);a(g).each(function(){if(a.data(this)===a.data(f)||a.data(this)===a.data(d))e=e?!1:!0;e&&a(this).prop("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked)})}a(d).parent().parent().toggleClass(b.selectedClass,d.checked);f=d;h()});a("form#changelist-form table#result_list tr").find("td:gt(0) :input").change(function(){e=!0});a('form#changelist-form button[name="index"]').click(function(a){if(e)return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."))}); 5 | a('form#changelist-form input[name="_save"]').click(function(c){var d=!1;a("select option:selected",b.actionContainer).each(function(){a(this).val()&&(d=!0)});if(d)return e?confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.")):confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button."))})}; 6 | a.fn.actions.defaults={actionContainer:"div.actions",counterContainer:"span.action-counter",allContainer:"div.actions span.all",acrossInput:"div.actions input.select-across",acrossQuestions:"div.actions span.question",acrossClears:"div.actions span.clear",allToggle:"#action-toggle",selectedClass:"selected"}})(django.jQuery); 7 | -------------------------------------------------------------------------------- /static_cdn/admin/js/admin/DateTimeShortcuts.js: -------------------------------------------------------------------------------- 1 | /*global addEvent, Calendar, cancelEventPropagation, findPosX, findPosY, getStyle, get_format, gettext, interpolate, ngettext, quickElement, removeEvent*/ 2 | // Inserts shortcut buttons after all of the following: 3 | // 4 | // 5 | (function() { 6 | 'use strict'; 7 | var DateTimeShortcuts = { 8 | calendars: [], 9 | calendarInputs: [], 10 | clockInputs: [], 11 | dismissClockFunc: [], 12 | dismissCalendarFunc: [], 13 | calendarDivName1: 'calendarbox', // name of calendar
    that gets toggled 14 | calendarDivName2: 'calendarin', // name of
    that contains calendar 15 | calendarLinkName: 'calendarlink',// name of the link that is used to toggle 16 | clockDivName: 'clockbox', // name of clock
    that gets toggled 17 | clockLinkName: 'clocklink', // name of the link that is used to toggle 18 | shortCutsClass: 'datetimeshortcuts', // class of the clock and cal shortcuts 19 | timezoneWarningClass: 'timezonewarning', // class of the warning for timezone mismatch 20 | timezoneOffset: 0, 21 | init: function() { 22 | var body = document.getElementsByTagName('body')[0]; 23 | var serverOffset = body.getAttribute('data-admin-utc-offset'); 24 | if (serverOffset !== undefined) { 25 | var localOffset = new Date().getTimezoneOffset() * -60; 26 | DateTimeShortcuts.timezoneOffset = localOffset - serverOffset; 27 | } 28 | 29 | var inputs = document.getElementsByTagName('input'); 30 | for (var i = 0; i < inputs.length; i++) { 31 | var inp = inputs[i]; 32 | if (inp.getAttribute('type') === 'text' && inp.className.match(/vTimeField/)) { 33 | DateTimeShortcuts.addClock(inp); 34 | DateTimeShortcuts.addTimezoneWarning(inp); 35 | } 36 | else if (inp.getAttribute('type') === 'text' && inp.className.match(/vDateField/)) { 37 | DateTimeShortcuts.addCalendar(inp); 38 | DateTimeShortcuts.addTimezoneWarning(inp); 39 | } 40 | } 41 | }, 42 | // Return the current time while accounting for the server timezone. 43 | now: function() { 44 | var body = document.getElementsByTagName('body')[0]; 45 | var serverOffset = body.getAttribute('data-admin-utc-offset'); 46 | if (serverOffset !== undefined) { 47 | var localNow = new Date(); 48 | var localOffset = localNow.getTimezoneOffset() * -60; 49 | localNow.setTime(localNow.getTime() + 1000 * (serverOffset - localOffset)); 50 | return localNow; 51 | } else { 52 | return new Date(); 53 | } 54 | }, 55 | // Add a warning when the time zone in the browser and backend do not match. 56 | addTimezoneWarning: function(inp) { 57 | var $ = django.jQuery; 58 | var warningClass = DateTimeShortcuts.timezoneWarningClass; 59 | var timezoneOffset = DateTimeShortcuts.timezoneOffset / 3600; 60 | 61 | // Only warn if there is a time zone mismatch. 62 | if (!timezoneOffset) { 63 | return; 64 | } 65 | 66 | // Check if warning is already there. 67 | if ($(inp).siblings('.' + warningClass).length) { 68 | return; 69 | } 70 | 71 | var message; 72 | if (timezoneOffset > 0) { 73 | message = ngettext( 74 | 'Note: You are %s hour ahead of server time.', 75 | 'Note: You are %s hours ahead of server time.', 76 | timezoneOffset 77 | ); 78 | } 79 | else { 80 | timezoneOffset *= -1; 81 | message = ngettext( 82 | 'Note: You are %s hour behind server time.', 83 | 'Note: You are %s hours behind server time.', 84 | timezoneOffset 85 | ); 86 | } 87 | message = interpolate(message, [timezoneOffset]); 88 | 89 | var $warning = $(''); 90 | $warning.attr('class', warningClass); 91 | $warning.text(message); 92 | 93 | $(inp).parent() 94 | .append($('
    ')) 95 | .append($warning); 96 | }, 97 | // Add clock widget to a given field 98 | addClock: function(inp) { 99 | var num = DateTimeShortcuts.clockInputs.length; 100 | DateTimeShortcuts.clockInputs[num] = inp; 101 | DateTimeShortcuts.dismissClockFunc[num] = function() { DateTimeShortcuts.dismissClock(num); return true; }; 102 | 103 | // Shortcut links (clock icon and "Now" link) 104 | var shortcuts_span = document.createElement('span'); 105 | shortcuts_span.className = DateTimeShortcuts.shortCutsClass; 106 | inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling); 107 | var now_link = document.createElement('a'); 108 | now_link.setAttribute('href', "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", -1);"); 109 | now_link.appendChild(document.createTextNode(gettext('Now'))); 110 | var clock_link = document.createElement('a'); 111 | clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');'); 112 | clock_link.id = DateTimeShortcuts.clockLinkName + num; 113 | quickElement( 114 | 'span', clock_link, '', 115 | 'class', 'clock-icon', 116 | 'title', gettext('Choose a Time') 117 | ); 118 | shortcuts_span.appendChild(document.createTextNode('\u00A0')); 119 | shortcuts_span.appendChild(now_link); 120 | shortcuts_span.appendChild(document.createTextNode('\u00A0|\u00A0')); 121 | shortcuts_span.appendChild(clock_link); 122 | 123 | // Create clock link div 124 | // 125 | // Markup looks like: 126 | //
    127 | //

    Choose a time

    128 | // 135 | //

    Cancel

    136 | //
    137 | 138 | var clock_box = document.createElement('div'); 139 | clock_box.style.display = 'none'; 140 | clock_box.style.position = 'absolute'; 141 | clock_box.className = 'clockbox module'; 142 | clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num); 143 | document.body.appendChild(clock_box); 144 | addEvent(clock_box, 'click', cancelEventPropagation); 145 | 146 | quickElement('h2', clock_box, gettext('Choose a time')); 147 | var time_list = quickElement('ul', clock_box); 148 | time_list.className = 'timelist'; 149 | quickElement("a", quickElement("li", time_list), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", -1);"); 150 | quickElement("a", quickElement("li", time_list), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 0);"); 151 | quickElement("a", quickElement("li", time_list), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 6);"); 152 | quickElement("a", quickElement("li", time_list), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 12);"); 153 | quickElement("a", quickElement("li", time_list), gettext("6 p.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", 18);"); 154 | 155 | var cancel_p = quickElement('p', clock_box); 156 | cancel_p.className = 'calendar-cancel'; 157 | quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');'); 158 | django.jQuery(document).bind('keyup', function(event) { 159 | if (event.which === 27) { 160 | // ESC key closes popup 161 | DateTimeShortcuts.dismissClock(num); 162 | event.preventDefault(); 163 | } 164 | }); 165 | }, 166 | openClock: function(num) { 167 | var clock_box = document.getElementById(DateTimeShortcuts.clockDivName + num); 168 | var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName + num); 169 | 170 | // Recalculate the clockbox position 171 | // is it left-to-right or right-to-left layout ? 172 | if (getStyle(document.body, 'direction') !== 'rtl') { 173 | clock_box.style.left = findPosX(clock_link) + 17 + 'px'; 174 | } 175 | else { 176 | // since style's width is in em, it'd be tough to calculate 177 | // px value of it. let's use an estimated px for now 178 | // TODO: IE returns wrong value for findPosX when in rtl mode 179 | // (it returns as it was left aligned), needs to be fixed. 180 | clock_box.style.left = findPosX(clock_link) - 110 + 'px'; 181 | } 182 | clock_box.style.top = Math.max(0, findPosY(clock_link) - 30) + 'px'; 183 | 184 | // Show the clock box 185 | clock_box.style.display = 'block'; 186 | addEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]); 187 | }, 188 | dismissClock: function(num) { 189 | document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none'; 190 | removeEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]); 191 | }, 192 | handleClockQuicklink: function(num, val) { 193 | var d; 194 | if (val === -1) { 195 | d = DateTimeShortcuts.now(); 196 | } 197 | else { 198 | d = new Date(1970, 1, 1, val, 0, 0, 0); 199 | } 200 | DateTimeShortcuts.clockInputs[num].value = d.strftime(get_format('TIME_INPUT_FORMATS')[0]); 201 | DateTimeShortcuts.clockInputs[num].focus(); 202 | DateTimeShortcuts.dismissClock(num); 203 | }, 204 | // Add calendar widget to a given field. 205 | addCalendar: function(inp) { 206 | var num = DateTimeShortcuts.calendars.length; 207 | 208 | DateTimeShortcuts.calendarInputs[num] = inp; 209 | DateTimeShortcuts.dismissCalendarFunc[num] = function() { DateTimeShortcuts.dismissCalendar(num); return true; }; 210 | 211 | // Shortcut links (calendar icon and "Today" link) 212 | var shortcuts_span = document.createElement('span'); 213 | shortcuts_span.className = DateTimeShortcuts.shortCutsClass; 214 | inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling); 215 | var today_link = document.createElement('a'); 216 | today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);'); 217 | today_link.appendChild(document.createTextNode(gettext('Today'))); 218 | var cal_link = document.createElement('a'); 219 | cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');'); 220 | cal_link.id = DateTimeShortcuts.calendarLinkName + num; 221 | quickElement( 222 | 'span', cal_link, '', 223 | 'class', 'date-icon', 224 | 'title', gettext('Choose a Date') 225 | ); 226 | shortcuts_span.appendChild(document.createTextNode('\u00A0')); 227 | shortcuts_span.appendChild(today_link); 228 | shortcuts_span.appendChild(document.createTextNode('\u00A0|\u00A0')); 229 | shortcuts_span.appendChild(cal_link); 230 | 231 | // Create calendarbox div. 232 | // 233 | // Markup looks like: 234 | // 235 | //
    236 | //

    237 | // 238 | // February 2003 239 | //

    240 | //
    241 | // 242 | //
    243 | //
    244 | // Yesterday | Today | Tomorrow 245 | //
    246 | //

    Cancel

    247 | //
    248 | var cal_box = document.createElement('div'); 249 | cal_box.style.display = 'none'; 250 | cal_box.style.position = 'absolute'; 251 | cal_box.className = 'calendarbox module'; 252 | cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num); 253 | document.body.appendChild(cal_box); 254 | addEvent(cal_box, 'click', cancelEventPropagation); 255 | 256 | // next-prev links 257 | var cal_nav = quickElement('div', cal_box); 258 | var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev(' + num + ');'); 259 | cal_nav_prev.className = 'calendarnav-previous'; 260 | var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext(' + num + ');'); 261 | cal_nav_next.className = 'calendarnav-next'; 262 | 263 | // main box 264 | var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num); 265 | cal_main.className = 'calendar'; 266 | DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num)); 267 | DateTimeShortcuts.calendars[num].drawCurrent(); 268 | 269 | // calendar shortcuts 270 | var shortcuts = quickElement('div', cal_box); 271 | shortcuts.className = 'calendar-shortcuts'; 272 | quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);'); 273 | shortcuts.appendChild(document.createTextNode('\u00A0|\u00A0')); 274 | quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);'); 275 | shortcuts.appendChild(document.createTextNode('\u00A0|\u00A0')); 276 | quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);'); 277 | 278 | // cancel bar 279 | var cancel_p = quickElement('p', cal_box); 280 | cancel_p.className = 'calendar-cancel'; 281 | quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');'); 282 | django.jQuery(document).bind('keyup', function(event) { 283 | if (event.which === 27) { 284 | // ESC key closes popup 285 | DateTimeShortcuts.dismissCalendar(num); 286 | event.preventDefault(); 287 | } 288 | }); 289 | }, 290 | openCalendar: function(num) { 291 | var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1 + num); 292 | var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName + num); 293 | var inp = DateTimeShortcuts.calendarInputs[num]; 294 | 295 | // Determine if the current value in the input has a valid date. 296 | // If so, draw the calendar with that date's year and month. 297 | if (inp.value) { 298 | var format = get_format('DATE_INPUT_FORMATS')[0]; 299 | var selected = inp.value.strptime(format); 300 | var year = selected.getFullYear(); 301 | var month = selected.getMonth() + 1; 302 | var re = /\d{4}/; 303 | if (re.test(year.toString()) && month >= 1 && month <= 12) { 304 | DateTimeShortcuts.calendars[num].drawDate(month, year, selected); 305 | } 306 | } 307 | 308 | // Recalculate the clockbox position 309 | // is it left-to-right or right-to-left layout ? 310 | if (getStyle(document.body, 'direction') !== 'rtl') { 311 | cal_box.style.left = findPosX(cal_link) + 17 + 'px'; 312 | } 313 | else { 314 | // since style's width is in em, it'd be tough to calculate 315 | // px value of it. let's use an estimated px for now 316 | // TODO: IE returns wrong value for findPosX when in rtl mode 317 | // (it returns as it was left aligned), needs to be fixed. 318 | cal_box.style.left = findPosX(cal_link) - 180 + 'px'; 319 | } 320 | cal_box.style.top = Math.max(0, findPosY(cal_link) - 75) + 'px'; 321 | 322 | cal_box.style.display = 'block'; 323 | addEvent(document, 'click', DateTimeShortcuts.dismissCalendarFunc[num]); 324 | }, 325 | dismissCalendar: function(num) { 326 | document.getElementById(DateTimeShortcuts.calendarDivName1 + num).style.display = 'none'; 327 | removeEvent(document, 'click', DateTimeShortcuts.dismissCalendarFunc[num]); 328 | }, 329 | drawPrev: function(num) { 330 | DateTimeShortcuts.calendars[num].drawPreviousMonth(); 331 | }, 332 | drawNext: function(num) { 333 | DateTimeShortcuts.calendars[num].drawNextMonth(); 334 | }, 335 | handleCalendarCallback: function(num) { 336 | var format = get_format('DATE_INPUT_FORMATS')[0]; 337 | // the format needs to be escaped a little 338 | format = format.replace('\\', '\\\\'); 339 | format = format.replace('\r', '\\r'); 340 | format = format.replace('\n', '\\n'); 341 | format = format.replace('\t', '\\t'); 342 | format = format.replace("'", "\\'"); 343 | return ["function(y, m, d) { DateTimeShortcuts.calendarInputs[", 344 | num, 345 | "].value = new Date(y, m-1, d).strftime('", 346 | format, 347 | "');DateTimeShortcuts.calendarInputs[", 348 | num, 349 | "].focus();document.getElementById(DateTimeShortcuts.calendarDivName1+", 350 | num, 351 | ").style.display='none';}"].join(''); 352 | }, 353 | handleCalendarQuickLink: function(num, offset) { 354 | var d = DateTimeShortcuts.now(); 355 | d.setDate(d.getDate() + offset); 356 | DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]); 357 | DateTimeShortcuts.calendarInputs[num].focus(); 358 | DateTimeShortcuts.dismissCalendar(num); 359 | } 360 | }; 361 | 362 | addEvent(window, 'load', DateTimeShortcuts.init); 363 | window.DateTimeShortcuts = DateTimeShortcuts; 364 | })(); 365 | -------------------------------------------------------------------------------- /static_cdn/admin/js/admin/RelatedObjectLookups.js: -------------------------------------------------------------------------------- 1 | /*global SelectBox, interpolate*/ 2 | // Handles related-objects functionality: lookup link for raw_id_fields 3 | // and Add Another links. 4 | 5 | (function() { 6 | 'use strict'; 7 | 8 | function html_unescape(text) { 9 | // Unescape a string that was escaped using django.utils.html.escape. 10 | text = text.replace(/</g, '<'); 11 | text = text.replace(/>/g, '>'); 12 | text = text.replace(/"/g, '"'); 13 | text = text.replace(/'/g, "'"); 14 | text = text.replace(/&/g, '&'); 15 | return text; 16 | } 17 | 18 | // IE doesn't accept periods or dashes in the window name, but the element IDs 19 | // we use to generate popup window names may contain them, therefore we map them 20 | // to allowed characters in a reversible way so that we can locate the correct 21 | // element when the popup window is dismissed. 22 | function id_to_windowname(text) { 23 | text = text.replace(/\./g, '__dot__'); 24 | text = text.replace(/\-/g, '__dash__'); 25 | return text; 26 | } 27 | 28 | function windowname_to_id(text) { 29 | text = text.replace(/__dot__/g, '.'); 30 | text = text.replace(/__dash__/g, '-'); 31 | return text; 32 | } 33 | 34 | function showAdminPopup(triggeringLink, name_regexp, add_popup) { 35 | var name = triggeringLink.id.replace(name_regexp, ''); 36 | name = id_to_windowname(name); 37 | var href = triggeringLink.href; 38 | if (add_popup) { 39 | if (href.indexOf('?') === -1) { 40 | href += '?_popup=1'; 41 | } else { 42 | href += '&_popup=1'; 43 | } 44 | } 45 | var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes'); 46 | win.focus(); 47 | return false; 48 | } 49 | 50 | function showRelatedObjectLookupPopup(triggeringLink) { 51 | return showAdminPopup(triggeringLink, /^lookup_/, true); 52 | } 53 | 54 | function dismissRelatedLookupPopup(win, chosenId) { 55 | var name = windowname_to_id(win.name); 56 | var elem = document.getElementById(name); 57 | if (elem.className.indexOf('vManyToManyRawIdAdminField') !== -1 && elem.value) { 58 | elem.value += ',' + chosenId; 59 | } else { 60 | document.getElementById(name).value = chosenId; 61 | } 62 | win.close(); 63 | } 64 | 65 | function showRelatedObjectPopup(triggeringLink) { 66 | return showAdminPopup(triggeringLink, /^(change|add|delete)_/, false); 67 | } 68 | 69 | function updateRelatedObjectLinks(triggeringLink) { 70 | var $this = django.jQuery(triggeringLink); 71 | var siblings = $this.nextAll('.change-related, .delete-related'); 72 | if (!siblings.length) { 73 | return; 74 | } 75 | var value = $this.val(); 76 | if (value) { 77 | siblings.each(function() { 78 | var elm = django.jQuery(this); 79 | elm.attr('href', elm.attr('data-href-template').replace('__fk__', value)); 80 | }); 81 | } else { 82 | siblings.removeAttr('href'); 83 | } 84 | } 85 | 86 | function dismissAddRelatedObjectPopup(win, newId, newRepr) { 87 | // newId and newRepr are expected to have previously been escaped by 88 | // django.utils.html.escape. 89 | newId = html_unescape(newId); 90 | newRepr = html_unescape(newRepr); 91 | var name = windowname_to_id(win.name); 92 | var elem = document.getElementById(name); 93 | if (elem) { 94 | var elemName = elem.nodeName.toUpperCase(); 95 | if (elemName === 'SELECT') { 96 | elem.options[elem.options.length] = new Option(newRepr, newId, true, true); 97 | } else if (elemName === 'INPUT') { 98 | if (elem.className.indexOf('vManyToManyRawIdAdminField') !== -1 && elem.value) { 99 | elem.value += ',' + newId; 100 | } else { 101 | elem.value = newId; 102 | } 103 | } 104 | // Trigger a change event to update related links if required. 105 | django.jQuery(elem).trigger('change'); 106 | } else { 107 | var toId = name + "_to"; 108 | var o = new Option(newRepr, newId); 109 | SelectBox.add_to_cache(toId, o); 110 | SelectBox.redisplay(toId); 111 | } 112 | win.close(); 113 | } 114 | 115 | function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) { 116 | objId = html_unescape(objId); 117 | newRepr = html_unescape(newRepr); 118 | var id = windowname_to_id(win.name).replace(/^edit_/, ''); 119 | var selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); 120 | var selects = django.jQuery(selectsSelector); 121 | selects.find('option').each(function() { 122 | if (this.value === objId) { 123 | this.innerHTML = newRepr; 124 | this.value = newId; 125 | } 126 | }); 127 | win.close(); 128 | } 129 | 130 | function dismissDeleteRelatedObjectPopup(win, objId) { 131 | objId = html_unescape(objId); 132 | var id = windowname_to_id(win.name).replace(/^delete_/, ''); 133 | var selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); 134 | var selects = django.jQuery(selectsSelector); 135 | selects.find('option').each(function() { 136 | if (this.value === objId) { 137 | django.jQuery(this).remove(); 138 | } 139 | }).trigger('change'); 140 | win.close(); 141 | } 142 | 143 | // Global for testing purposes 144 | window.html_unescape = html_unescape; 145 | window.id_to_windowname = id_to_windowname; 146 | window.windowname_to_id = windowname_to_id; 147 | 148 | window.showRelatedObjectLookupPopup = showRelatedObjectLookupPopup; 149 | window.dismissRelatedLookupPopup = dismissRelatedLookupPopup; 150 | window.showRelatedObjectPopup = showRelatedObjectPopup; 151 | window.updateRelatedObjectLinks = updateRelatedObjectLinks; 152 | window.dismissAddRelatedObjectPopup = dismissAddRelatedObjectPopup; 153 | window.dismissChangeRelatedObjectPopup = dismissChangeRelatedObjectPopup; 154 | window.dismissDeleteRelatedObjectPopup = dismissDeleteRelatedObjectPopup; 155 | 156 | // Kept for backward compatibility 157 | window.showAddAnotherPopup = showRelatedObjectPopup; 158 | window.dismissAddAnotherPopup = dismissAddRelatedObjectPopup; 159 | 160 | })(); 161 | -------------------------------------------------------------------------------- /static_cdn/admin/js/calendar.js: -------------------------------------------------------------------------------- 1 | /*global gettext, get_format, quickElement, removeChildren*/ 2 | /* 3 | calendar.js - Calendar functions by Adrian Holovaty 4 | depends on core.js for utility functions like removeChildren or quickElement 5 | */ 6 | 7 | (function() { 8 | 'use strict'; 9 | // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions 10 | var CalendarNamespace = { 11 | monthsOfYear: gettext('January February March April May June July August September October November December').split(' '), 12 | daysOfWeek: gettext('S M T W T F S').split(' '), 13 | firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')), 14 | isLeapYear: function(year) { 15 | return (((year % 4) === 0) && ((year % 100) !== 0 ) || ((year % 400) === 0)); 16 | }, 17 | getDaysInMonth: function(month, year) { 18 | var days; 19 | if (month === 1 || month === 3 || month === 5 || month === 7 || month === 8 || month === 10 || month === 12) { 20 | days = 31; 21 | } 22 | else if (month === 4 || month === 6 || month === 9 || month === 11) { 23 | days = 30; 24 | } 25 | else if (month === 2 && CalendarNamespace.isLeapYear(year)) { 26 | days = 29; 27 | } 28 | else { 29 | days = 28; 30 | } 31 | return days; 32 | }, 33 | draw: function(month, year, div_id, callback, selected) { // month = 1-12, year = 1-9999 34 | var today = new Date(); 35 | var todayDay = today.getDate(); 36 | var todayMonth = today.getMonth() + 1; 37 | var todayYear = today.getFullYear(); 38 | var todayClass = ''; 39 | 40 | // Use UTC functions here because the date field does not contain time 41 | // and using the UTC function variants prevent the local time offset 42 | // from altering the date, specifically the day field. For example: 43 | // 44 | // ``` 45 | // var x = new Date('2013-10-02'); 46 | // var day = x.getDate(); 47 | // ``` 48 | // 49 | // The day variable above will be 1 instead of 2 in, say, US Pacific time 50 | // zone. 51 | var isSelectedMonth = false; 52 | if (typeof selected !== 'undefined') { 53 | isSelectedMonth = (selected.getUTCFullYear() === year && (selected.getUTCMonth() + 1) === month); 54 | } 55 | 56 | month = parseInt(month); 57 | year = parseInt(year); 58 | var calDiv = document.getElementById(div_id); 59 | removeChildren(calDiv); 60 | var calTable = document.createElement('table'); 61 | quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month - 1] + ' ' + year); 62 | var tableBody = quickElement('tbody', calTable); 63 | 64 | // Draw days-of-week header 65 | var tableRow = quickElement('tr', tableBody); 66 | for (var i = 0; i < 7; i++) { 67 | quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]); 68 | } 69 | 70 | var startingPos = new Date(year, month - 1, 1 - CalendarNamespace.firstDayOfWeek).getDay(); 71 | var days = CalendarNamespace.getDaysInMonth(month, year); 72 | 73 | var nonDayCell; 74 | 75 | // Draw blanks before first of month 76 | tableRow = quickElement('tr', tableBody); 77 | for (i = 0; i < startingPos; i++) { 78 | nonDayCell = quickElement('td', tableRow, ' '); 79 | nonDayCell.className = "nonday"; 80 | } 81 | 82 | // Draw days of month 83 | var currentDay = 1; 84 | for (i = startingPos; currentDay <= days; i++) { 85 | if (i % 7 === 0 && currentDay !== 1) { 86 | tableRow = quickElement('tr', tableBody); 87 | } 88 | if ((currentDay === todayDay) && (month === todayMonth) && (year === todayYear)) { 89 | todayClass = 'today'; 90 | } else { 91 | todayClass = ''; 92 | } 93 | 94 | // use UTC function; see above for explanation. 95 | if (isSelectedMonth && currentDay === selected.getUTCDate()) { 96 | if (todayClass !== '') { 97 | todayClass += " "; 98 | } 99 | todayClass += "selected"; 100 | } 101 | 102 | var cell = quickElement('td', tableRow, '', 'class', todayClass); 103 | 104 | quickElement('a', cell, currentDay, 'href', 'javascript:void(' + callback + '(' + year + ',' + month + ',' + currentDay + '));'); 105 | currentDay++; 106 | } 107 | 108 | // Draw blanks after end of month (optional, but makes for valid code) 109 | while (tableRow.childNodes.length < 7) { 110 | nonDayCell = quickElement('td', tableRow, ' '); 111 | nonDayCell.className = "nonday"; 112 | } 113 | 114 | calDiv.appendChild(calTable); 115 | } 116 | }; 117 | 118 | // Calendar -- A calendar instance 119 | function Calendar(div_id, callback, selected) { 120 | // div_id (string) is the ID of the element in which the calendar will 121 | // be displayed 122 | // callback (string) is the name of a JavaScript function that will be 123 | // called with the parameters (year, month, day) when a day in the 124 | // calendar is clicked 125 | this.div_id = div_id; 126 | this.callback = callback; 127 | this.today = new Date(); 128 | this.currentMonth = this.today.getMonth() + 1; 129 | this.currentYear = this.today.getFullYear(); 130 | if (typeof selected !== 'undefined') { 131 | this.selected = selected; 132 | } 133 | } 134 | Calendar.prototype = { 135 | drawCurrent: function() { 136 | CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback, this.selected); 137 | }, 138 | drawDate: function(month, year, selected) { 139 | this.currentMonth = month; 140 | this.currentYear = year; 141 | 142 | if(selected) { 143 | this.selected = selected; 144 | } 145 | 146 | this.drawCurrent(); 147 | }, 148 | drawPreviousMonth: function() { 149 | if (this.currentMonth === 1) { 150 | this.currentMonth = 12; 151 | this.currentYear--; 152 | } 153 | else { 154 | this.currentMonth--; 155 | } 156 | this.drawCurrent(); 157 | }, 158 | drawNextMonth: function() { 159 | if (this.currentMonth === 12) { 160 | this.currentMonth = 1; 161 | this.currentYear++; 162 | } 163 | else { 164 | this.currentMonth++; 165 | } 166 | this.drawCurrent(); 167 | }, 168 | drawPreviousYear: function() { 169 | this.currentYear--; 170 | this.drawCurrent(); 171 | }, 172 | drawNextYear: function() { 173 | this.currentYear++; 174 | this.drawCurrent(); 175 | } 176 | }; 177 | window.Calendar = Calendar; 178 | })(); 179 | -------------------------------------------------------------------------------- /static_cdn/admin/js/collapse.js: -------------------------------------------------------------------------------- 1 | /*global gettext*/ 2 | (function($) { 3 | 'use strict'; 4 | $(document).ready(function() { 5 | // Add anchor tag for Show/Hide link 6 | $("fieldset.collapse").each(function(i, elem) { 7 | // Don't hide if fields in this fieldset have errors 8 | if ($(elem).find("div.errors").length === 0) { 9 | $(elem).addClass("collapsed").find("h2").first().append(' (' + gettext("Show") + 11 | ')'); 12 | } 13 | }); 14 | // Add toggle to anchor tag 15 | $("fieldset.collapse a.collapse-toggle").click(function(ev) { 16 | if ($(this).closest("fieldset").hasClass("collapsed")) { 17 | // Show 18 | $(this).text(gettext("Hide")).closest("fieldset").removeClass("collapsed").trigger("show.fieldset", [$(this).attr("id")]); 19 | } else { 20 | // Hide 21 | $(this).text(gettext("Show")).closest("fieldset").addClass("collapsed").trigger("hide.fieldset", [$(this).attr("id")]); 22 | } 23 | return false; 24 | }); 25 | }); 26 | })(django.jQuery); 27 | -------------------------------------------------------------------------------- /static_cdn/admin/js/collapse.min.js: -------------------------------------------------------------------------------- 1 | (function(a){a(document).ready(function(){a("fieldset.collapse").each(function(b,c){0===a(c).find("div.errors").length&&a(c).addClass("collapsed").find("h2").first().append(' ('+gettext("Show")+")")});a("fieldset.collapse a.collapse-toggle").click(function(b){a(this).closest("fieldset").hasClass("collapsed")?a(this).text(gettext("Hide")).closest("fieldset").removeClass("collapsed").trigger("show.fieldset",[a(this).attr("id")]):a(this).text(gettext("Show")).closest("fieldset").addClass("collapsed").trigger("hide.fieldset", 2 | [a(this).attr("id")]);return!1})})})(django.jQuery); 3 | -------------------------------------------------------------------------------- /static_cdn/admin/js/core.js: -------------------------------------------------------------------------------- 1 | // Core javascript helper functions 2 | 3 | // basic browser identification & version 4 | var isOpera = (navigator.userAgent.indexOf("Opera") >= 0) && parseFloat(navigator.appVersion); 5 | var isIE = ((document.all) && (!isOpera)) && parseFloat(navigator.appVersion.split("MSIE ")[1].split(";")[0]); 6 | 7 | // Cross-browser event handlers. 8 | function addEvent(obj, evType, fn) { 9 | 'use strict'; 10 | if (obj.addEventListener) { 11 | obj.addEventListener(evType, fn, false); 12 | return true; 13 | } else if (obj.attachEvent) { 14 | var r = obj.attachEvent("on" + evType, fn); 15 | return r; 16 | } else { 17 | return false; 18 | } 19 | } 20 | 21 | function removeEvent(obj, evType, fn) { 22 | 'use strict'; 23 | if (obj.removeEventListener) { 24 | obj.removeEventListener(evType, fn, false); 25 | return true; 26 | } else if (obj.detachEvent) { 27 | obj.detachEvent("on" + evType, fn); 28 | return true; 29 | } else { 30 | return false; 31 | } 32 | } 33 | 34 | function cancelEventPropagation(e) { 35 | 'use strict'; 36 | if (!e) { 37 | e = window.event; 38 | } 39 | e.cancelBubble = true; 40 | if (e.stopPropagation) { 41 | e.stopPropagation(); 42 | } 43 | } 44 | 45 | // quickElement(tagType, parentReference [, textInChildNode, attribute, attributeValue ...]); 46 | function quickElement() { 47 | 'use strict'; 48 | var obj = document.createElement(arguments[0]); 49 | if (arguments[2]) { 50 | var textNode = document.createTextNode(arguments[2]); 51 | obj.appendChild(textNode); 52 | } 53 | var len = arguments.length; 54 | for (var i = 3; i < len; i += 2) { 55 | obj.setAttribute(arguments[i], arguments[i + 1]); 56 | } 57 | arguments[1].appendChild(obj); 58 | return obj; 59 | } 60 | 61 | // "a" is reference to an object 62 | function removeChildren(a) { 63 | 'use strict'; 64 | while (a.hasChildNodes()) { 65 | a.removeChild(a.lastChild); 66 | } 67 | } 68 | 69 | // ---------------------------------------------------------------------------- 70 | // Cross-browser xmlhttp object 71 | // from http://jibbering.com/2002/4/httprequest.html 72 | // ---------------------------------------------------------------------------- 73 | var xmlhttp; 74 | /*@cc_on @*/ 75 | /*@if (@_jscript_version >= 5) 76 | try { 77 | xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); 78 | } catch (e) { 79 | try { 80 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); 81 | } catch (E) { 82 | xmlhttp = false; 83 | } 84 | } 85 | @else 86 | xmlhttp = false; 87 | @end @*/ 88 | if (!xmlhttp && typeof XMLHttpRequest !== 'undefined') { 89 | xmlhttp = new XMLHttpRequest(); 90 | } 91 | 92 | // ---------------------------------------------------------------------------- 93 | // Find-position functions by PPK 94 | // See http://www.quirksmode.org/js/findpos.html 95 | // ---------------------------------------------------------------------------- 96 | function findPosX(obj) { 97 | 'use strict'; 98 | var curleft = 0; 99 | if (obj.offsetParent) { 100 | while (obj.offsetParent) { 101 | curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft); 102 | obj = obj.offsetParent; 103 | } 104 | // IE offsetParent does not include the top-level 105 | if (isIE && obj.parentElement) { 106 | curleft += obj.offsetLeft - obj.scrollLeft; 107 | } 108 | } else if (obj.x) { 109 | curleft += obj.x; 110 | } 111 | return curleft; 112 | } 113 | 114 | function findPosY(obj) { 115 | 'use strict'; 116 | var curtop = 0; 117 | if (obj.offsetParent) { 118 | while (obj.offsetParent) { 119 | curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop); 120 | obj = obj.offsetParent; 121 | } 122 | // IE offsetParent does not include the top-level 123 | if (isIE && obj.parentElement) { 124 | curtop += obj.offsetTop - obj.scrollTop; 125 | } 126 | } else if (obj.y) { 127 | curtop += obj.y; 128 | } 129 | return curtop; 130 | } 131 | 132 | //----------------------------------------------------------------------------- 133 | // Date object extensions 134 | // ---------------------------------------------------------------------------- 135 | (function() { 136 | 'use strict'; 137 | Date.prototype.getTwelveHours = function() { 138 | var hours = this.getHours(); 139 | if (hours === 0) { 140 | return 12; 141 | } 142 | else { 143 | return hours <= 12 ? hours : hours - 12; 144 | } 145 | }; 146 | 147 | Date.prototype.getTwoDigitMonth = function() { 148 | return (this.getMonth() < 9) ? '0' + (this.getMonth() + 1) : (this.getMonth() + 1); 149 | }; 150 | 151 | Date.prototype.getTwoDigitDate = function() { 152 | return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate(); 153 | }; 154 | 155 | Date.prototype.getTwoDigitTwelveHour = function() { 156 | return (this.getTwelveHours() < 10) ? '0' + this.getTwelveHours() : this.getTwelveHours(); 157 | }; 158 | 159 | Date.prototype.getTwoDigitHour = function() { 160 | return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours(); 161 | }; 162 | 163 | Date.prototype.getTwoDigitMinute = function() { 164 | return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes(); 165 | }; 166 | 167 | Date.prototype.getTwoDigitSecond = function() { 168 | return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds(); 169 | }; 170 | 171 | Date.prototype.getHourMinute = function() { 172 | return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute(); 173 | }; 174 | 175 | Date.prototype.getHourMinuteSecond = function() { 176 | return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond(); 177 | }; 178 | 179 | Date.prototype.strftime = function(format) { 180 | var fields = { 181 | c: this.toString(), 182 | d: this.getTwoDigitDate(), 183 | H: this.getTwoDigitHour(), 184 | I: this.getTwoDigitTwelveHour(), 185 | m: this.getTwoDigitMonth(), 186 | M: this.getTwoDigitMinute(), 187 | p: (this.getHours() >= 12) ? 'PM' : 'AM', 188 | S: this.getTwoDigitSecond(), 189 | w: '0' + this.getDay(), 190 | x: this.toLocaleDateString(), 191 | X: this.toLocaleTimeString(), 192 | y: ('' + this.getFullYear()).substr(2, 4), 193 | Y: '' + this.getFullYear(), 194 | '%': '%' 195 | }; 196 | var result = '', i = 0; 197 | while (i < format.length) { 198 | if (format.charAt(i) === '%') { 199 | result = result + fields[format.charAt(i + 1)]; 200 | ++i; 201 | } 202 | else { 203 | result = result + format.charAt(i); 204 | } 205 | ++i; 206 | } 207 | return result; 208 | }; 209 | 210 | // ---------------------------------------------------------------------------- 211 | // String object extensions 212 | // ---------------------------------------------------------------------------- 213 | String.prototype.pad_left = function(pad_length, pad_string) { 214 | var new_string = this; 215 | for (var i = 0; new_string.length < pad_length; i++) { 216 | new_string = pad_string + new_string; 217 | } 218 | return new_string; 219 | }; 220 | 221 | String.prototype.strptime = function(format) { 222 | var split_format = format.split(/[.\-/]/); 223 | var date = this.split(/[.\-/]/); 224 | var i = 0; 225 | var day, month, year; 226 | while (i < split_format.length) { 227 | switch (split_format[i]) { 228 | case "%d": 229 | day = date[i]; 230 | break; 231 | case "%m": 232 | month = date[i] - 1; 233 | break; 234 | case "%Y": 235 | year = date[i]; 236 | break; 237 | case "%y": 238 | year = date[i]; 239 | break; 240 | } 241 | ++i; 242 | } 243 | return new Date(year, month, day); 244 | }; 245 | 246 | })(); 247 | // ---------------------------------------------------------------------------- 248 | // Get the computed style for and element 249 | // ---------------------------------------------------------------------------- 250 | function getStyle(oElm, strCssRule) { 251 | 'use strict'; 252 | var strValue = ""; 253 | if(document.defaultView && document.defaultView.getComputedStyle) { 254 | strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule); 255 | } 256 | else if(oElm.currentStyle) { 257 | strCssRule = strCssRule.replace(/\-(\w)/g, function(strMatch, p1) { 258 | return p1.toUpperCase(); 259 | }); 260 | strValue = oElm.currentStyle[strCssRule]; 261 | } 262 | return strValue; 263 | } 264 | -------------------------------------------------------------------------------- /static_cdn/admin/js/inlines.js: -------------------------------------------------------------------------------- 1 | /*global DateTimeShortcuts, SelectFilter*/ 2 | /** 3 | * Django admin inlines 4 | * 5 | * Based on jQuery Formset 1.1 6 | * @author Stanislaus Madueke (stan DOT madueke AT gmail DOT com) 7 | * @requires jQuery 1.2.6 or later 8 | * 9 | * Copyright (c) 2009, Stanislaus Madueke 10 | * All rights reserved. 11 | * 12 | * Spiced up with Code from Zain Memon's GSoC project 2009 13 | * and modified for Django by Jannis Leidel, Travis Swicegood and Julien Phalip. 14 | * 15 | * Licensed under the New BSD License 16 | * See: http://www.opensource.org/licenses/bsd-license.php 17 | */ 18 | (function($) { 19 | 'use strict'; 20 | $.fn.formset = function(opts) { 21 | var options = $.extend({}, $.fn.formset.defaults, opts); 22 | var $this = $(this); 23 | var $parent = $this.parent(); 24 | var updateElementIndex = function(el, prefix, ndx) { 25 | var id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))"); 26 | var replacement = prefix + "-" + ndx; 27 | if ($(el).prop("for")) { 28 | $(el).prop("for", $(el).prop("for").replace(id_regex, replacement)); 29 | } 30 | if (el.id) { 31 | el.id = el.id.replace(id_regex, replacement); 32 | } 33 | if (el.name) { 34 | el.name = el.name.replace(id_regex, replacement); 35 | } 36 | }; 37 | var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off"); 38 | var nextIndex = parseInt(totalForms.val(), 10); 39 | var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off"); 40 | // only show the add button if we are allowed to add more items, 41 | // note that max_num = None translates to a blank string. 42 | var showAddButton = maxForms.val() === '' || (maxForms.val() - totalForms.val()) > 0; 43 | $this.each(function(i) { 44 | $(this).not("." + options.emptyCssClass).addClass(options.formCssClass); 45 | }); 46 | if ($this.length && showAddButton) { 47 | var addButton; 48 | if ($this.prop("tagName") === "TR") { 49 | // If forms are laid out as table rows, insert the 50 | // "add" button in a new table row: 51 | var numCols = this.eq(-1).children().length; 52 | $parent.append('' + options.addText + ""); 53 | addButton = $parent.find("tr:last a"); 54 | } else { 55 | // Otherwise, insert it immediately after the last form: 56 | $this.filter(":last").after('"); 57 | addButton = $this.filter(":last").next().find("a"); 58 | } 59 | addButton.click(function(e) { 60 | e.preventDefault(); 61 | var template = $("#" + options.prefix + "-empty"); 62 | var row = template.clone(true); 63 | row.removeClass(options.emptyCssClass) 64 | .addClass(options.formCssClass) 65 | .attr("id", options.prefix + "-" + nextIndex); 66 | if (row.is("tr")) { 67 | // If the forms are laid out in table rows, insert 68 | // the remove button into the last table cell: 69 | row.children(":last").append('"); 70 | } else if (row.is("ul") || row.is("ol")) { 71 | // If they're laid out as an ordered/unordered list, 72 | // insert an
  • after the last list item: 73 | row.append('
  • ' + options.deleteText + "
  • "); 74 | } else { 75 | // Otherwise, just insert the remove button as the 76 | // last child element of the form's container: 77 | row.children(":first").append('' + options.deleteText + ""); 78 | } 79 | row.find("*").each(function() { 80 | updateElementIndex(this, options.prefix, totalForms.val()); 81 | }); 82 | // Insert the new form when it has been fully edited 83 | row.insertBefore($(template)); 84 | // Update number of total forms 85 | $(totalForms).val(parseInt(totalForms.val(), 10) + 1); 86 | nextIndex += 1; 87 | // Hide add button in case we've hit the max, except we want to add infinitely 88 | if ((maxForms.val() !== '') && (maxForms.val() - totalForms.val()) <= 0) { 89 | addButton.parent().hide(); 90 | } 91 | // The delete button of each row triggers a bunch of other things 92 | row.find("a." + options.deleteCssClass).click(function(e1) { 93 | e1.preventDefault(); 94 | // Remove the parent form containing this button: 95 | row.remove(); 96 | nextIndex -= 1; 97 | // If a post-delete callback was provided, call it with the deleted form: 98 | if (options.removed) { 99 | options.removed(row); 100 | } 101 | $(document).trigger('formset:removed', [row, options.prefix]); 102 | // Update the TOTAL_FORMS form count. 103 | var forms = $("." + options.formCssClass); 104 | $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length); 105 | // Show add button again once we drop below max 106 | if ((maxForms.val() === '') || (maxForms.val() - forms.length) > 0) { 107 | addButton.parent().show(); 108 | } 109 | // Also, update names and ids for all remaining form controls 110 | // so they remain in sequence: 111 | var i, formCount; 112 | var updateElementCallback = function() { 113 | updateElementIndex(this, options.prefix, i); 114 | }; 115 | for (i = 0, formCount = forms.length; i < formCount; i++) { 116 | updateElementIndex($(forms).get(i), options.prefix, i); 117 | $(forms.get(i)).find("*").each(updateElementCallback); 118 | } 119 | }); 120 | // If a post-add callback was supplied, call it with the added form: 121 | if (options.added) { 122 | options.added(row); 123 | } 124 | $(document).trigger('formset:added', [row, options.prefix]); 125 | }); 126 | } 127 | return this; 128 | }; 129 | 130 | /* Setup plugin defaults */ 131 | $.fn.formset.defaults = { 132 | prefix: "form", // The form prefix for your django formset 133 | addText: "add another", // Text for the add link 134 | deleteText: "remove", // Text for the delete link 135 | addCssClass: "add-row", // CSS class applied to the add link 136 | deleteCssClass: "delete-row", // CSS class applied to the delete link 137 | emptyCssClass: "empty-row", // CSS class applied to the empty row 138 | formCssClass: "dynamic-form", // CSS class applied to each form in a formset 139 | added: null, // Function called each time a new form is added 140 | removed: null // Function called each time a form is deleted 141 | }; 142 | 143 | 144 | // Tabular inlines --------------------------------------------------------- 145 | $.fn.tabularFormset = function(options) { 146 | var $rows = $(this); 147 | var alternatingRows = function(row) { 148 | $($rows.selector).not(".add-row").removeClass("row1 row2") 149 | .filter(":even").addClass("row1").end() 150 | .filter(":odd").addClass("row2"); 151 | }; 152 | 153 | var reinitDateTimeShortCuts = function() { 154 | // Reinitialize the calendar and clock widgets by force 155 | if (typeof DateTimeShortcuts !== "undefined") { 156 | $(".datetimeshortcuts").remove(); 157 | DateTimeShortcuts.init(); 158 | } 159 | }; 160 | 161 | var updateSelectFilter = function() { 162 | // If any SelectFilter widgets are a part of the new form, 163 | // instantiate a new SelectFilter instance for it. 164 | if (typeof SelectFilter !== 'undefined') { 165 | $('.selectfilter').each(function(index, value) { 166 | var namearr = value.name.split('-'); 167 | SelectFilter.init(value.id, namearr[namearr.length - 1], false); 168 | }); 169 | $('.selectfilterstacked').each(function(index, value) { 170 | var namearr = value.name.split('-'); 171 | SelectFilter.init(value.id, namearr[namearr.length - 1], true); 172 | }); 173 | } 174 | }; 175 | 176 | var initPrepopulatedFields = function(row) { 177 | row.find('.prepopulated_field').each(function() { 178 | var field = $(this), 179 | input = field.find('input, select, textarea'), 180 | dependency_list = input.data('dependency_list') || [], 181 | dependencies = []; 182 | $.each(dependency_list, function(i, field_name) { 183 | dependencies.push('#' + row.find('.field-' + field_name).find('input, select, textarea').attr('id')); 184 | }); 185 | if (dependencies.length) { 186 | input.prepopulate(dependencies, input.attr('maxlength')); 187 | } 188 | }); 189 | }; 190 | 191 | $rows.formset({ 192 | prefix: options.prefix, 193 | addText: options.addText, 194 | formCssClass: "dynamic-" + options.prefix, 195 | deleteCssClass: "inline-deletelink", 196 | deleteText: options.deleteText, 197 | emptyCssClass: "empty-form", 198 | removed: alternatingRows, 199 | added: function(row) { 200 | initPrepopulatedFields(row); 201 | reinitDateTimeShortCuts(); 202 | updateSelectFilter(); 203 | alternatingRows(row); 204 | } 205 | }); 206 | 207 | return $rows; 208 | }; 209 | 210 | // Stacked inlines --------------------------------------------------------- 211 | $.fn.stackedFormset = function(options) { 212 | var $rows = $(this); 213 | var updateInlineLabel = function(row) { 214 | $($rows.selector).find(".inline_label").each(function(i) { 215 | var count = i + 1; 216 | $(this).html($(this).html().replace(/(#\d+)/g, "#" + count)); 217 | }); 218 | }; 219 | 220 | var reinitDateTimeShortCuts = function() { 221 | // Reinitialize the calendar and clock widgets by force, yuck. 222 | if (typeof DateTimeShortcuts !== "undefined") { 223 | $(".datetimeshortcuts").remove(); 224 | DateTimeShortcuts.init(); 225 | } 226 | }; 227 | 228 | var updateSelectFilter = function() { 229 | // If any SelectFilter widgets were added, instantiate a new instance. 230 | if (typeof SelectFilter !== "undefined") { 231 | $(".selectfilter").each(function(index, value) { 232 | var namearr = value.name.split('-'); 233 | SelectFilter.init(value.id, namearr[namearr.length - 1], false); 234 | }); 235 | $(".selectfilterstacked").each(function(index, value) { 236 | var namearr = value.name.split('-'); 237 | SelectFilter.init(value.id, namearr[namearr.length - 1], true); 238 | }); 239 | } 240 | }; 241 | 242 | var initPrepopulatedFields = function(row) { 243 | row.find('.prepopulated_field').each(function() { 244 | var field = $(this), 245 | input = field.find('input, select, textarea'), 246 | dependency_list = input.data('dependency_list') || [], 247 | dependencies = []; 248 | $.each(dependency_list, function(i, field_name) { 249 | dependencies.push('#' + row.find('.form-row .field-' + field_name).find('input, select, textarea').attr('id')); 250 | }); 251 | if (dependencies.length) { 252 | input.prepopulate(dependencies, input.attr('maxlength')); 253 | } 254 | }); 255 | }; 256 | 257 | $rows.formset({ 258 | prefix: options.prefix, 259 | addText: options.addText, 260 | formCssClass: "dynamic-" + options.prefix, 261 | deleteCssClass: "inline-deletelink", 262 | deleteText: options.deleteText, 263 | emptyCssClass: "empty-form", 264 | removed: updateInlineLabel, 265 | added: function(row) { 266 | initPrepopulatedFields(row); 267 | reinitDateTimeShortCuts(); 268 | updateSelectFilter(); 269 | updateInlineLabel(row); 270 | } 271 | }); 272 | 273 | return $rows; 274 | }; 275 | })(django.jQuery); 276 | -------------------------------------------------------------------------------- /static_cdn/admin/js/inlines.min.js: -------------------------------------------------------------------------------- 1 | (function(b){b.fn.formset=function(d){var a=b.extend({},b.fn.formset.defaults,d),e=b(this);d=e.parent();var k=function(a,f,l){var c=new RegExp("("+f+"-(\\d+|__prefix__))");f=f+"-"+l;b(a).prop("for")&&b(a).prop("for",b(a).prop("for").replace(c,f));a.id&&(a.id=a.id.replace(c,f));a.name&&(a.name=a.name.replace(c,f))},h=b("#id_"+a.prefix+"-TOTAL_FORMS").prop("autocomplete","off"),l=parseInt(h.val(),10),f=b("#id_"+a.prefix+"-MAX_NUM_FORMS").prop("autocomplete","off"),c=""===f.val()||0'+a.addText+""),m=d.find("tr:last a")):(e.filter(":last").after('"),m=e.filter(":last").next().find("a"));m.click(function(c){c.preventDefault();c=b("#"+a.prefix+ 3 | "-empty");var g=c.clone(!0);g.removeClass(a.emptyCssClass).addClass(a.formCssClass).attr("id",a.prefix+"-"+l);g.is("tr")?g.children(":last").append('"):g.is("ul")||g.is("ol")?g.append('
  • '+a.deleteText+"
  • "):g.children(":first").append(''+a.deleteText+"");g.find("*").each(function(){k(this, 4 | a.prefix,h.val())});g.insertBefore(b(c));b(h).val(parseInt(h.val(),10)+1);l+=1;""!==f.val()&&0>=f.val()-h.val()&&m.parent().hide();g.find("a."+a.deleteCssClass).click(function(c){c.preventDefault();g.remove();--l;a.removed&&a.removed(g);b(document).trigger("formset:removed",[g,a.prefix]);c=b("."+a.formCssClass);b("#id_"+a.prefix+"-TOTAL_FORMS").val(c.length);(""===f.val()||0 0) { 26 | values.push(field.val()); 27 | } 28 | }); 29 | prepopulatedField.val(URLify(values.join(' '), maxLength, allowUnicode)); 30 | }; 31 | 32 | prepopulatedField.data('_changed', false); 33 | prepopulatedField.change(function() { 34 | prepopulatedField.data('_changed', true); 35 | }); 36 | 37 | if (!prepopulatedField.val()) { 38 | $(dependencies.join(',')).keyup(populate).change(populate).focus(populate); 39 | } 40 | }); 41 | }; 42 | })(django.jQuery); 43 | -------------------------------------------------------------------------------- /static_cdn/admin/js/prepopulate.min.js: -------------------------------------------------------------------------------- 1 | (function(c){c.fn.prepopulate=function(e,f,g){return this.each(function(){var a=c(this),b=function(){if(!a.data("_changed")){var b=[];c.each(e,function(a,d){d=c(d);0 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /static_cdn/css/base.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: #777777; 3 | } -------------------------------------------------------------------------------- /trydjango19.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": "." 6 | } 7 | ] 8 | } 9 | --------------------------------------------------------------------------------