From 71a83694f37b3daf751410191a39e884c65f2658 Mon Sep 17 00:00:00 2001 From: Nazar Kotyuk Date: Thu, 17 Jul 2014 17:07:51 +0300 Subject: [PATCH] Hotels --- .gitignore | 4 +- article/admin.py | 10 + article/admin_blog.py | 10 + article/forms.py | 30 +- article/models.py | 38 +- city/management/commands/create_hotels.py | 88 +++ city/management/commands/hotel_photos.py | 89 +++ city/models.py | 20 + functions/search_forms.py | 6 +- place_conference/models.py | 2 +- place_exposition/models.py | 22 +- proj/admin_urls.py | 1 + proj/settings.py | 1 + proj/urls.py | 7 + proj/views.py | 7 +- static/debug_toolbar/.DS_Store | Bin 0 -> 6148 bytes static/debug_toolbar/css/toolbar.css | 649 +++++++++++++++++++ static/debug_toolbar/img/ajax-loader.gif | Bin 0 -> 404 bytes static/debug_toolbar/img/back.png | Bin 0 -> 574 bytes static/debug_toolbar/img/back_hover.png | Bin 0 -> 613 bytes static/debug_toolbar/img/close.png | Bin 0 -> 498 bytes static/debug_toolbar/img/close_hover.png | Bin 0 -> 706 bytes static/debug_toolbar/img/djdt_vertical.png | Bin 0 -> 882 bytes static/debug_toolbar/img/indicator.png | Bin 0 -> 436 bytes static/debug_toolbar/js/toolbar.js | 284 ++++++++ static/debug_toolbar/js/toolbar.profiling.js | 20 + static/debug_toolbar/js/toolbar.sql.js | 7 + static/debug_toolbar/js/toolbar.template.js | 11 + static/debug_toolbar/js/toolbar.timer.js | 48 ++ templates/admin/blog/blog_add.html | 25 + templates/client/includes/booking_block.html | 55 ++ templates/client/includes/event_object.html | 16 +- theme/models.py | 5 + 33 files changed, 1432 insertions(+), 23 deletions(-) create mode 100644 article/admin_blog.py create mode 100644 city/management/commands/create_hotels.py create mode 100644 city/management/commands/hotel_photos.py create mode 100644 static/debug_toolbar/.DS_Store create mode 100644 static/debug_toolbar/css/toolbar.css create mode 100644 static/debug_toolbar/img/ajax-loader.gif create mode 100644 static/debug_toolbar/img/back.png create mode 100644 static/debug_toolbar/img/back_hover.png create mode 100644 static/debug_toolbar/img/close.png create mode 100644 static/debug_toolbar/img/close_hover.png create mode 100644 static/debug_toolbar/img/djdt_vertical.png create mode 100644 static/debug_toolbar/img/indicator.png create mode 100644 static/debug_toolbar/js/toolbar.js create mode 100644 static/debug_toolbar/js/toolbar.profiling.js create mode 100644 static/debug_toolbar/js/toolbar.sql.js create mode 100644 static/debug_toolbar/js/toolbar.template.js create mode 100644 static/debug_toolbar/js/toolbar.timer.js create mode 100644 templates/admin/blog/blog_add.html create mode 100644 templates/client/includes/booking_block.html diff --git a/.gitignore b/.gitignore index 0a0dfc98..3ae9d200 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ *.egg-info *.doc .idea/ -/proj/local.py \ No newline at end of file +media/ +/proj/local.py + diff --git a/article/admin.py b/article/admin.py index 0abdc8d5..a664da6d 100644 --- a/article/admin.py +++ b/article/admin.py @@ -110,3 +110,13 @@ def article_change(request, url): return render_to_response('article_add.html', args) + +#----------------------- +from django.views.generic import CreateView +from models import Blog +from forms import BlogForm + +class BlogCreate(CreateView): + model = Blog + form_class = BlogForm + template_name = 'admin/blog/blog_add.html' diff --git a/article/admin_blog.py b/article/admin_blog.py new file mode 100644 index 00000000..62163b00 --- /dev/null +++ b/article/admin_blog.py @@ -0,0 +1,10 @@ +from django.conf.urls import patterns, url +from admin import BlogCreate + +urlpatterns = patterns('', + url(r'^add/$', BlogCreate.as_view()), + #url(r'^delete/(?P.*)/$', 'article_delete'), + #url(r'^change/(.*)/$', 'article_change'), + #url(r'^copy/(.*)/$', 'article_copy'), + #url(r'^all/$', 'article_all'), +) diff --git a/article/forms.py b/article/forms.py index 1045ebf1..5eac49f7 100644 --- a/article/forms.py +++ b/article/forms.py @@ -112,4 +112,32 @@ class ArticleDeleteForm(forms.ModelForm): class Meta: model = Article - fields = ('url',) \ No newline at end of file + fields = ('url',) + +#---------------------------------- +from models import Blog + +class BlogForm(forms.ModelForm): + class Meta: + model = Blog + exclude = ('created', 'modified', 'creator', 'theme', 'tag') + + def __init__(self, *args, **kwargs): + super(BlogForm, self).__init__(*args, **kwargs) + + + if len(settings.LANGUAGES) in range(10): + for lid, (code, name) in enumerate(settings.LANGUAGES): + # uses enumerate for detect iteration number + # first iteration is a default lang so it required fields + required = True if lid == 0 else False + self.fields['main_title_%s' % code] = forms.CharField(label='Заголовок', required=required) + self.fields['preview_%s' % code] = forms.CharField(label='Превью', required=required, widget=CKEditorWidget) + self.fields['description_%s' % code] = forms.CharField(label='Описание', required=required, widget=CKEditorWidget) + #meta data + self.fields['title_%s' % code] = forms.CharField(label='Тайтл', required=False, max_length=255, + widget=forms.TextInput(attrs={'style':'width: 550px'})) + self.fields['keywords_%s' % code] = forms.CharField(label='Дескрипшен', required=False, max_length=255, + widget=forms.TextInput(attrs={'style':'width: 550px'})) + self.fields['descriptions_%s' % code] = forms.CharField(label='Кейвордс', required=False, max_length=255, + widget=forms.TextInput(attrs={'style':'width: 550px'})) \ No newline at end of file diff --git a/article/models.py b/article/models.py index e8eaabaf..009474de 100644 --- a/article/models.py +++ b/article/models.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- +import copy from django.db import models +from django.utils.translation import ugettext_lazy as _ from hvad.models import TranslatableModel, TranslatedFields, TranslationManager -from django.template.defaultfilters import slugify -import copy +from sorl.thumbnail import ImageField + class ArticleManager(TranslationManager): def safe_get(self, **kwargs): @@ -102,3 +104,35 @@ from django.db.models.signals import post_save from functions.signal_handlers import post_save_handler post_save.connect(post_save_handler, sender=Article) + + +#-------------------------------- +class Blog(TranslatableModel): + url = models.SlugField(unique=True) + theme = models.ManyToManyField('theme.Theme', related_name='blog_theme') + tag = models.ManyToManyField('theme.Tag', related_name='blog_tag',blank=True, null=True) + creator = models.ForeignKey('accounts.User', verbose_name='Автор', + on_delete=models.PROTECT, related_name='blog') + date = models.DateField(verbose_name=_(u'Дата')) + preview_img = ImageField(upload_to='article', blank=True) + + # + main_page = models.PositiveIntegerField(default=0, db_index=True) + translations = TranslatedFields( + main_title = models.CharField(max_length=255), + preview = models.TextField(), + description = models.TextField(), + #-----meta + title = models.CharField(max_length=255, blank=True), + descriptions = models.CharField(max_length=255, blank=True), + keywords = models.CharField(max_length=255, blank=True), + ) + #fields saves information about creating and changing model + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + def __unicode__(self): + return self.lazy_translation_getter('main_title', self.pk) + + +#post_save.connect(post_save_handler, sender=Blog) \ No newline at end of file diff --git a/city/management/commands/create_hotels.py b/city/management/commands/create_hotels.py new file mode 100644 index 00000000..11d04f8b --- /dev/null +++ b/city/management/commands/create_hotels.py @@ -0,0 +1,88 @@ +import pickle, json, urllib2 +import urllib2, base64 +from django.core.management.base import BaseCommand, CommandError +from django.db.models import Q +from django.conf import settings +from city.models import Hotel, City + +'https://distribution-xml.booking.com/json/bookings.getHotelPhotos?' +'https://distribution-xml.booking.com/json/bookings.getHotels?' + +HOTEL_URL = 'https://distribution-xml.booking.com/json/bookings.getHotels?' +HOTEL_PHOTO_URL = 'https://distribution-xml.booking.com/json/bookings.getHotelPhotos?' + + +username = 'expomap' +password = '33xp00m33p' +langs = [code for code, name in settings.LANGUAGES] + +def create_hotels(hotels, city): + dj_hotels = [] + dj_hotels_translation = [] + tr_model = Hotel._meta.translations_model + for hotel in hotels: + h = Hotel(id=hotel['hotel_id'], url=hotel['url'], city=city, ranking=hotel['ranking'], + hotel_class=hotel['class'], latitude=hotel['location']['latitude'], + longitude=hotel['location']['longitude']) + dj_hotels.append(h) + for lang in langs: + tr = tr_model(name=hotel['name'], address=hotel['address'], master_id=hotel['hotel_id'], language_code=lang) + dj_hotels_translation.append(tr) + + Hotel.objects.bulk_create(dj_hotels) + #print dj_hotels + tr_model.objects.bulk_create(dj_hotels_translation) + print('city: %s'%str(city)) + +def main(): + + cities = City.objects.select_related('place_expositions', 'place_conferences').\ + filter(Q(place_expositions__city__isnull=False) | Q(place_conferences__city__isnull=False)).distinct() + for city in cities: + + url = HOTEL_URL + 'city_ids=%s'%city.id + offset = 0 + rows = 500 + flag = True + while(flag): + new_url = url + '&offset=%s&rows=%s'%(offset, rows) + request = urllib2.Request(new_url) + base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '') + request.add_header("Authorization", "Basic %s" % base64string) + try: + response = urllib2.urlopen(request) + code = response.getcode() + except urllib2.HTTPError, e: + code = e.code + except urllib2.URLError, e: + code = e.code + + json_hotels = response.read() + hotels = json.loads(json_hotels) + create_hotels(hotels, city) + offset +=rows + if not hotels: + flag = False + + +class Command(BaseCommand): + def handle(self, *args, **options): + main() + """ + request = urllib2.Request(URL) + base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '') + request.add_header("Authorization", "Basic %s" % base64string) + + try: + response = urllib2.urlopen(request) + code = response.getcode() + except urllib2.HTTPError, e: + code = e.code + except urllib2.URLError, e: + code = e.code + + json_hotels = response.read() + hotels = json.loads(json_hotels) + + print(hotels) + """ \ No newline at end of file diff --git a/city/management/commands/hotel_photos.py b/city/management/commands/hotel_photos.py new file mode 100644 index 00000000..b34486b5 --- /dev/null +++ b/city/management/commands/hotel_photos.py @@ -0,0 +1,89 @@ +import pickle, json, urllib2 +import urllib2, base64 +from django.conf import settings +from django.core.management.base import BaseCommand, CommandError +from city.models import Hotel, City +from functions.files import get_alternative_filename + +username = 'expomap' +password = '33xp00m33p' +HOTEL_URL = 'https://distribution-xml.booking.com/json/bookings.getHotels?' +HOTEL_PHOTO_URL = 'https://distribution-xml.booking.com/json/bookings.getHotelPhotos?' + +from concurrent.futures import ThreadPoolExecutor + + +def upload(photo): + url = photo['url_max300'] + name = url.split('/')[-1] + alt_name = get_alternative_filename(settings.MEDIA_ROOT+'hotels/', name) + download_to = settings.MEDIA_ROOT+'hotels/'+alt_name + try: + response = urllib2.urlopen(url, timeout=3) + except: + return (photo['hotel_id'], '') + + with open(download_to,'wb') as f: + f.write(response.read()) + f.close() + return (photo['hotel_id'], 'hotels/'+alt_name) + + +def download_photos(photos): + result = {} + with ThreadPoolExecutor(5) as executor: + + for i in executor.map(upload, photos): + result[i[0]] = i[1] + return result + + """ + result = {} + for photo in photos: + res = upload(photo) + result[res[0]] = res[1] + return result + """ + + +def run(hotels): + ids = [str(hotel.id) for hotel in hotels]# comment after testing + url = HOTEL_PHOTO_URL+'hotel_ids=%s'%','.join(ids) + request = urllib2.Request(url) + base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '') + request.add_header("Authorization", "Basic %s" % base64string) + try: + response = urllib2.urlopen(request) + code = response.getcode() + except urllib2.HTTPError, e: + code = e.code + except urllib2.URLError, e: + code = e.code + + json_photos = response.read() + photos = json.loads(json_photos) + + + result = download_photos(photos) + for key, value in result.iteritems(): + Hotel.objects.filter(id=key).update(photo=value) + print(key) + +def main(): + #hotels = Hotel.objects.all() + hotels = Hotel.objects.filter(photo='') + fr = 0 + to = 20 + step = 20 + + + while(fr < len(hotels)): + cur_hotels = hotels[fr:to] + run(cur_hotels) + fr += step + to += step + + +class Command(BaseCommand): + def handle(self, *args, **options): + main() diff --git a/city/models.py b/city/models.py index 9ca28779..e006efd3 100644 --- a/city/models.py +++ b/city/models.py @@ -3,6 +3,7 @@ from django.db import models from django.db.models.signals import post_save, pre_save from hvad.models import TranslatableModel, TranslatedFields, TranslationManager from bitfield import BitField +from sorl.thumbnail import ImageField # models from directories.models import Iata from service.models import Service @@ -52,7 +53,26 @@ class City(TranslatableModel): def __unicode__(self): return self.lazy_translation_getter('name', self.pk) + def get_hotels(self): + return self.hotels.all()[:4] +class Hotel(TranslatableModel): + url = models.URLField(max_length=255) + city = models.ForeignKey(City, related_name='hotels') + + ranking = models.FloatField(blank=True, null=True) + hotel_class = models.CharField(max_length=10, blank=True) + latitude = models.FloatField(blank=True, null=True) + longitude = models.FloatField(blank=True, null=True) + photo = ImageField(upload_to='hotels') + + translations = TranslatedFields( + name = models.CharField(max_length=255, blank=True), + address = models.CharField(max_length=255, blank=True) + + ) + post_save.connect(post_save_handler, sender=City) +post_save.connect(post_save_handler, sender=Hotel) \ No newline at end of file diff --git a/functions/search_forms.py b/functions/search_forms.py index df75154c..33b914e8 100644 --- a/functions/search_forms.py +++ b/functions/search_forms.py @@ -20,9 +20,9 @@ class AbstactSearchForm(forms.Form): class CompanySearchForm(AbstactSearchForm): th = forms.MultipleChoiceField(label=_(u'Тематика'), required=False, - choices=[(theme.id, theme.name) for theme in Theme.objects.filter()]) + choices=[(theme.id, theme.name) for theme in Theme.objects.all()]) tg = forms.MultipleChoiceField(label=_(u'Теги'), required=False, - choices=[(tag.id, tag.name) for tag in Tag.objects.filter()]) + choices=[(tag.id, tag.name) for tag in Tag.objects.all()]) c = forms.CharField(label=_(u'Страна'), required=False, widget=forms.SelectMultiple()) @@ -85,7 +85,7 @@ class ExpositionSearchForm(forms.Form): th = forms.CharField(label=_(u'Тематика'), required=False, widget=forms.SelectMultiple()) tg = forms.CharField(label=_(u'Теги'), required=False, widget=forms.SelectMultiple()) - area = forms.MultipleChoiceField(label=_(u'Регион'), choices=[(item.id, item.name) for item in Area.objects.all()], + area = forms.MultipleChoiceField(label=_(u'Регион'), choices=[(item.id, item.name) for item in Area.objects.language()], required=False, widget=forms.CheckboxSelectMultiple()) co = forms.CharField(label=_(u'Страна'), required=False, widget=forms.SelectMultiple()) ci = forms.CharField(label=_(u'Город'), required=False, widget=forms.SelectMultiple()) diff --git a/place_conference/models.py b/place_conference/models.py index 06577ab9..b4cbdcab 100644 --- a/place_conference/models.py +++ b/place_conference/models.py @@ -27,7 +27,7 @@ class PlaceConference(TranslatableModel, ExpoMixin): url = models.SlugField(unique=True) country = models.ForeignKey('country.Country', on_delete=models.PROTECT) - city = models.ForeignKey('city.City', on_delete=models.PROTECT) + city = models.ForeignKey('city.City', on_delete=models.PROTECT, related_name='place_conferences') #type uses EnumField for creating Enum type field in Mysql database type = EnumField(values = [item1 for item1, item2 in CONFERENCE_TYPE]) #information diff --git a/place_exposition/models.py b/place_exposition/models.py index 677d85d8..a639e231 100644 --- a/place_exposition/models.py +++ b/place_exposition/models.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- from django.db import models +from django.db.models import Q from django.contrib.contenttypes import generic from django.db.models.signals import post_save, pre_save from django.utils.translation import ugettext as _ +from functools import partial # from hvad.models import TranslatableModel, TranslatedFields, TranslationManager @@ -19,6 +21,8 @@ from place_conference.models import PlaceConference EXPOSITION_TYPE = (('Exposition complex', u'Выставочный комплекс'), ('Convention centre', u'Конгрессно-выставочный центр'), ('Exposition centre', u'Выставочный центр'),) +dist=lambda s,d: (s[0]-d[0])**2+(s[1]-d[1])**2 + class PlaceExposition(TranslatableModel, ExpoMixin): """ Create PlaceConference model @@ -31,7 +35,7 @@ class PlaceExposition(TranslatableModel, ExpoMixin): url = models.SlugField(unique=True, max_length=255) country = models.ForeignKey('country.Country', on_delete=models.PROTECT) - city = models.ForeignKey('city.City', on_delete=models.PROTECT, related_name='place_expostions') + city = models.ForeignKey('city.City', on_delete=models.PROTECT, related_name='place_expositions') #type uses EnumField for creating Enum type field in Mysql database type = EnumField(values = [item1 for item1, item2 in EXPOSITION_TYPE]) #information @@ -136,6 +140,22 @@ class PlaceExposition(TranslatableModel, ExpoMixin): #return pl_exp[] return list(pl_exp)+ list(pl_conf)#PlaceExposition.objects.filter(city=self.city).exclude(id=self.id) + def get_nearest_hotels(self): + if not self.address: + return None + # get coordinates of all hotels in current city + qs_hotels_all = self.city.hotels.filter(city=self.city) + hotels_coord = [(hotel.latitude, hotel.longitude) for hotel in qs_hotels_all] + # coordinate current place + place_coord = (self.address['lat'], self.address['lng']) + # 4 coordinates of 4 nearest hotels + hotels_coord = sorted(hotels_coord, key=partial(dist, place_coord))[:4] + # start generating filter for queryset + qs = [Q(latitude=item[0]) & Q(longitude=item[1]) for item in hotels_coord] + res = reduce(lambda a,b: a|b, qs) + + return qs_hotels_all.filter(res) + def get_type(self): type = {'Convention centre': _(u'Конгессо-выставочный центр'), 'Exposition centre': _(u'Выставочный центр'), 'Exposition complex': _(u'Выставочный комплекс')} diff --git a/proj/admin_urls.py b/proj/admin_urls.py index 997f0d76..7cd20cd4 100644 --- a/proj/admin_urls.py +++ b/proj/admin_urls.py @@ -12,6 +12,7 @@ urlpatterns = required( url(r'^', include('import_xls.admin_urls')), url(r'^accounts/', include('accounts.admin_urls')), url(r'^article/', include('article.admin_urls')), + url(r'^blog/', include('article.admin_blog')), url(r'^city/', include('city.admin_urls')), url(r'^company/', include('company.admin_urls')), url(r'^conference/', include('conference.admin_urls')), diff --git a/proj/settings.py b/proj/settings.py index b9d15fc1..4377d9d7 100644 --- a/proj/settings.py +++ b/proj/settings.py @@ -385,6 +385,7 @@ LOGGING = { CALLBACK_EMAIL = 'kotzilla@ukr.net' +BOOKING_AID = '333667' try: from local import * diff --git a/proj/urls.py b/proj/urls.py index f3e2afe8..eea51ce2 100644 --- a/proj/urls.py +++ b/proj/urls.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from django.conf import settings from django.conf.urls import patterns, include, url from core.views import PlaceListView, PlacePhotoView, PlaceSearchView, EventSearchView from core.simple_index_view import AdvertisingView, AboutView @@ -58,4 +59,10 @@ urlpatterns += patterns('', url(r'^callback/', 'core.simple_index_view.callback'), # url(r'^profile/change-password/', 'accounts.views.change_password'), + ) + +if settings.DEBUG: + import debug_toolbar + urlpatterns += patterns('', + url(r'^__debug__/', include(debug_toolbar.urls)), ) \ No newline at end of file diff --git a/proj/views.py b/proj/views.py index abc290c3..fafffb3f 100644 --- a/proj/views.py +++ b/proj/views.py @@ -2,18 +2,21 @@ from django.core.context_processors import csrf from django.shortcuts import render_to_response from django.template import RequestContext +from django.views.generic import TemplateView +from django.conf import settings from exposition.models import Exposition from theme.models import Theme from news.models import News from article.models import Article -from django.views.generic import TemplateView + from functions.forms import ThemeSearch, PlaceSearch from functions.search_forms import EventSearchForm from functions.custom_views import ExpoListView def expo_context(request): - cont = {'theme_search_form': ThemeSearch(), 'place_search_form': PlaceSearch(), 'expo_catalog': Exposition.catalog} + cont = {'theme_search_form': ThemeSearch(), 'place_search_form': PlaceSearch(), 'expo_catalog': Exposition.catalog, + 'book_aid': settings.BOOKING_AID} return cont diff --git a/static/debug_toolbar/.DS_Store b/static/debug_toolbar/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..84ab3c93a48d178cf684fec99811cfee01cffea1 GIT binary patch literal 6148 zcmeHKy-ve05VqR_2}lqm2H3o@bSMfxBT*<53sMja6qQ7&XrvOOHl;(Ul!1ZY_dxJM z3_J{Xwp&pZ76yc>yXgF#&v&-&OJv84G46Nc4aOYCm<5Vhu%Y=za2$0)3dV!TagNSa z)RGbOKBB9MXmb2V2Jqb#S;8*aMb!KH{#r>Vt5n{3p;(%kowMwDcovuJv!E$^K^A7+ zjvuy9v3D3|&B)kCQnp5R7#$~#Ufo&QlW7(vX``)@lehsPwUZ=`WzU!0H15;_?L0~1 ztf?k74%>pK?yUCvuDewh?#AYzEc!b;m9p5}t_%jwt!=HXySoRGyt%u7czk+(dDS#? z_#%}o8yvzL7^dRupq;j4dI6qc^e~E$7$63SfoW#I?0MG0G#5#=5d*})uNc7nL4YE9 z26K&S>wpG-A91{dhypg=B@l%{&tR?*MnJeu1=OkBTrs##2fr|Jp21wBPG?-L4D*GN t0`wdd1>4&@-581P=)P2q+q;AqM`GflpG3S6l!9 literal 0 HcmV?d00001 diff --git a/static/debug_toolbar/css/toolbar.css b/static/debug_toolbar/css/toolbar.css new file mode 100644 index 00000000..c85b155b --- /dev/null +++ b/static/debug_toolbar/css/toolbar.css @@ -0,0 +1,649 @@ +/* http://www.positioniseverything.net/easyclearing.html */ +#djDebug .clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} +#djDebug .clearfix {display: inline-block;} +/* Hides from IE-mac \*/ +#djDebug .clearfix {display: block;} +* html #djDebug .clearfix {height: 1%;} +/* end hide from IE-mac */ + +/* Debug Toolbar CSS Reset, adapted from Eric Meyer's CSS Reset */ +#djDebug {color:#000;background:#FFF;} +#djDebug, #djDebug div, #djDebug span, #djDebug applet, #djDebug object, #djDebug iframe, +#djDebug h1, #djDebug h2, #djDebug h3, #djDebug h4, #djDebug h5, #djDebug h6, #djDebug p, #djDebug blockquote, #djDebug pre, +#djDebug a, #djDebug abbr, #djDebug acronym, #djDebug address, #djDebug big, #djDebug cite, #djDebug code, +#djDebug del, #djDebug dfn, #djDebug em, #djDebug font, #djDebug img, #djDebug ins, #djDebug kbd, #djDebug q, #djDebug s, #djDebug samp, +#djDebug small, #djDebug strike, #djDebug strong, #djDebug sub, #djDebug sup, #djDebug tt, #djDebug var, +#djDebug b, #djDebug u, #djDebug i, #djDebug center, +#djDebug dl, #djDebug dt, #djDebug dd, #djDebug ol, #djDebug ul, #djDebug li, +#djDebug fieldset, #djDebug form, #djDebug label, #djDebug legend, +#djDebug table, #djDebug caption, #djDebug tbody, #djDebug tfoot, #djDebug thead, #djDebug tr, #djDebug th, #djDebug td, +#djDebug button { + margin:0; + padding:0; + min-width:0; + width:auto; + border:0; + outline:0; + font-size:12px; + line-height:1.5em; + color:#000; + vertical-align:baseline; + background-color:transparent; + font-family:sans-serif; + text-align:left; + text-shadow: none; + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; +} + +#djDebug button { + background-color: #eee; + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eee), color-stop(100%, #cccccc)); + background-image: -webkit-linear-gradient(top, #eee, #cccccc); + background-image: -moz-linear-gradient(top, #eee, #cccccc); + background-image: -ms-linear-gradient(top, #eee, #cccccc); + background-image: -o-linear-gradient(top, #eee, #cccccc); + background-image: linear-gradient(top, #eee, #cccccc); + border: 1px solid #ccc; + border-bottom: 1px solid #bbb; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + color: #333; + line-height: 1; + padding: 0 8px; + text-align: center; + text-shadow: 0 1px 0 #eee; +} + +#djDebug button:hover { + background-color: #ddd; + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ddd), color-stop(100%, #bbb)); + background-image: -webkit-linear-gradient(top, #ddd, #bbb); + background-image: -moz-linear-gradient(top, #ddd, #bbb); + background-image: -ms-linear-gradient(top, #ddd, #bbb); + background-image: -o-linear-gradient(top, #ddd, #bbb); + background-image: linear-gradient(top, #ddd, #bbb); + border-color: #bbb; + border-bottom-color: #999; + cursor: pointer; + text-shadow: 0 1px 0 #ddd; +} + +#djDebug button:active { + border: 1px solid #aaa; + border-bottom: 1px solid #888; + -webkit-box-shadow: inset 0 0 5px 2px #aaa, 0 1px 0 0 #eee; + -moz-box-shadow: inset 0 0 5px 2px #aaa, 0 1px 0 0 #eee; + box-shadow: inset 0 0 5px 2px #aaa, 0 1px 0 0 #eee; +} + +#djDebug #djDebugToolbar { + background-color:#111; + width:200px; + z-index:100000000; + position:fixed; + top:0; + bottom:0; + right:0; + opacity:0.9; + overflow-y: auto; +} + +#djDebug #djDebugToolbar small { + color:#999; +} + +#djDebug #djDebugToolbar ul { + margin:0; + padding:0; + list-style:none; +} + +#djDebug #djDebugToolbar li { + border-bottom:1px solid #222; + color:#fff; + display:block; + font-weight:bold; + float:none; + margin:0; + padding:0; + position:relative; + width:auto; +} + +#djDebug #djDebugToolbar input[type=checkbox] { + float: right; + margin: 10px; +} + +#djDebug #djDebugToolbar li>a, +#djDebug #djDebugToolbar li>div.contentless { + font-weight:normal; + font-style:normal; + text-decoration:none; + display:block; + font-size:16px; + padding:10px 10px 5px 25px; + color:#fff; +} +#djDebug #djDebugToolbar li>div.disabled { + font-style: italic; + color: #999; +} + +#djDebug #djDebugToolbar li a:hover { + color:#111; + background-color:#ffc; +} + +#djDebug #djDebugToolbar li.active { + background: #333 no-repeat left center; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAQAAAAngNWGAAABe0lEQVR4AW2SO0tDQRCFz+bGJxEUrKzsBBsb/4DYiIWdECvB/6CCYGtp6QNRjJ1FihSCVpZGMIhYSBAfIGKRx70xyY3JbrKOk7DJLp7DXm7Il9nMmREYQgQeAI1W1/zZUhR9ZI9gjSZb0iHMRSPbE1QzhhF2jN4H6YdRCHaPvOTjdDb1jWECBhiJoC1tg6Kotbw9WkxBoIUGaqiiQs8fSCj+t9qAIL1nlg9fKgSGKKNEJ2RUMqh7QCDIr58k31AlrIiA0CqhDTQJtUFAqsTFxjV85FGAz1XrkDZodPewkih8IkdwCRWu2U6VerQ0O3OzuTSJ/k62JiIXJI2NL0wBjDiTseQHW8fnGY6myf3+Dz49x88+vjr9SoPaoG6lLteuCApMiu1otAWG/s7BXtYEzv3yZOyrc5nV3XTZjPAv7Jqp2AVf9+dOyx4EFCTqCAnimZB1z9X38fk05RblfVQE1LkR5a6vwCivruANV2ynjU5FHpIE+AsCnCuNfgGtjt1gZaIn2wAAAABJRU5ErkJggg=="); + padding-left:10px; +} + +#djDebug #djDebugToolbar li.active a:hover { + color:#b36a60; + background-color:transparent; +} + +#djDebug #djDebugToolbar li small { + font-size:12px; + color:#999; + font-style:normal; + text-decoration:none; + font-variant:small-caps; +} + +#djDebug #djDebugToolbarHandle { + position:fixed; + background-color:#fff; + border:1px solid #111; + top:30px; + right:0; + z-index:100000000; + opacity:0.75; +} + +#djDebug #djShowToolBarButton { + display:block; + height:75px; + width:30px; + border-right:none; + border-bottom:4px solid #fff; + border-top:4px solid #fff; + border-left:4px solid #fff; + color:#fff; + font-size:10px; + font-weight:bold; + text-decoration:none; + text-align:center; + text-indent:-999999px; + background: #000 no-repeat left center; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABLCAIAAACN/FLOAAADOUlEQVR4Ae2WUWhSXxzHp5v+y4mGGkkEETIfIhyEUThaD0XlGg7qZTJdpGOzQSiVC9uWlCxsMmvW0k2WBDVJMzJWBAaG6ORfGZMexAd9EXzxwWFI9qB24K7DZUNRdlSC++H35P1yPpff/Z1zbCMgICAg2AECgUClUmk0msHBQRqN1jyxxWIp/6Wrq6s5UkKsVCrP1wCfz0csrpGlpaXWiFdXV1sjdrvdiMW5XG6jBoxG47801YTYbDZj1mKxyOPx2loLmUzmcDhcLpdKpTbDJxQKbTZbLBYrlUqw/+l02uVySSSShijpdDrYneWqhEIh0AOUVtDPcDhcroFkMslgMJCJTSZTuWasVisaK4vFyufzZRw+n89gMMjlcqlUqtfrvV4v/pMXCgU2m41ArFAo8EemWCzenhGJRGDE8LcnArHD4YArqtXqSjGZTAZjdrsdgRjMKlyRyWRWilEoFHDCYLFAIIBADHYt3K/Vk6lUCktGo1EE4kQigS2XzWbHqpLJZLBkPB5HIAavX66TSCSCQBwMBusV+/1+BGKPx1Ov2Ol0IhDrdLr1OtFqtTv3EjBYnWwuY0ux9jHI7eTGiu2Bm9/Ki9tr7deTl9+nhq6fIZFITRXDmns73hoxqJP9ggaKw78XPm88wirw04IXz6yMNFB8Z3kY//v+Q5x3yRns0fP/dc0TA/SOy9ijVz/06MXg+43q+0emL3T38LY8mn9/DRPPelSN+0NP2sOhgx1MoXbAHw/w9koUPYrJvqOn+Ih9h4UHb9uGXsfufi3Z4Ch9TM8aXaO9km6UJgiN/t8D9xjQVKlnoQnQA5RW0E9H+BYUVCkw2J2MXcjEatOlWqxY6axDyG6FYP4xfumnPs1Vw0Cf/MQ56TEw4WbvOP6TrxUWmOxOBGIwqHDRQG5eJD6yPSMQ8cCIwdiAsgeBGB4LoKTq05VifbLjMDZllyMQg1mFK9KZuyvFOijtX4qbDQenGwIx2LVwv1ZPfkgZsaQzOo1A7E1sHv3+7MOLY71V6lNmDku+id9DIAavD1tdY72ITCIQLwcn6hUv+m8gEIOrpl7xfecIAvEVnXhlfbquGtaebSMgICAgaBR/AF2yboPNdvDUAAAAAElFTkSuQmCC"); + opacity:0.5; +} + +#djDebug #djShowToolBarButton:hover { + background-color:#111; + border-top-color:#FFE761; + border-left-color:#FFE761; + border-bottom-color:#FFE761; + cursor:move; + opacity:1.0; +} + +#djDebug code { + display:block; + font-family:Consolas, Monaco, "Bitstream Vera Sans Mono", "Lucida Console", monospace; + font-size: 12px; + white-space:pre; + overflow:auto; +} + +#djDebug .djDebugOdd { + background-color:#f5f5f5; +} + +#djDebug .panelContent { + display:none; + position:fixed; + margin:0; + top:0; + right:200px; + bottom:0; + left:0px; + background-color:#eee; + color:#666; + z-index:100000000; +} + +#djDebug .panelContent > div { + border-bottom:1px solid #ddd; +} + +#djDebug .djDebugPanelTitle { + position:absolute; + background-color:#ffc; + color:#666; + padding-left:20px; + top:0; + right:0; + left:0; + height:50px; +} + +#djDebug .djDebugPanelTitle code { + display:inline; + font-size:inherit; +} + +#djDebug .djDebugPanelContent { + position:absolute; + top:50px; + right:0; + bottom:0; + left:0; + height:auto; + padding:5px 0 0 20px; +} + +#djDebug .djDebugPanelContent .loader { + display:block; + margin:80px auto; +} + +#djDebug .djDebugPanelContent .scroll { + height:100%; + overflow:auto; + display:block; + padding:0 10px 0 0; +} + +#djDebug h3 { + font-size:24px; + font-weight:normal; + line-height:50px; +} + +#djDebug h4 { + font-size:20px; + font-weight:bold; + margin-top:0.8em; +} + +#djDebug .panelContent table { + border:1px solid #ccc; + border-collapse:collapse; + width:100%; + background-color:#fff; + display:block; + margin-top:0.8em; + overflow: auto; +} +#djDebug .panelContent tbody td, +#djDebug .panelContent tbody th { + vertical-align:top; + padding:2px 3px; +} +#djDebug .panelContent tbody td.time { + text-align: center; +} + +#djDebug .panelContent thead th { + padding:1px 6px 1px 3px; + text-align:left; + font-weight:bold; + font-size:14px; + white-space: nowrap; +} +#djDebug .panelContent tbody th { + width:12em; + text-align:right; + color:#666; + padding-right:.5em; +} + +#djDebug .djTemplateHideContextDiv { + background-color:#fff; +} + +/* +#djDebug .panelContent p a:hover, #djDebug .panelContent dd a:hover { + color:#111; + background-color:#ffc; +} + +#djDebug .panelContent p { + padding:0 5px; +} + +#djDebug .panelContent p, #djDebug .panelContent table, #djDebug .panelContent ol, #djDebug .panelContent ul, #djDebug .panelContent dl { + margin:5px 0 15px; + background-color:#fff; +} +#djDebug .panelContent table { + clear:both; + border:0; + padding:0; + margin:0; + border-collapse:collapse; + border-spacing:0; +} + +#djDebug .panelContent table a { + color:#000; + padding:2px 4px; +} +#djDebug .panelContent table a:hover { + background-color:#ffc; +} + +#djDebug .panelContent table th { + background-color:#333; + font-weight:bold; + color:#fff; + padding:3px 7px 3px; + text-align:left; + cursor:pointer; +} +#djDebug .panelContent table td { + padding:5px 10px; + font-size:14px; + background-color:#fff; + color:#000; + vertical-align:top; + border:0; +} +#djDebug .panelContent table tr.djDebugOdd td { + background-color:#eee; +} +*/ + +#djDebug .panelContent .djDebugClose { + text-indent:-9999999px; + display:block; + position:absolute; + top:4px; + right:15px; + height:40px; + width:40px; + background: no-repeat center center; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAQAAACQTsNJAAABuUlEQVR4Ab2WXeoaMRTFZxHz6pObcA0DeXUHhXktFl8LXYAPXYBLKhQGBOFqW3XS8YOW6vjHmnp6wWZyHU1maqHnQDAf/Ehu7twYhUQxdUixO/wr8ts3oeg9TQjCEx5R7SGvKCd4nPNsIyShD4QGf6QkBBkQWnrgg4zqS2fm01kbze3M3GFGjyBvCdLFqYRUySM1zLAOUXJ6dZAACcoPBOHkFpK5qY1BQBt5sExC0gAijEkriMuLfI9m8SqXNxbSd+QSbVSCnPtXyNjdCCoZ7PANF7C4/Y4tznASNzW+QqaP9lFcj4cLW4PY+vFepsSQ2Hbnp5vw2ShB231Cau72EkfUs53lC4R+YQkSXsBAiFdXc72IkupmDODDfKkhwKtdygUgHAuXw7gEIN7jCIQNsfc43sDuqlgsbC57A+u94q82nFVscv8Vy2Rbi72csGKQ+RPignvytGuZbPW0P6KNjvdpz97aIf3jLz/ArfuKXz9dCt7IojR9qihNAuUx33vL454grOqF+t2/F2rPk/H5pzaa2+Ynw3lIaOlh6BlVlDUCMlLND3pKhRdQUPof/1o4x9Qlxe6G/+T8BlqvQqkd4EyZAAAAAElFTkSuQmCC"); +} + +#djDebug .panelContent .djDebugClose:hover { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAACiUlEQVR4Ad2Yz2oTURSH+xCz7cqX6DMUZtudCxExigq2WhcKYtGFVLrwAboSKoVGxT+tJWpTa2lLTDsm6SSTjtZoIq0prf+2Hu8PcmHInJvJPYwuPPDBMDPn8DE5c+fcDEgjDENHMahwOwx2zg1IsE1wFXcVvoIM+J173L8hckrRUpAlLeSmITKsKNoKMHioJRUZU1DKjNmKTCUWDWpUL21RJbcAcIxz/chM9StyvVeh8rOHtH7nJi2dOc6Ba7gnSWY8ScQ1JVdfv6C1yQlegAH3+su5XjLDvUTKXNK77H0Ul4Bck0jZJJLhEry5GV1ULvNg1iSTiYlw64SfX0ShNEAtfp3pEhnhjJmekIJapqcyEhWZZt4OtuDqlXPUWHxKYXaGli+c1Ocpf/4E1Wfv0afcPK1dG+VyTW/TdFQk6Pdp7BfWSMdhtQIZSFDbe0s6DiqezVMJtIjTfXGnuv3b9Iib+RxF47C2Te3SJkUDsqZ81GZkHIgMdV+ora8YC62MnqbvH0Iyxa/WZ3pz+awxH7UZkSH9YaMolZfPdaJZZvd9XOJLU0sYQW1ucROJoCcOyh51x1G9ip4Ri1j9NLoxDaEbWPDTWDbrx/lHsZ740dilSKChBc1q+fp+3SyQjp/NBnoi1sB4KpLXl13QSo/n2GKFW1fpaKdG+8UNSEQbmPY2VulbWKfi5A0uFzUTFzR+ib/NFJSBWolLvKYd++i9WkhNxF9i35Y29/W9KB8DxDPJJU4EBP9wMPJFoyLmCetRUc8gPK5JRDOhIBOlJ9nE4Rn3yIdnwXYi2Crq7QSOU99OaGBNKTMu3XK63GQvADXcNDbhGcWeQAA5mf/ybwkOR3FM4XbAsSOt9wcLTn8FNtAKkQAAAABJRU5ErkJggg=="); +} + +#djDebug .panelContent .djDebugClose.djDebugBack { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAACBUlEQVR4Ad2Y0WriQBSGfYjc7tW+hM8g5HbfYMHbxcXbhT6AF30AH6cXvRCEttK0JgZi0qhQaRNtNWV2fuiADicZcxirdOCn45mccz4mMyczbXDbeDx2pH5IuRD6n7YGR3UdkPBSaiQlSoQxPOMeA+S3VIxENRXD1wZIS2rAANA1RCwuSAdBLKtTF6RnCur7fjGZTLZJkhQQ+rAdANM7FORfVaA0Td/zPBdlDWN4xgDTNYG4Zc7T6TQjASqA4jjOKmBaVSA3lNN8Pi8Es8GXBkEuGqTNh2DDtCkQvU5gal+FpYZYZJ3RQH5RxPqaWG82qmuw02uGyoHcuyB9anfowZ6el+I2jITellkOu9gWH5UwJbupvwvimWZDgVzdeWLohyqpAlF2zE7dWfEUiKMPBkGwNxt6QmjwEKik+Ltnz9ZvpTCITcA4AGnqA1EUreFkgrm+fwSEsuO3spfCIDYB0gRIi9gtlVsWSVRSAOzaMSOw4zVSDbGp4nZGIPxXg6TWXo39xarsjMV6LtuXLmiz2cx6QUNMuqAZSvxqtbJW4hHLVOKVFvpDSZK8HPmjt6C+vn9OcAz4S4FA3hcejEasoyKmlnFUVK+DklsFAl2c9vDMuE6EYbhR1wn0bV8nlEAtLKvLvXK62smeK8RwbVzC21IpAyCF77f8twQlR+onEkLow8aN9x+oYk85YNJqYQAAAABJRU5ErkJggg=="); +} + +#djDebug .panelContent .djDebugClose.djDebugBack:hover { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAACLElEQVR4Ad2YT8sSURTG/RCzbdWX8DMIs23XMrBlTLiTSIKKIqgP4C6KQAuKsLCycqGLRHNsXqck2giStIiiRdDtPtABuz0zNw+XkAYe3vHce57zY/7cOfetaI/VahVZHbOKIZz/ilU02jcBBW9YZVaGC2OYg7nhQU5ZrVlhj9bIDQFSs5ooAFzN4KUFSWASWMm+INe8pvnSvJ1PzaLfg3COmB8G3n8Jcq7MKH14z4yvXjCD0yepMIY5HpiGDyQuSj56+cSMrrQ4ABHmZi/6ZTC1MpCUJb3u3oa5SsjlIKjFQeosYda5JaZ6mLt3OAxquiBsncieP4ZRCMGLrjMuyAlG7D4To2Yi5/44eWZYDdTeBWmzt8M1W95sm09Z+kd8dv0S4maY1EthCt6m9i5ITq8GAcHx+cN7KSogEqdXx3NVcgGJ3MF3R29+MCMpiOPbx40Uxd/f4q8uNgth4E1gIoBU3YHleOgYcJjvX78AQuL4LfFCGHgTkCpAau7A4umj0nuNIlIUALtxXBEcuI0kF950cTsoEO2tQdGAtyb8w4rfiof1cF5fvqDN73dCL2jwpAuaf4m/fD7UEg8v7xIv2rqTsme9cB+9AX1btuzre0bdBuh7krMMBMr/YWOUaVpF9BP7t4rSg3DFvua5xRJF8wddb/OMOfrmWbGdyKcT2U7gPPh2QgRqE1gN7ZYzZp29Qim8QmzC61YbBcAGuf/hvyW4IqvjKAjhHDGt309H4mp9BS17eAAAAABJRU5ErkJggg=="); +} + +#djDebug .panelContent dt, #djDebug .panelContent dd { + display:block; +} + +#djDebug .panelContent dt { + margin-top:0.75em; +} + +#djDebug .panelContent dd { + margin-left:10px; +} + +#djDebug a.toggleTemplate { + padding:4px; + background-color:#bbb; + -webkit-border-radius:3px; + -moz-border-radius:3px; + border-radius:3px; +} + +#djDebug a.toggleTemplate:hover { + padding:4px; + background-color:#444; + color:#ffe761; + -webkit-border-radius:3px; + -moz-border-radius:3px; + border-radius:3px; +} + + +#djDebug a.djTemplateShowContext, #djDebug a.djTemplateShowContext span.toggleArrow { + color:#999; +} + +#djDebug a.djTemplateShowContext:hover, #djDebug a.djTemplateShowContext:hover span.toggleArrow { + color:#000; + cursor:pointer; +} + +#djDebug .djDebugSqlWrap { + position:relative; +} + +#djDebug .djDebugCollapsed { + display: none; + text-decoration: none; + color: #333; +} + +#djDebug .djDebugUncollapsed { + color: #333; + text-decoration: none; +} + +#djDebug .djUnselected { + display: none; +} +#djDebug tr.djHiddenByDefault { + display: none; +} +#djDebug tr.djSelected { + display: table-row; +} + +#djDebug .djDebugSql { + z-index:100000002; +} + +#djDebug .djSQLDetailsDiv tbody th { + text-align: left; +} + +#djDebug .djSqlExplain td { + white-space: pre; +} + +#djDebug span.djDebugLineChart { + background-color:#777; + height:3px; + position:absolute; + bottom:0; + top:0; + left:0; + display:block; + z-index:1000000001; +} +#djDebug span.djDebugLineChartWarning { + background-color:#900; +} + +#djDebug .highlight { color:#000; } +#djDebug .highlight .err { color:#000; } /* Error */ +#djDebug .highlight .g { color:#000; } /* Generic */ +#djDebug .highlight .k { color:#000; font-weight:bold } /* Keyword */ +#djDebug .highlight .o { color:#000; } /* Operator */ +#djDebug .highlight .n { color:#000; } /* Name */ +#djDebug .highlight .mi { color:#000; font-weight:bold } /* Literal.Number.Integer */ +#djDebug .highlight .l { color:#000; } /* Literal */ +#djDebug .highlight .x { color:#000; } /* Other */ +#djDebug .highlight .p { color:#000; } /* Punctuation */ +#djDebug .highlight .m { color:#000; font-weight:bold } /* Literal.Number */ +#djDebug .highlight .s { color:#333 } /* Literal.String */ +#djDebug .highlight .w { color:#888888 } /* Text.Whitespace */ +#djDebug .highlight .il { color:#000; font-weight:bold } /* Literal.Number.Integer.Long */ +#djDebug .highlight .na { color:#333 } /* Name.Attribute */ +#djDebug .highlight .nt { color:#000; font-weight:bold } /* Name.Tag */ +#djDebug .highlight .nv { color:#333 } /* Name.Variable */ +#djDebug .highlight .s2 { color:#333 } /* Literal.String.Double */ +#djDebug .highlight .cp { color:#333 } /* Comment.Preproc */ + +#djDebug .timeline { + width: 30%; +} +#djDebug .djDebugTimeline { + position: relative; + height: 100%; + min-height: 100%; +} +#djDebug div.djDebugLineChart { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + vertical-align: middle; +} +#djDebug div.djDebugLineChart strong { + text-indent: -10000em; + display: block; + font-weight: normal; + vertical-align: middle; + background-color:#ccc; +} + +#djDebug div.djDebugLineChartWarning strong { + background-color:#900; +} + +#djDebug .djDebugInTransaction div.djDebugLineChart strong { + background-color: #d3ff82; +} +#djDebug .djDebugStartTransaction div.djDebugLineChart strong { + border-left: 1px solid #94b24d; +} +#djDebug .djDebugEndTransaction div.djDebugLineChart strong { + border-right: 1px solid #94b24d; +} +#djDebug .djDebugHover div.djDebugLineChart strong { + background-color: #000; +} +#djDebug .djDebugInTransaction.djDebugHover div.djDebugLineChart strong { + background-color: #94b24d; +} + + +#djDebug .panelContent ul.stats { + position: relative; + list-style-type: none; +} +#djDebug .panelContent ul.stats li { + width: 30%; + float: left; +} +#djDebug .panelContent ul.stats li strong.label { + display: block; +} +#djDebug .panelContent ul.stats li span.color { + height: 12px; + width: 3px; + display: inline-block; +} +#djDebug .panelContent ul.stats li span.info { + display: block; + padding-left: 5px; +} + +#djDebug .panelcontent thead th { + white-space: nowrap; +} +#djDebug .djDebugRowWarning .time { + color: red; +} +#djdebug .panelcontent table .toggle { + width: 14px; + padding-top: 3px; +} +#djDebug .panelContent table .actions { + min-width: 70px; + white-space: nowrap; +} +#djdebug .panelcontent table .color { + width: 3px; +} +#djdebug .panelcontent table .color span { + width: 3px; + height: 12px; + overflow: hidden; + padding: 0; +} +#djDebug .djToggleSwitch { + text-decoration: none; + border: 1px solid #999; + height: 12px; + width: 12px; + line-height: 12px; + text-align: center; + color: #777; + display: inline-block; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF', endColorstr='#DCDCDC'); /* for IE */ + background: -webkit-gradient(linear, left top, left bottom, from(#FFF), to(#DCDCDC)); /* for webkit browsers */ + background:-moz-linear-gradient(center top , #FFFFFF 0pt, #DCDCDC 100%) repeat scroll 0 0 transparent; +} +#djDebug .djNoToggleSwitch { + height: 14px; + width: 14px; + display: inline-block; +} + +#djDebug .djSQLDetailsDiv { + margin-top:0.8em; +} +#djDebug pre { + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS-3 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ + color: #555; + border:1px solid #ccc; + border-collapse:collapse; + background-color:#fff; + display:block; + overflow: auto; + padding:2px 3px; + margin-bottom: 3px; + font-family:Consolas, Monaco, "Bitstream Vera Sans Mono", "Lucida Console", monospace; +} +#djDebug .stack span { + color: #000; + font-weight: bold; +} +#djDebug .stack span.path { + color: #777; + font-weight: normal; +} +#djDebug .stack span.code { + font-weight: normal; +} + +@media print { + #djDebug { + display: none; + } +} diff --git a/static/debug_toolbar/img/ajax-loader.gif b/static/debug_toolbar/img/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..a7c3f2bacbe630950c16f53e3c27dd840f2e8622 GIT binary patch literal 404 zcmZ?wbhEHb)Mnsj_{hNU?%lhzw6s;LRsl)He^Smxsfi`2DGKG8B^e5dS&0=n`H3ld znR#jX42nNl7`PZ17!?0=`?-b$J39ur8tEA@GXjNlfS3VfAOn+8OCQJSX*X{)e?H13 zeJ||u>DC8kZ4r?R)6{G4&Dyt|CtcU`diyE8Uq?3owA-;j!N^AxXd>8TMr31bj{uEP z;7?56IIHFOnwrlu67PNQNtrQY{;7pt&RzvNJJ_?&Ze06Pg>MsMs)$s6#HZT6Q+}5p z&C*E81%TGdiiN4(8Lw%U?wsno9F=b>WnG7*rn?>{@R)9v%+M)yIi1FiTcrX vD}VECG@HG3ZvWp+k0+)$$G&~0?NxTdRajt8g3>tw(O*m=3=Gzwa03GXAUBr* literal 0 HcmV?d00001 diff --git a/static/debug_toolbar/img/back.png b/static/debug_toolbar/img/back.png new file mode 100644 index 0000000000000000000000000000000000000000..aef96c126ed416459c614d62341490584aba1bd2 GIT binary patch literal 574 zcmV-E0>S->P)-0s!BgwG)4cHdyZ+r`D(g+726eE=V)7rhXKw$ijF24d2vP-zowHDz{w z=ztC<8FLt`bl|7snVfSzCNn29ZE)LoJa(jhNVyRDpSA`^bsdoKQfee6N`x^y;~oR# zw^WQoH5J3x21rY4zyQ!SL@X{y2SF^WQx~LX3hMiQF_}!ZNs<&0`mh}U(>oO8Usa$q zP2cl87iA4&c*X$JHG#Ng&eQ2MBLOOa;yBJKU|LlmHE*hlGhhW3B zDGMo|ob_jD+5nSq{6{ z79W)`CA+D=3*wn(LxEh~d1B~?DyafdcFa!QS@9HzqYnl_us0ieLTK<1sHFJ2XV2De zr7(z1z&HSD>H|>}t>I*XxxRk{gtFtevX{ajHUZKENQ>Alm0K1`R8j!!+A$-r<26zZ zv8m#AMj-rGgQV78js3-{?2N^FF58zbXtUYOdO<@>x}X_K{A#tbR^k!MRN|Eu`a?;Q zyd3$Xx1hehe@<`=_)CF6-WMK>My#VErj~J3RIh`QTLl7Loc8d{xK4y&xKY;$^le`! zlt3*ktING|y4uN}E5vYZT*BK@DFYyd@3;K71SLo6ClW&F!^VyGAE;taIbhOiVE_OC M07*qoM6N<$f}|Y*7ytkO literal 0 HcmV?d00001 diff --git a/static/debug_toolbar/img/back_hover.png b/static/debug_toolbar/img/back_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..2ce3edaf8007361915f4f6824f1488749182dda5 GIT binary patch literal 613 zcmV-r0-F7aP)zYs1M*Sia-mBu&}anp^HRwY+k1%+6a=g zh@wT%?LN=}yFD{E50{Vz9^UcXd!F-S{@gkDt!R(cY86=>vx*^{|B6*K+BX3OZ&+nk zh6`hugSp{BPFby4VUO0x4FOWKnkWEV&ETa4NnjFK$-W@hyr%imyq!HVa|kO<*E`RNaB)c<2~#nD1Y|07ByUE%8Da zcoUE+Kx*#5;_0K(dyOJe6ac$%ToD|&jU*S|ba6W<5bdo&(SWxm{KJahiih=ZUSGbT z&F^w8As2IzZ|vkU~v|6ya4 zX<9|}6Z^M{(t~itzUH~b5=HX|U2pS@Ir`>Vv7N}L6WLDSJot7(1Zopl4egdQW}Ur4 zDZD~#!s}KW1;7Tm|KYzSxFW0LCJNzs1+c%-;JxvJ06CP3RA+IPWc%1WWBP5{@ga&`4 zBm@}{T6*AvjOt5g=F?dl&F#$GVMdQ2Zwb=Hsf1L?BQ?yh4pDM?b&voF$`1tLShe!!+fbBz^h%#1t1&?m&3ROAl~B$gblIxINreSs#q*+E_(y(z2dJn zoK0#&@Rg^UXGE&VCdP;>C oP*D0G|5`Z5)Fs94hX3UJ23oH|sU6@l|v+c^4=ra^%+noy$F^USdS{Djp(S=mH@Bz9KDuqVHKdmKdQ)_8UOgkp& zB$JNTXdP$V~Msa=llf^0SAue&;4FojJ~dYq%##W;{v6H6>SHzo50r30{B!_xj7ZUNXbI zM9N&!yX<`wmw;T8NZBNk;S#*L8C_H^^I+B_lZlCN>x7?QM4>c5Eq zTBfHm5*3+d-VV0l>XmcUSbR!hc7~QOoYdzjfBpp3XYbLc+&rya8|89MZ_{*CB=)KZ$6>Vs8AwpudrLYFDxS?#3ABjQeQ~F{{oC}2oB13?9(Bi2y^5X@i&*_Mx-ku*8(8quST^g&`A4yy_|e#y10009yNklzDm8c75ZG9Mxwgi$zJ4@Kn~4(eqxU8G~PK`50A+m@6pY%*)s(oL2G zHAyovRs;ry=;U7+lODteeGz=|!C^@DpmyM{!(~HJc2t7<;rHbIaz2;e{hf1cBOo9k zAlLx{fk35FX*8O_!9g00);zJrVk!TntE;OyQbMd$D$mydpU+1uu92msrPhd7S65pj zcDvn(#kpK=qXvvd=5RP%E|*HBHp3?r3T-x9EEX%3 zO0fUwblT-|NhFenDCu-M*q!C7ghCN*qfrFn zL?VGLm(6C!s*=fMuw*MN)$bc$-bkf_=tUng$Hlj zhF-_+el6MHD1A)N8eOBkl5UhH2#x;V1NRuvRH8C!;Rl`7^{KPrwF)-m~?>PRGuN4-U>`nw?FsN|RKyF?n zKC(R{5b?l>!PtPZ2Z0zK3!tRx)0JX`iPQ{r>F3i(|c2>QiP8OTLNULm&pP4_jShy@*UA5HANO z>J=~gZy*qZtEOJ@edh=Q@fDqTWqrD?8rGg|BOo9kAZQeS09~?fgUxpE)Bpeg07*qo IM6N<$g4PV2Q~&?~ literal 0 HcmV?d00001 diff --git a/static/debug_toolbar/img/indicator.png b/static/debug_toolbar/img/indicator.png new file mode 100644 index 0000000000000000000000000000000000000000..828a6c01c4bbcdcceade3d7987573dbc44582fc3 GIT binary patch literal 436 zcmV;l0ZaagP)H zGlmg%jNS+7hfxT2kG$mLbT;*kVFCsiiJ&cQgQBRlyggb>L7;^OYN(<@&mTxA{QIBwk9GMB#n(POaY8IlddcdLp literal 0 HcmV?d00001 diff --git a/static/debug_toolbar/js/toolbar.js b/static/debug_toolbar/js/toolbar.js new file mode 100644 index 00000000..771bdda8 --- /dev/null +++ b/static/debug_toolbar/js/toolbar.js @@ -0,0 +1,284 @@ +(function ($) { + var djdt = { + handleDragged: false, + events: { + ready: [] + }, + isReady: false, + init: function() { + $('#djDebug').show(); + var current = null; + $(document).on('click', '#djDebugPanelList li a', function() { + if (!this.className) { + return false; + } + current = $('#djDebug #' + this.className); + if (current.is(':visible')) { + $(document).trigger('close.djDebug'); + $(this).parent().removeClass('active'); + } else { + $('.panelContent').hide(); // Hide any that are already open + var inner = current.find('.djDebugPanelContent .scroll'), + store_id = $('#djDebug').data('store-id'), + render_panel_url = $('#djDebug').data('render-panel-url'); + if (store_id !== '' && inner.children().length === 0) { + var ajax_data = { + data: { + store_id: store_id, + panel_id: this.className + }, + type: 'GET', + url: render_panel_url + }; + $.ajax(ajax_data).done(function(data){ + inner.prev().remove(); // Remove AJAX loader + inner.html(data); + }).fail(function(xhr){ + var message = '
Back

'+xhr.status+': '+xhr.statusText+'

'; + $('#djDebugWindow').html(message).show(); + }); + } + current.show(); + $('#djDebugToolbar li').removeClass('active'); + $(this).parent().addClass('active'); + } + return false; + }); + $(document).on('click', '#djDebug a.djDebugClose', function() { + $(document).trigger('close.djDebug'); + $('#djDebugToolbar li').removeClass('active'); + return false; + }); + $(document).on('click', '#djDebug .djDebugPanelButton input[type=checkbox]', function() { + djdt.cookie.set($(this).attr('data-cookie'), $(this).prop('checked') ? 'on' : 'off', { + path: '/', + expires: 10 + }); + }); + + // Used by the SQL and template panels + $(document).on('click', '#djDebug .remoteCall', function() { + var self = $(this); + var name = self[0].tagName.toLowerCase(); + var ajax_data = {}; + + if (name == 'button') { + var form = self.parents('form:eq(0)'); + ajax_data['url'] = self.attr('formaction'); + + if (form.length) { + ajax_data['data'] = form.serialize(); + ajax_data['type'] = form.attr('method') || 'POST'; + } + } + + if (name == 'a') { + ajax_data['url'] = self.attr('href'); + } + + $.ajax(ajax_data).done(function(data){ + $('#djDebugWindow').html(data).show(); + }).fail(function(xhr){ + var message = '
Back

'+xhr.status+': '+xhr.statusText+'

'; + $('#djDebugWindow').html(message).show(); + }); + + $(document).on('click', '#djDebugWindow a.djDebugBack', function() { + $(this).parent().parent().hide(); + return false; + }); + + return false; + }); + + // Used by the cache, profiling and SQL panels + $(document).on('click', '#djDebug a.djToggleSwitch', function(e) { + e.preventDefault(); + var btn = $(this); + var id = btn.attr('data-toggle-id'); + var open_me = btn.text() == btn.attr('data-toggle-open'); + if (id === '' || !id) { + return; + } + var name = btn.attr('data-toggle-name'); + btn.parents('.djDebugPanelContent').find('#' + name + '_' + id).find('.djDebugCollapsed').toggle(open_me); + btn.parents('.djDebugPanelContent').find('#' + name + '_' + id).find('.djDebugUncollapsed').toggle(!open_me); + $(this).parents('.djDebugPanelContent').find('.djToggleDetails_' + id).each(function(){ + var $this = $(this); + if (open_me) { + $this.addClass('djSelected'); + $this.removeClass('djUnselected'); + btn.text(btn.attr('data-toggle-close')); + $this.find('.djToggleSwitch').text(btn.text()); + } else { + $this.removeClass('djSelected'); + $this.addClass('djUnselected'); + btn.text(btn.attr('data-toggle-open')); + $this.find('.djToggleSwitch').text(btn.text()); + } + }); + return; + }); + + $('#djHideToolBarButton').click(function() { + djdt.hide_toolbar(true); + return false; + }); + $('#djShowToolBarButton').click(function() { + if (!djdt.handleDragged) { + djdt.show_toolbar(); + } + return false; + }); + var handle = $('#djDebugToolbarHandle'); + $('#djShowToolBarButton').on('mousedown', function (event) { + var startPageY = event.pageY; + var baseY = handle.offset().top - startPageY; + $(document).on('mousemove.djDebug', function (event) { + // Chrome can send spurious mousemove events, so don't do anything unless the + // cursor really moved. Otherwise, it will be impossible to expand the toolbar + // due to djdt.handleDragged being set to true. + if (djdt.handleDragged || event.pageY != startPageY) { + var offset = handle.offset(); + offset.top = baseY + event.pageY; + handle.offset(offset); + djdt.handleDragged = true; + } + }); + return false; + }); + $(document).on('mouseup', function () { + $(document).off('mousemove.djDebug'); + if (djdt.handleDragged) { + var top = handle.offset().top; + djdt.cookie.set('djdttop', top, { + path: '/', + expires: 10 + }); + setTimeout(function () { + djdt.handleDragged = false; + }, 10); + return false; + } + }); + $(document).bind('close.djDebug', function() { + // If a sub-panel is open, close that + if ($('#djDebugWindow').is(':visible')) { + $('#djDebugWindow').hide(); + return; + } + // If a panel is open, close that + if ($('.panelContent').is(':visible')) { + $('.panelContent').hide(); + $('#djDebugToolbar li').removeClass('active'); + return; + } + // Otherwise, just minimize the toolbar + if ($('#djDebugToolbar').is(':visible')) { + djdt.hide_toolbar(true); + return; + } + }); + if (djdt.cookie.get('djdt') == 'hide') { + djdt.hide_toolbar(false); + } else { + djdt.show_toolbar(false); + } + $('#djDebug .djDebugHoverable').hover(function(){ + $(this).addClass('djDebugHover'); + }, function(){ + $(this).removeClass('djDebugHover'); + }); + djdt.isReady = true; + $.each(djdt.events.ready, function(_, callback){ + callback(djdt); + }); + }, + close: function() { + $(document).trigger('close.djDebug'); + return false; + }, + hide_toolbar: function(setCookie) { + // close any sub panels + $('#djDebugWindow').hide(); + // close all panels + $('.panelContent').hide(); + $('#djDebugToolbar li').removeClass('active'); + // finally close toolbar + $('#djDebugToolbar').hide('fast'); + $('#djDebugToolbarHandle').show(); + // set handle position + var handleTop = djdt.cookie.get('djdttop'); + if (handleTop) { + $('#djDebugToolbarHandle').css({top: handleTop + 'px'}); + } + // Unbind keydown + $(document).unbind('keydown.djDebug'); + if (setCookie) { + djdt.cookie.set('djdt', 'hide', { + path: '/', + expires: 10 + }); + } + }, + show_toolbar: function(animate) { + // Set up keybindings + $(document).bind('keydown.djDebug', function(e) { + if (e.keyCode == 27) { + djdt.close(); + } + }); + $('#djDebugToolbarHandle').hide(); + if (animate) { + $('#djDebugToolbar').show('fast'); + } else { + $('#djDebugToolbar').show(); + } + djdt.cookie.set('djdt', 'show', { + path: '/', + expires: 10 + }); + }, + ready: function(callback){ + if (djdt.isReady) { + callback(djdt); + } else { + djdt.events.ready.push(callback); + } + }, + cookie: { + get: function(key){ + if (document.cookie.indexOf(key) === -1) return null; + + var cookieArray = document.cookie.split('; '), + cookies = {}; + + cookieArray.forEach(function(e){ + var parts = e.split('='); + cookies[ parts[0] ] = parts[1]; + }); + + return cookies[ key ]; + }, + set: function(key, value, options){ + options = options || {}; + + if (typeof options.expires === 'number') { + var days = options.expires, t = options.expires = new Date(); + t.setDate(t.getDate() + days); + } + + document.cookie = [ + encodeURIComponent(key) + '=' + String(value), + options.expires ? '; expires=' + options.expires.toUTCString() : '', + options.path ? '; path=' + options.path : '', + options.domain ? '; domain=' + options.domain : '', + options.secure ? '; secure' : '' + ].join(''); + + return value; + } + } + }; + $(document).ready(djdt.init); +})(djdt.jQuery); diff --git a/static/debug_toolbar/js/toolbar.profiling.js b/static/debug_toolbar/js/toolbar.profiling.js new file mode 100644 index 00000000..1018e9b4 --- /dev/null +++ b/static/debug_toolbar/js/toolbar.profiling.js @@ -0,0 +1,20 @@ +(function ($) { + function getSubcalls(row) { + var id = row.attr('id'); + return $('.djDebugProfileRow[id^="'+id+'_"]'); + } + function getDirectSubcalls(row) { + var subcalls = getSubcalls(row); + var depth = parseInt(row.attr('depth'), 10) + 1; + return subcalls.filter('[depth='+depth+']'); + } + $('.djDebugProfileRow .djDebugProfileToggle').on('click', function(){ + var row = $(this).closest('.djDebugProfileRow'); + var subcalls = getSubcalls(row); + if (subcalls.css('display') == 'none') { + getDirectSubcalls(row).show(); + } else { + subcalls.hide(); + } + }); +})(djdt.jQuery); diff --git a/static/debug_toolbar/js/toolbar.sql.js b/static/debug_toolbar/js/toolbar.sql.js new file mode 100644 index 00000000..e470ac8f --- /dev/null +++ b/static/debug_toolbar/js/toolbar.sql.js @@ -0,0 +1,7 @@ +(function ($) { + $('#djDebug a.djDebugToggle').on('click', function(e) { + e.preventDefault(); + $(this).parent().find('.djDebugCollapsed').toggle(); + $(this).parent().find('.djDebugUncollapsed').toggle(); + }); +})(djdt.jQuery); diff --git a/static/debug_toolbar/js/toolbar.template.js b/static/debug_toolbar/js/toolbar.template.js new file mode 100644 index 00000000..01ac8a4a --- /dev/null +++ b/static/debug_toolbar/js/toolbar.template.js @@ -0,0 +1,11 @@ +(function ($) { + var uarr = String.fromCharCode(0x25b6), + darr = String.fromCharCode(0x25bc); + + $('a.djTemplateShowContext').on('click', function() { + var arrow = $(this).children('.toggleArrow'); + arrow.html(arrow.html() == uarr ? darr : uarr); + $(this).parent().next().toggle(); + return false; + }); +})(djdt.jQuery); diff --git a/static/debug_toolbar/js/toolbar.timer.js b/static/debug_toolbar/js/toolbar.timer.js new file mode 100644 index 00000000..cc9d6ae7 --- /dev/null +++ b/static/debug_toolbar/js/toolbar.timer.js @@ -0,0 +1,48 @@ +(function ($) { + // Browser timing remains hidden unless we can successfully access the performance object + var perf = window.performance || window.msPerformance || + window.webkitPerformance || window.mozPerformance; + if (!perf) + return; + + var rowCount = 0, + timingOffset = perf.timing.navigationStart, + timingEnd = perf.timing.loadEventEnd, + totalTime = timingEnd - timingOffset; + function getLeft(stat) { + return ((perf.timing[stat] - timingOffset) / (totalTime)) * 100.0; + } + function getCSSWidth(stat, endStat) { + var width = ((perf.timing[endStat] - perf.timing[stat]) / (totalTime)) * 100.0; + // Calculate relative percent (same as sql panel logic) + width = 100.0 * width / (100.0 - getLeft(stat)); + return (width < 1) ? "2px" : width + "%"; + } + function addRow(stat, endStat) { + rowCount++; + var $row = $(''); + if (endStat) { + // Render a start through end bar + $row.html('' + stat.replace('Start', '') + '' + + '
 
' + + '' + (perf.timing[stat] - timingOffset) + ' (+' + (perf.timing[endStat] - perf.timing[stat]) + ')'); + } else { + // Render a point in time + $row.html('' + stat + '' + + '
 
' + + '' + (perf.timing[stat] - timingOffset) + ''); + } + $('#djDebugBrowserTimingTableBody').append($row); + } + + // This is a reasonably complete and ordered set of timing periods (2 params) and events (1 param) + addRow('domainLookupStart', 'domainLookupEnd'); + addRow('connectStart', 'connectEnd'); + addRow('requestStart', 'responseEnd'); // There is no requestEnd + addRow('responseStart', 'responseEnd'); + addRow('domLoading', 'domComplete'); // Spans the events below + addRow('domInteractive'); + addRow('domContentLoadedEventStart', 'domContentLoadedEventEnd'); + addRow('loadEventStart', 'loadEventEnd'); + $('#djDebugBrowserTiming').css("display", "block"); +})(djdt.jQuery); diff --git a/templates/admin/blog/blog_add.html b/templates/admin/blog/blog_add.html new file mode 100644 index 00000000..f286cd5b --- /dev/null +++ b/templates/admin/blog/blog_add.html @@ -0,0 +1,25 @@ +{% extends 'base.html' %} +{% load static %} + +{% block scripts %} + + + {# selects #} + + + + {# ajax #} + + + +{% endblock %} + +{% block body %} +
{% csrf_token %} + {{ form.as_p }} +
+ + +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/client/includes/booking_block.html b/templates/client/includes/booking_block.html new file mode 100644 index 00000000..bedb0be4 --- /dev/null +++ b/templates/client/includes/booking_block.html @@ -0,0 +1,55 @@ +{% load i18n %} +{% load thumbnail %} +{% comment %} + object which is transmitted must have city(required) and may have place field(not required) + +{% endcomment %} + + \ No newline at end of file diff --git a/templates/client/includes/event_object.html b/templates/client/includes/event_object.html index d46bec14..7f26937f 100644 --- a/templates/client/includes/event_object.html +++ b/templates/client/includes/event_object.html @@ -1,5 +1,6 @@ {% load static %} {% load i18n %} +{% load thumbnail %} {% load template_filters %} {% block page_body %} @@ -249,18 +250,9 @@ {% endif %} - + {% with obj=exposition %} + {% include 'client/includes/booking_block.html' %} + {% endwith %}
{% if exposition.get_nearest_events|slice:":6" %}
diff --git a/theme/models.py b/theme/models.py index 88cba883..4f204f0d 100644 --- a/theme/models.py +++ b/theme/models.py @@ -174,3 +174,8 @@ pre_save.connect(pre_save_handler, sender=Tag) post_save.connect(post_save_handler, sender=Theme) post_save.connect(post_save_handler, sender=Tag) + + +#----------------------- + +