diff --git a/accounts/urls.py b/accounts/urls.py index 375e0e07..eae55d03 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -3,12 +3,13 @@ from django.conf.urls import patterns, url from django.contrib.auth.decorators import login_required from views import SettingsView, ProfileView, CalendarView, UserView, UserExpositionsView, UserConferenceView, UserSeminarView from views import NameView, HomeView, AvatarView, WorkView, AboutCompanyView, PhoneView, EmailView, WebPageView,\ - SocialView, AboutView + SocialView, AboutView, ProfileCompanyView from views import test urlpatterns = patterns('', url(r'^profile/$', login_required(ProfileView.as_view())), + url(r'^profile/company/$', login_required(ProfileCompanyView.as_view())), url(r'^profile/settings/$', login_required(SettingsView.as_view())), url(r'^profile/calendar/$', login_required(CalendarView.as_view())), url(r'^user/(?P.*)/expositions/(?P\d+)/$', UserExpositionsView.as_view()), diff --git a/accounts/views.py b/accounts/views.py index 49a33656..957c7234 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -8,6 +8,7 @@ from django.utils.translation import ugettext as _ from django.utils import timezone # forms from forms import ChangePasswordForm, EmailAnnouncementForm +from company.forms import CompanyFormClient from edit_forms import AvatarForm, NameForm, HomeForm, WorkForm, AboutCompanyForm, PhoneForm, EmailForm,\ WebPageForm, SocialForm, AboutForm from models import User @@ -89,7 +90,7 @@ def get_calendar(request, year, month): return HttpResponse(json.dumps(args), content_type='application/json') class ProfileView(TemplateView): - template_name = 'accounts/profile.html' + template_name = 'accounts/new_profile.html' def post(self): return HttpResponse(self.request.POST) @@ -111,6 +112,18 @@ class ProfileView(TemplateView): context.update(profile_forms) return context +class ProfileCompanyView(FormView): + form_class = CompanyFormClient + template_name = 'accounts/fill_company.html' + success_url = '/profile/company/' + + def form_valid(self, form): + return HttpResponse('success') + + def form_invalid(self, form): + return HttpResponse(form.errors) + + class MessagesView(TemplateView): template_name = 'accounts/messages.html' diff --git a/article/admin.py b/article/admin.py index a664da6d..26801086 100644 --- a/article/admin.py +++ b/article/admin.py @@ -1,12 +1,12 @@ # -*- coding: utf-8 -*- from django.shortcuts import render_to_response, get_object_or_404 -from django.http import HttpResponseRedirect +from django.http import HttpResponseRedirect, HttpResponse from django.core.context_processors import csrf from django.conf import settings from django.contrib.auth.decorators import login_required from django.contrib.contenttypes.models import ContentType #models and forms -from forms import ArticleForm, ArticleDeleteForm, Article +from forms import ArticleForm, ArticleDeleteForm, Article, NewsForm from theme.models import Tag from file.models import FileModel, TmpFile from file.forms import FileModelForm @@ -25,7 +25,7 @@ def article_all(request): @login_required def article_copy(request, url): - article = Article.objects.safe_get(url=url) + article = Article.objects.safe_get(slug=url) if not article: return HttpResponseRedirect(get_referer(request)) else: @@ -60,7 +60,7 @@ def article_change(request, url): """ try: #check if article_id exists else redirect to the list of cities - article = Article.objects.get(url=url) + article = Article.objects.get(slug=url) file_form = FileModelForm(initial={'model': 'article.Article'}) article_id = getattr(article, 'id') except: @@ -77,7 +77,7 @@ def article_change(request, url): else: data = {} #fill form with data from database - data['author'] = article.user + data['author'] = article.author data['theme'] = [item.id for item in article.theme.all()] data['tag'] = [item.id for item in article.tag.all()] #hidden field @@ -112,6 +112,104 @@ def article_change(request, url): return render_to_response('article_add.html', args) #----------------------- +from django.views.generic import ListView, FormView +from forms import BlogForm + +class BlogList(ListView): + model = Article + template_name = 'article/article_admin_list.html' + + def get_queryset(self): + return self.model.objects.blogs() + + def get_context_data(self, **kwargs): + context = super(BlogList, self).get_context_data(**kwargs) + context['blog_flag'] = True + return context + +class BlogView(FormView): + form_class = BlogForm + template_name = 'article/blog_form.html' + success_url = '/admin/article/blog/all/' + obj = None + + def set_obj(self): + slug = self.kwargs.get('slug') + if slug: + article = get_object_or_404(Article, slug=slug) + self.obj = article + else: + self.obj = None + + def form_valid(self, form): + self.set_obj() + author = self.request.user + form.save(author, article=self.obj) + return HttpResponseRedirect(self.success_url) + + def form_invalid(self, form): + + return HttpResponse(form.errors) + + def get_form(self, form_class): + if self.request.POST: + return super(BlogView, self).get_form(form_class) + self.set_obj() + if self.obj: + article = self.obj + data = {} + data['theme'] = [item.id for item in article.theme.all()] + data['exposition'] = article.exposition + data['conference'] = article.conference + a = ','.join(['%s:%s'%(item.id, item.name) for item in article.tag.all()]) + + data['tag'] = ','.join(['%s:%s'%(item.id, item.name) for item in article.tag.all()]) + for code, name in settings.LANGUAGES: + obj = Article._meta.translations_model.objects.get(language_code = code,master__id=getattr(article, 'id')) #access to translated fields + data['main_title_%s' % code] = obj.main_title + data['preview_%s' % code] = obj.preview + data['description_%s' % code] = obj.description + data['title_%s' % code] = obj.title + data['keywords_%s' % code] = obj.keywords + data['descriptions_%s' % code] = obj.descriptions + form = form_class(data) + #form.fields['tag'].widget.attrs['data-init-text'] = [item.name for item in article.tag.all()] + return form_class(data) + else: + return form_class() + + + + def get_context_data(self, **kwargs): + context = super(BlogView, self).get_context_data(**kwargs) + self.set_obj() + context['article'] = self.obj + context['languages'] = settings.LANGUAGES + return context + + +class NewsList(ListView): + model = Article + template_name = 'article/article_admin_list.html' + + def get_queryset(self): + return self.model.objects.news() + + def get_context_data(self, **kwargs): + context = super(NewsList, self).get_context_data(**kwargs) + context['news_flag'] = True + return context + +class NewsView(BlogView): + form_class = NewsForm + template_name = 'article/blog_form.html' + success_url = '/admin/article/news/all/' + obj = None + + + + +""" from django.views.generic import CreateView from models import Blog from forms import BlogForm @@ -120,3 +218,4 @@ class BlogCreate(CreateView): model = Blog form_class = BlogForm template_name = 'admin/blog/blog_add.html' +""" \ No newline at end of file diff --git a/article/admin_blog.py b/article/admin_blog.py deleted file mode 100644 index 62163b00..00000000 --- a/article/admin_blog.py +++ /dev/null @@ -1,10 +0,0 @@ -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/admin_urls.py b/article/admin_urls.py index e9537329..3b083c2f 100644 --- a/article/admin_urls.py +++ b/article/admin_urls.py @@ -1,10 +1,19 @@ # -*- coding: utf-8 -*- from django.conf.urls import patterns, url +from admin import BlogList, BlogView, NewsList, NewsView urlpatterns = patterns('article.admin', + url(r'^add/$', 'article_add'), url(r'^delete/(?P.*)/$', 'article_delete'), url(r'^change/(.*)/$', 'article_change'), url(r'^copy/(.*)/$', 'article_copy'), url(r'^all/$', 'article_all'), + url(r'^blog/all/$', BlogList.as_view()), + url(r'^blog/$', BlogView.as_view()), + url(r'^news/all/$', NewsList.as_view()), + url(r'^news/$', NewsView.as_view()), + + url(r'^blog/(?P.*)/$', BlogView.as_view()), + url(r'^news/(?P.*)/$', NewsView.as_view()), ) \ No newline at end of file diff --git a/article/forms.py b/article/forms.py index 5eac49f7..44fcdad8 100644 --- a/article/forms.py +++ b/article/forms.py @@ -12,8 +12,92 @@ from functions.form_check import translit_with_separator from models import Article from accounts.models import User from theme.models import Theme, Tag +from exposition.models import Exposition +from conference.models import Conference +class BlogForm(forms.Form): + type = Article.blog + theme = forms.ModelMultipleChoiceField(label='Тематики', queryset=Theme.objects.all(), required=False, + widget=forms.SelectMultiple(attrs={'style':'width: 550px'})) + tag = forms.CharField(label=u'Теги', widget=forms.HiddenInput(), required=False) + logo = forms.ImageField(label=u'Лого', required=False) + def __init__(self, *args, **kwargs): + """ + create dynamical translated fields fields + """ + super(BlogForm, self).__init__(*args, **kwargs) + #creates translated forms example: name_ru, name_en + # len(10) is a hack for detect if settings.LANGUAGES is not configured it return all langs + 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=False, widget=CKEditorWidget) + self.fields['description_%s' % code] = forms.CharField(label='Описание', required=False, 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'})) + + def save(self, author, article=None): + data = self.cleaned_data + #create new Article object or get exists + if not article: + article = Article() + + article.author = author + article.type = self.type + article.logo = data['logo'] + # fill translated fields and save object + fill_with_signal(Article, article, data) + # fill manytomany fields + article.theme.clear() + article.tag.clear() + article.theme.add(*Theme.objects.filter(id__in=data['theme'])) + article.tag.add(*Tag.objects.filter(id__in=data['tag'])) + #for item in data['theme']: + # article.theme.add(item.id)#.id cause select uses queryset + + #for item in data['tag']: + # article.tag.add(item) + + article.save() + + return article + + def clean_tag(self): + tags = self.cleaned_data.get('tag') + if tags: + res = [] + for id in tags.split(','): + try: + res.append(int(id)) + except: + continue + return res + else: + return [] + +class NewsForm(BlogForm): + type = Article.news + exposition = forms.ModelChoiceField(label = u'Выставка', required=False, queryset=Exposition.objects.all()) + conference = forms.ModelChoiceField(label = u'Конференция', required=False, queryset=Conference.objects.all()) + + def save(self, author, article=None): + article = super(NewsForm, self).save(author, article) + exposition = self.cleaned_data.get('exposition') + conference = self.cleaned_data.get('conference') + article.exposition = exposition + article.conference = conference + article.save() + return article + class ArticleForm(forms.Form): """ Create Article form for creating conference @@ -115,6 +199,7 @@ class ArticleDeleteForm(forms.ModelForm): fields = ('url',) #---------------------------------- +""" from models import Blog class BlogForm(forms.ModelForm): @@ -140,4 +225,5 @@ class BlogForm(forms.ModelForm): 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 + widget=forms.TextInput(attrs={'style':'width: 550px'})) +""" \ No newline at end of file diff --git a/article/models.py b/article/models.py index 009474de..6f65aaa3 100644 --- a/article/models.py +++ b/article/models.py @@ -2,8 +2,12 @@ import copy from django.db import models from django.utils.translation import ugettext_lazy as _ +from django.utils.timezone import now from hvad.models import TranslatableModel, TranslatedFields, TranslationManager +from django.utils.html import strip_tags from sorl.thumbnail import ImageField +from functions.url_utils import slugify, unique_slug +from functions.model_utils import base_concrete_model class ArticleManager(TranslationManager): @@ -14,6 +18,20 @@ class ArticleManager(TranslationManager): except: return None + def news(self): + """ + return queryset of news + """ + model = self.model + return model.objects.filter(type=model.news) + + def blogs(self): + """ + return queryset of blogs + """ + model = self.model + return model.objects.filter(type=model.blog) + class Article(TranslatableModel): """ Create Article model @@ -21,15 +39,45 @@ class Article(TranslatableModel): Uses hvad.TranslatableModel which is child of django.db.models class """ + + MAX_ON_MAIN_PAGE = 3 + # types of article + blog = 1 + news = 2 + #set manager of this model objects = ArticleManager() - - url = models.SlugField(unique=True) + slug = models.SlugField(unique=True, max_length=255) + logo = ImageField(upload_to='articles_preview', blank=True) theme = models.ManyToManyField('theme.Theme') tag = models.ManyToManyField('theme.Tag', related_name='tags',blank=True, null=True) - user = models.ForeignKey('accounts.User', verbose_name='Автор', + author = models.ForeignKey('accounts.User', verbose_name='Автор', on_delete=models.PROTECT, related_name='articles') - main_page = models.PositiveIntegerField(default=0, db_index=True) + exposition = models.ForeignKey('exposition.Exposition', blank=True, null=True) + conference = models.ForeignKey('conference.Conference', blank=True, null=True) + type = models.PositiveSmallIntegerField(default=1) + allow_comments = models.BooleanField(default=True) + + # fields that provides features of a visible page on the website + publish_date = models.DateTimeField(blank=True, null=True) + expiry_date = models.DateTimeField(_("Expires on"), + help_text=_("With Published chosen, won't be shown after this time"), + blank=True, null=True) + in_sitemap = models.BooleanField(_("Show in sitemap"), default=False) + + # fields that provides features of a visible on main page + main_page = models.BooleanField(default=False) + main_page_time = models.DateTimeField(blank=True, null=True) + + # field that check if need generate description + gen_description = models.BooleanField(_("Generate description"), + help_text=_("If checked, the description will be automatically " + "generated from content. Uncheck if you want to manually " + "set a custom description."), default=True) + +# published = models. + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) #translated fields translations = TranslatedFields( @@ -45,6 +93,97 @@ class Article(TranslatableModel): def __unicode__(self): return self.lazy_translation_getter('main_title', self.pk) + def translation_model(self): + return self._meta.translations_model + + + def publish(self): + self.in_sitemap = True + if not self.publish_date: + # save time only first time + self.publish_date = now() + self.save() + + return self + + def get_event(self): + if self.exposition: + return self.exposition + elif self.conference: + return self.conference + return None + + + def save(self, *args, **kwargs): + + # If no slug is provided, generates one before saving. + if not self.slug: + self.slug = self.generate_unique_slug() + + #Set the description field on save. + if self.gen_description: + self.description = strip_tags(self.description_from_content()) + super(Article, self).save(*args, **kwargs) + + def description_from_content(self): + """ + """ + # place for logic + return '' + + def generate_unique_slug(self): + """ + Create a unique slug by passing the result of get_slug() to + utils.urls.unique_slug, which appends an index if necessary. + """ + # For custom content types, use the ``Page`` instance for + # slug lookup. + concrete_model = base_concrete_model(Article, self) + slug_qs = concrete_model.objects.exclude(id=self.id) + return unique_slug(slug_qs, "slug", self.get_slug()) + + def get_slug(self): + """ + Allows subclasses to implement their own slug creation logic. + """ + return slugify(self.get_available_title()) + + def get_available_title(self): + #print self.lazy_translation_getter('main_title', self.pk) + return u'%s'%self.lazy_translation_getter('main_title', self.pk) + + + def _get_next_or_previous_by_publish_date(self, is_next, **kwargs): + """ + Retrieves next or previous object by publish date. We implement + our own version instead of Django's so we can hook into the + published manager and concrete subclasses. + """ + arg = "publish_date__gt" if is_next else "publish_date__lt" + order = "publish_date" if is_next else "-publish_date" + lookup = {arg: self.publish_date} + concrete_model = base_concrete_model(Article, self) + try: + queryset = concrete_model.objects.published + except AttributeError: + queryset = concrete_model.objects.all + try: + return queryset(**kwargs).filter(**lookup).order_by(order)[0] + except IndexError: + pass + + def get_next_by_publish_date(self, **kwargs): + """ + Retrieves next object by publish date. + """ + return self._get_next_or_previous_by_publish_date(True, **kwargs) + + def get_previous_by_publish_date(self, **kwargs): + """ + Retrieves previous object by publish date. + """ + return self._get_next_or_previous_by_publish_date(False, **kwargs) + def clone(self): """ Return an identical copy of the instance with a new ID. @@ -100,39 +239,19 @@ class Article(TranslatableModel): return duplicate -from django.db.models.signals import post_save -from functions.signal_handlers import post_save_handler - -post_save.connect(post_save_handler, sender=Article) + def admin_url(self): + if self.type == 1: + return '/admin/article/blog/%s'%self.slug + elif self.type == 2: + return '/admin/article/news/%s'%self.slug + def get_permanent_url(self): + if self.type == 1: + return '/blogs/%s'%self.slug + elif self.type == 2: + return '/news/%s'%self.slug -#-------------------------------- -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) - +from django.db.models.signals import post_save +from functions.signal_handlers import post_save_handler -#post_save.connect(post_save_handler, sender=Blog) \ No newline at end of file +post_save.connect(post_save_handler, sender=Article) \ No newline at end of file diff --git a/article/urls.py b/article/urls.py new file mode 100644 index 00000000..84a18675 --- /dev/null +++ b/article/urls.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +from django.conf.urls import patterns, url +from views import BlogList, NewsList, BlogDetail, NewsDetail + +urlpatterns = patterns('', + url(r'blogs/$', BlogList.as_view()), + url(r'news/$', NewsList.as_view()), + url(r'blogs/(?P.*)$', BlogDetail.as_view()), + url(r'news/(?P.*)$', NewsDetail.as_view()), +) diff --git a/article/views.py b/article/views.py new file mode 100644 index 00000000..862e73fb --- /dev/null +++ b/article/views.py @@ -0,0 +1,55 @@ +from django.views.generic import DetailView, ListView +from django.http import HttpResponse +from models import Article + +class NewsList(ListView): + model = Article + template_name = 'article/news_list.html' + + def get_queryset(self): + if self.request.GET: + qs = self.model.objects.news() + themes = self.request.GET.getlist('theme') + if themes: + qs = qs.filter(theme__id__in=themes) + + tags = self.request.GET.getlist('tag') + if tags: + qs = qs.filter(tag__id__in=tags) + + return qs + else: + return self.model.objects.news() + +class NewsDetail(DetailView): + model = Article + slug_field = 'slug' + template_name = 'article/news.html' + + +class BlogList(ListView): + model = Article + template_name = 'article/blog_list.html' + + def get_queryset(self): + if self.request.GET: + qs = self.model.objects.blogs() + + themes = self.request.GET.getlist('theme') + if themes: + qs = qs.filter(theme__id__in=themes) + + tags = self.request.GET.getlist('tag') + if tags: + qs = qs.filter(tag__id__in=tags) + + return qs + else: + return self.model.objects.blogs() + + + +class BlogDetail(DetailView): + model = Article + slug_field = 'slug' + template_name = 'article/article.html' \ No newline at end of file diff --git a/city/admin.py b/city/admin.py index 476013e2..75efe755 100644 --- a/city/admin.py +++ b/city/admin.py @@ -104,6 +104,4 @@ def search_city(request): qs = City.objects.language().filter(country=country, translations__name__contains=term) result = [{'id': city.id, 'label': city.name} for city in qs] - - return HttpResponse(json.dumps(result), content_type='application/json') - return HttpResponse(country_id) \ No newline at end of file + return HttpResponse(json.dumps(result), content_type='application/json') \ No newline at end of file diff --git a/company/forms.py b/company/forms.py index 26c09324..0bdef773 100644 --- a/company/forms.py +++ b/company/forms.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from django import forms from django.conf import settings +from django.utils.translation import ugettext as _ from ckeditor.widgets import CKEditorWidget from django.core.exceptions import ValidationError from django.forms.util import ErrorList @@ -208,4 +209,50 @@ class CompanyDeleteForm(forms.ModelForm): class Meta: model = Company - fields = ('id',) \ No newline at end of file + fields = ('id',) + +class CompanyFormClient(forms.Form): + + # translated fields + name = forms.CharField(label=_(u'название')) + specialization = forms.CharField(label=_(u'краткое описание компании'), required=False) + address_inf = forms.CharField(label=_(u'адрес компании'), required=False) + description = forms.CharField(label=_(u'подробное описание компании'), required=False) + # + logo = forms.ImageField(required=False) + country = forms.ModelChoiceField(label=_(u'Страна'), queryset=Country.objects.all(), empty_label=None) + city = forms.CharField(label=_(u'Город'), widget=forms.HiddenInput()) + theme = forms.ModelMultipleChoiceField(label=_(u'Тематики'), queryset=Theme.objects.all()) + tag = forms.CharField(label=u'Теги', widget=forms.HiddenInput(), required=False) + + phone = forms.CharField(label='Телефон', required=False) + fax = forms.CharField(label='Факс', required=False) + web_page = forms.URLField(label='Веб-сайт', required=False) + email = forms.EmailField(label='Email', required=False) + foundation = forms.IntegerField(label=_(u'Год основания'), required=False) + staff_number = forms.IntegerField(label=_(u'Количество сотрудников'), required=False) + vk = forms.URLField(label=_(u'в контакте'), required=False) + twitter = forms.URLField(label=u'Twitter', required=False) + facebook = forms.URLField(label=u'Facebook', required=False) + linkedin = forms.URLField(label=u'Linkedin', required=False) + + + def __init__(self, *args, **kwargs): + """ + create dynamical translated fields fields + """ + super(CompanyFormClient, self).__init__(*args, **kwargs) + #creates translated forms example: name_ru, name_en + # len(10) is a hack for detect if settings.LANGUAGES is not configured it return all langs + 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['name_%s' % code] = forms.CharField(label=_(u'название'), required=required) + self.fields['description_%s' % code] = forms.CharField(label=_(u'подробное описание компании'), + required=False) + self.fields['specialization_%s' % code] = forms.CharField(label=_(u'краткое описание компании'), + required=False) + self.fields['address_inf_%s' % code] = forms.CharField(label=_(u'адрес компании'), + required=False) \ No newline at end of file diff --git a/exposition/views.py b/exposition/views.py index d77b9910..e9bcff9f 100644 --- a/exposition/views.py +++ b/exposition/views.py @@ -10,6 +10,7 @@ from functions.search_forms import ExpositionSearchForm from service.views import order_forms from django.shortcuts import get_object_or_404 from django.http import Http404 +from django.utils import translation # from service.models import Service from country.models import Country @@ -24,14 +25,20 @@ class ExpositionByCountry(ListView): model = Country template_name = 'exposition/exposition_by_country.html' def get_queryset(self): - return self.model.objects.select_related('exposition_country').filter(exposition_country__country__isnull=False).all().distinct() + lang = translation.get_language() + return self.model.objects.select_related('exposition_country')\ + .filter(exposition_country__country__isnull=False, translations__language_code=lang)\ + .order_by('translations__name').distinct() class ExpositionByTheme(ListView): model = Theme template_name = 'exposition/exposition_by_theme.html' def get_queryset(self): - return self.model.objects.select_related('exposition_themes').filter(exposition_themes__theme__isnull=False).all().distinct() + lang = translation.get_language() + return self.model.objects.select_related('exposition_themes')\ + .filter(exposition_themes__theme__isnull=False, translations__language_code=lang)\ + .order_by('translations__name').distinct() class ExpositionByCity(ListView): @@ -39,7 +46,10 @@ class ExpositionByCity(ListView): template_name = 'exposition/exposition_by_city.html' def get_queryset(self): - return self.model.objects.select_related('exposition_city').filter(exposition_city__city__isnull=False).all().distinct() + lang = translation.get_language() + return self.model.objects.select_related('exposition_city')\ + .filter(exposition_city__city__isnull=False, translations__language_code=lang)\ + .order_by('translations__name').distinct() class ExpositionServiceView(FormView, ExpoMixin): params = None @@ -156,7 +166,7 @@ class ExpositionSearchView(ListView): if queries.has_key('page'): del queries['page'] context['queries'] = queries - context['search_action'] = '/expositions/search/' + context['search_action'] = '/expo/search/' return context diff --git a/functions/model_utils.py b/functions/model_utils.py new file mode 100644 index 00000000..d548d446 --- /dev/null +++ b/functions/model_utils.py @@ -0,0 +1,37 @@ +def base_concrete_model(abstract, instance): + """ + Used in methods of abstract models to find the super-most concrete + (non abstract) model in the inheritance chain that inherits from the + given abstract model. This is so the methods in the abstract model can + query data consistently across the correct concrete model. + + Consider the following:: + + class Abstract(models.Model) + + class Meta: + abstract = True + + def concrete(self): + return base_concrete_model(Abstract, self) + + class Super(Abstract): + pass + + class Sub(Super): + pass + + sub = Sub.objects.create() + sub.concrete() # returns Super + + In actual Mezzanine usage, this allows methods in the ``Displayable`` and + ``Orderable`` abstract models to access the ``Page`` instance when + instances of custom content types, (eg: models that inherit from ``Page``) + need to query the ``Page`` model to determine correct values for ``slug`` + and ``_order`` which are only relevant in the context of the ``Page`` + model and not the model of the custom content type. + """ + for cls in reversed(instance.__class__.__mro__): + if issubclass(cls, abstract) and not cls._meta.abstract: + return cls + return instance.__class__ diff --git a/functions/search_forms.py b/functions/search_forms.py index 33b914e8..132467ce 100644 --- a/functions/search_forms.py +++ b/functions/search_forms.py @@ -77,12 +77,14 @@ class CompanySearchForm(AbstactSearchForm): from country.models import Area +from theme.models import Theme class ExpositionSearchForm(forms.Form): q = forms.CharField(label=_(u'Поиск'), required=False) w = forms.CharField(label=_(u'Где'), required=False) - th = forms.CharField(label=_(u'Тематика'), required=False, widget=forms.SelectMultiple()) + th = forms.ModelMultipleChoiceField(label=_(u'Тематика'), queryset=Theme.objects.all(), + 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.language()], diff --git a/functions/url_utils.py b/functions/url_utils.py new file mode 100644 index 00000000..34e9e3ab --- /dev/null +++ b/functions/url_utils.py @@ -0,0 +1,37 @@ +import unicodedata, re + +from django.utils.encoding import smart_text +from django.core.exceptions import ObjectDoesNotExist + +def unique_slug(queryset, slug_field, slug): + """ + Ensures a slug is unique for the given queryset, appending + an integer to its end until the slug is unique. + """ + i = 0 + while True: + if i > 0: + if i > 1: + slug = slug.rsplit("-", 1)[0] + slug = "%s-%s" % (slug, i) + try: + queryset.get(**{slug_field: slug}) + except ObjectDoesNotExist: + break + i += 1 + return slug + +def slugify(s): + """ + Replacement for Django's slugify which allows unicode chars in + slugs, for URLs in Chinese, Russian, etc. + Adopted from https://github.com/mozilla/unicode-slugify/ + """ + chars = [] + for char in smart_text(s): + cat = unicodedata.category(char)[0] + if cat in "LN" or char in "-_~": + chars.append(char) + elif cat == "Z": + chars.append(" ") + return re.sub("[-\s]+", "-", "".join(chars).strip()).lower() \ No newline at end of file diff --git a/news/models.py b/news/models.py index 7f8263c6..96792e50 100644 --- a/news/models.py +++ b/news/models.py @@ -17,6 +17,8 @@ class NewsManager(TranslationManager): TYPES = ('announcement', 'news', 'overview') class News(TranslatableModel): + MAX_ON_MAIN_PAGE = 3 + #set manager of this model objects = NewsManager() diff --git a/proj/admin_urls.py b/proj/admin_urls.py index 7cd20cd4..997f0d76 100644 --- a/proj/admin_urls.py +++ b/proj/admin_urls.py @@ -12,7 +12,6 @@ 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 6503f3ec..7b08caa9 100644 --- a/proj/settings.py +++ b/proj/settings.py @@ -51,6 +51,8 @@ TIME_ZONE = 'UTC' # http://www.i18nguy.com/unicode/language-identifiers.html LANGUAGE_CODE = 'ru' +DEFAULT_LANGUAGE = 'ru' + LANGUAGES = ( ('ru', _('Russian')), ('en', _('English')), @@ -379,9 +381,12 @@ LOGGING = { } THUMBNAIL_DEBUG = True + CALLBACK_EMAIL = 'kotzilla@ukr.net' + BOOKING_AID = '333667' + try: from local import * except ImportError, e: diff --git a/proj/urls.py b/proj/urls.py index 26f63bb2..badff0eb 100644 --- a/proj/urls.py +++ b/proj/urls.py @@ -15,6 +15,7 @@ urlpatterns = patterns('', url(r'^', include('webinar.urls')), url(r'^', include('company.urls')), url(r'^', include('photoreport.urls')), + url(r'^', include('article.urls')), url(r'^country/', include('country.urls')), url(r'^city/', include('city.urls')), url(r'^organiser/', include('organiser.urls')), diff --git a/settings/templatetags/template_filters.py b/settings/templatetags/template_filters.py index b54a57ab..0ad33831 100644 --- a/settings/templatetags/template_filters.py +++ b/settings/templatetags/template_filters.py @@ -132,3 +132,50 @@ def random_social(value): @register.filter def is_current_page(request, param): return request.path == param + +from country.models import Country +from django.utils import translation +from city.models import City + +@register.filter +def get_country_by_area(value): + lang = translation.get_language() + countries = Country.objects.select_related('exposition_country')\ + .filter(exposition_country__country__isnull=False, translations__language_code=lang, area__id=value)\ + .order_by('translations__name').distinct() + return list(countries) + +@register.filter +def get_city_by_country(value): + lang = translation.get_language() + cities = City.objects.select_related('exposition_city')\ + .filter(exposition_city__city__isnull=False, translations__language_code=lang, country__id=value)\ + .order_by('translations__name').distinct() + + return list(cities) + +class SetVarNode(template.Node): + + def __init__(self, var_name, var_value): + self.var_name = var_name + self.var_value = var_value + + def render(self, context): + try: + value = template.Variable(self.var_value).resolve(context) + except template.VariableDoesNotExist: + value = "" + context[self.var_name] = value + return u"" + + +def set_var(parser, token): + """ + {% set = %} + """ + parts = token.split_contents() + if len(parts) < 4: + raise template.TemplateSyntaxError("'set' tag must be of the form: {% set = %}") + return SetVarNode(parts[1], parts[3]) + +register.tag('set', set_var) \ No newline at end of file diff --git a/static/client/css/main.css b/static/client/css/main.css index 8f85443f..d41b45df 100644 --- a/static/client/css/main.css +++ b/static/client/css/main.css @@ -11504,6 +11504,20 @@ hr + .rq-note { #mCSB_1 { min-height: 188px; } +/* Page group by*/ +.leter-list{ + float:left; + width: 30%; + min-height:6em; +} + + + +.leter-list .leter{ + color: #ff6600; + } + +/* END block*/ /*dimonn style*/ .clear { clear: both;} @@ -11850,4 +11864,171 @@ margin: 5px -11px 0 -15px;} .places_list .cli-info { margin-bottom: 5px;} .places_list .button.about { margin-top: 0;} -/*dimonn style*/ \ No newline at end of file +/*dimonn style*/ + +/*dimonn style 14.07.2014*/ + .end_reg_list {margin:0 0 0 0;padding:0 0 0 0;} + .end_reg_list li {padding:0 0 24px 0;list-style-type:none;} + .end_reg_list li:last-child {padding:0 0 0 0;} + .end_reg_list li.input_top {padding-right:140px;} + .end_reg_list .input_bottom {padding-right:120px;} + .end_reg_list li table {} + .end_reg_list li table tr th {text-align:left;vertical-align:top;padding:13px 5px 0 0;font-size:17px;color:#000;font-weight:normal;} + .end_reg_list li table tr td {text-align:left;vertical-align:top;} + .end_reg_list li table tr td p {padding:0 0 25px 0;margin:0 0 0 0;text-align:center;font-size:13px;color:#a2a2a2;} + .end_reg_list li table tr td.width1 {width:78px;padding:0 9px 0 0;} + .end_reg_list li table tr td.width2 {width:88px;padding:0 9px 0 0;} + .end_reg_list li table tr td.width3 {width:205px;} + + .add_pic_block {display:block;width:100px;height:80px;padding:20px 0 0 0;text-align:center;font-size:12px;color:#a2a2a2;font-weight:500;text-decoration:none;position:relative;line-height:1.0;-webkit-transition:background .3s, color .3s;-moz-transition:background .3s, color .3s;-ms-transition:background .3s, color .3s;-o-transition:background .3s, color .3s;transition:background .3s, color .3s;font-family:'dindisplay_pro';} + .add_pic_block span {display:block;margin:0 auto;width:35px;height:35px;background-color:#d0d0d0;-webkit-border-radius:50%;-moz-border-radius:50%;border-radius:50%;background-image:url(../img/add_pic_block_bg.png);background-position:center center;background-repeat:no-repeat;-webkit-transition:background .3s, color .3s;-moz-transition:background .3s, color .3s;-ms-transition:background .3s, color .3s;-o-transition:background .3s, color .3s;transition:background .3s, color .3s; position: relative;} + .add_pic_block .input { display: block; width: 100px; height: 100px; position: absolute; left: 0; top: 0; opacity: 0; cursor: pointer;} + .add_pic_block i {display:block;font-style:normal;padding:10px 0 1px 0;} + .add_pic_block b {font-size:14px;font-weight:500;} + .add_pic_block b:before {content:'';display:inline-block;width:14px;height:12px;background:url(../img/sprites.png) -365px -53px no-repeat;margin:0 4px 0 0;position:relative;top:1px;} + + .add_pic_block:hover { color: #ff6600;} + .add_pic_block:hover span { background-color: #ff6600;} + .add_pic_block:hover b:before { background-position: -181px -32px;} + + .add_link_text { padding-left: 0 !important; line-height: 20px; min-height: 25px;} + .add_link_text_text { font-size: 17px; color: #a2a2a2;font-family:'dindisplay_pro'; font-weight: 500; display: inline-block; position: relative; top: -1px;} + .add_link_text_top { min-height: 60px;} + + .add_link_text a {color: #a2a2a2;} + + .add_link_text .edit-wrap { display: inline-block!important; position: relative; left: 0; top: 0; margin: 0 5px 0 0!important; height: 20px;} + .add_link_text a.e-btn {color: #a2a2a2; display: block; padding: 0 0 0 22px; margin: 0 5px 0 0; width: auto; height: auto;font-size: 17px; color: #a2a2a2;font-family:'dindisplay_pro'; font-weight: 500; opacity: 1; float: left;} + .add_link_text a.e-btn:before { content:'';display: inline-block;width:16px;height:17px; background: url(../img/sprites.png) -385px -51px;-webkit-transition: color .3s;-moz-transition: color .3s;-ms-transition: color .3s;-o-transition: color .3s;transition: color .3s; position: absolute; top: 0; left: 0;} + .add_link_text b { margin-left: 10px;} + .add_link_text b:before {content:'';display:inline-block;width:14px;height:12px;background:url(../img/sprites.png) -365px -53px no-repeat;margin:0 4px 0 0;} + .add_link_text_medium a:before { top: 2px;} + + .add_link_text.p-editable.pe-current .edit-wrap .e-form {display: block!important; top: -5px;} + .add_link_text.p-editable.pe-current a.e-btn { text-indent: -9000px; position: relative; padding: 5px 0 5px 5px; left: -5px; position: absolute; top: -5px;} + .add_link_text.p-editable.pe-current a.e-btn:before { position: absolute; left: 5px; top: 5px;display: block !important;background-position: -405px -51px;} + .add_link_text.p-editable.pe-current .add_link_text_text { display: none;} + + .add_link_text_medium a.e-btn, .add_link_text_medium .add_link_text_text, .add_link_text_medium { font-size: 15px !important;} + .add_link_text_medium .add_link_text_text { top: 0;} + + .i-info header .i-place.add_link_text:before { display: none;} + .i-info header .i-place.add_link_text a { text-decoration: underline;color: #a2a2a2;} + .i-info header .i-place.add_link_text a:hover { color: #ff6600;} + + .dd_width_1 { width: 200px !important;} + .dd_width_2 { width: 328px; padding-right: 23px!important;padding-left: 75px!important;} + .dd_width_3 { width:218px; padding-right: 23px!important;} + .dd_width_4 { width: 320px !important;} + .dd_width_5 { width: 260px !important;} + + .i-place.add_link_text.p-editable.pe-current .add_link_text_text { display: block; padding-left: 35px; top: 0;} + .i-place.add_link_text.p-editable.pe-current a.e-btn:before { left: 10px;} + + + .add_link_text a:hover { color: #ff6600;} + .add_link_text a:hover:before { background-position: -425px -51px;} + + + .add_link_teg .select { float: left; width: 368px; margin: 0 13px 0 0; min-height: 36px;} + .add_link_teg b { float: left; position: relative; top: 10px; font-size: 15px; color: #a2a2a2;font-family:'dindisplay_pro'; font-weight: 500;} + .add_link_teg b:before {content:'';display:inline-block;width:14px;height:12px;background:url(../img/sprites.png) -365px -53px no-repeat;margin:0 4px 0 0;} + + .ic-buttons_pos { position: relative;} + .ic-buttons_text { position: absolute; left: 0; top: 32px; font-size: 13px; color: #a2a2a2; font-weight: 500;font-family:'dindisplay_pro';} + + .add_indent { margin-bottom: 4px;} + .ic-links_indent { padding-top: 5px;} + + .soc-media-buttons1 { display: inline-block; position: relative; margin: 0 0 0 0!important; top: -2px; left: 5px;} + .soc-media-indent { margin: 29px 0 0 0;} + .pe-current .soc-media-buttons1 { position: static;} +/* + .soc-media-buttons1 li { position: relative;} + .soc-media-buttons1 li span { display: block; position: absolute; left: 0; top: 0;} + .soc-media-buttons1 li:hover span { display: none;} + .soc-media-buttons1 .add_link_teg b { top: 6px;} +*/ + + + .add_indo_table { width: 100%;font-family:'dindisplay_pro';} + .add_indo_table tr th { text-align: left; vertical-align: top; font-size: 19px; color: #a2a2a2; font-weight: normal; padding: 0 0 13px 0;} + .add_indo_table tr th b { font-size: 20px; color: #a2a2a2;font-family:'dindisplay_pro'; font-weight: 500;} + .add_indo_table tr th b:before {content:'';display:inline-block;width:14px;height:12px;background:url(../img/sprites.png) -365px -53px no-repeat;margin:0 4px 0 0;} + .add_indo_table tr td { text-align: left; vertical-align: middle; font-size: 17px; color: #464646; padding: 5px 0;} + .add_indo_table tr td.click_td span { color: #ff6600; font-size: 14px;} + .add_indo_table tr td.click_td span a {color: #ff6600;} + .add_indo_table tr td.click_td span a:hover { opacity: 0.5;} + .add_indo_table tr td.click_td span a:before { content:'';display: inline-block;width:11px;height:12px; background: url(../img/sprites.png) 0 0; position: relative; top:2px; margin: 0 4px 0 0;} + + .add_indo_table tr td.click_td b { color: #ff6600; font-weight: normal; font-size: 14px;} + .add_indo_table tr td.click_td b a {color: #ff6600;} + .add_indo_table tr td.click_td b a:hover { opacity: 0.5;} + .add_indo_table tr td.click_td b a:before { content:'';display: inline-block;width:12px;height:13px; background: url(../img/sprites.png) -368px -69px; position: relative; top:2px; margin: 0 4px 0 0;} + .add_indo_table tr td .headline { width: 1px; height: 1px; position: relative;} + .add_indo_table tr td .headline p { position: absolute; left: 0; top: 5px;} + + .add_pic_list li { position: relative;} + .add_pic_list li span.close { display: block; position: absolute; right: 29px; top: 9px; width: 16px; height: 16px; background: url(../img/sprites.png) -385px -72px no-repeat; cursor: pointer;} + + .add_pic_list li span.close:hover { background-position: -404px -72px;} + + .add_pic_list li a.add_pic_link {text-align:center;background:#ffffff; display: block;-webkit-box-shadow:inset 0 1px 0 #e8e8e7;-moz-box-shadow:inset 0 1px 0 #e8e8e7;box-shadow:inset 0 1px 0 #e8e8e7;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box; +font-size:16px;color:#a2a2a2;font-weight:500;text-decoration:none;position:relative;line-height:1.0;-webkit-transition:background .3s, color .3s;-moz-transition:background .3s, color .3s;-ms-transition:background .3s, color .3s;-o-transition:background .3s, color .3s;transition:background .3s, color .3s;font-family:'dindisplay_pro';} + .add_pic_list li a.add_pic_link span {display:block;margin:30px auto 0 auto;width:46px;height:46px;background-color:#d0d0d0;-webkit-border-radius:50%;-moz-border-radius:50%;border-radius:50%;background-image:url(../img/add_pic_block_bg2.png);background-position:center center;background-repeat:no-repeat;-webkit-transition:background .3s, color .3s;-moz-transition:background .3s, color .3s;-ms-transition:background .3s, color .3s;-o-transition:background .3s, color .3s;transition:background .3s, color .3s; position: relative;} + .add_pic_list li a.add_pic_link .input { display: block; width: 100%; height: 100%; position: absolute; left: 0; top: 0; opacity: 0; cursor: pointer;} + .add_pic_list li a.add_pic_link i {display:block;font-style:normal;padding:10px 0 1px 0;} + .add_pic_list li a.add_pic_link b {font-size:14px;font-weight:500;} + .add_pic_list li a.add_pic_link b:before {content:'';display:inline-block;width:14px;height:12px;background:url(../img/sprites.png) -365px -53px no-repeat;margin:0 4px 0 0;position:relative;top:1px;} + .add_pic_list li a.add_pic_link:hover { color: #ff6600;} + .add_pic_list li a.add_pic_link:hover span { background-color: #ff6600;} + .add_pic_list li a.add_pic_link:hover b:before { background-position: -181px -32px;} + + + .i-staff-list > ul > li a.add_pic_link {text-align:center;background:#ffffff; display: block;-webkit-box-shadow:inset 0 1px 0 #e8e8e7;-moz-box-shadow:inset 0 1px 0 #e8e8e7;box-shadow:inset 0 1px 0 #e8e8e7;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box; width: 90px; height: 79px; padding: 11px 0 0 0; +font-size:13px;color:#a2a2a2;font-weight:500;text-decoration:none;position:relative;line-height:1.0;-webkit-transition:background .3s, color .3s;-moz-transition:background .3s, color .3s;-ms-transition:background .3s, color .3s;-o-transition:background .3s, color .3s;transition:background .3s, color .3s;font-family:'dindisplay_pro';} + .i-staff-list > ul > li a.add_pic_link span {display:block;margin:0 auto;width:27px;height:27px;background-color:#d0d0d0;-webkit-border-radius:50%;-moz-border-radius:50%;border-radius:50%;background-image:url(../img/add_pic_block_bg1.png);background-position:center center;background-repeat:no-repeat;-webkit-transition:background .3s, color .3s;-moz-transition:background .3s, color .3s;-ms-transition:background .3s, color .3s;-o-transition:background .3s, color .3s;transition:background .3s, color .3s; position: relative;} + .i-staff-list > ul > li a.add_pic_link .input { display: block; width: 100%; height: 100%; position: absolute; left: 0; top: 0; opacity: 0; cursor: pointer;} + .i-staff-list > ul > li a.add_pic_link i {display:block;font-style:normal;padding:10px 0 1px 0;} + .i-staff-list > ul > li a.add_pic_link b {font-size:14px;font-weight:500;} + .i-staff-list > ul > li a.add_pic_link b:before {content:'';display:inline-block;width:14px;height:12px;background:url(../img/sprites.png) -365px -53px no-repeat;margin:0 4px 0 0;position:relative;top:1px;} + .i-staff-list > ul > li a.add_pic_link:hover { color: #ff6600;} + .i-staff-list > ul > li a.add_pic_link:hover span { background-color: #ff6600;} + .i-staff-list > ul > li a.add_pic_link:hover b:before { background-position: -181px -32px;} + + .reason_block { font-size: 11px; color: #ff6600; line-height: 13px; margin: -10px 0 0 0;} + .reason_block p { padding: 6px 0 0 0; margin:0 0 0 0;} + + .i-info header { position: relative;} + + .site_link { position: absolute; right: 0; width: 201px; top: 41px; font-size: 15px !important; color: #ff6600 !important;font-family:'dindisplay_pro'; font-weight: 500; z-index: 50;} + .site_link a { text-decoration: none !important;color: #ff6600 !important;} + .site_link a:before { content:''; width: 16px; height: 16px; background: url(../img/sprites.png) -426px -73px; display: inline-block; margin: 0 5px 0 0; position: relative; top: 4px;} + + .site_link a:hover:before { background-position: -426px -73px!important;} + + .i-contacts1 { margin-top: 0!important;} + .i-additional1 {margin-bottom: 0!important;} + + .cl-item_active { border: 1px solid #fe9232;} + .doings_block { padding-right: 0;} + .doings_block .button { border-color: #ccc; margin: 0 10px 10px 0; font-weight: 400; color: #424242;font-family:'dindisplay_pro'; font-size: 17px;} + .doings_block .button:hover { color: #fff;border-color: #ff7600;} + .doings_block .button.more:after { background-position: -158px -16px;} + .doings_block .button.more:hover:after { background-position: -165px -23px;} + + + .button.dark_green {border-color:#a5c67d;color:#4e9000;} + .button.dark_green:hover {border-color:#4e9000;background:#4e9000;color:#fff;} + .button.icon-up:before {width:13px;height:15px;background-position:-348px -92px;} + .button.icon-up:hover:before {background-position:-365px -92px;} + + .s-news-list ul li {} + .s-news-list .nl-pict { float: left; margin: 0 10px 5px 0;} + + .add_company { text-align: right;} + .add_company a { color: #fff; text-decoration: underline; word-spacing: normal; position: relative; top: -6px;} + .add_company a:hover { text-decoration: none; color: #fff;} + .add_company a:before { content:'';background: url(../img/sprites.png) -405px -51px; display: inline-block !important; width: 16px; height: 17px; position: relative; left: -5px; top: 4px;} + .add_company a:hover:before {background: url(../img/sprites.png) -405px -51px !important;} +/*dimonn style 14.07.2014*/ \ No newline at end of file diff --git a/static/client/img/2.png b/static/client/img/2.png new file mode 100644 index 00000000..42786c85 Binary files /dev/null and b/static/client/img/2.png differ diff --git a/static/client/img/ad-themes/Thumbs.db b/static/client/img/ad-themes/Thumbs.db new file mode 100644 index 00000000..97f15f1f Binary files /dev/null and b/static/client/img/ad-themes/Thumbs.db differ diff --git a/static/client/img/ad-themes/adt-1.png b/static/client/img/ad-themes/adt-1.png new file mode 100644 index 00000000..e672d56b Binary files /dev/null and b/static/client/img/ad-themes/adt-1.png differ diff --git a/static/client/img/ad-themes/adt-2.png b/static/client/img/ad-themes/adt-2.png new file mode 100644 index 00000000..473bc938 Binary files /dev/null and b/static/client/img/ad-themes/adt-2.png differ diff --git a/static/client/img/ad-themes/adt-3.png b/static/client/img/ad-themes/adt-3.png new file mode 100644 index 00000000..56844291 Binary files /dev/null and b/static/client/img/ad-themes/adt-3.png differ diff --git a/static/client/img/add_link_text.png b/static/client/img/add_link_text.png new file mode 100644 index 00000000..74974dd2 Binary files /dev/null and b/static/client/img/add_link_text.png differ diff --git a/static/client/img/add_pic_block_bg.png b/static/client/img/add_pic_block_bg.png new file mode 100644 index 00000000..64a30668 Binary files /dev/null and b/static/client/img/add_pic_block_bg.png differ diff --git a/static/client/img/add_pic_block_bg1.png b/static/client/img/add_pic_block_bg1.png new file mode 100644 index 00000000..74debc37 Binary files /dev/null and b/static/client/img/add_pic_block_bg1.png differ diff --git a/static/client/img/add_pic_block_bg2.png b/static/client/img/add_pic_block_bg2.png new file mode 100644 index 00000000..e515e3b1 Binary files /dev/null and b/static/client/img/add_pic_block_bg2.png differ diff --git a/static/client/img/soc-medias/icon-fb_hover.png b/static/client/img/soc-medias/icon-fb_hover.png new file mode 100644 index 00000000..ab5d6798 Binary files /dev/null and b/static/client/img/soc-medias/icon-fb_hover.png differ diff --git a/static/client/img/soc-medias/icon-lin_hover.png b/static/client/img/soc-medias/icon-lin_hover.png new file mode 100644 index 00000000..c33719f4 Binary files /dev/null and b/static/client/img/soc-medias/icon-lin_hover.png differ diff --git a/static/client/img/soc-medias/sm-icon-twit_hover.png b/static/client/img/soc-medias/sm-icon-twit_hover.png new file mode 100644 index 00000000..7b5b587d Binary files /dev/null and b/static/client/img/soc-medias/sm-icon-twit_hover.png differ diff --git a/static/client/img/soc-medias/sm-icon-vk_hover.png b/static/client/img/soc-medias/sm-icon-vk_hover.png new file mode 100644 index 00000000..c94aee90 Binary files /dev/null and b/static/client/img/soc-medias/sm-icon-vk_hover.png differ diff --git a/static/client/img/sprites.png b/static/client/img/sprites.png index fa25870d..77d3a20c 100644 Binary files a/static/client/img/sprites.png and b/static/client/img/sprites.png differ diff --git a/static/client/js/profile.js b/static/client/js/profile.js index e90905b4..9e144f3f 100644 --- a/static/client/js/profile.js +++ b/static/client/js/profile.js @@ -103,8 +103,8 @@ function handleAboutForm(data){ function formHandler(id, handleFunction){ $(id).on('submit', function(event){ - event.preventDefault() - $this = $(this) + event.preventDefault(); + $this = $(this); var url = $this.attr('action'); var formData = $this.serialize(); $.post(url, formData, handleFunction); @@ -123,10 +123,9 @@ $(document).ready(function(){ formHandler('#web_page_form', handleWebPageForm); formHandler('#about_form', handleAboutForm); - //$('#id_country').onchange = function(){alert('111');} - $('#id_country').on('change', function(){alert('111');}) +// $('#id_country').on('change', function(){alert('111');}) -}) +}); diff --git a/static/custom_js/make_select.js b/static/custom_js/make_select.js index 08304949..04ec7a53 100644 --- a/static/custom_js/make_select.js +++ b/static/custom_js/make_select.js @@ -7,6 +7,8 @@ $(document).ready(function(){ });//end select + + $('#id_city').select2({ placeholder: "Search city", width: 'element', @@ -34,13 +36,58 @@ $(document).ready(function(){ return {results: results}; } }, - initSelection : function(element, callback) { - var id= $(element).val(); - var text = $(element).attr('data-init-text'); - callback({id: id, text:text}); + initSelection : function(element, callback) { + var id= $(element).val(); + var text = $(element).attr('data-init-text'); + callback({id: id, text:text}); - } + } }); + // + $('#id_tag').select2({ + placeholder: "Search tag", + width: '550px', + multiple: true, + ajax: { + + url: "/admin/theme/tag/search/", + dataType: "json", + quietMillis: 200, + multiple: true, + + data: function(term, page, theme){ + var theme = $('#id_theme').serialize(); + return {term: term, + page: page, + theme: theme}; + }, + + results: function (data) { + var results = []; + $.each(data, function(index, item){ + results.push({ + id: item.id, + text: item.label + }); + }); + return {results: results}; + } + }, + initSelection : function(element, callback) { + var data = []; + $(element.val().split(",")).each(function(i) { + var item = this.split(':'); + data.push({ + id: item[0], + text: item[1] + }); + }); + callback(data); + + } + + }); + })//end ready diff --git a/templates/admin/article/article_add.html b/templates/admin/article/article_add.html index 66fe50c6..2adcb5a2 100644 --- a/templates/admin/article/article_add.html +++ b/templates/admin/article/article_add.html @@ -33,9 +33,8 @@ {{ form.article_id }} {# main_title #} - {% with field='main_title' form=form languages=languages %} - {% include 'admin/forms/multilang.html' %} - {% endwith %} + + {% include 'admin/forms/multilang.html' with field='main_title' form=form languages=languages %} {# theme #}
@@ -53,9 +52,9 @@
{# preview #} - {% with field='preview' form=form languages=languages %} - {% include 'admin/forms/multilang.html' %} - {% endwith %} + + {% include 'admin/forms/multilang.html' with field='preview' form=form languages=languages %} + {# author #}
@@ -65,21 +64,18 @@
{# description #} - {% with field='description' form=form languages=languages %} - {% include 'admin/forms/multilang.html' %} - {% endwith %} + {% include 'admin/forms/multilang.html' with field='description' form=form languages=languages %} {# keywords #} - {% with field='keywords' form=form languages=languages %} - {% include 'admin/forms/multilang.html' %} - {% endwith %} + + {% include 'admin/forms/multilang.html' with field='keywords' form=form languages=languages %} + {# title #} - {% with field='title' form=form languages=languages %} - {% include 'admin/forms/multilang.html' %} - {% endwith %} + + {% include 'admin/forms/multilang.html' with field='title' form=form languages=languages %} + {# descriptions #} - {% with field='descriptions' form=form languages=languages %} - {% include 'admin/forms/multilang.html' %} - {% endwith %} + + {% include 'admin/forms/multilang.html' with field='descriptions' form=form languages=languages %} diff --git a/templates/admin/article/article_admin_list.html b/templates/admin/article/article_admin_list.html new file mode 100644 index 00000000..1c0526b5 --- /dev/null +++ b/templates/admin/article/article_admin_list.html @@ -0,0 +1,54 @@ +{% extends 'base.html' %} +{% block body %} +
+
+

Список статей

+
+
+ + + + + + + + + + + + {% for item in object_list %} + + + + + + + + + + + {% endfor %} + +
ЗаголовокАвтор 
{{ item.main_title }}{% ifnotequal item.author None %}{{ item.author }} {% endifnotequal %} + + Изменить + + + + Копировать + + + + Удалить + +
+ + Добавить + {% if blog_flag %}статью{% else %}{% if news_flag %}новость{% endif %}{% endif %} + +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/admin/article/blog_form.html b/templates/admin/article/blog_form.html new file mode 100644 index 00000000..eb531763 --- /dev/null +++ b/templates/admin/article/blog_form.html @@ -0,0 +1,99 @@ +{% extends 'base.html' %} +{% load static %} +{# Displays article form #} + + {% block scripts %} + + + {# selects #} + + + + {# ajax #} + + + + {% endblock %} + +{% block body %} +
{% csrf_token %} +
+ {% if article %} Изменить {% else %} Добавить {% endif %}статью + +
+
+

Основная информация

+
+
+ + {# main_title #} + {% include 'admin/forms/multilang.html' with field='main_title' form=form languages=languages %} + + {# theme #} +
+ +
+ {{ form.theme }} + {{ form.theme.errors }} +
+
+ {# tag #} +
+ +
+ {{ form.tag }} + {{ form.tag.errors }} +
+
+ {# exposition #} + {% if form.exposition %} +
+ +
+ {{ form.exposition }} + {{ form.exposition.errors }} +
+
+ {% endif %} + {# conference #} + {% if form.conference%} +
+ +
+ {{ form.conference }} + {{ form.conference.errors }} +
+
+ {% endif %} + {# logo #} +
+ +
+ {{ form.logo }} + {% if article.logo %} + + + {% endif %} + {{ form.logo.errors }} +
+
+ {# preview #} + {% include 'admin/forms/multilang.html' with field='preview' form=form languages=languages %} + {# description #} + {% include 'admin/forms/multilang.html' with field='description' form=form languages=languages %} + {# keywords #} + {% include 'admin/forms/multilang.html' with field='keywords' form=form languages=languages %} + {# title #} + {% include 'admin/forms/multilang.html' with field='title' form=form languages=languages %} + {# descriptions #} + {% include 'admin/forms/multilang.html' with field='descriptions' form=form languages=languages %} +
+
+
+ + + +
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/admin/base.html b/templates/admin/base.html index fd794200..f8d573ce 100644 --- a/templates/admin/base.html +++ b/templates/admin/base.html @@ -110,8 +110,8 @@